feat: ship validated HyperTwist Windows installer
This commit is contained in:
parent
02ad8fa781
commit
d0e3f96364
23 changed files with 4777 additions and 16 deletions
|
|
@ -18,11 +18,21 @@ Current operator delivery:
|
||||||
- ZIP size: `1,093,537,260` bytes
|
- ZIP size: `1,093,537,260` bytes
|
||||||
- ZIP SHA-256:
|
- ZIP SHA-256:
|
||||||
`630963f96c681fc49130cbc56c6c850008d4cddda7e83f2ee9c077c52d7709a9`
|
`630963f96c681fc49130cbc56c6c850008d4cddda7e83f2ee9c077c52d7709a9`
|
||||||
|
- Validated installer:
|
||||||
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19-Setup.exe`
|
||||||
|
- Installer size: `851049086` bytes
|
||||||
|
- Installer SHA-256:
|
||||||
|
`c31ed6b0b2ae1feb449c27e484d72dc2e07ba220e3cdafa4c3605429d638e0ea`
|
||||||
|
|
||||||
The delivered folder was compared against the validated archive source by
|
The delivered folder was compared against the validated archive source by
|
||||||
hashing all `173` files. The comparison found `0` mismatches. The Downloads ZIP
|
hashing all `173` files. The comparison found `0` mismatches. The Downloads ZIP
|
||||||
size and SHA-256 also match the validation-source ZIP.
|
size and SHA-256 also match the validation-source ZIP.
|
||||||
|
|
||||||
|
The installer is separately grounded by
|
||||||
|
`docs/generated/alpha_test_20260726_installer/README.md`. It installs the same
|
||||||
|
Release 19 runtime payload, bundles the signed Microsoft Visual C++ runtime,
|
||||||
|
and has green install, launch, in-place upgrade, and uninstall lifecycle proof.
|
||||||
|
|
||||||
## Product Scope
|
## Product Scope
|
||||||
|
|
||||||
This package contains the repaired first-run and player-facing shell, reliable
|
This package contains the repaired first-run and player-facing shell, reliable
|
||||||
|
|
@ -63,6 +73,11 @@ where the visible global assistant could reject dictation on 4D, 5D, or
|
||||||
- Browser production build: `1,872` modules transformed.
|
- Browser production build: `1,872` modules transformed.
|
||||||
- Exact solver table: `676,207,080` bytes, SHA-256
|
- Exact solver table: `676,207,080` bytes, SHA-256
|
||||||
`dc6de3d909a37afe2ba7f1f978543a13eae215bd20d954d66813524a8ca20034`.
|
`dc6de3d909a37afe2ba7f1f978543a13eae215bd20d954d66813524a8ca20034`.
|
||||||
|
- Windows installer build: `passed`, `143` payload files,
|
||||||
|
`1,585,341,236` payload bytes, and `0` NSIS compiler warnings.
|
||||||
|
- Installer lifecycle: first install, complete hash parity, readiness, Shipping
|
||||||
|
launch, in-place upgrade, second parity, uninstall, user-data preservation,
|
||||||
|
and owned-state cleanup all `passed`.
|
||||||
|
|
||||||
The automation authority is
|
The automation authority is
|
||||||
`player_experience_automation_index.json`. Package, staged-browser,
|
`player_experience_automation_index.json`. Package, staged-browser,
|
||||||
|
|
@ -130,6 +145,7 @@ conditions:
|
||||||
real audio hardware.
|
real audio hardware.
|
||||||
- Live XR headset-session and controller-input observation still requires a
|
- Live XR headset-session and controller-input observation still requires a
|
||||||
connected headset and controllers.
|
connected headset and controllers.
|
||||||
- Installer/uninstaller, code signing, clean-machine prerequisites,
|
- Installer/uninstaller ownership and isolated-current-host prerequisite proof
|
||||||
entitlement, and update-channel rollout remain release-engineering gates
|
are now closed. Trusted code signing, genuinely fresh-machine proof,
|
||||||
above this portable Alpha package.
|
entitlement-backed public delivery, and update-channel rollout remain
|
||||||
|
release-engineering gates above this Alpha package.
|
||||||
|
|
|
||||||
119
docs/generated/alpha_test_20260726_installer/README.md
Normal file
119
docs/generated/alpha_test_20260726_installer/README.md
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
# HyperTwist Alpha R19 Windows Installer Evidence
|
||||||
|
|
||||||
|
## Authority
|
||||||
|
|
||||||
|
This directory is the durable evidence index for the first validated
|
||||||
|
HyperTwist Windows installer above the Release 19 Shipping Alpha payload.
|
||||||
|
|
||||||
|
Current operator delivery:
|
||||||
|
|
||||||
|
- installer:
|
||||||
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19-Setup.exe`
|
||||||
|
- size: `851049086` bytes
|
||||||
|
- SHA-256:
|
||||||
|
`c31ed6b0b2ae1feb449c27e484d72dc2e07ba220e3cdafa4c3605429d638e0ea`
|
||||||
|
- Authenticode: `NotSigned`
|
||||||
|
|
||||||
|
The unsigned status is an explicit Alpha limitation. Production distribution
|
||||||
|
still requires a trusted Authenticode certificate and signed-artifact proof.
|
||||||
|
|
||||||
|
## Installer Ownership
|
||||||
|
|
||||||
|
The NSIS installer owns a per-machine, 64-bit installation with:
|
||||||
|
|
||||||
|
- Windows 10 22H2 / Windows 11 and x64 preflight
|
||||||
|
- a valid Microsoft-signed Visual C++ 2015-2022 x64 redistributable
|
||||||
|
- the complete `143`-file Release 19 runtime payload
|
||||||
|
- PDB and debug-manifest exclusion
|
||||||
|
- a complete SHA-256 payload manifest
|
||||||
|
- Add/Remove Programs registration
|
||||||
|
- Start Menu app, readiness, and uninstall shortcuts
|
||||||
|
- an optional all-users desktop shortcut
|
||||||
|
- marker-and-registry-gated upgrade and uninstall ownership
|
||||||
|
- a hard `HyperTwist` install-directory leaf contract
|
||||||
|
- refusal of unowned non-empty install directories
|
||||||
|
- user-visible, manifest-aware readiness reporting
|
||||||
|
- preservation of settings, saves, replays, and diagnostics during uninstall
|
||||||
|
|
||||||
|
The prior payload is not cleaned for upgrade until the bundled prerequisite
|
||||||
|
has succeeded. Failed builds remove incomplete installer output rather than
|
||||||
|
leaving a corrupt executable at the release destination.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
The final build passed with:
|
||||||
|
|
||||||
|
- NSIS `3.12`
|
||||||
|
- `0` compiler warnings
|
||||||
|
- payload files: `143`
|
||||||
|
- payload bytes: `1585341236`
|
||||||
|
- exact solver table: `676207080` bytes
|
||||||
|
- exact solver SHA-256:
|
||||||
|
`dc6de3d909a37afe2ba7f1f978543a13eae215bd20d954d66813524a8ca20034`
|
||||||
|
- source readiness: `ready-with-warnings`
|
||||||
|
- required readiness failures: `0`
|
||||||
|
- optional warnings: unsigned desktop code and no active OpenXR runtime
|
||||||
|
|
||||||
|
Bounded contract proof also passed:
|
||||||
|
|
||||||
|
- all `3` PowerShell scripts parsed on Linux PowerShell and Windows PowerShell
|
||||||
|
- disposable NSIS contract compilation completed with `0` warnings
|
||||||
|
- an unsafe install-directory leaf was refused with exit code `13`
|
||||||
|
- an unowned non-empty `HyperTwist` directory was refused with exit code `14`
|
||||||
|
- the unrelated sentinel survived and no product registration was created
|
||||||
|
- manifest traversal input was blocked as `invalid-path:../escape.txt`
|
||||||
|
- manifest file-count and total-size tampering were blocked
|
||||||
|
- the interactive readiness wait completed under redirected-input proof
|
||||||
|
|
||||||
|
The final lifecycle used a path containing spaces and passed:
|
||||||
|
|
||||||
|
- unowned-directory refusal
|
||||||
|
- first silent install, exit `0`
|
||||||
|
- first `143`-entry payload hash parity
|
||||||
|
- Add/Remove Programs and product-registration ownership
|
||||||
|
- resolved app, readiness, uninstall, and desktop shortcut contracts
|
||||||
|
- installed readiness with `0` required failures
|
||||||
|
- stock-Shipping launch diagnostics with runtime initialization
|
||||||
|
- `0` fatal lines and `0` package-owned listeners
|
||||||
|
- in-place upgrade, exit `0`
|
||||||
|
- second `143`-entry payload hash parity
|
||||||
|
- silent uninstall, exit `0`
|
||||||
|
- user-data sentinel preservation
|
||||||
|
- install-root, registration, and shortcut removal
|
||||||
|
- final owned-process count `0`
|
||||||
|
|
||||||
|
The validation class is `isolated-current-host`. No Windows Sandbox, clean
|
||||||
|
Hyper-V VM, or base VHD was available, so this evidence does not masquerade as
|
||||||
|
a fresh-machine proof.
|
||||||
|
|
||||||
|
## Failure Lineage
|
||||||
|
|
||||||
|
`pre-release-shortcut-failure-report.json` records the intentionally rejected
|
||||||
|
candidate whose readiness shortcut embedded the installing administrator's
|
||||||
|
temporary path. That report proved first-install payload parity and successful
|
||||||
|
failure cleanup. The final installer supersedes it with a per-user report path,
|
||||||
|
manifest-aware arguments, an interactive wait, and resolved shortcut-target
|
||||||
|
validation.
|
||||||
|
|
||||||
|
## Evidence Map
|
||||||
|
|
||||||
|
- `windows-installer-build-report.json`: final build and installer identity
|
||||||
|
- `windows-installer-payload-manifest.json`: complete payload hashes and sizes
|
||||||
|
- `windows-installer-source-readiness-report.json`: source-host readiness
|
||||||
|
- `windows-installer-lifecycle-report.json`: final install-to-uninstall proof
|
||||||
|
- `installed-readiness-report.json`: installed-host and manifest proof
|
||||||
|
- `installed-runtime.hyperdiagnostics.log`: Shipping runtime initialization
|
||||||
|
- `installed-first-run-launch.log`: first-run menu launch authority
|
||||||
|
- `manifest-hardening-positive.json`: full manifest reconciliation proof
|
||||||
|
- `makensis.log`: final compiler transcript
|
||||||
|
- `pre-release-shortcut-failure-report.json`: superseded failure lineage
|
||||||
|
- `post-task-hygiene-report.json`: doctrine-ordered artifact disposition
|
||||||
|
|
||||||
|
## Remaining External Gates
|
||||||
|
|
||||||
|
- trusted Authenticode code signing
|
||||||
|
- a genuinely fresh Windows VM install and first-launch proof
|
||||||
|
- entitlement-backed public release URL wiring
|
||||||
|
- update-channel, rollback, and staged-rollout proof
|
||||||
|
- real headset/controller observation
|
||||||
|
- configured-provider, microphone, and audible-TTS observation
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
session=20260726T092358Z
|
||||||
|
world=L_HyperTwist_ClassicTraining
|
||||||
|
runtime_log=C:/HyperTwist Installer Validation/20260726T091926Z/evidence/isolated-user/Saved/Logs/HyperTwistRuntime-latest.log
|
||||||
|
latest_diagnostics_log=C:/HyperTwist Installer Validation/20260726T091926Z/evidence/isolated-user/Saved/Logs/HyperTwistFirstRunLaunch-latest.log
|
||||||
|
[2026-07-26T09:23:58Z] [BeginPlay] First-run controller booted on world 'L_HyperTwist_ClassicTraining'.
|
||||||
|
[2026-07-26T09:23:58Z] [ApplyFirstRunInputMode] Applied game-and-UI input mode with unlocked cursor capture.
|
||||||
|
[2026-07-26T09:23:58Z] [ShowFirstRunLaunchMenu] Fell back to the native first-run widget class.
|
||||||
|
[2026-07-26T09:23:58Z] [ShowFirstRunLaunchMenu] Added the first-run launch widget to the viewport at z-order 100.
|
||||||
|
[2026-07-26T09:23:58Z] [ApplyFirstRunInputMode] Applied game-and-UI input mode with unlocked cursor capture.
|
||||||
|
[2026-07-26T09:24:00Z] [StartupRecovery] The first-run launch widget never produced a visible non-zero layout after 20 attempts (last size 0x0).
|
||||||
|
[2026-07-26T09:24:00Z] [StartupRecovery] Attempting fallback route 'classic-cube-training'.
|
||||||
|
[2026-07-26T09:24:00Z] [OpenFirstRunRoute] Opening route 'classic-cube-training' (dedicated-map).
|
||||||
|
[2026-07-26T09:24:00Z] [OpenMapRoute] Opening map '/Game/HyperTwistTraining/Maps/L_HyperTwist_ClassicTraining' with options 'game=/Script/UnrealHyperTwist.HyperTwistClassicCubeGameMode'.
|
||||||
|
result=startup-recovered
|
||||||
|
last_failure=The first-run launch widget never produced a visible non-zero layout after 20 attempts (last size 0x0).
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
{
|
||||||
|
"reportVersion": "ht-windows-readiness/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T09:23:56.9501545Z",
|
||||||
|
"result": "ready-with-warnings",
|
||||||
|
"payloadRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"targetInstallRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"requiredFailureCount": 0,
|
||||||
|
"optionalWarningCount": 2,
|
||||||
|
"checks": [
|
||||||
|
{
|
||||||
|
"id": "windows-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires a 64-bit Windows operating system.",
|
||||||
|
"evidence": {
|
||||||
|
"architecture": "64-bit",
|
||||||
|
"processArchitecture": "AMD64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-supported-build",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires Windows build 19045 or newer.",
|
||||||
|
"evidence": {
|
||||||
|
"caption": "Microsoft Windows 11 Home",
|
||||||
|
"version": "10.0.22631",
|
||||||
|
"build": 22631,
|
||||||
|
"minimumBuild": 19045
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system-memory",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least 8 GiB of physical memory is required for the desktop Alpha.",
|
||||||
|
"evidence": {
|
||||||
|
"totalBytes": 16893206528,
|
||||||
|
"minimumBytes": 8589934592
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "install-volume-free-space",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The target volume must have enough free space for installation and first-run caches.",
|
||||||
|
"evidence": {
|
||||||
|
"targetInstallRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"availableBytes": 167681560576,
|
||||||
|
"minimumBytes": 4294967296
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vc-runtime-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Microsoft Visual C++ 2015-2022 x64 runtime 14.44.35211.0 or newer is required and is bundled by the installer.",
|
||||||
|
"evidence": {
|
||||||
|
"registryPath": "HKLM:\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64",
|
||||||
|
"installed": true,
|
||||||
|
"version": "14.44.35211.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-media-and-graphics-libraries",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Windows DirectX, XInput, and Media Foundation runtime libraries must be available.",
|
||||||
|
"evidence": {
|
||||||
|
"systemDirectory": "C:\\Windows\\system32",
|
||||||
|
"requiredLibraries": [
|
||||||
|
"d3d11.dll",
|
||||||
|
"d3d12.dll",
|
||||||
|
"dxgi.dll",
|
||||||
|
"mf.dll",
|
||||||
|
"mfplat.dll",
|
||||||
|
"mfreadwrite.dll",
|
||||||
|
"xinput1_4.dll"
|
||||||
|
],
|
||||||
|
"missingLibraries": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "graphics-adapter",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least one Windows graphics adapter must be visible.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel(R) Iris(R) Xe Graphics",
|
||||||
|
"driverVersion": "31.0.101.3358",
|
||||||
|
"driverDate": "2022-08-04T02:00:00.0000000+02:00",
|
||||||
|
"adapterRamBytes": 1073741824,
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audio-device",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "An audio device is optional for puzzle play and recommended for narration and speech features.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Digital Microphones",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for USB Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Bluetooth® Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Audio Device",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Virtual Audio Cable",
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "openxr-runtime",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "An active OpenXR runtime is optional for keyboard/mouse play and required only for live headset sessions.",
|
||||||
|
"evidence": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "required-payload-files",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must contain every required executable, runtime, cooked-data, browser, solver, and OpenXR file.",
|
||||||
|
"evidence": {
|
||||||
|
"payloadRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"requiredFileCount": 15,
|
||||||
|
"cefRuntimeFiles": [
|
||||||
|
"Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/libcef.dll"
|
||||||
|
],
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "desktop-code-signature",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "The Alpha payload is currently unsigned; production distribution requires Authenticode signing.",
|
||||||
|
"evidence": {
|
||||||
|
"status": "NotSigned",
|
||||||
|
"signer": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "payload-manifest-parity",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must match the release manifest without missing, truncated, or altered files.",
|
||||||
|
"evidence": {
|
||||||
|
"manifestPath": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\\Installer\\payload-manifest.json",
|
||||||
|
"manifestVersion": "ht-windows-installer-payload/v1",
|
||||||
|
"manifestEntryCount": 143,
|
||||||
|
"declaredFileCount": 143,
|
||||||
|
"declaredTotalSizeBytes": 1585341236,
|
||||||
|
"computedTotalSizeBytes": 1585341236,
|
||||||
|
"hashesVerified": true,
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
format=hypertwist-runtime-diagnostics/v1
|
||||||
|
session=20260726T092358Z
|
||||||
|
process_id=14248
|
||||||
|
command_line=-notraceserver -traceautostart=0 -NullRHI -nosound -windowed -ResX=1280 -ResY=720 -log -FORCELOGFLUSH -abslog=C:\HyperTwist Installer Validation\20260726T091926Z\evidence\installed-runtime.log -HyperTwistDiagnosticsLog="C:\HyperTwist Installer Validation\20260726T091926Z\evidence\installed-runtime.hyperdiagnostics.log" -UserDir="C:\HyperTwist Installer Validation\20260726T091926Z\evidence\isolated-user"
|
||||||
|
diagnostics_path=C:/HyperTwist Installer Validation/20260726T091926Z/evidence/installed-runtime.hyperdiagnostics.log
|
||||||
|
[2026-07-26T09:23:58Z] [Process] HyperTwist runtime module initialized.
|
||||||
|
[2026-07-26T09:24:00Z] [MapReady] Runtime map ready: /Game/HyperTwistTraining/Maps/L_HyperTwist_ClassicTraining.L_HyperTwist_ClassicTraining.
|
||||||
|
[2026-07-26T09:24:00Z] [ClassicPresentation] Classic cube presentation initialized with 26 renderable pieces and orbit pawn ready.
|
||||||
|
[2026-07-26T09:24:07Z] [ClassicScrambleSettlement] Classic cube scramble settled with 11 completed quarter turns, 0 queued rotations, and 26 renderable pieces; renderable state valid.
|
||||||
557
docs/generated/alpha_test_20260726_installer/makensis.log
Normal file
557
docs/generated/alpha_test_20260726_installer/makensis.log
Normal file
|
|
@ -0,0 +1,557 @@
|
||||||
|
MakeNSIS v3.12 - Copyright 1999-2026 Contributors
|
||||||
|
See the file COPYING for license details.
|
||||||
|
Credits can be found in the Users Manual.
|
||||||
|
|
||||||
|
Command line defined: "PRODUCT_VERSION=0.19.0.0"
|
||||||
|
Command line defined: "DISPLAY_VERSION=Alpha R19"
|
||||||
|
Command line defined: "RELEASE_ID=20260723-R19"
|
||||||
|
Command line defined: "OUTPUT_FILE=C:\HyperTwist_worktrees\installer-release19-20260726\HyperTwist-Alpha-Test-20260723-R19-Setup.exe"
|
||||||
|
Command line defined: "PAYLOAD_ROOT=C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows"
|
||||||
|
Command line defined: "PAYLOAD_MANIFEST=C:\HyperTwist_worktrees\installer-release19-20260726\validation\windows-installer-payload-manifest.json"
|
||||||
|
Command line defined: "READINESS_SCRIPT=C:\HyperTwist_worktrees\phase10validate\scripts\Test-HyperTwistWindowsReadiness.ps1"
|
||||||
|
Command line defined: "VC_REDIST_PATH=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\v143\vc_redist.x64.exe"
|
||||||
|
Command line defined: "INSTALLER_ICON=C:\HyperTwist_worktrees\installer-release19-20260726\build-context\HyperTwist.ico"
|
||||||
|
Command line defined: "PAYLOAD_SIZE_KB=1548185"
|
||||||
|
Processing config: C:\Program Files (x86)\NSIS\nsisconf.nsh
|
||||||
|
Processing default plugins: "C:\Program Files (x86)\NSIS\Plugins\x86-unicode\*.dll"
|
||||||
|
+ AdvSplash::show
|
||||||
|
+ Banner::destroy
|
||||||
|
+ Banner::getWindow
|
||||||
|
+ Banner::show
|
||||||
|
+ BgImage::AddImage
|
||||||
|
+ BgImage::AddText
|
||||||
|
+ BgImage::Clear
|
||||||
|
+ BgImage::Destroy
|
||||||
|
+ BgImage::Redraw
|
||||||
|
+ BgImage::SetBg
|
||||||
|
+ BgImage::SetReturn
|
||||||
|
+ BgImage::Sound
|
||||||
|
+ Dialer::AttemptConnect
|
||||||
|
+ Dialer::AutodialHangup
|
||||||
|
+ Dialer::AutodialOnline
|
||||||
|
+ Dialer::AutodialUnattended
|
||||||
|
+ Dialer::GetConnectedState
|
||||||
|
+ InstallOptions::dialog
|
||||||
|
+ InstallOptions::initDialog
|
||||||
|
+ InstallOptions::make_unicode
|
||||||
|
+ InstallOptions::show
|
||||||
|
+ LangDLL::LangDialog
|
||||||
|
+ Math::Script
|
||||||
|
+ NSISdl::download
|
||||||
|
+ NSISdl::download_quiet
|
||||||
|
+ Splash::show
|
||||||
|
+ StartMenu::Init
|
||||||
|
+ StartMenu::Select
|
||||||
|
+ StartMenu::Show
|
||||||
|
+ System::Alloc
|
||||||
|
+ System::Call
|
||||||
|
+ System::Copy
|
||||||
|
+ System::Free
|
||||||
|
+ System::Get
|
||||||
|
+ System::Int64Op
|
||||||
|
+ System::Store
|
||||||
|
+ System::StrAlloc
|
||||||
|
+ TypeLib::GetLibVersion
|
||||||
|
+ TypeLib::Register
|
||||||
|
+ TypeLib::UnRegister
|
||||||
|
+ UserInfo::GetAccountType
|
||||||
|
+ UserInfo::GetName
|
||||||
|
+ UserInfo::GetOriginalAccountType
|
||||||
|
+ VPatch::GetFileCRC32
|
||||||
|
+ VPatch::GetFileMD5
|
||||||
|
+ VPatch::vpatchfile
|
||||||
|
+ nsDialogs::Create
|
||||||
|
+ nsDialogs::CreateControl
|
||||||
|
+ nsDialogs::CreateItem
|
||||||
|
+ nsDialogs::CreateTimer
|
||||||
|
+ nsDialogs::GetUserData
|
||||||
|
+ nsDialogs::KillTimer
|
||||||
|
+ nsDialogs::OnBack
|
||||||
|
+ nsDialogs::OnChange
|
||||||
|
+ nsDialogs::OnClick
|
||||||
|
+ nsDialogs::OnNotify
|
||||||
|
+ nsDialogs::SelectFileDialog
|
||||||
|
+ nsDialogs::SelectFolderDialog
|
||||||
|
+ nsDialogs::SetRTL
|
||||||
|
+ nsDialogs::SetUserData
|
||||||
|
+ nsDialogs::Show
|
||||||
|
+ nsExec::Exec
|
||||||
|
+ nsExec::ExecToLog
|
||||||
|
+ nsExec::ExecToStack
|
||||||
|
|
||||||
|
!define: "MUI_INSERT_NSISCONF"=""
|
||||||
|
|
||||||
|
Changing directory to: "C:\HyperTwist_worktrees\phase10validate\packaging\windows"
|
||||||
|
|
||||||
|
Processing script file: "C:\HyperTwist_worktrees\phase10validate\packaging\windows\HyperTwistInstaller.nsi" (ACP)
|
||||||
|
Unicode: true
|
||||||
|
Processing default plugins: "C:\Program Files (x86)\NSIS\Plugins\x86-unicode\*.dll"
|
||||||
|
|
||||||
|
!include: "C:\Program Files (x86)\NSIS\Include\MUI2.nsh" (UTF8)
|
||||||
|
!include: "C:\Program Files (x86)\NSIS\Contrib\Modern UI 2\MUI2.nsh" (UTF8)
|
||||||
|
NSIS Modern User Interface version 2.1 - Copyright 2002-2026 Joost Verburg (C:\Program Files (x86)\NSIS\Contrib\Modern UI 2\MUI2.nsh:14)
|
||||||
|
!include: closed: "C:\Program Files (x86)\NSIS\Contrib\Modern UI 2\MUI2.nsh"
|
||||||
|
!include: closed: "C:\Program Files (x86)\NSIS\Include\MUI2.nsh"
|
||||||
|
!include: "C:\Program Files (x86)\NSIS\Include\LogicLib.nsh" (UTF8)
|
||||||
|
!include: closed: "C:\Program Files (x86)\NSIS\Include\LogicLib.nsh"
|
||||||
|
!include: "C:\Program Files (x86)\NSIS\Include\WinVer.nsh" (UTF8)
|
||||||
|
!include: closed: "C:\Program Files (x86)\NSIS\Include\WinVer.nsh"
|
||||||
|
!include: "C:\Program Files (x86)\NSIS\Include\x64.nsh" (UTF8)
|
||||||
|
!define: "___X64__NSH___"=""
|
||||||
|
!include: "C:\Program Files (x86)\NSIS\Include\LogicLib.nsh" (UTF8)
|
||||||
|
!include: closed: "C:\Program Files (x86)\NSIS\Include\LogicLib.nsh"
|
||||||
|
!define: "IsWow64"=""" IsWow64 """
|
||||||
|
!define: "RunningX64"=""" RunningX64 """
|
||||||
|
!define: "GetNativeMachineArchitecture"="!insertmacro GetNativeMachineArchitecture "
|
||||||
|
!define: "IsNativeMachineArchitecture"=""" IsNativeMachineArchitecture "
|
||||||
|
!define: "IsNativeIA32"=""" IsNativeMachineArchitecture 332"
|
||||||
|
!define: "IsNativeAMD64"=""" IsNativeMachineArchitecture 34404"
|
||||||
|
!define: "IsNativeARM64"=""" IsNativeMachineArchitecture 43620"
|
||||||
|
!define: "DisableX64FSRedirection"="!insertmacro DisableX64FSRedirection"
|
||||||
|
!define: "EnableX64FSRedirection"="!insertmacro EnableX64FSRedirection"
|
||||||
|
!include: closed: "C:\Program Files (x86)\NSIS\Include\x64.nsh"
|
||||||
|
!include: "C:\Program Files (x86)\NSIS\Include\FileFunc.nsh" (UTF8)
|
||||||
|
!include: closed: "C:\Program Files (x86)\NSIS\Include\FileFunc.nsh"
|
||||||
|
!define: "PRODUCT_NAME"="HyperTwist"
|
||||||
|
!define: "PRODUCT_CHANNEL"="Alpha"
|
||||||
|
!define: "PRODUCT_PUBLISHER"="HyperTwist"
|
||||||
|
!define: "PRODUCT_WEBSITE"="https://hypertwist.app"
|
||||||
|
!define: "PRODUCT_SUPPORT"="https://hypertwist.app/support"
|
||||||
|
!define: "PRODUCT_REG_KEY"="Software\HyperTwist\HyperTwist"
|
||||||
|
!define: "PRODUCT_UNINSTALL_KEY"="Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist"
|
||||||
|
!define: "INSTALL_MARKER"="HyperTwist.install-marker"
|
||||||
|
Name: "HyperTwist Alpha"
|
||||||
|
Caption: "HyperTwist Alpha R19 Setup"
|
||||||
|
BrandingText: "HyperTwist | Explore dimensions beyond the ordinary"
|
||||||
|
OutFile: "C:\HyperTwist_worktrees\installer-release19-20260726\HyperTwist-Alpha-Test-20260723-R19-Setup.exe"
|
||||||
|
InstallDir: "$PROGRAMFILES64\HyperTwist"
|
||||||
|
CRCCheck: force
|
||||||
|
SetDatablockOptimize: on
|
||||||
|
SetCompressor: /SOLID lzma
|
||||||
|
SetCompressorDictSize: 64 mb
|
||||||
|
ShowInstDetails: show
|
||||||
|
ShowUninstDetails: show
|
||||||
|
Icon: "C:\HyperTwist_worktrees\installer-release19-20260726\build-context\HyperTwist.ico"
|
||||||
|
UninstallIcon: "C:\HyperTwist_worktrees\installer-release19-20260726\build-context\HyperTwist.ico"
|
||||||
|
VIAddVersionKey: "ProductName" "HyperTwist"
|
||||||
|
VIAddVersionKey: "ProductVersion" "Alpha R19"
|
||||||
|
VIAddVersionKey: "CompanyName" "HyperTwist"
|
||||||
|
VIAddVersionKey: "FileDescription" "HyperTwist Alpha Installer"
|
||||||
|
VIAddVersionKey: "FileVersion" "0.19.0.0"
|
||||||
|
VIAddVersionKey: "LegalCopyright" "Copyright (c) HyperTwist"
|
||||||
|
VIAddVersionKey: "OriginalFilename" "HyperTwist-Setup.exe"
|
||||||
|
!define: "MUI_ABORTWARNING"=""
|
||||||
|
!define: "MUI_ICON"="C:\HyperTwist_worktrees\installer-release19-20260726\build-context\HyperTwist.ico"
|
||||||
|
!define: "MUI_UNICON"="C:\HyperTwist_worktrees\installer-release19-20260726\build-context\HyperTwist.ico"
|
||||||
|
!define: "MUI_FINISHPAGE_LINK"="Visit hypertwist.app"
|
||||||
|
!define: "MUI_FINISHPAGE_LINK_LOCATION"="https://hypertwist.app"
|
||||||
|
!insertmacro: MUI_PAGE_WELCOME
|
||||||
|
!insertmacro: end of MUI_PAGE_WELCOME
|
||||||
|
!insertmacro: MUI_PAGE_COMPONENTS
|
||||||
|
!insertmacro: end of MUI_PAGE_COMPONENTS
|
||||||
|
!insertmacro: MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro: end of MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro: MUI_PAGE_INSTFILES
|
||||||
|
!insertmacro: end of MUI_PAGE_INSTFILES
|
||||||
|
!insertmacro: MUI_PAGE_FINISH
|
||||||
|
!insertmacro: end of MUI_PAGE_FINISH
|
||||||
|
!insertmacro: MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro: end of MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro: MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro: end of MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro: MUI_UNPAGE_FINISH
|
||||||
|
!insertmacro: end of MUI_UNPAGE_FINISH
|
||||||
|
!insertmacro: MUI_LANGUAGE
|
||||||
|
!insertmacro: end of MUI_LANGUAGE
|
||||||
|
Function: ".onInit"
|
||||||
|
SetRegView: 64
|
||||||
|
!insertmacro: _If
|
||||||
|
!insertmacro: end of _If
|
||||||
|
MessageBox: 16: "HyperTwist requires 64-bit Windows."
|
||||||
|
SetErrorLevel: 10
|
||||||
|
Quit
|
||||||
|
!insertmacro: _EndIf
|
||||||
|
!insertmacro: end of _EndIf
|
||||||
|
!insertmacro: _If
|
||||||
|
!insertmacro: end of _If
|
||||||
|
MessageBox: 16: "HyperTwist requires Windows 10 version 22H2 or Windows 11."
|
||||||
|
SetErrorLevel: 11
|
||||||
|
Quit
|
||||||
|
!insertmacro: _EndIf
|
||||||
|
!insertmacro: end of _EndIf
|
||||||
|
ReadRegStr $1 HKLM\Software\HyperTwist\HyperTwist\InstallLocation
|
||||||
|
StrCmp "$1" "" equal=install_location_ready, nonequal=
|
||||||
|
StrCpy $INSTDIR "$1" () ()
|
||||||
|
ReadRegStr $0 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentBuildNumber
|
||||||
|
IntCmp $0:19045 equal=windows_build_ok, < windows_build_too_old, > windows_build_ok
|
||||||
|
MessageBox: 16: "This Windows build is too old for the supported HyperTwist Alpha baseline. Update to Windows 10 22H2 or Windows 11 and try again."
|
||||||
|
SetErrorLevel: 12
|
||||||
|
Quit
|
||||||
|
FunctionEnd
|
||||||
|
Function: "CleanOwnedPayloadForUpgrade"
|
||||||
|
ReadRegStr $0 HKLM\Software\HyperTwist\HyperTwist\InstallLocation
|
||||||
|
StrCmp "$0" "$INSTDIR" equal=registry_owner_confirmed, nonequal=cleanup_done
|
||||||
|
IfFileExists: "$INSTDIR\Installer\HyperTwist.install-marker" ? 0 : cleanup_done
|
||||||
|
DetailPrint: "Removing the previous HyperTwist payload before upgrade."
|
||||||
|
RMDir: /r "$INSTDIR\Content"
|
||||||
|
RMDir: /r "$INSTDIR\Engine"
|
||||||
|
RMDir: /r "$INSTDIR\UnrealHyperTwist"
|
||||||
|
RMDir: /r "$INSTDIR\Installer"
|
||||||
|
Delete: "$INSTDIR\Manifest_DebugFiles_Win64.txt"
|
||||||
|
Delete: "$INSTDIR\Manifest_NonUFSFiles_Win64.txt"
|
||||||
|
Delete: "$INSTDIR\Manifest_UFSFiles_Win64.txt"
|
||||||
|
Delete: "$INSTDIR\UnrealHyperTwist.exe"
|
||||||
|
Delete: "$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
FunctionEnd
|
||||||
|
Function: "AssertSafeInstallLocation"
|
||||||
|
!insertmacro: GetFileNameCall
|
||||||
|
!insertmacro: end of GetFileNameCall
|
||||||
|
StrCmp "$0" "HyperTwist" equal=install_leaf_safe, nonequal=install_location_refused
|
||||||
|
ReadRegStr $0 HKLM\Software\HyperTwist\HyperTwist\InstallLocation
|
||||||
|
StrCmp "$0" "$INSTDIR" equal=install_registry_owner_candidate, nonequal=install_unowned_scan
|
||||||
|
IfFileExists: "$INSTDIR\Installer\HyperTwist.install-marker" ? install_location_safe : install_unowned_scan
|
||||||
|
FindFirst: spec="$INSTDIR\*" handle=$0 output=$1
|
||||||
|
StrCmp "$1" "" equal=install_unowned_empty, nonequal=
|
||||||
|
StrCmp "$1" "." equal=install_unowned_continue, nonequal=
|
||||||
|
StrCmp "$1" ".." equal=install_unowned_continue, nonequal=
|
||||||
|
FindClose: $0
|
||||||
|
MessageBox: 16: "The selected HyperTwist folder is not empty and is not owned by an existing registered HyperTwist installation. Choose an empty folder named HyperTwist."
|
||||||
|
SetErrorLevel: 14
|
||||||
|
Abort: ""
|
||||||
|
FindNext: handle=$0 output=$1
|
||||||
|
Goto: install_unowned_scan_next
|
||||||
|
FindClose: $0
|
||||||
|
Goto: install_location_safe
|
||||||
|
MessageBox: 16: "The installation folder itself must be named HyperTwist, for example C:\Program Files\HyperTwist or D:\Games\HyperTwist."
|
||||||
|
SetErrorLevel: 13
|
||||||
|
Abort: ""
|
||||||
|
FunctionEnd
|
||||||
|
Section: "-ValidateInstallLocation"
|
||||||
|
Call "AssertSafeInstallLocation"
|
||||||
|
SectionEnd
|
||||||
|
Section: "-MicrosoftRuntime"
|
||||||
|
SetOutPath: "$PLUGINSDIR"
|
||||||
|
File: "vc_redist.x64.exe"->"vc_redist.x64.exe" 25635768 bytes
|
||||||
|
DetailPrint: "Installing or repairing the Microsoft Visual C++ 2015-2022 x64 runtime."
|
||||||
|
ExecWait: ""$PLUGINSDIR\vc_redist.x64.exe" /install /quiet /norestart" (->$0)
|
||||||
|
!insertmacro: _If
|
||||||
|
!insertmacro: end of _If
|
||||||
|
DetailPrint: "The Microsoft runtime requested a restart."
|
||||||
|
SetRebootFlag: true
|
||||||
|
!insertmacro: _ElseIf
|
||||||
|
!insertmacro: end of _ElseIf
|
||||||
|
DetailPrint: "A compatible or newer Microsoft runtime is already installed."
|
||||||
|
!insertmacro: _ElseIf
|
||||||
|
!insertmacro: end of _ElseIf
|
||||||
|
MessageBox: 16: "Microsoft Visual C++ runtime setup failed with exit code $0. HyperTwist was not installed."
|
||||||
|
SetErrorLevel: 20
|
||||||
|
Abort: ""
|
||||||
|
!insertmacro: _EndIf
|
||||||
|
!insertmacro: end of _EndIf
|
||||||
|
SectionEnd
|
||||||
|
Section: "!HyperTwist application" ->(SEC_CORE)
|
||||||
|
SectionIn: [RO]
|
||||||
|
AddSize: 1548185 kb
|
||||||
|
Call "CleanOwnedPayloadForUpgrade"
|
||||||
|
SetOutPath: "$INSTDIR"
|
||||||
|
File: "Manifest_NonUFSFiles_Win64.txt" 10686 bytes
|
||||||
|
File: "Manifest_UFSFiles_Win64.txt" 255758 bytes
|
||||||
|
File: "UnrealHyperTwist.exe" 165376 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Content\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Content\Browser\"
|
||||||
|
File: "index.html" 7473 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Content\Browser\dist\"
|
||||||
|
File: "browser-spatial-runtime.js" 30651 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Content\Browser\dist\assets\"
|
||||||
|
File: "MathUtils.js" 185 bytes
|
||||||
|
File: "MeshoptDecoder.js" 595800 bytes
|
||||||
|
File: "Painter.js" 255062 bytes
|
||||||
|
File: "client.js" 875934 bytes
|
||||||
|
File: "decode.js" 26052 bytes
|
||||||
|
File: "easing-0f4db1c0.esm.js" 29269 bytes
|
||||||
|
File: "events-b389eeca.esm.js" 608404 bytes
|
||||||
|
File: "gltf-viewer.module.js" 371169 bytes
|
||||||
|
File: "index.js" 101 bytes
|
||||||
|
File: "index10.js" 463085 bytes
|
||||||
|
File: "index11.js" 1010478 bytes
|
||||||
|
File: "index12.js" 8792 bytes
|
||||||
|
File: "index13.js" 867555 bytes
|
||||||
|
File: "index2.js" 16990 bytes
|
||||||
|
File: "index3.js" 541053 bytes
|
||||||
|
File: "index4.js" 44323 bytes
|
||||||
|
File: "index5.js" 65696 bytes
|
||||||
|
File: "index6.js" 1608912 bytes
|
||||||
|
File: "index7.js" 200923 bytes
|
||||||
|
File: "index8.js" 2925000 bytes
|
||||||
|
File: "index9.js" 536 bytes
|
||||||
|
File: "install.js" 396204 bytes
|
||||||
|
File: "inter.js" 440193 bytes
|
||||||
|
File: "jsx-runtime.js" 22632 bytes
|
||||||
|
File: "leva.esm.js" 282310 bytes
|
||||||
|
File: "maath.esm.js" 13221 bytes
|
||||||
|
File: "model-viewer-effects.js" 28163 bytes
|
||||||
|
File: "model-viewer.js" 569271 bytes
|
||||||
|
File: "morphPath.js" 59852 bytes
|
||||||
|
File: "property.js" 20774 bytes
|
||||||
|
File: "react-spring_core.modern.js" 69814 bytes
|
||||||
|
File: "react-spring_three.modern.js" 1577 bytes
|
||||||
|
File: "react-spring_web.modern.js" 6888 bytes
|
||||||
|
File: "react-three-fiber.esm.js" 7829 bytes
|
||||||
|
File: "three.module.js" 1292285 bytes
|
||||||
|
File: "tslib.es6.js" 3434 bytes
|
||||||
|
File: "use-gesture-react.esm.js" 42626 bytes
|
||||||
|
File: "vanilla.js" 541 bytes
|
||||||
|
File: "vision_bundle.js" 169647 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Content\Browser\src\"
|
||||||
|
File: "browser-runtime-bootstrap.js" 3422 bytes
|
||||||
|
File: "browser-spatial-runtime-fallback.js" 30201 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\CEF3\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\CEF3\Win64\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\CEF3\Win64\128.4.13+ge76af7e+chromium-128.0.6613.138\"
|
||||||
|
File: "chrome_100_percent.pak" 695026 bytes
|
||||||
|
File: "chrome_200_percent.pak" 1094579 bytes
|
||||||
|
File: "chrome_elf.dll" 1370552 bytes
|
||||||
|
File: "d3dcompiler_47.dll" 4927552 bytes
|
||||||
|
File: "dxcompiler.dll" 20817848 bytes
|
||||||
|
File: "dxil.dll" 1519176 bytes
|
||||||
|
File: "icudtl.dat" 10468208 bytes
|
||||||
|
File: "libEGL.dll" 536504 bytes
|
||||||
|
File: "libGLESv2.dll" 8959416 bytes
|
||||||
|
File: "libcef.dll" 239992248 bytes
|
||||||
|
File: "resources.pak" 8683856 bytes
|
||||||
|
File: "snapshot_blob.bin" 313526 bytes
|
||||||
|
File: "v8_context_snapshot.bin" 665981 bytes
|
||||||
|
File: "vk_swiftshader.dll" 5572536 bytes
|
||||||
|
File: "vulkan-1.dll" 930744 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\CEF3\Win64\128.4.13+ge76af7e+chromium-128.0.6613.138\Resources\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\CEF3\Win64\128.4.13+ge76af7e+chromium-128.0.6613.138\Resources\locales\"
|
||||||
|
File: "af.pak" 538998 bytes
|
||||||
|
File: "am.pak" 866444 bytes
|
||||||
|
File: "ar.pak" 953918 bytes
|
||||||
|
File: "bg.pak" 987762 bytes
|
||||||
|
File: "bn.pak" 1269605 bytes
|
||||||
|
File: "ca.pak" 612377 bytes
|
||||||
|
File: "cs.pak" 622919 bytes
|
||||||
|
File: "da.pak" 567958 bytes
|
||||||
|
File: "de.pak" 609935 bytes
|
||||||
|
File: "el.pak" 1080416 bytes
|
||||||
|
File: "en-GB.pak" 492124 bytes
|
||||||
|
File: "en-US.pak" 497015 bytes
|
||||||
|
File: "es-419.pak" 598355 bytes
|
||||||
|
File: "es.pak" 596806 bytes
|
||||||
|
File: "et.pak" 544221 bytes
|
||||||
|
File: "fa.pak" 879421 bytes
|
||||||
|
File: "fi.pak" 552657 bytes
|
||||||
|
File: "fil.pak" 624599 bytes
|
||||||
|
File: "fr.pak" 646732 bytes
|
||||||
|
File: "gu.pak" 1255599 bytes
|
||||||
|
File: "he.pak" 777593 bytes
|
||||||
|
File: "hi.pak" 1330999 bytes
|
||||||
|
File: "hr.pak" 600581 bytes
|
||||||
|
File: "hu.pak" 646489 bytes
|
||||||
|
File: "id.pak" 535422 bytes
|
||||||
|
File: "it.pak" 594371 bytes
|
||||||
|
File: "ja.pak" 719063 bytes
|
||||||
|
File: "kn.pak" 1424332 bytes
|
||||||
|
File: "ko.pak" 606589 bytes
|
||||||
|
File: "lt.pak" 652194 bytes
|
||||||
|
File: "lv.pak" 651016 bytes
|
||||||
|
File: "ml.pak" 1479560 bytes
|
||||||
|
File: "mr.pak" 1223735 bytes
|
||||||
|
File: "ms.pak" 560048 bytes
|
||||||
|
File: "nb.pak" 543051 bytes
|
||||||
|
File: "nl.pak" 562204 bytes
|
||||||
|
File: "pl.pak" 627081 bytes
|
||||||
|
File: "pt-BR.pak" 587941 bytes
|
||||||
|
File: "pt-PT.pak" 592511 bytes
|
||||||
|
File: "ro.pak" 612678 bytes
|
||||||
|
File: "ru.pak" 1003077 bytes
|
||||||
|
File: "sk.pak" 632482 bytes
|
||||||
|
File: "sl.pak" 607050 bytes
|
||||||
|
File: "sr.pak" 929699 bytes
|
||||||
|
File: "sv.pak" 547471 bytes
|
||||||
|
File: "sw.pak" 576117 bytes
|
||||||
|
File: "ta.pak" 1475609 bytes
|
||||||
|
File: "te.pak" 1361935 bytes
|
||||||
|
File: "th.pak" 1144623 bytes
|
||||||
|
File: "tr.pak" 587129 bytes
|
||||||
|
File: "uk.pak" 1001189 bytes
|
||||||
|
File: "ur.pak" 872334 bytes
|
||||||
|
File: "vi.pak" 695768 bytes
|
||||||
|
File: "zh-CN.pak" 503346 bytes
|
||||||
|
File: "zh-TW.pak" 500142 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\DbgHelp\"
|
||||||
|
File: "dbghelp.dll" 2232688 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\MsQuic\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\MsQuic\v220\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\MsQuic\v220\win64\"
|
||||||
|
File: "msquic.dll" 2547080 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\NVIDIA\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\NVIDIA\NVaftermath\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\NVIDIA\NVaftermath\Win64\"
|
||||||
|
File: "GFSDK_Aftermath_Lib.x64.dll" 5442592 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Ogg\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Ogg\Win64\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Ogg\Win64\VS2015\"
|
||||||
|
File: "libogg_64.dll" 59832 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\OpenXR\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\OpenXR\win64\"
|
||||||
|
File: "openxr_loader.dll" 1971640 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Vorbis\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Vorbis\Win64\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Vorbis\Win64\VS2015\"
|
||||||
|
File: "libvorbis_64.dll" 1724856 bytes
|
||||||
|
File: "libvorbisfile_64.dll" 48568 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Windows\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Windows\XAudio2_9\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\ThirdParty\Windows\XAudio2_9\x64\"
|
||||||
|
File: "xaudio2_9redist.dll" 858144 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Binaries\Win64\"
|
||||||
|
File: "EpicWebHelper.exe" 4751288 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Config\"
|
||||||
|
File: "StagedBuild_UnrealHyperTwist.ini" 3 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Content\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Content\Renderer\"
|
||||||
|
File: "TessellationTable.bin" 259568 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Content\Slate\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Content\Slate\Cursor\"
|
||||||
|
File: "invisible.cur" 326 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Content\SlateDebug\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Content\SlateDebug\Fonts\"
|
||||||
|
File: "LastResort.tps" 930 bytes
|
||||||
|
File: "LastResort.ttf" 5395052 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Plugins\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Plugins\NNE\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Plugins\NNE\NNERuntimeORT\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Plugins\NNE\NNERuntimeORT\Binaries\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Plugins\NNE\NNERuntimeORT\Binaries\ThirdParty\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Plugins\NNE\NNERuntimeORT\Binaries\ThirdParty\Onnxruntime\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\Engine\Plugins\NNE\NNERuntimeORT\Binaries\ThirdParty\Onnxruntime\Win64\"
|
||||||
|
File: "onnxruntime.dll" 14692872 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Binaries\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Binaries\Win64\"
|
||||||
|
File: "UnrealHyperTwist-Win64-Shipping.exe" 181121024 bytes
|
||||||
|
File: "tbb12.dll" 331704 bytes
|
||||||
|
File: "tbbmalloc.dll" 117688 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Binaries\Win64\D3D12\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Binaries\Win64\D3D12\x64\"
|
||||||
|
File: "D3D12Core.dll" 4544000 bytes
|
||||||
|
File: "d3d12SDKLayers.dll" 5104632 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Binaries\Win64\DML\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Binaries\Win64\DML\x64\"
|
||||||
|
File: "DirectML.dll" 18537968 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Content\"
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Content\Paks\"
|
||||||
|
File: "UnrealHyperTwist-Windows.pak" 11069853 bytes
|
||||||
|
File: "UnrealHyperTwist-Windows.ucas" 281222144 bytes
|
||||||
|
File: "UnrealHyperTwist-Windows.utoc" 216013 bytes
|
||||||
|
File: "global.ucas" 3325696 bytes
|
||||||
|
File: "global.utoc" 806 bytes
|
||||||
|
File: Descending to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows\UnrealHyperTwist\Saved\"
|
||||||
|
File: "twophase-ht.tbl" 676207080 bytes
|
||||||
|
File: Returning to: "C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723\Windows"
|
||||||
|
SetOutPath: "$INSTDIR\Installer"
|
||||||
|
File: "windows-installer-payload-manifest.json"->"payload-manifest.json" 44356 bytes
|
||||||
|
File: "Test-HyperTwistWindowsReadiness.ps1"->"Test-HyperTwistWindowsReadiness.ps1" 21840 bytes
|
||||||
|
FileOpen: $INSTDIR\Installer\HyperTwist.install-marker as w -> $0
|
||||||
|
FileWrite: product=HyperTwist
|
||||||
|
->$0
|
||||||
|
FileWrite: release=20260723-R19
|
||||||
|
->$0
|
||||||
|
FileWrite: version=Alpha R19
|
||||||
|
->$0
|
||||||
|
FileClose: $0
|
||||||
|
WriteUninstaller: "$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
WriteRegStr: HKLM\Software\HyperTwist\HyperTwist\InstallLocation=$INSTDIR
|
||||||
|
WriteRegStr: HKLM\Software\HyperTwist\HyperTwist\ReleaseId=20260723-R19
|
||||||
|
WriteRegStr: HKLM\Software\HyperTwist\HyperTwist\DisplayVersion=Alpha R19
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\DisplayName=HyperTwist Alpha
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\DisplayVersion=Alpha R19
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\Publisher=HyperTwist
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\InstallLocation=$INSTDIR
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\DisplayIcon=$INSTDIR\UnrealHyperTwist.exe,0
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\URLInfoAbout=https://hypertwist.app
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\HelpLink=https://hypertwist.app/support
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\UninstallString="$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
WriteRegStr: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\QuietUninstallString="$INSTDIR\Uninstall HyperTwist.exe" /S
|
||||||
|
WriteRegDWORD: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\EstimatedSize=1548185
|
||||||
|
WriteRegDWORD: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\NoModify=1
|
||||||
|
WriteRegDWORD: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist\NoRepair=1
|
||||||
|
SetShellVarContext: all
|
||||||
|
CreateDirectory: "$SMPROGRAMS\HyperTwist"
|
||||||
|
CreateShortcut: "$SMPROGRAMS\HyperTwist\HyperTwist.lnk"->"$INSTDIR\UnrealHyperTwist.exe" icon:$INSTDIR\UnrealHyperTwist.exe,0, nwd=0, showmode=0x0, hotkey=0x0, comment=
|
||||||
|
CreateShortcut: "$SMPROGRAMS\HyperTwist\System Readiness Report.lnk"->"$SYSDIR\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -File "$INSTDIR\Installer\Test-HyperTwistWindowsReadiness.ps1" -PayloadRoot "$INSTDIR" -TargetInstallRoot "$INSTDIR" -ExpectedPayloadManifestPath "$INSTDIR\Installer\payload-manifest.json" -WaitForUser icon:$INSTDIR\UnrealHyperTwist.exe,0, nwd=0, showmode=0x0, hotkey=0x0, comment=
|
||||||
|
CreateShortcut: "$SMPROGRAMS\HyperTwist\Uninstall HyperTwist.lnk"->"$INSTDIR\Uninstall HyperTwist.exe" icon:,0, nwd=0, showmode=0x0, hotkey=0x0, comment=
|
||||||
|
SectionEnd
|
||||||
|
Section: "Desktop shortcut" ->(SEC_DESKTOP)
|
||||||
|
SetShellVarContext: all
|
||||||
|
CreateShortcut: "$DESKTOP\HyperTwist.lnk"->"$INSTDIR\UnrealHyperTwist.exe" icon:$INSTDIR\UnrealHyperTwist.exe,0, nwd=0, showmode=0x0, hotkey=0x0, comment=
|
||||||
|
SectionEnd
|
||||||
|
LangString: "DESC_SEC_CORE" 1033 "The complete HyperTwist desktop Alpha, puzzle runtimes, learning studio, browser shell, and local solver data."
|
||||||
|
LangString: "DESC_SEC_DESKTOP" 1033 "Create an all-users HyperTwist shortcut on the desktop."
|
||||||
|
!insertmacro: MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||||
|
!insertmacro: end of MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||||
|
!insertmacro: MUI_DESCRIPTION_TEXT
|
||||||
|
!insertmacro: end of MUI_DESCRIPTION_TEXT
|
||||||
|
!insertmacro: MUI_DESCRIPTION_TEXT
|
||||||
|
!insertmacro: end of MUI_DESCRIPTION_TEXT
|
||||||
|
!insertmacro: MUI_FUNCTION_DESCRIPTION_END
|
||||||
|
!insertmacro: end of MUI_FUNCTION_DESCRIPTION_END
|
||||||
|
Section: "Uninstall"
|
||||||
|
SetRegView: 64
|
||||||
|
!insertmacro: GetFileNameCall
|
||||||
|
!insertmacro: end of GetFileNameCall
|
||||||
|
StrCmp "$1" "HyperTwist" equal=uninstall_leaf_safe, nonequal=uninstall_refused
|
||||||
|
ReadRegStr $0 HKLM\Software\HyperTwist\HyperTwist\InstallLocation
|
||||||
|
StrCmp "$0" "$INSTDIR" equal=uninstall_registry_owned, nonequal=uninstall_refused
|
||||||
|
IfFileExists: "$INSTDIR\Installer\HyperTwist.install-marker" ? uninstall_owned : uninstall_refused
|
||||||
|
MessageBox: 16: "HyperTwist registry ownership or the install marker is missing. The uninstaller will not delete an unverified directory."
|
||||||
|
SetErrorLevel: 30
|
||||||
|
Abort: ""
|
||||||
|
SetShellVarContext: all
|
||||||
|
Delete: "$DESKTOP\HyperTwist.lnk"
|
||||||
|
RMDir: /r "$SMPROGRAMS\HyperTwist"
|
||||||
|
DeleteRegKey: HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist
|
||||||
|
DeleteRegKey: HKLM\Software\HyperTwist\HyperTwist
|
||||||
|
DeleteRegKey: HKLM\Software\HyperTwist
|
||||||
|
RMDir: /r "$INSTDIR\Content"
|
||||||
|
RMDir: /r "$INSTDIR\Engine"
|
||||||
|
RMDir: /r "$INSTDIR\UnrealHyperTwist"
|
||||||
|
Delete: "$INSTDIR\Manifest_DebugFiles_Win64.txt"
|
||||||
|
Delete: "$INSTDIR\Manifest_NonUFSFiles_Win64.txt"
|
||||||
|
Delete: "$INSTDIR\Manifest_UFSFiles_Win64.txt"
|
||||||
|
Delete: "$INSTDIR\UnrealHyperTwist.exe"
|
||||||
|
Delete: "$INSTDIR\Installer\payload-manifest.json"
|
||||||
|
Delete: "$INSTDIR\Installer\Test-HyperTwistWindowsReadiness.ps1"
|
||||||
|
Delete: "$INSTDIR\Installer\HyperTwist.install-marker"
|
||||||
|
RMDir: "$INSTDIR\Installer"
|
||||||
|
Delete: "$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
RMDir: "$INSTDIR"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Processed 1 file, writing output (x86-unicode):
|
||||||
|
Adding plug-ins initializing function... Done!
|
||||||
|
Processing pages... Done!
|
||||||
|
Removing unused resources... Done!
|
||||||
|
Generating language tables... Done!
|
||||||
|
Generating uninstaller... Done!
|
||||||
|
|
||||||
|
Output: "C:\HyperTwist_worktrees\installer-release19-20260726\HyperTwist-Alpha-Test-20260723-R19-Setup.exe"
|
||||||
|
Install: 5 pages (320 bytes), 4 sections (3 required) (8288 bytes), 796 instructions (22288 bytes), 489 strings (19966 bytes), 1 language table (342 bytes).
|
||||||
|
Uninstall: 3 pages (256 bytes), 1 section (2072 bytes), 326 instructions (9128 bytes), 183 strings (5968 bytes), 1 language table (282 bytes).
|
||||||
|
Datablock optimizer saved 26498 bytes (~0.0%).
|
||||||
|
|
||||||
|
Using lzma (compress whole) compression.
|
||||||
|
|
||||||
|
EXE header size: 41472 / 38912 bytes
|
||||||
|
Install code: (51692 bytes)
|
||||||
|
Install data: (1611092306 bytes)
|
||||||
|
Uninstall code+data: (67420 bytes)
|
||||||
|
Compressed data: 851007610 / 1611211418 bytes
|
||||||
|
CRC (0x2B3F13D2): 4 / 4 bytes
|
||||||
|
|
||||||
|
Total size: 851049086 / 1611250334 bytes (52.8%)
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
{
|
||||||
|
"reportVersion": "ht-windows-readiness/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T08:30:49.1663635Z",
|
||||||
|
"result": "ready-with-warnings",
|
||||||
|
"payloadRoot": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723\\Windows",
|
||||||
|
"targetInstallRoot": "C:\\Program Files\\HyperTwist",
|
||||||
|
"requiredFailureCount": 0,
|
||||||
|
"optionalWarningCount": 2,
|
||||||
|
"checks": [
|
||||||
|
{
|
||||||
|
"id": "windows-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires a 64-bit Windows operating system.",
|
||||||
|
"evidence": {
|
||||||
|
"architecture": "64-bit",
|
||||||
|
"processArchitecture": "AMD64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-supported-build",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires Windows build 19045 or newer.",
|
||||||
|
"evidence": {
|
||||||
|
"caption": "Microsoft Windows 11 Home",
|
||||||
|
"version": "10.0.22631",
|
||||||
|
"build": 22631,
|
||||||
|
"minimumBuild": 19045
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system-memory",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least 8 GiB of physical memory is required for the desktop Alpha.",
|
||||||
|
"evidence": {
|
||||||
|
"totalBytes": 16893206528,
|
||||||
|
"minimumBytes": 8589934592
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "install-volume-free-space",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The target volume must have enough free space for installation and first-run caches.",
|
||||||
|
"evidence": {
|
||||||
|
"targetInstallRoot": "C:\\Program Files\\HyperTwist",
|
||||||
|
"availableBytes": 171947429888,
|
||||||
|
"minimumBytes": 4294967296
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vc-runtime-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Microsoft Visual C++ 2015-2022 x64 runtime 14.44.35211.0 or newer is required and is bundled by the installer.",
|
||||||
|
"evidence": {
|
||||||
|
"registryPath": "HKLM:\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64",
|
||||||
|
"installed": true,
|
||||||
|
"version": "14.44.35211.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-media-and-graphics-libraries",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Windows DirectX, XInput, and Media Foundation runtime libraries must be available.",
|
||||||
|
"evidence": {
|
||||||
|
"systemDirectory": "C:\\Windows\\system32",
|
||||||
|
"requiredLibraries": [
|
||||||
|
"d3d11.dll",
|
||||||
|
"d3d12.dll",
|
||||||
|
"dxgi.dll",
|
||||||
|
"mf.dll",
|
||||||
|
"mfplat.dll",
|
||||||
|
"mfreadwrite.dll",
|
||||||
|
"xinput1_4.dll"
|
||||||
|
],
|
||||||
|
"missingLibraries": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "graphics-adapter",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least one Windows graphics adapter must be visible.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel(R) Iris(R) Xe Graphics",
|
||||||
|
"driverVersion": "31.0.101.3358",
|
||||||
|
"driverDate": "2022-08-04T02:00:00.0000000+02:00",
|
||||||
|
"adapterRamBytes": 1073741824,
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audio-device",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "An audio device is optional for puzzle play and recommended for narration and speech features.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Digital Microphones",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for USB Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Bluetooth® Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Audio Device",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Virtual Audio Cable",
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "openxr-runtime",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "An active OpenXR runtime is optional for keyboard/mouse play and required only for live headset sessions.",
|
||||||
|
"evidence": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "required-payload-files",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must contain every required executable, runtime, cooked-data, browser, solver, and OpenXR file.",
|
||||||
|
"evidence": {
|
||||||
|
"payloadRoot": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723\\Windows",
|
||||||
|
"requiredFileCount": 15,
|
||||||
|
"cefRuntimeFiles": [
|
||||||
|
"Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/libcef.dll"
|
||||||
|
],
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "desktop-code-signature",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "The Alpha payload is currently unsigned; production distribution requires Authenticode signing.",
|
||||||
|
"evidence": {
|
||||||
|
"status": "NotSigned",
|
||||||
|
"signer": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "payload-manifest-parity",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must match the release manifest without missing, truncated, or altered files.",
|
||||||
|
"evidence": {
|
||||||
|
"manifestPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\validation\\windows-installer-payload-manifest.json",
|
||||||
|
"manifestVersion": "ht-windows-installer-payload/v1",
|
||||||
|
"manifestEntryCount": 143,
|
||||||
|
"declaredFileCount": 143,
|
||||||
|
"declaredTotalSizeBytes": 1585341236,
|
||||||
|
"computedTotalSizeBytes": 1585341236,
|
||||||
|
"hashesVerified": true,
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
{
|
||||||
|
"reportVersion": "ht-post-task-hygiene/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T09:38:34Z",
|
||||||
|
"doctrine": "docs/ops/HYPERTWIST_PACKET_CLEANUP_AND_REBUILDABLE_ARTIFACT_HYGIENE_2026-05-20.md",
|
||||||
|
"result": "passed-with-protected-retention",
|
||||||
|
"inventory": {
|
||||||
|
"initialPhase10ValidateFileCount": 53308,
|
||||||
|
"initialPhase10ValidateSizeBytes": 29264296595,
|
||||||
|
"postCleanupPhase10ValidateFileCount": 19793,
|
||||||
|
"postCleanupPhase10ValidateSizeBytes": 2514767231,
|
||||||
|
"finalWindowsFreeBytes": 167725654016
|
||||||
|
},
|
||||||
|
"safeDeletion": {
|
||||||
|
"measuredTargetCount": 52,
|
||||||
|
"measuredFileCount": 37793,
|
||||||
|
"measuredSizeBytes": 54474200710,
|
||||||
|
"passes": [
|
||||||
|
{
|
||||||
|
"class": "superseded-top-level-package-and-probe-roots",
|
||||||
|
"targetCount": 23,
|
||||||
|
"fileCount": 4264,
|
||||||
|
"sizeBytes": 27475757341
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "generated-subtrees-inside-phase10validate",
|
||||||
|
"targetCount": 24,
|
||||||
|
"fileCount": 33519,
|
||||||
|
"sizeBytes": 26749605009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "intentionally-interrupted-installer-partials",
|
||||||
|
"targetCount": 2,
|
||||||
|
"fileCount": 2,
|
||||||
|
"sizeBytes": 248464450
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "incomplete-source-comparison-manifest",
|
||||||
|
"targetCount": 1,
|
||||||
|
"fileCount": 1,
|
||||||
|
"sizeBytes": 334999
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "evidence-harvested-installer-lifecycle-roots",
|
||||||
|
"targetCount": 2,
|
||||||
|
"fileCount": 7,
|
||||||
|
"sizeBytes": 38911
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"additionalUnmeasuredDisposableArtifactsRemoved": [
|
||||||
|
"tiny-payload NSIS contract roots",
|
||||||
|
"readiness interactive-contract files",
|
||||||
|
"malicious-manifest contract files",
|
||||||
|
"hash-staged Downloads incoming file"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"protectedRetention": [
|
||||||
|
{
|
||||||
|
"path": "C:\\HyperTwist_worktrees\\phase10validate",
|
||||||
|
"fileCount": 19793,
|
||||||
|
"sizeBytes": 2514767231,
|
||||||
|
"reason": "Source/custody envelope rather than rebuildable-only output; complete duplicate proof was blocked by four relative source-tree reparse points."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release17_20260723",
|
||||||
|
"fileCount": 30,
|
||||||
|
"sizeBytes": 2138251,
|
||||||
|
"reason": "Release 17 rollback provenance."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release18_20260723",
|
||||||
|
"fileCount": 172,
|
||||||
|
"sizeBytes": 2288143046,
|
||||||
|
"reason": "Release 18 historical package evidence."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release18_shipping_20260723",
|
||||||
|
"fileCount": 175,
|
||||||
|
"sizeBytes": 1920603184,
|
||||||
|
"reason": "Release 18 Shipping rollback evidence."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723",
|
||||||
|
"fileCount": 173,
|
||||||
|
"sizeBytes": 1920589115,
|
||||||
|
"reason": "Current Release 19 installer source authority."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\HyperTwist_worktrees\\installer-release19-20260726",
|
||||||
|
"fileCount": 7,
|
||||||
|
"sizeBytes": 851156084,
|
||||||
|
"reason": "Current validated installer and machine-generated build evidence."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\Users\\Anthracite Ace\\Downloads\\HyperTwist-Alpha-Test-20260723-R19",
|
||||||
|
"fileCount": 178,
|
||||||
|
"sizeBytes": 1920681761,
|
||||||
|
"reason": "Current portable operator delivery."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\Users\\Anthracite Ace\\Downloads\\HyperTwist-Alpha-Test-20260723-R19.zip",
|
||||||
|
"fileCount": 1,
|
||||||
|
"sizeBytes": 1093537260,
|
||||||
|
"reason": "Current verified portable archive delivery."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\Users\\Anthracite Ace\\Downloads\\HyperTwist-Alpha-Test-20260723-R19-Setup.exe",
|
||||||
|
"fileCount": 1,
|
||||||
|
"sizeBytes": 851049086,
|
||||||
|
"reason": "Current validated installer delivery."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:\\Users\\Anthracite Ace\\AppData\\Local\\UnrealHyperTwist\\Saved",
|
||||||
|
"fileCount": 275,
|
||||||
|
"sizeBytes": 736756671,
|
||||||
|
"reason": "Protected operator settings, saves, replays, logs, and diagnostics."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/dev/src/HyperTwist",
|
||||||
|
"reason": "VPS main-worktree dependencies, mirrors, custody, source, and pre-existing ambiguous generated roots were not packet-created and were retained."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"finalVerification": {
|
||||||
|
"temporaryLifecycleRootsAbsent": true,
|
||||||
|
"partialInstallerOutputsAbsent": true,
|
||||||
|
"disposableContractRootsAbsent": true,
|
||||||
|
"downloadsStagingAbsent": true,
|
||||||
|
"hyperTwistInstallerRegistrationAbsent": true,
|
||||||
|
"makensisProcessCount": 0,
|
||||||
|
"todoJsonPolicy": "ignored",
|
||||||
|
"protectedPathsPresent": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"reportVersion": "ht-windows-installer-lifecycle/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T07:56:13.8198132Z",
|
||||||
|
"result": "failed",
|
||||||
|
"validationClass": "isolated-current-host",
|
||||||
|
"cleanMachineAvailable": false,
|
||||||
|
"cleanMachineBoundary": "No Windows Sandbox, clean Hyper-V VM, or base VHD was available on the validation host.",
|
||||||
|
"installerPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\HyperTwist-Alpha-Test-20260723-R19-Setup.exe",
|
||||||
|
"installerSizeBytes": 851127022,
|
||||||
|
"installerSha256": "42b9c7ce17b40cbce9adcef15cbc904e239bac673615447909d7a21419ab5ac0",
|
||||||
|
"installerSignatureStatus": "NotSigned",
|
||||||
|
"installRoot": "C:\\HyperTwistInstallerValidation\\20260726T075613Z\\HyperTwist",
|
||||||
|
"firstInstallExitCode": 0,
|
||||||
|
"upgradeInstallExitCode": null,
|
||||||
|
"payloadParityAfterFirstInstall": {
|
||||||
|
"passed": true,
|
||||||
|
"manifestEntryCount": 143,
|
||||||
|
"failureCount": 0,
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"unexpectedFiles": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"unexpectedPdbFiles": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"payloadParityAfterUpgrade": null,
|
||||||
|
"readiness": null,
|
||||||
|
"launchSmoke": null,
|
||||||
|
"uninstallExitCode": null,
|
||||||
|
"registrationVerified": true,
|
||||||
|
"shortcutsVerified": false,
|
||||||
|
"shortcutDetails": {
|
||||||
|
"application": {
|
||||||
|
"path": "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\HyperTwist\\HyperTwist.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\HyperTwistInstallerValidation\\20260726T075613Z\\HyperTwist\\UnrealHyperTwist.exe",
|
||||||
|
"arguments": ""
|
||||||
|
},
|
||||||
|
"readiness": {
|
||||||
|
"path": "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\HyperTwist\\System Readiness Report.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
||||||
|
"arguments": "-NoProfile -ExecutionPolicy Bypass -File \"C:\\HyperTwistInstallerValidation\\20260726T075613Z\\HyperTwist\\Installer\\Test-HyperTwistWindowsReadiness.ps1\" -PayloadRoot \"C:\\HyperTwistInstallerValidation\\20260726T075613Z\\HyperTwist\" -ReportPath \"C:\\Users\\Anthracite Ace\\AppData\\Local\\Temp\\HyperTwist-readiness.json\""
|
||||||
|
},
|
||||||
|
"uninstall": {
|
||||||
|
"path": "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\HyperTwist\\Uninstall HyperTwist.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\HyperTwistInstallerValidation\\20260726T075613Z\\HyperTwist\\Uninstall HyperTwist.exe",
|
||||||
|
"arguments": ""
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"path": "C:\\Users\\Public\\Desktop\\HyperTwist.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\HyperTwistInstallerValidation\\20260726T075613Z\\HyperTwist\\UnrealHyperTwist.exe",
|
||||||
|
"arguments": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userDataPreserved": false,
|
||||||
|
"installRootRemoved": false,
|
||||||
|
"registrationRemoved": false,
|
||||||
|
"shortcutsRemoved": false,
|
||||||
|
"cleanupCompleted": false,
|
||||||
|
"error": "One or more installer-managed shortcuts are missing."
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"reportVersion": "ht-windows-installer-build/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T08:31:34.7586689Z",
|
||||||
|
"result": "passed",
|
||||||
|
"releaseId": "20260723-R19",
|
||||||
|
"displayVersion": "Alpha R19",
|
||||||
|
"productVersion": "0.19.0.0",
|
||||||
|
"packageRoot": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723",
|
||||||
|
"payloadRoot": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723\\Windows",
|
||||||
|
"installerPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\HyperTwist-Alpha-Test-20260723-R19-Setup.exe",
|
||||||
|
"payloadManifestPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\validation\\windows-installer-payload-manifest.json",
|
||||||
|
"sourceReadinessReportPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\validation\\windows-installer-source-readiness-report.json",
|
||||||
|
"makensisPath": "C:\\Program Files (x86)\\NSIS\\makensis.exe",
|
||||||
|
"makensisLogPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\validation\\makensis.log",
|
||||||
|
"vcRedist": {
|
||||||
|
"path": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Redist\\MSVC\\v143\\vc_redist.x64.exe",
|
||||||
|
"version": "14.44.35211.0",
|
||||||
|
"sizeBytes": 25635768,
|
||||||
|
"sha256": "cc0ff0eb1dc3f5188ae6300faef32bf5beeba4bdd6e8e445a9184072096b713b",
|
||||||
|
"signatureStatus": "Valid",
|
||||||
|
"signer": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||||
|
},
|
||||||
|
"excludedPatterns": [
|
||||||
|
"*.pdb",
|
||||||
|
"Manifest_DebugFiles_Win64.txt"
|
||||||
|
],
|
||||||
|
"payloadFileCount": 143,
|
||||||
|
"payloadSizeBytes": 1585341236,
|
||||||
|
"installerSizeBytes": 851049086,
|
||||||
|
"installerSha256": "c31ed6b0b2ae1feb449c27e484d72dc2e07ba220e3cdafa4c3605429d638e0ea",
|
||||||
|
"installerSignatureStatus": "NotSigned",
|
||||||
|
"incompleteInstallerRemoved": false,
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,287 @@
|
||||||
|
{
|
||||||
|
"reportVersion": "ht-windows-installer-lifecycle/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T09:19:26.8973913Z",
|
||||||
|
"result": "passed",
|
||||||
|
"validationClass": "isolated-current-host",
|
||||||
|
"cleanMachineAvailable": false,
|
||||||
|
"cleanMachineBoundary": "No Windows Sandbox, clean Hyper-V VM, or base VHD was available on the validation host.",
|
||||||
|
"installerPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\HyperTwist-Alpha-Test-20260723-R19-Setup.exe",
|
||||||
|
"installerSizeBytes": 851049086,
|
||||||
|
"installerSha256": "c31ed6b0b2ae1feb449c27e484d72dc2e07ba220e3cdafa4c3605429d638e0ea",
|
||||||
|
"installerSignatureStatus": "NotSigned",
|
||||||
|
"installRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"unownedNonEmptyRefusal": {
|
||||||
|
"passed": true,
|
||||||
|
"exitCode": 14,
|
||||||
|
"expectedExitCode": 14,
|
||||||
|
"sentinelPreserved": true,
|
||||||
|
"registrationAbsent": true
|
||||||
|
},
|
||||||
|
"firstInstallExitCode": 0,
|
||||||
|
"upgradeInstallExitCode": 0,
|
||||||
|
"payloadParityAfterFirstInstall": {
|
||||||
|
"passed": true,
|
||||||
|
"manifestEntryCount": 143,
|
||||||
|
"failureCount": 0,
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"unexpectedFiles": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"unexpectedPdbFiles": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"payloadParityAfterUpgrade": {
|
||||||
|
"passed": true,
|
||||||
|
"manifestEntryCount": 143,
|
||||||
|
"failureCount": 0,
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"unexpectedFiles": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"unexpectedPdbFiles": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"readiness": {
|
||||||
|
"reportVersion": "ht-windows-readiness/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T09:23:56.9501545Z",
|
||||||
|
"result": "ready-with-warnings",
|
||||||
|
"payloadRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"targetInstallRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"requiredFailureCount": 0,
|
||||||
|
"optionalWarningCount": 2,
|
||||||
|
"checks": [
|
||||||
|
{
|
||||||
|
"id": "windows-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires a 64-bit Windows operating system.",
|
||||||
|
"evidence": {
|
||||||
|
"architecture": "64-bit",
|
||||||
|
"processArchitecture": "AMD64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-supported-build",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires Windows build 19045 or newer.",
|
||||||
|
"evidence": {
|
||||||
|
"caption": "Microsoft Windows 11 Home",
|
||||||
|
"version": "10.0.22631",
|
||||||
|
"build": 22631,
|
||||||
|
"minimumBuild": 19045
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system-memory",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least 8 GiB of physical memory is required for the desktop Alpha.",
|
||||||
|
"evidence": {
|
||||||
|
"totalBytes": 16893206528,
|
||||||
|
"minimumBytes": 8589934592
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "install-volume-free-space",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The target volume must have enough free space for installation and first-run caches.",
|
||||||
|
"evidence": {
|
||||||
|
"targetInstallRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"availableBytes": 167681560576,
|
||||||
|
"minimumBytes": 4294967296
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vc-runtime-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Microsoft Visual C++ 2015-2022 x64 runtime 14.44.35211.0 or newer is required and is bundled by the installer.",
|
||||||
|
"evidence": {
|
||||||
|
"registryPath": "HKLM:\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64",
|
||||||
|
"installed": true,
|
||||||
|
"version": "14.44.35211.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-media-and-graphics-libraries",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Windows DirectX, XInput, and Media Foundation runtime libraries must be available.",
|
||||||
|
"evidence": {
|
||||||
|
"systemDirectory": "C:\\Windows\\system32",
|
||||||
|
"requiredLibraries": [
|
||||||
|
"d3d11.dll",
|
||||||
|
"d3d12.dll",
|
||||||
|
"dxgi.dll",
|
||||||
|
"mf.dll",
|
||||||
|
"mfplat.dll",
|
||||||
|
"mfreadwrite.dll",
|
||||||
|
"xinput1_4.dll"
|
||||||
|
],
|
||||||
|
"missingLibraries": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "graphics-adapter",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least one Windows graphics adapter must be visible.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel(R) Iris(R) Xe Graphics",
|
||||||
|
"driverVersion": "31.0.101.3358",
|
||||||
|
"driverDate": "2022-08-04T02:00:00.0000000+02:00",
|
||||||
|
"adapterRamBytes": 1073741824,
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audio-device",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "An audio device is optional for puzzle play and recommended for narration and speech features.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Digital Microphones",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for USB Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Bluetooth® Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Audio Device",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Virtual Audio Cable",
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "openxr-runtime",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "An active OpenXR runtime is optional for keyboard/mouse play and required only for live headset sessions.",
|
||||||
|
"evidence": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "required-payload-files",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must contain every required executable, runtime, cooked-data, browser, solver, and OpenXR file.",
|
||||||
|
"evidence": {
|
||||||
|
"payloadRoot": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist",
|
||||||
|
"requiredFileCount": 15,
|
||||||
|
"cefRuntimeFiles": [
|
||||||
|
"Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/libcef.dll"
|
||||||
|
],
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "desktop-code-signature",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "The Alpha payload is currently unsigned; production distribution requires Authenticode signing.",
|
||||||
|
"evidence": {
|
||||||
|
"status": "NotSigned",
|
||||||
|
"signer": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "payload-manifest-parity",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must match the release manifest without missing, truncated, or altered files.",
|
||||||
|
"evidence": {
|
||||||
|
"manifestPath": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\\Installer\\payload-manifest.json",
|
||||||
|
"manifestVersion": "ht-windows-installer-payload/v1",
|
||||||
|
"manifestEntryCount": 143,
|
||||||
|
"declaredFileCount": 143,
|
||||||
|
"declaredTotalSizeBytes": 1585341236,
|
||||||
|
"computedTotalSizeBytes": 1585341236,
|
||||||
|
"hashesVerified": true,
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"launchSmoke": {
|
||||||
|
"passed": true,
|
||||||
|
"startedAtUtc": "2026-07-26T09:23:57.0508749Z",
|
||||||
|
"launcherProcessId": 3756,
|
||||||
|
"ownedProcessIds": [
|
||||||
|
3756,
|
||||||
|
14248
|
||||||
|
],
|
||||||
|
"stoppedProcessIds": [
|
||||||
|
3756,
|
||||||
|
14248
|
||||||
|
],
|
||||||
|
"runtimeLogPath": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\evidence\\installed-runtime.log",
|
||||||
|
"diagnosticsPath": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\evidence\\installed-runtime.hyperdiagnostics.log",
|
||||||
|
"diagnosticsInitialized": true,
|
||||||
|
"fatalLines": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"listeningEndpoints": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"uninstallExitCode": 0,
|
||||||
|
"registrationVerified": true,
|
||||||
|
"shortcutsVerified": true,
|
||||||
|
"shortcutDetails": {
|
||||||
|
"application": {
|
||||||
|
"path": "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\HyperTwist\\HyperTwist.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\\UnrealHyperTwist.exe",
|
||||||
|
"arguments": ""
|
||||||
|
},
|
||||||
|
"readiness": {
|
||||||
|
"path": "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\HyperTwist\\System Readiness Report.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
||||||
|
"arguments": "-NoProfile -ExecutionPolicy Bypass -File \"C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\\Installer\\Test-HyperTwistWindowsReadiness.ps1\" -PayloadRoot \"C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\" -TargetInstallRoot \"C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\" -ExpectedPayloadManifestPath \"C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\\Installer\\payload-manifest.json\" -WaitForUser"
|
||||||
|
},
|
||||||
|
"uninstall": {
|
||||||
|
"path": "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\HyperTwist\\Uninstall HyperTwist.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\\Uninstall HyperTwist.exe",
|
||||||
|
"arguments": ""
|
||||||
|
},
|
||||||
|
"desktop": {
|
||||||
|
"path": "C:\\Users\\Public\\Desktop\\HyperTwist.lnk",
|
||||||
|
"exists": true,
|
||||||
|
"targetPath": "C:\\HyperTwist Installer Validation\\20260726T091926Z\\HyperTwist\\UnrealHyperTwist.exe",
|
||||||
|
"arguments": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userDataPreserved": true,
|
||||||
|
"installRootRemoved": true,
|
||||||
|
"registrationRemoved": true,
|
||||||
|
"shortcutsRemoved": true,
|
||||||
|
"cleanupCompleted": true,
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,729 @@
|
||||||
|
{
|
||||||
|
"manifestVersion": "ht-windows-installer-payload/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T08:31:40.6337955Z",
|
||||||
|
"releaseId": "20260723-R19",
|
||||||
|
"sourcePayloadRoot": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723\\Windows",
|
||||||
|
"excludedPatterns": [
|
||||||
|
"*.pdb",
|
||||||
|
"Manifest_DebugFiles_Win64.txt"
|
||||||
|
],
|
||||||
|
"fileCount": 143,
|
||||||
|
"totalSizeBytes": 1585341236,
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/client.js",
|
||||||
|
"sizeBytes": 875934,
|
||||||
|
"sha256": "524383f29f700b5907b999ec80fe1d4f472ac14af8ea5580a906696eba0955d9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/decode.js",
|
||||||
|
"sizeBytes": 26052,
|
||||||
|
"sha256": "f6b754561563af8aeda1e6aa9f503496a45f90cf079ce74119cdba7087058c9b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/easing-0f4db1c0.esm.js",
|
||||||
|
"sizeBytes": 29269,
|
||||||
|
"sha256": "38ddf7add1b0274ecb8e422332452e1cc2661758d576324c0267f1893cc96704"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/events-b389eeca.esm.js",
|
||||||
|
"sizeBytes": 608404,
|
||||||
|
"sha256": "415f094c85d96883fe17136b2ccaf7c0599c74c1fec1d50fbfe77c5aa49e8a78"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/gltf-viewer.module.js",
|
||||||
|
"sizeBytes": 371169,
|
||||||
|
"sha256": "803cf04b8bb52f4540459a6b755215ace8e3f9ca06ed6e269c2de58b1791084d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index.js",
|
||||||
|
"sizeBytes": 101,
|
||||||
|
"sha256": "c17a644a35874aec14eb885b7570e76742265aab419e26bf5ec3aef3d0c33004"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index10.js",
|
||||||
|
"sizeBytes": 463085,
|
||||||
|
"sha256": "5eb1d53e1f4ad93014c9db5e7053a284ee75d12f67922a5342d5babaaf62f88f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index11.js",
|
||||||
|
"sizeBytes": 1010478,
|
||||||
|
"sha256": "943fa33589d184eb7c2580122f44baf69426d720fc7459aad7b3b452666cdcbd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index12.js",
|
||||||
|
"sizeBytes": 8792,
|
||||||
|
"sha256": "4ff02630aa51698e0e571bdd1615df1e47908ccb94c27fcf30abf886677c2dbd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index13.js",
|
||||||
|
"sizeBytes": 867555,
|
||||||
|
"sha256": "dd8d1a29141fa69a55d38f196aee7ea64b02354bbeadfd5578f98533cdd8959f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index2.js",
|
||||||
|
"sizeBytes": 16990,
|
||||||
|
"sha256": "00f5a4f3a3d11486be6feebae2511963dd06903eed45e1a1dc44c1b3be610d18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index3.js",
|
||||||
|
"sizeBytes": 541053,
|
||||||
|
"sha256": "0fcda6a7676782f695f3e713f721b7dd998cb12740ab81814af7ca263547c69b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index4.js",
|
||||||
|
"sizeBytes": 44323,
|
||||||
|
"sha256": "cfec865d65f73d1ef3102352554f5fb10a0d6c7b3572241de9077fbd89f11d26"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index5.js",
|
||||||
|
"sizeBytes": 65696,
|
||||||
|
"sha256": "e83b58f0daa45e909992294461784bc49ca4fd4d857227767719b2eb43d390d9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index6.js",
|
||||||
|
"sizeBytes": 1608912,
|
||||||
|
"sha256": "bac438344a5a247cfbeb8b4025903b7c0fec959a04c80e2375f1bd53a89b27d0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index7.js",
|
||||||
|
"sizeBytes": 200923,
|
||||||
|
"sha256": "493590d87a9126e4e74489acd71981ccae2cfef540956fbc41b1220ff4e6a117"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index8.js",
|
||||||
|
"sizeBytes": 2925000,
|
||||||
|
"sha256": "b94712cac9e7b384811054142511b411e9e50ea84e4244be57296d934a2b3ab8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/index9.js",
|
||||||
|
"sizeBytes": 536,
|
||||||
|
"sha256": "1a22f6a2f3f1694a068d86a10cdbb0612007a82609dad95d661de48924f47395"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/install.js",
|
||||||
|
"sizeBytes": 396204,
|
||||||
|
"sha256": "43d1b725ff895424f5d6067851ff0b23a6822f4ab00e7e40877ae90925c985d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/inter.js",
|
||||||
|
"sizeBytes": 440193,
|
||||||
|
"sha256": "24b0d2388654b0e94d12a73a0ab262c18155cd90b4ddefc048ac8be673f5a9ce"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/jsx-runtime.js",
|
||||||
|
"sizeBytes": 22632,
|
||||||
|
"sha256": "a994feec9287fe3f3f3afd143dbf386e6ce68921d2573df3778fb1594dfe0954"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/leva.esm.js",
|
||||||
|
"sizeBytes": 282310,
|
||||||
|
"sha256": "8b8e8048af8e722e886919ef3fc42e17201aa4fdc972979f40980bb324a24783"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/maath.esm.js",
|
||||||
|
"sizeBytes": 13221,
|
||||||
|
"sha256": "9e0bb39344397d519cc0601ac2d9409e891b4ad627a509ca16a9d1a7c047959b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/MathUtils.js",
|
||||||
|
"sizeBytes": 185,
|
||||||
|
"sha256": "04ead5c1ece921b0dbb5c3a8c7b1b9f59698f43fe5f2c2ba7390307d35fe275d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/MeshoptDecoder.js",
|
||||||
|
"sizeBytes": 595800,
|
||||||
|
"sha256": "902a1fbb9e9dadb8aaac060e2f38f51bb9afc0f3f526c66d8f78339079af527d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/model-viewer.js",
|
||||||
|
"sizeBytes": 569271,
|
||||||
|
"sha256": "78b871924c1fe17e3907e221a0488ccb74a237622363917400c08e81300ddff2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/model-viewer-effects.js",
|
||||||
|
"sizeBytes": 28163,
|
||||||
|
"sha256": "1e8577509a823663aae78e29dd8f7a499a24ac30eb0df5874fac12d5a8d2ed45"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/morphPath.js",
|
||||||
|
"sizeBytes": 59852,
|
||||||
|
"sha256": "47274c7da895da1dd209982343f7e0b96e69c8849785c370ab23b4bb909e9cb6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/Painter.js",
|
||||||
|
"sizeBytes": 255062,
|
||||||
|
"sha256": "482c8b4179b89e56847e02b9175d4d1b554a269d09b9f7c3b89a191c55f9ac87"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/property.js",
|
||||||
|
"sizeBytes": 20774,
|
||||||
|
"sha256": "7d5b7c2bdf95125984b778c7b1ad8db105d85cec36d3f0a74205c6cc6f3fa267"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/react-spring_core.modern.js",
|
||||||
|
"sizeBytes": 69814,
|
||||||
|
"sha256": "cbf81e7fec6557b7baef30cd7f180ac9cc3ade3ddb5bada3e4382ab7a63e9511"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/react-spring_three.modern.js",
|
||||||
|
"sizeBytes": 1577,
|
||||||
|
"sha256": "ee4a91412c95a90241efff06bb7c80475e252250b8795eb2abd1265a18c0254b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/react-spring_web.modern.js",
|
||||||
|
"sizeBytes": 6888,
|
||||||
|
"sha256": "ca824b8b650778235149947119e4e37e5e9c997870cd9bc248d9bcd1efe9d911"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/react-three-fiber.esm.js",
|
||||||
|
"sizeBytes": 7829,
|
||||||
|
"sha256": "3ca075d4805914a117e2496a0b3c5d49aedb99ed0fc5df9cfb19aa59700d3b25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/three.module.js",
|
||||||
|
"sizeBytes": 1292285,
|
||||||
|
"sha256": "31e68a7aa67d4d54c90d64ed6b1a86040965e1d619c2229154dc5ff63be67a1b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/tslib.es6.js",
|
||||||
|
"sizeBytes": 3434,
|
||||||
|
"sha256": "e525bc57e4875c563602b26f5ff4ce5c8cabc69f8ca5107cef68ce182bf6b81f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/use-gesture-react.esm.js",
|
||||||
|
"sizeBytes": 42626,
|
||||||
|
"sha256": "f3ff4be03a822f20e3275013068617c96ef4e2f147988806f7620bfbad4b8b11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/vanilla.js",
|
||||||
|
"sizeBytes": 541,
|
||||||
|
"sha256": "264fdf8ce2d8c33fef425b00082363420a4c1c3d5b737a44b3f64ad6ea62292a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/assets/vision_bundle.js",
|
||||||
|
"sizeBytes": 169647,
|
||||||
|
"sha256": "268be65875c0724747ceae21789108e4f40f6402bc18baf469362a90003f9af5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/dist/browser-spatial-runtime.js",
|
||||||
|
"sizeBytes": 30651,
|
||||||
|
"sha256": "0feb7fc24108b4804e4b801518ce91a0a5a9eb8f806edaedb7506d8a82bb283e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/index.html",
|
||||||
|
"sizeBytes": 7473,
|
||||||
|
"sha256": "00a730f4d8ee099d0d0d63a171b94194f9fe9c9c92de810a411050c0b260a562"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/src/browser-runtime-bootstrap.js",
|
||||||
|
"sizeBytes": 3422,
|
||||||
|
"sha256": "e35963e1888deac61578141579c64e686c15cb964b2b4d8d8c080ed35b4ed00e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Content/Browser/src/browser-spatial-runtime-fallback.js",
|
||||||
|
"sizeBytes": 30201,
|
||||||
|
"sha256": "0089004d3aa86de1edefcc7c95ea0fc80c9352e49778bc384f6d676e8a9ad1a4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/chrome_100_percent.pak",
|
||||||
|
"sizeBytes": 695026,
|
||||||
|
"sha256": "3f665b02bbe58d6423c2e86211bd8f074d8a36726438e639541ad695f8430b9b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/chrome_200_percent.pak",
|
||||||
|
"sizeBytes": 1094579,
|
||||||
|
"sha256": "8152796c92c3481a546564be8f0b2ca90bf50d1bf4a141db166c90377239794d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/chrome_elf.dll",
|
||||||
|
"sizeBytes": 1370552,
|
||||||
|
"sha256": "6cb248829b22689691fcfeb93258e12d8b19204d62dafc75bfa84bd21b142679"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/d3dcompiler_47.dll",
|
||||||
|
"sizeBytes": 4927552,
|
||||||
|
"sha256": "7b52ad25b00b6c67e721ec0105601dcb462fefe233a55e5a93927ed69650829f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/dxcompiler.dll",
|
||||||
|
"sizeBytes": 20817848,
|
||||||
|
"sha256": "7e8d14f9c13cf9d7344a865503cbe91e8cbe8e3b023525e5f208c155a1a28075"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/dxil.dll",
|
||||||
|
"sizeBytes": 1519176,
|
||||||
|
"sha256": "3b8648bd722480535753c28d34ee9de98ddb69f7e01bef96068303ffbd80ccc4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/icudtl.dat",
|
||||||
|
"sizeBytes": 10468208,
|
||||||
|
"sha256": "9ae98c06cbb0ea43c5cd6b5725310c008c65e46072421a1118cb88e1de9a8b92"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/libcef.dll",
|
||||||
|
"sizeBytes": 239992248,
|
||||||
|
"sha256": "e89ec24b1abac5c77260c49c7bd33d010ddd67b752d22d87dc142d37d2e8d966"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/libEGL.dll",
|
||||||
|
"sizeBytes": 536504,
|
||||||
|
"sha256": "f3f527ac94b3e81e36c123d1a0b04c7e5cc6e079ae1fbd689540ab85108797d6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/libGLESv2.dll",
|
||||||
|
"sizeBytes": 8959416,
|
||||||
|
"sha256": "251bbd3d72cbe381857401ad62e42b5627d2c4c05fbcdd4f68e774720ba01c44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/resources.pak",
|
||||||
|
"sizeBytes": 8683856,
|
||||||
|
"sha256": "aa8d203d593ed170696eec09137e2421882f46273337a00d16c6b23e91de675e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/af.pak",
|
||||||
|
"sizeBytes": 538998,
|
||||||
|
"sha256": "c514fe813e56c4767e9b190acca7a44d6f0f6d7c03dec6c4afb6586f0c89ebb7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/am.pak",
|
||||||
|
"sizeBytes": 866444,
|
||||||
|
"sha256": "fd641fb8513ea2b93a5f34f45a9a8af3596e73dd738207bcc07ecfbd398f4285"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ar.pak",
|
||||||
|
"sizeBytes": 953918,
|
||||||
|
"sha256": "1d11e3b7cae4762d0c35dc83c331813f49a7f9bc492eb63cada01954af8a7d2a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/bg.pak",
|
||||||
|
"sizeBytes": 987762,
|
||||||
|
"sha256": "d2fa3f3e66113fbd7efe891eef6f66915e04dfa8aedbb162cebe27ee7db4d248"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/bn.pak",
|
||||||
|
"sizeBytes": 1269605,
|
||||||
|
"sha256": "a3f81cf087eb69c505243db32d36fce0f4266d074f22dd6e1742a1311cc8d5c5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ca.pak",
|
||||||
|
"sizeBytes": 612377,
|
||||||
|
"sha256": "bc32492cbaa82d9de625548c79f03173ec4db4d3e25d2e5d3099a7d7231f8ff1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/cs.pak",
|
||||||
|
"sizeBytes": 622919,
|
||||||
|
"sha256": "3223737e45b3f06acd90d2ea6b923c99ef3a988f072234328f5cd337d428a219"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/da.pak",
|
||||||
|
"sizeBytes": 567958,
|
||||||
|
"sha256": "a2960a7b635fc8a100e325b5ebe0bd696cccaa0af5d77ec1ea2ef3a7ad77471c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/de.pak",
|
||||||
|
"sizeBytes": 609935,
|
||||||
|
"sha256": "d7a8385e3e1bedd61d102be6b19d5e8cf09c814528cfd782c1d3bf62812690b8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/el.pak",
|
||||||
|
"sizeBytes": 1080416,
|
||||||
|
"sha256": "889501de74431bc33ca326df8711c46e3def70cd82b1124a44524ee2829167c2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/en-GB.pak",
|
||||||
|
"sizeBytes": 492124,
|
||||||
|
"sha256": "86c1766ba2e7b86f111445a1f57c5120e1be78a4b6e7b2e124dcd31116c7ccdb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/en-US.pak",
|
||||||
|
"sizeBytes": 497015,
|
||||||
|
"sha256": "fc44badc0f1ee3daa57d905a9e39ae3ee6dbd38049cbd944905630409038ff2b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/es.pak",
|
||||||
|
"sizeBytes": 596806,
|
||||||
|
"sha256": "270147cc81547477f181b5c6b75dd8cf46eb124de802de8eb2bc6855d2ef8fe8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/es-419.pak",
|
||||||
|
"sizeBytes": 598355,
|
||||||
|
"sha256": "d7088cd07d220af16275befc09c56c2524d4b63a424876ce2f7f5442f56dcaa3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/et.pak",
|
||||||
|
"sizeBytes": 544221,
|
||||||
|
"sha256": "21046ded9f9aab82bbc7ff1579fbc80b94bd6da09a3e4817188391d4af1c24be"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/fa.pak",
|
||||||
|
"sizeBytes": 879421,
|
||||||
|
"sha256": "af1dd21b0aa302cbebc56d39abd8bcfda981734e04c7ab8040e905cbbbaa193c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/fi.pak",
|
||||||
|
"sizeBytes": 552657,
|
||||||
|
"sha256": "48a5e49251723e3e191c8502ff1b6dedf39e168ac252fcf535b36ad52e9ea8fd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/fil.pak",
|
||||||
|
"sizeBytes": 624599,
|
||||||
|
"sha256": "7117986303e4954ac39bb144ac76bacb450f7be68ae1fde970ee639ad39bd9d8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/fr.pak",
|
||||||
|
"sizeBytes": 646732,
|
||||||
|
"sha256": "4dee926b878d106a3599c1c884bb84dcdd7785836032384420f5fd0c76cea640"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/gu.pak",
|
||||||
|
"sizeBytes": 1255599,
|
||||||
|
"sha256": "9af5364f7cbe7ef972c0fb9b62bf2c13cb1a9ff4dde1d6fd2ffcacd088adb987"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/he.pak",
|
||||||
|
"sizeBytes": 777593,
|
||||||
|
"sha256": "ad956cf0f663b25c19907bb8737b2342704223ac79f8a85b7a3038d52e9afa7a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/hi.pak",
|
||||||
|
"sizeBytes": 1330999,
|
||||||
|
"sha256": "6b2629ccdc38a3c14ee5de4eba558527bbc4c590c87cc9393f9b7e337b8e5efa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/hr.pak",
|
||||||
|
"sizeBytes": 600581,
|
||||||
|
"sha256": "d2d55568886ef5bb2a073e619f8dbf98a3ff341ce5ba6f3f362224081cc0cdc8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/hu.pak",
|
||||||
|
"sizeBytes": 646489,
|
||||||
|
"sha256": "d3f6a1560e893042b92f40a56b5761790e94a78efda73a26a640dd21997443ae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/id.pak",
|
||||||
|
"sizeBytes": 535422,
|
||||||
|
"sha256": "8f84ac460c88e44518e2c5165d0758e8d0f2c6223cfb5ca6ad5507aae79f67bd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/it.pak",
|
||||||
|
"sizeBytes": 594371,
|
||||||
|
"sha256": "fd236c934edfae7fe10176f9d7a2293838d2cd59f54beb7af689cd61014a51c9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ja.pak",
|
||||||
|
"sizeBytes": 719063,
|
||||||
|
"sha256": "539e2195c7e7bbf7b2976e9b3b4950bc4a6616a590cf85678bd264387382de1c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/kn.pak",
|
||||||
|
"sizeBytes": 1424332,
|
||||||
|
"sha256": "70d9698ad1cb9d78e1eab70e7e1161ca4216399969991922abd0edeae0ecbb01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ko.pak",
|
||||||
|
"sizeBytes": 606589,
|
||||||
|
"sha256": "a21b8cb55ed43abd51fb2f97d40208be637b3cb2dae2f55b3abd210722e67951"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/lt.pak",
|
||||||
|
"sizeBytes": 652194,
|
||||||
|
"sha256": "160b2da4626a0ce7570460ed48326352f25624753dcc6a6aa90c6906eca15eb5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/lv.pak",
|
||||||
|
"sizeBytes": 651016,
|
||||||
|
"sha256": "70e1736c8d1406513ccf47ad85eec64f46f2ada1a7aab1ddddeb049170152f14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ml.pak",
|
||||||
|
"sizeBytes": 1479560,
|
||||||
|
"sha256": "7f42ec438ff13b97b775146033fce3ee33a73d0806e89b61f6f284a80e1c350b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/mr.pak",
|
||||||
|
"sizeBytes": 1223735,
|
||||||
|
"sha256": "7277f688e1773d68088ce48efabf2dde4386c7cc5cfc579a8e16806eb0e37989"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ms.pak",
|
||||||
|
"sizeBytes": 560048,
|
||||||
|
"sha256": "95d27fc7023e763c546bf19d9d214b1d1eaef1ea01dab23391fe5fba7361a674"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/nb.pak",
|
||||||
|
"sizeBytes": 543051,
|
||||||
|
"sha256": "c135a7f5f35a3533a2da5666768cb78402580ecb41e1309eee580816a8a0ac28"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/nl.pak",
|
||||||
|
"sizeBytes": 562204,
|
||||||
|
"sha256": "39bbe7e945c5cedf6a53f88fbc5c298a65e48192fe46c4e6a66c289b0869de1c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/pl.pak",
|
||||||
|
"sizeBytes": 627081,
|
||||||
|
"sha256": "9ad6f0c5b4c3f335b155251b07261f5241a29892667fa607817e48abeae19462"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/pt-BR.pak",
|
||||||
|
"sizeBytes": 587941,
|
||||||
|
"sha256": "8e5466e2acbe6e350dc3b0752495dfa44eaf1da8e6054ffba9c320c4277c96d1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/pt-PT.pak",
|
||||||
|
"sizeBytes": 592511,
|
||||||
|
"sha256": "f193c222cfd9cd723dbd7839cf45c14b7749cde5527b552160df819c72b442c1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ro.pak",
|
||||||
|
"sizeBytes": 612678,
|
||||||
|
"sha256": "31c2568ba713ce7d9b2a784b8bce09b116408a5943171b2baf84b83a2cdd2801"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ru.pak",
|
||||||
|
"sizeBytes": 1003077,
|
||||||
|
"sha256": "8badbaff9761b5cfa26a409524c2c85f252ec2166449edb32246a2bee5f914b0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/sk.pak",
|
||||||
|
"sizeBytes": 632482,
|
||||||
|
"sha256": "6491c4f1c9e8ad0a498cf2a5fe11467fd419fa105622977105915639341f1c27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/sl.pak",
|
||||||
|
"sizeBytes": 607050,
|
||||||
|
"sha256": "97b5ab48cc42512a693fa7887acc7d4f3ea5cdd9e6bbf334fa2940c922e121af"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/sr.pak",
|
||||||
|
"sizeBytes": 929699,
|
||||||
|
"sha256": "d53039029b8b60ffca583896abe66e860016bf8b250df689bece5e17c2d86abc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/sv.pak",
|
||||||
|
"sizeBytes": 547471,
|
||||||
|
"sha256": "669fbcc98ccb78259f497e965efbf2ba38e5c0e5ad6d50c588f013c018e03d7a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/sw.pak",
|
||||||
|
"sizeBytes": 576117,
|
||||||
|
"sha256": "c8a7fe1af281b73985da58b66570150c4df27b0425f81068df6949799ada2769"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ta.pak",
|
||||||
|
"sizeBytes": 1475609,
|
||||||
|
"sha256": "4019bcfd216e224924e34cb879b8cec6d91fde49d4a362aede9120bc9355543e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/te.pak",
|
||||||
|
"sizeBytes": 1361935,
|
||||||
|
"sha256": "cd3a666d5f0091ac4c6f065b45ab21a30a9fe2a1073f8c6bf6192f123ad8156c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/th.pak",
|
||||||
|
"sizeBytes": 1144623,
|
||||||
|
"sha256": "114d7a817a0c73f2d0bff438eb6a076ad76a8bfb2c561e542aeb699cbf1298ef"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/tr.pak",
|
||||||
|
"sizeBytes": 587129,
|
||||||
|
"sha256": "982728b531abdb1c2e33fc65203bb20e3abac226674b4611d8d609a82a483cb2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/uk.pak",
|
||||||
|
"sizeBytes": 1001189,
|
||||||
|
"sha256": "54e5c7d4cb654c880c54051b35ec108dff28621afcc896a7d227d3b01a98c60b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/ur.pak",
|
||||||
|
"sizeBytes": 872334,
|
||||||
|
"sha256": "04a50bcbedd0760bb9c6e0628d8e520d58e8f9e9655c76349bceea5a891783d5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/vi.pak",
|
||||||
|
"sizeBytes": 695768,
|
||||||
|
"sha256": "f87b6a8530ffa5760367c62260b6bceaeb9148f58ad4041222dbd9592488299e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/zh-CN.pak",
|
||||||
|
"sizeBytes": 503346,
|
||||||
|
"sha256": "dc5703f8267b4343a9d8e6acf5b82a4a52559f494c4555aded02f29cf20ed631"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/Resources/locales/zh-TW.pak",
|
||||||
|
"sizeBytes": 500142,
|
||||||
|
"sha256": "ccaf09ef99e6feda260aee9cd073bd7513223f770422d799d7490a6f16f44fc5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/snapshot_blob.bin",
|
||||||
|
"sizeBytes": 313526,
|
||||||
|
"sha256": "e8a4351c04b18aef318612989c147e2878082306094e39349fb0fea8711a19a0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/v8_context_snapshot.bin",
|
||||||
|
"sizeBytes": 665981,
|
||||||
|
"sha256": "b443db3a84c0c020e1ceeeb355018d6589eb8ef5b48e110ef6e02fd723781d78"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/vk_swiftshader.dll",
|
||||||
|
"sizeBytes": 5572536,
|
||||||
|
"sha256": "06b32c4dae03afe26c5acb821fdf19b7bdb9e3ffe8f29af93bba4e8e49722287"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/vulkan-1.dll",
|
||||||
|
"sizeBytes": 930744,
|
||||||
|
"sha256": "ede9bf15fc0a3dc6f60d76eda8a7a765b57866edc5410c91709c82c4b7fe7e5f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/DbgHelp/dbghelp.dll",
|
||||||
|
"sizeBytes": 2232688,
|
||||||
|
"sha256": "d65dff2ebe90bf79fba62f3bb1f105a7ce8efaefaa8349379a886bb893a4ef45"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/MsQuic/v220/win64/msquic.dll",
|
||||||
|
"sizeBytes": 2547080,
|
||||||
|
"sha256": "832f4ae560b1623aa4d8f87b982e9c9414312723fbc905ddab93fd80d7f1cea2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/NVIDIA/NVaftermath/Win64/GFSDK_Aftermath_Lib.x64.dll",
|
||||||
|
"sizeBytes": 5442592,
|
||||||
|
"sha256": "f2f1a88185345b28d05673e11111ee21845f3ebe65919cf6b3085bee7d09e30a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/Ogg/Win64/VS2015/libogg_64.dll",
|
||||||
|
"sizeBytes": 59832,
|
||||||
|
"sha256": "1e2fe8a3dfe9616edcb3cd3a5a958c791f690d5b604eb1658b0f844cef156eee"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/OpenXR/win64/openxr_loader.dll",
|
||||||
|
"sizeBytes": 1971640,
|
||||||
|
"sha256": "36020b5170c5a653132468e7b297c5e06eaff5ba4d26d5478d723f88f699f8b5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/Vorbis/Win64/VS2015/libvorbis_64.dll",
|
||||||
|
"sizeBytes": 1724856,
|
||||||
|
"sha256": "676bbdc5838755d7a881c847f84ca79997b525882594b66160ab800676cab9c0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/Vorbis/Win64/VS2015/libvorbisfile_64.dll",
|
||||||
|
"sizeBytes": 48568,
|
||||||
|
"sha256": "ceb067771c03ae1a7afc125c15c85dbab027aaec72575dc101c618eba2bafea0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/ThirdParty/Windows/XAudio2_9/x64/xaudio2_9redist.dll",
|
||||||
|
"sizeBytes": 858144,
|
||||||
|
"sha256": "013984e33e884bd0b823734ab86a599a8dceffed675039ff293d15ffcf7f2be9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Binaries/Win64/EpicWebHelper.exe",
|
||||||
|
"sizeBytes": 4751288,
|
||||||
|
"sha256": "f727e281c69b7cbffc4343310342ff78dfccf40f94fc8ba09e9ce6b1bf842a17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Config/StagedBuild_UnrealHyperTwist.ini",
|
||||||
|
"sizeBytes": 3,
|
||||||
|
"sha256": "f1945cd6c19e56b3c1c78943ef5ec18116907a4ca1efc40a57d48ab1db7adfc5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Content/Renderer/TessellationTable.bin",
|
||||||
|
"sizeBytes": 259568,
|
||||||
|
"sha256": "edc4f3b628a139c5e185bbaeca661c95c1f427368d3b92892c5cff36c56dd941"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Content/Slate/Cursor/invisible.cur",
|
||||||
|
"sizeBytes": 326,
|
||||||
|
"sha256": "fef3980fa567e9c45d5d8dcaa432a2c1a3f3bb17fe67d7ab198164f56c142aa1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Content/SlateDebug/Fonts/LastResort.tps",
|
||||||
|
"sizeBytes": 930,
|
||||||
|
"sha256": "0f775fa99d05e21d43d2d06d55982b23dcdccdb512a9a5a07aff674f212c41b8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Content/SlateDebug/Fonts/LastResort.ttf",
|
||||||
|
"sizeBytes": 5395052,
|
||||||
|
"sha256": "fff0f8de0b868b964950fe97c9b60f893e9bc85a4f90b3629c5693db058b97b9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Engine/Plugins/NNE/NNERuntimeORT/Binaries/ThirdParty/Onnxruntime/Win64/onnxruntime.dll",
|
||||||
|
"sizeBytes": 14692872,
|
||||||
|
"sha256": "381497f383b457180aba6e5bf56a2eb18cefd6735cfd47257539f6d87fbc8584"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Manifest_NonUFSFiles_Win64.txt",
|
||||||
|
"sizeBytes": 10686,
|
||||||
|
"sha256": "b8abaae2ce29e4fc950008d19930e2dccfbe6b6b667baa789c4b67dce60f5710"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "Manifest_UFSFiles_Win64.txt",
|
||||||
|
"sizeBytes": 255758,
|
||||||
|
"sha256": "cb6e852604f98c5a63ad4c9eecaf32826522f660362b0eceb7d2a36b6531f869"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist.exe",
|
||||||
|
"sizeBytes": 165376,
|
||||||
|
"sha256": "886f69c6a823770b3ed68db4fe3790a488124c99c98dbd41944a6bed5d634dc6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Binaries/Win64/D3D12/x64/D3D12Core.dll",
|
||||||
|
"sizeBytes": 4544000,
|
||||||
|
"sha256": "fb197903fea91aaf352d2322f342b1cec8db36ff0292a49f24173577e08f26cf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Binaries/Win64/D3D12/x64/d3d12SDKLayers.dll",
|
||||||
|
"sizeBytes": 5104632,
|
||||||
|
"sha256": "a817223446f53b3da894edb1ee7a92b94573690e689a9470b87bf42866115f91"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Binaries/Win64/DML/x64/DirectML.dll",
|
||||||
|
"sizeBytes": 18537968,
|
||||||
|
"sha256": "664255a3d9a6b976e2d0e2440403537d9d0dd91b1fad866768638b4e73a2c33a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Binaries/Win64/tbb12.dll",
|
||||||
|
"sizeBytes": 331704,
|
||||||
|
"sha256": "645b681e3581c04d57f468bd85c17648172decf873653ab00382211b96cc98fb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Binaries/Win64/tbbmalloc.dll",
|
||||||
|
"sizeBytes": 117688,
|
||||||
|
"sha256": "f81a11f2e6e93036bab4e51a1daab9940fb8a9a5ec0f508c4cb76d398e27c100"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Binaries/Win64/UnrealHyperTwist-Win64-Shipping.exe",
|
||||||
|
"sizeBytes": 181121024,
|
||||||
|
"sha256": "e583531cbb21d22f6c223eb12bf0cf81f82798faff9e2fbec4ebeb953bf98bf3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Content/Paks/global.ucas",
|
||||||
|
"sizeBytes": 3325696,
|
||||||
|
"sha256": "c7e20318d6b887c26a131d33bed944410469b1f331e76bbfe0e5f0168d808188"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Content/Paks/global.utoc",
|
||||||
|
"sizeBytes": 806,
|
||||||
|
"sha256": "846861acb8db76d1a68a9614d89d327fb7ae4ade5a1c9aa63be79c713118d424"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Content/Paks/UnrealHyperTwist-Windows.pak",
|
||||||
|
"sizeBytes": 11069853,
|
||||||
|
"sha256": "605e0b2ff7dd284762f4d4281945535f2a3ff86065904a2ce4f1c2837c72c900"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Content/Paks/UnrealHyperTwist-Windows.ucas",
|
||||||
|
"sizeBytes": 281222144,
|
||||||
|
"sha256": "d52a40ad8633351078b351f4bc1321d12ee12b397ad585f7a8a43418f54cfe62"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Content/Paks/UnrealHyperTwist-Windows.utoc",
|
||||||
|
"sizeBytes": 216013,
|
||||||
|
"sha256": "f317d5ac0c82871400697dc29b17925a49d55c7aa2608ddc4f91cfea896ec07e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relativePath": "UnrealHyperTwist/Saved/twophase-ht.tbl",
|
||||||
|
"sizeBytes": 676207080,
|
||||||
|
"sha256": "dc6de3d909a37afe2ba7f1f978543a13eae215bd20d954d66813524a8ca20034"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
{
|
||||||
|
"reportVersion": "ht-windows-readiness/v1",
|
||||||
|
"generatedAtUtc": "2026-07-26T08:31:51.1163747Z",
|
||||||
|
"result": "ready-with-warnings",
|
||||||
|
"payloadRoot": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723\\Windows",
|
||||||
|
"targetInstallRoot": "C:\\Program Files\\HyperTwist",
|
||||||
|
"requiredFailureCount": 0,
|
||||||
|
"optionalWarningCount": 2,
|
||||||
|
"checks": [
|
||||||
|
{
|
||||||
|
"id": "windows-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires a 64-bit Windows operating system.",
|
||||||
|
"evidence": {
|
||||||
|
"architecture": "64-bit",
|
||||||
|
"processArchitecture": "AMD64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-supported-build",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "HyperTwist requires Windows build 19045 or newer.",
|
||||||
|
"evidence": {
|
||||||
|
"caption": "Microsoft Windows 11 Home",
|
||||||
|
"version": "10.0.22631",
|
||||||
|
"build": 22631,
|
||||||
|
"minimumBuild": 19045
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system-memory",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least 8 GiB of physical memory is required for the desktop Alpha.",
|
||||||
|
"evidence": {
|
||||||
|
"totalBytes": 16893206528,
|
||||||
|
"minimumBytes": 8589934592
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "install-volume-free-space",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The target volume must have enough free space for installation and first-run caches.",
|
||||||
|
"evidence": {
|
||||||
|
"targetInstallRoot": "C:\\Program Files\\HyperTwist",
|
||||||
|
"availableBytes": 171945615360,
|
||||||
|
"minimumBytes": 4294967296
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vc-runtime-x64",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Microsoft Visual C++ 2015-2022 x64 runtime 14.44.35211.0 or newer is required and is bundled by the installer.",
|
||||||
|
"evidence": {
|
||||||
|
"registryPath": "HKLM:\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64",
|
||||||
|
"installed": true,
|
||||||
|
"version": "14.44.35211.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "windows-media-and-graphics-libraries",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "Windows DirectX, XInput, and Media Foundation runtime libraries must be available.",
|
||||||
|
"evidence": {
|
||||||
|
"systemDirectory": "C:\\Windows\\system32",
|
||||||
|
"requiredLibraries": [
|
||||||
|
"d3d11.dll",
|
||||||
|
"d3d12.dll",
|
||||||
|
"dxgi.dll",
|
||||||
|
"mf.dll",
|
||||||
|
"mfplat.dll",
|
||||||
|
"mfreadwrite.dll",
|
||||||
|
"xinput1_4.dll"
|
||||||
|
],
|
||||||
|
"missingLibraries": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "graphics-adapter",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "At least one Windows graphics adapter must be visible.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel(R) Iris(R) Xe Graphics",
|
||||||
|
"driverVersion": "31.0.101.3358",
|
||||||
|
"driverDate": "2022-08-04T02:00:00.0000000+02:00",
|
||||||
|
"adapterRamBytes": 1073741824,
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audio-device",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "An audio device is optional for puzzle play and recommended for narration and speech features.",
|
||||||
|
"evidence": [
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Digital Microphones",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for USB Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intel® Smart Sound Technology for Bluetooth® Audio",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Audio Device",
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Virtual Audio Cable",
|
||||||
|
"status": "OK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "openxr-runtime",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "An active OpenXR runtime is optional for keyboard/mouse play and required only for live headset sessions.",
|
||||||
|
"evidence": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "required-payload-files",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must contain every required executable, runtime, cooked-data, browser, solver, and OpenXR file.",
|
||||||
|
"evidence": {
|
||||||
|
"payloadRoot": "C:\\HyperTwist_worktrees\\phase10validate_packaged_alpha_release19_shipping_20260723\\Windows",
|
||||||
|
"requiredFileCount": 15,
|
||||||
|
"cefRuntimeFiles": [
|
||||||
|
"Engine/Binaries/ThirdParty/CEF3/Win64/128.4.13+ge76af7e+chromium-128.0.6613.138/libcef.dll"
|
||||||
|
],
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "desktop-code-signature",
|
||||||
|
"class": "optional",
|
||||||
|
"passed": false,
|
||||||
|
"summary": "The Alpha payload is currently unsigned; production distribution requires Authenticode signing.",
|
||||||
|
"evidence": {
|
||||||
|
"status": "NotSigned",
|
||||||
|
"signer": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "payload-manifest-parity",
|
||||||
|
"class": "required",
|
||||||
|
"passed": true,
|
||||||
|
"summary": "The installed payload must match the release manifest without missing, truncated, or altered files.",
|
||||||
|
"evidence": {
|
||||||
|
"manifestPath": "C:\\HyperTwist_worktrees\\installer-release19-20260726\\validation\\windows-installer-payload-manifest.json",
|
||||||
|
"manifestVersion": "ht-windows-installer-payload/v1",
|
||||||
|
"manifestEntryCount": 143,
|
||||||
|
"declaredFileCount": 143,
|
||||||
|
"declaredTotalSizeBytes": 1585341236,
|
||||||
|
"computedTotalSizeBytes": 1585341236,
|
||||||
|
"hashesVerified": true,
|
||||||
|
"failures": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -357,6 +357,7 @@ Current operator delivery:
|
||||||
|
|
||||||
- `C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19`
|
- `C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19`
|
||||||
- `C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19.zip`
|
- `C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19.zip`
|
||||||
|
- `C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19-Setup.exe`
|
||||||
|
|
||||||
Durable pulled evidence:
|
Durable pulled evidence:
|
||||||
|
|
||||||
|
|
@ -392,6 +393,12 @@ Final acceptance facts:
|
||||||
`caa45f3d3104a8e5406f493a60c8a136d852bd35e0bd1c8dfbf79738c1343892`
|
`caa45f3d3104a8e5406f493a60c8a136d852bd35e0bd1c8dfbf79738c1343892`
|
||||||
- no fatal signature, package-owned listener, trace-control listener, or
|
- no fatal signature, package-owned listener, trace-control listener, or
|
||||||
lingering owned packaged process remained
|
lingering owned packaged process remained
|
||||||
|
- the later `2026-07-26` installer authority passed with size `851049086`
|
||||||
|
bytes, SHA-256
|
||||||
|
`c31ed6b0b2ae1feb449c27e484d72dc2e07ba220e3cdafa4c3605429d638e0ea`,
|
||||||
|
`143` manifest-owned payload files, and green install, readiness, Shipping
|
||||||
|
launch, in-place upgrade, second parity, uninstall, user-data preservation,
|
||||||
|
and cleanup proof
|
||||||
|
|
||||||
The global-assistant regression fix is part of this exact package. A standalone
|
The global-assistant regression fix is part of this exact package. A standalone
|
||||||
speech session no longer requires an active Classic training run, so the fixed
|
speech session no longer requires an active Classic training run, so the fixed
|
||||||
|
|
@ -400,6 +407,34 @@ provider-reachability, microphone, and audible-TTS test still requires
|
||||||
intentionally configured services and hardware and is not inferred from
|
intentionally configured services and hardware and is not inferred from
|
||||||
structural automation.
|
structural automation.
|
||||||
|
|
||||||
|
### Release 19 Windows installer authority
|
||||||
|
|
||||||
|
Durable evidence:
|
||||||
|
|
||||||
|
`docs/generated/alpha_test_20260726_installer`
|
||||||
|
|
||||||
|
The installer is now the preferred first-time Alpha delivery while the
|
||||||
|
validated folder and ZIP remain portable and rollback-friendly alternatives.
|
||||||
|
It owns:
|
||||||
|
|
||||||
|
- x64 Windows 10 22H2 / Windows 11 preflight
|
||||||
|
- a valid Microsoft-signed Visual C++ 2015-2022 x64 prerequisite
|
||||||
|
- a complete `143`-file payload manifest with SHA-256 parity
|
||||||
|
- safe install-directory leaf and non-empty ownership refusal
|
||||||
|
- Add/Remove Programs plus resolved app/readiness/uninstall shortcuts
|
||||||
|
- marker-and-registry-gated upgrade and uninstall
|
||||||
|
- preservation of settings, saves, replays, and diagnostics
|
||||||
|
|
||||||
|
The lifecycle harness deliberately used an install path containing spaces. It
|
||||||
|
proved an unowned non-empty target was refused before prerequisite or payload
|
||||||
|
mutation, then passed first install, full parity, installed readiness,
|
||||||
|
stock-Shipping initialization, in-place upgrade, second parity, and uninstall.
|
||||||
|
No install root, registration, shortcut, listener, or owned process remained.
|
||||||
|
|
||||||
|
This is `isolated-current-host` evidence because no clean VM or Windows Sandbox
|
||||||
|
was available. The executable is `NotSigned`; trusted Authenticode remains a
|
||||||
|
production gate rather than an inferred Alpha capability.
|
||||||
|
|
||||||
## Operator diagnostics
|
## Operator diagnostics
|
||||||
|
|
||||||
The delivered Alpha uses stock Shipping configuration and first-party direct
|
The delivered Alpha uses stock Shipping configuration and first-party direct
|
||||||
|
|
@ -427,14 +462,15 @@ Never distribute a loose `UnrealHyperTwist.exe`. The executable depends on the
|
||||||
complete staged `Windows` directory, including engine binaries, project
|
complete staged `Windows` directory, including engine binaries, project
|
||||||
content containers, and runtime DLLs such as `tbbmalloc.dll`.
|
content containers, and runtime DLLs such as `tbbmalloc.dll`.
|
||||||
|
|
||||||
The approved Alpha distribution shape is:
|
The approved Alpha distribution shapes are:
|
||||||
|
|
||||||
|
- the validated installer for normal first-time operator testing
|
||||||
- an extracted folder for direct operator testing
|
- an extracted folder for direct operator testing
|
||||||
- a separately verified ZIP of that complete folder
|
- a separately verified ZIP of that complete folder
|
||||||
- matching release metadata with SHA-256, byte count, file/entry count, and
|
- matching release metadata with SHA-256, byte count, file/entry count, and
|
||||||
validation references
|
validation references
|
||||||
|
|
||||||
Approved current delivery:
|
Historical Release 17 rollback delivery:
|
||||||
|
|
||||||
- folder:
|
- folder:
|
||||||
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723`
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723`
|
||||||
|
|
@ -444,6 +480,19 @@ Approved current delivery:
|
||||||
- ZIP facts: `103` entries, `1082134734` bytes, SHA-256
|
- ZIP facts: `103` entries, `1082134734` bytes, SHA-256
|
||||||
`1ad8e1c0fc967b227ca09fb68c515ed644eca3e4bda07fdf8c378b438000fc42`
|
`1ad8e1c0fc967b227ca09fb68c515ed644eca3e4bda07fdf8c378b438000fc42`
|
||||||
|
|
||||||
|
Approved current Release 19 delivery:
|
||||||
|
|
||||||
|
- folder:
|
||||||
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19`
|
||||||
|
- ZIP:
|
||||||
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19.zip`
|
||||||
|
- ZIP facts: `167` entries, `1093537260` bytes, SHA-256
|
||||||
|
`630963f96c681fc49130cbc56c6c850008d4cddda7e83f2ee9c077c52d7709a9`
|
||||||
|
- installer:
|
||||||
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19-Setup.exe`
|
||||||
|
- installer facts: `851049086` bytes, SHA-256
|
||||||
|
`c31ed6b0b2ae1feb449c27e484d72dc2e07ba220e3cdafa4c3605429d638e0ea`
|
||||||
|
|
||||||
The superseded July 9 folder and matching ZIP were deleted only after the
|
The superseded July 9 folder and matching ZIP were deleted only after the
|
||||||
replacement folder, archive, critical-entry hashes, and final Downloads launch
|
replacement folder, archive, critical-entry hashes, and final Downloads launch
|
||||||
were verified. The retirement report is retained at
|
were verified. The retirement report is retained at
|
||||||
|
|
|
||||||
|
|
@ -576,6 +576,15 @@ Routing correction:
|
||||||
succeeded in `60.93` seconds and all `5`
|
succeeded in `60.93` seconds and all `5`
|
||||||
`HyperTwist.PlayerExperience` tests passed, including
|
`HyperTwist.PlayerExperience` tests passed, including
|
||||||
`GlobalAssistantSpeechSession`.
|
`GlobalAssistantSpeechSession`.
|
||||||
|
- [x] Release 19 Windows installer and isolated-host lifecycle gate on
|
||||||
|
`2026-07-26`: a first-party NSIS installer now owns x64/Windows preflight,
|
||||||
|
the signed Microsoft Visual C++ runtime, a complete `143`-file SHA-256
|
||||||
|
manifest, safe install-root and marker/registry ownership, resolved
|
||||||
|
shortcuts, readiness reporting, in-place upgrade, and uninstall that
|
||||||
|
preserves user data. The final `851049086`-byte installer passed first
|
||||||
|
install, full parity, stock-Shipping launch, upgrade, second parity,
|
||||||
|
uninstall, and cleanup from a path containing spaces. Durable proof lives in
|
||||||
|
`docs/generated/alpha_test_20260726_installer`.
|
||||||
|
|
||||||
**Estimated actions:** 20–30
|
**Estimated actions:** 20–30
|
||||||
**Estimated time:** 1–2 days
|
**Estimated time:** 1–2 days
|
||||||
|
|
@ -620,15 +629,18 @@ Routing correction:
|
||||||
|
|
||||||
## Immediate Next Step
|
## Immediate Next Step
|
||||||
|
|
||||||
**Current Alpha next move (`2026-07-23`):** Release 19 is now the current
|
**Current Alpha next move (`2026-07-26`):** Release 19 is now the current
|
||||||
portable-Alpha authority at
|
portable and installed-Alpha authority at
|
||||||
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19`, while
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19` and
|
||||||
Release 17 remains rollback authority until operator acceptance. Prioritize
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19-Setup.exe`,
|
||||||
installer/uninstaller, code-signing, clean-machine prerequisite, entitlement,
|
while Release 17 remains rollback authority until operator acceptance.
|
||||||
and update-channel rollout proof next. Separately retain the real-hardware
|
Installer/uninstaller and isolated-current-host prerequisite proof are closed.
|
||||||
XR/controller observation and configured-provider AI/STT/TTS audible smoke as
|
Prioritize trusted Authenticode signing, a genuinely fresh Windows VM install,
|
||||||
external-condition gates. Do not reopen MagicTile native-renderer widening or
|
entitlement-backed public release URLs, and update-channel/rollback rollout
|
||||||
unrelated simulator topology to perform this release engineering.
|
proof next. Separately retain the real-hardware XR/controller observation and
|
||||||
|
configured-provider AI/STT/TTS audible smoke as external-condition gates. Do
|
||||||
|
not reopen MagicTile native-renderer widening or unrelated simulator topology
|
||||||
|
to perform this release engineering.
|
||||||
|
|
||||||
**Phase 1 through Phase 5 are now closed on the intended simulator lane:** repo wiring, the
|
**Phase 1 through Phase 5 are now closed on the intended simulator lane:** repo wiring, the
|
||||||
classic-cube renderer/runtime loop, dedicated training maps and materials, solver-guided training,
|
classic-cube renderer/runtime loop, dedicated training maps and materials, solver-guided training,
|
||||||
|
|
|
||||||
|
|
@ -3880,6 +3880,63 @@ does not stand in for a real microphone, reachable provider, audible TTS
|
||||||
device, or explicit cloud consent; perform that external-service smoke only
|
device, or explicit cloud consent; perform that external-service smoke only
|
||||||
when those inputs are intentionally configured.
|
when those inputs are intentionally configured.
|
||||||
|
|
||||||
|
## Release 19 Windows installer and readiness lane (`2026-07-26`)
|
||||||
|
|
||||||
|
The first-party Windows distribution lane is:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\Build-HyperTwistWindowsInstaller.ps1
|
||||||
|
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\Test-HyperTwistWindowsReadiness.ps1
|
||||||
|
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\Test-HyperTwistWindowsInstaller.ps1 -InstallerPath <setup-exe>
|
||||||
|
```
|
||||||
|
|
||||||
|
`packaging\windows\HyperTwistInstaller.nsi` is the installer definition.
|
||||||
|
`Build-HyperTwistWindowsInstaller.ps1` validates required runtime, cooked,
|
||||||
|
browser, OpenXR, and exact solver files; rejects payload reparse points;
|
||||||
|
requires a valid Microsoft signature on the bundled Visual C++ runtime;
|
||||||
|
excludes PDB/debug material; writes a complete SHA-256 manifest; checks source
|
||||||
|
readiness; and deletes incomplete output on failure.
|
||||||
|
|
||||||
|
The installer:
|
||||||
|
|
||||||
|
- requires x64 Windows 10 22H2 or Windows 11
|
||||||
|
- requires the selected directory leaf to be `HyperTwist`
|
||||||
|
- refuses a non-empty directory unless the 64-bit product registry and install
|
||||||
|
marker both prove existing HyperTwist ownership
|
||||||
|
- installs or repairs the bundled prerequisite before cleaning an owned prior
|
||||||
|
payload
|
||||||
|
- registers Add/Remove Programs and all-users shortcuts
|
||||||
|
- gives the readiness shortcut a per-user report path, complete manifest
|
||||||
|
validation, and an interactive close prompt
|
||||||
|
- never launches the desktop process elevated from the finish page
|
||||||
|
- removes only marker/registry-owned install payload on uninstall
|
||||||
|
- preserves `%LOCALAPPDATA%\UnrealHyperTwist\Saved`
|
||||||
|
|
||||||
|
The lifecycle harness must run from an elevated Windows token. It refuses to
|
||||||
|
replace a pre-existing registered install, uses a unique validation run,
|
||||||
|
proves rejection of an unowned non-empty root, performs first install and full
|
||||||
|
hash parity, validates resolved shortcut targets/arguments, runs installed
|
||||||
|
readiness, launches stock Shipping with isolated user data and direct
|
||||||
|
diagnostics, performs in-place upgrade and second parity, then uninstalls and
|
||||||
|
proves user-data preservation plus install/registry/shortcut cleanup. Stop
|
||||||
|
only executables whose resolved path is inside that run's install root.
|
||||||
|
|
||||||
|
The final Release 19 installer is:
|
||||||
|
|
||||||
|
- delivery:
|
||||||
|
`C:\Users\Anthracite Ace\Downloads\HyperTwist-Alpha-Test-20260723-R19-Setup.exe`
|
||||||
|
- size: `851049086` bytes
|
||||||
|
- SHA-256:
|
||||||
|
`c31ed6b0b2ae1feb449c27e484d72dc2e07ba220e3cdafa4c3605429d638e0ea`
|
||||||
|
- payload: `143` files and `1585341236` bytes
|
||||||
|
- lifecycle: `passed`
|
||||||
|
- evidence: `docs/generated/alpha_test_20260726_installer`
|
||||||
|
|
||||||
|
This is `isolated-current-host` proof, not fresh-machine proof. The host had no
|
||||||
|
Windows Sandbox, clean Hyper-V VM, or base VHD. The Alpha is also unsigned.
|
||||||
|
Trusted Authenticode signing and a genuinely fresh Windows install remain
|
||||||
|
release gates.
|
||||||
|
|
||||||
### Remote-probe hygiene
|
### Remote-probe hygiene
|
||||||
|
|
||||||
A locally timed-out or interrupted SSH wrapper can leave its encoded
|
A locally timed-out or interrupted SSH wrapper can leave its encoded
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -224,6 +224,14 @@ public pages, manuals, and operator closeouts:
|
||||||
the `167`-entry ZIP reopened cleanly, and both the validation-archive and
|
the `167`-entry ZIP reopened cleanly, and both the validation-archive and
|
||||||
exact Downloads executables produced fresh semantic
|
exact Downloads executables produced fresh semantic
|
||||||
`launch-menu-renderable` frames
|
`launch-menu-renderable` frames
|
||||||
|
- the `2026-07-26` installer continuation then closed per-machine Windows
|
||||||
|
installation, readiness, in-place upgrade, and uninstall ownership above
|
||||||
|
that exact Release 19 payload: the final installer carries a complete
|
||||||
|
`143`-file SHA-256 manifest, bundles a valid Microsoft-signed Visual C++
|
||||||
|
runtime, refuses unsafe or unowned non-empty targets, preserves user data,
|
||||||
|
and passed install-to-uninstall lifecycle validation from a path containing
|
||||||
|
spaces; this remains isolated-current-host evidence rather than a fabricated
|
||||||
|
fresh-machine or trusted-code-signing claim
|
||||||
- Paddle checkout URLs, public Windows release URLs, production auth/runtime
|
- Paddle checkout URLs, public Windows release URLs, production auth/runtime
|
||||||
configuration, and corresponding-source/notices URLs remain deployment
|
configuration, and corresponding-source/notices URLs remain deployment
|
||||||
configuration gates, not hardcoded product facts
|
configuration gates, not hardcoded product facts
|
||||||
|
|
|
||||||
|
|
@ -579,14 +579,24 @@ Current consolidated milestone snapshot:
|
||||||
`-DisablePlugins=MovieRenderPipeline` plus `-SkipCookingEditorContent`,
|
`-DisablePlugins=MovieRenderPipeline` plus `-SkipCookingEditorContent`,
|
||||||
aggregate validation JSON `result: passed`, both packaged smoke maps green,
|
aggregate validation JSON `result: passed`, both packaged smoke maps green,
|
||||||
and `BuildCookRun time: 1381.37 s`
|
and `BuildCookRun time: 1381.37 s`
|
||||||
|
- Release 19 Windows installer/uninstaller and isolated-host prerequisite
|
||||||
|
validation are now closed through first-party NSIS, PowerShell build,
|
||||||
|
readiness, and lifecycle ownership. The final `851049086`-byte installer
|
||||||
|
carries `143` manifest-owned payload files, bundles a valid Microsoft-signed
|
||||||
|
Visual C++ runtime, refuses unsafe or unowned non-empty install roots,
|
||||||
|
preserves user data on uninstall, and passed install, full hash parity,
|
||||||
|
stock-Shipping launch, in-place upgrade, second parity, uninstall, and
|
||||||
|
cleanup from a path containing spaces. Durable evidence lives under
|
||||||
|
`docs/generated/alpha_test_20260726_installer`
|
||||||
- `Phase 10A` structural-only validation deprecation is now closed through
|
- `Phase 10A` structural-only validation deprecation is now closed through
|
||||||
`221` retained `Phase J` files carrying `443` deprecated validation
|
`221` retained `Phase J` files carrying `443` deprecated validation
|
||||||
identifiers and `443` disabled flags with `0` remaining live
|
identifiers and `443` disabled flags with `0` remaining live
|
||||||
`HyperTwist.Validation.*` or `HyperTwist.FirstParty.Validation.*` names
|
`HyperTwist.Validation.*` or `HyperTwist.FirstParty.Validation.*` names
|
||||||
- no implementation roadmap gate remains inside the current `Phase 1` through
|
- no implementation roadmap gate remains inside the current `Phase 1` through
|
||||||
`Phase 10` packet set; the remaining Alpha/release-engineering checks are the
|
`Phase 10` packet set; the remaining Alpha/release-engineering checks are the
|
||||||
operator-connected dashboard visual plus installer/uninstaller, code-signing,
|
operator-connected dashboard visual plus trusted code signing, genuinely
|
||||||
clean-machine prerequisites, entitlement, and update-channel rollout proof,
|
fresh-machine proof, entitlement-backed public release URLs, and
|
||||||
|
update-channel/rollback rollout proof,
|
||||||
while the remaining optional product-widening branches are the
|
while the remaining optional product-widening branches are the
|
||||||
alternative full-browser client path and any later dedicated native
|
alternative full-browser client path and any later dedicated native
|
||||||
`MagicTile` interaction/runtime replacement work rather than new
|
`MagicTile` interaction/runtime replacement work rather than new
|
||||||
|
|
|
||||||
331
packaging/windows/HyperTwistInstaller.nsi
Normal file
331
packaging/windows/HyperTwistInstaller.nsi
Normal file
|
|
@ -0,0 +1,331 @@
|
||||||
|
Unicode true
|
||||||
|
|
||||||
|
!include "MUI2.nsh"
|
||||||
|
!include "LogicLib.nsh"
|
||||||
|
!include "WinVer.nsh"
|
||||||
|
!include "x64.nsh"
|
||||||
|
!include "FileFunc.nsh"
|
||||||
|
|
||||||
|
!ifndef PRODUCT_VERSION
|
||||||
|
!error "PRODUCT_VERSION is required."
|
||||||
|
!endif
|
||||||
|
!ifndef DISPLAY_VERSION
|
||||||
|
!error "DISPLAY_VERSION is required."
|
||||||
|
!endif
|
||||||
|
!ifndef RELEASE_ID
|
||||||
|
!error "RELEASE_ID is required."
|
||||||
|
!endif
|
||||||
|
!ifndef OUTPUT_FILE
|
||||||
|
!error "OUTPUT_FILE is required."
|
||||||
|
!endif
|
||||||
|
!ifndef PAYLOAD_ROOT
|
||||||
|
!error "PAYLOAD_ROOT is required."
|
||||||
|
!endif
|
||||||
|
!ifndef PAYLOAD_MANIFEST
|
||||||
|
!error "PAYLOAD_MANIFEST is required."
|
||||||
|
!endif
|
||||||
|
!ifndef READINESS_SCRIPT
|
||||||
|
!error "READINESS_SCRIPT is required."
|
||||||
|
!endif
|
||||||
|
!ifndef VC_REDIST_PATH
|
||||||
|
!error "VC_REDIST_PATH is required."
|
||||||
|
!endif
|
||||||
|
!ifndef INSTALLER_ICON
|
||||||
|
!error "INSTALLER_ICON is required."
|
||||||
|
!endif
|
||||||
|
!ifndef PAYLOAD_SIZE_KB
|
||||||
|
!error "PAYLOAD_SIZE_KB is required."
|
||||||
|
!endif
|
||||||
|
|
||||||
|
!define PRODUCT_NAME "HyperTwist"
|
||||||
|
!define PRODUCT_CHANNEL "Alpha"
|
||||||
|
!define PRODUCT_PUBLISHER "HyperTwist"
|
||||||
|
!define PRODUCT_WEBSITE "https://hypertwist.app"
|
||||||
|
!define PRODUCT_SUPPORT "https://hypertwist.app/support"
|
||||||
|
!define PRODUCT_REG_KEY "Software\HyperTwist\HyperTwist"
|
||||||
|
!define PRODUCT_UNINSTALL_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist"
|
||||||
|
!define INSTALL_MARKER "HyperTwist.install-marker"
|
||||||
|
|
||||||
|
Name "${PRODUCT_NAME} ${PRODUCT_CHANNEL}"
|
||||||
|
Caption "${PRODUCT_NAME} ${DISPLAY_VERSION} Setup"
|
||||||
|
BrandingText "${PRODUCT_NAME} | Explore dimensions beyond the ordinary"
|
||||||
|
OutFile "${OUTPUT_FILE}"
|
||||||
|
InstallDir "$PROGRAMFILES64\HyperTwist"
|
||||||
|
RequestExecutionLevel admin
|
||||||
|
|
||||||
|
CRCCheck force
|
||||||
|
SetDatablockOptimize on
|
||||||
|
SetCompressor /SOLID lzma
|
||||||
|
SetCompressorDictSize 64
|
||||||
|
ShowInstDetails show
|
||||||
|
ShowUninstDetails show
|
||||||
|
ManifestDPIAware true
|
||||||
|
ManifestSupportedOS all
|
||||||
|
|
||||||
|
Icon "${INSTALLER_ICON}"
|
||||||
|
UninstallIcon "${INSTALLER_ICON}"
|
||||||
|
|
||||||
|
VIProductVersion "${PRODUCT_VERSION}"
|
||||||
|
VIAddVersionKey /LANG=1033 "ProductName" "${PRODUCT_NAME}"
|
||||||
|
VIAddVersionKey /LANG=1033 "ProductVersion" "${DISPLAY_VERSION}"
|
||||||
|
VIAddVersionKey /LANG=1033 "CompanyName" "${PRODUCT_PUBLISHER}"
|
||||||
|
VIAddVersionKey /LANG=1033 "FileDescription" "${PRODUCT_NAME} ${PRODUCT_CHANNEL} Installer"
|
||||||
|
VIAddVersionKey /LANG=1033 "FileVersion" "${PRODUCT_VERSION}"
|
||||||
|
VIAddVersionKey /LANG=1033 "LegalCopyright" "Copyright (c) HyperTwist"
|
||||||
|
VIAddVersionKey /LANG=1033 "OriginalFilename" "HyperTwist-Setup.exe"
|
||||||
|
|
||||||
|
!define MUI_ABORTWARNING
|
||||||
|
!define MUI_ICON "${INSTALLER_ICON}"
|
||||||
|
!define MUI_UNICON "${INSTALLER_ICON}"
|
||||||
|
!define MUI_FINISHPAGE_LINK "Visit hypertwist.app"
|
||||||
|
!define MUI_FINISHPAGE_LINK_LOCATION "${PRODUCT_WEBSITE}"
|
||||||
|
|
||||||
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
|
!insertmacro MUI_PAGE_COMPONENTS
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
|
||||||
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro MUI_UNPAGE_FINISH
|
||||||
|
|
||||||
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
|
|
||||||
|
Function .onInit
|
||||||
|
SetRegView 64
|
||||||
|
|
||||||
|
${IfNot} ${RunningX64}
|
||||||
|
MessageBox MB_OK|MB_ICONSTOP \
|
||||||
|
"HyperTwist requires 64-bit Windows." \
|
||||||
|
/SD IDOK
|
||||||
|
SetErrorLevel 10
|
||||||
|
Quit
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${IfNot} ${AtLeastWin10}
|
||||||
|
MessageBox MB_OK|MB_ICONSTOP \
|
||||||
|
"HyperTwist requires Windows 10 version 22H2 or Windows 11." \
|
||||||
|
/SD IDOK
|
||||||
|
SetErrorLevel 11
|
||||||
|
Quit
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
ReadRegStr $1 HKLM "${PRODUCT_REG_KEY}" "InstallLocation"
|
||||||
|
StrCmp $1 "" install_location_ready
|
||||||
|
StrCpy $INSTDIR $1
|
||||||
|
|
||||||
|
install_location_ready:
|
||||||
|
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentBuildNumber"
|
||||||
|
IntCmp $0 19045 windows_build_ok windows_build_too_old windows_build_ok
|
||||||
|
|
||||||
|
windows_build_too_old:
|
||||||
|
MessageBox MB_OK|MB_ICONSTOP \
|
||||||
|
"This Windows build is too old for the supported HyperTwist Alpha baseline. Update to Windows 10 22H2 or Windows 11 and try again." \
|
||||||
|
/SD IDOK
|
||||||
|
SetErrorLevel 12
|
||||||
|
Quit
|
||||||
|
|
||||||
|
windows_build_ok:
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function CleanOwnedPayloadForUpgrade
|
||||||
|
ReadRegStr $0 HKLM "${PRODUCT_REG_KEY}" "InstallLocation"
|
||||||
|
StrCmp $0 $INSTDIR registry_owner_confirmed cleanup_done
|
||||||
|
|
||||||
|
registry_owner_confirmed:
|
||||||
|
IfFileExists "$INSTDIR\Installer\${INSTALL_MARKER}" 0 cleanup_done
|
||||||
|
|
||||||
|
DetailPrint "Removing the previous HyperTwist payload before upgrade."
|
||||||
|
RMDir /r "$INSTDIR\Content"
|
||||||
|
RMDir /r "$INSTDIR\Engine"
|
||||||
|
RMDir /r "$INSTDIR\UnrealHyperTwist"
|
||||||
|
RMDir /r "$INSTDIR\Installer"
|
||||||
|
Delete "$INSTDIR\Manifest_DebugFiles_Win64.txt"
|
||||||
|
Delete "$INSTDIR\Manifest_NonUFSFiles_Win64.txt"
|
||||||
|
Delete "$INSTDIR\Manifest_UFSFiles_Win64.txt"
|
||||||
|
Delete "$INSTDIR\UnrealHyperTwist.exe"
|
||||||
|
Delete "$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
|
||||||
|
cleanup_done:
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function AssertSafeInstallLocation
|
||||||
|
${GetFileName} "$INSTDIR" $0
|
||||||
|
StrCmp $0 "HyperTwist" install_leaf_safe install_location_refused
|
||||||
|
|
||||||
|
install_leaf_safe:
|
||||||
|
ReadRegStr $0 HKLM "${PRODUCT_REG_KEY}" "InstallLocation"
|
||||||
|
StrCmp $0 $INSTDIR install_registry_owner_candidate install_unowned_scan
|
||||||
|
|
||||||
|
install_registry_owner_candidate:
|
||||||
|
IfFileExists "$INSTDIR\Installer\${INSTALL_MARKER}" install_location_safe install_unowned_scan
|
||||||
|
|
||||||
|
install_unowned_scan:
|
||||||
|
FindFirst $0 $1 "$INSTDIR\*"
|
||||||
|
|
||||||
|
install_unowned_scan_next:
|
||||||
|
StrCmp $1 "" install_unowned_empty
|
||||||
|
StrCmp $1 "." install_unowned_continue
|
||||||
|
StrCmp $1 ".." install_unowned_continue
|
||||||
|
FindClose $0
|
||||||
|
MessageBox MB_OK|MB_ICONSTOP \
|
||||||
|
"The selected HyperTwist folder is not empty and is not owned by an existing registered HyperTwist installation. Choose an empty folder named HyperTwist." \
|
||||||
|
/SD IDOK
|
||||||
|
SetErrorLevel 14
|
||||||
|
Abort
|
||||||
|
|
||||||
|
install_unowned_continue:
|
||||||
|
FindNext $0 $1
|
||||||
|
Goto install_unowned_scan_next
|
||||||
|
|
||||||
|
install_unowned_empty:
|
||||||
|
FindClose $0
|
||||||
|
Goto install_location_safe
|
||||||
|
|
||||||
|
install_location_refused:
|
||||||
|
MessageBox MB_OK|MB_ICONSTOP \
|
||||||
|
"The installation folder itself must be named HyperTwist, for example C:\Program Files\HyperTwist or D:\Games\HyperTwist." \
|
||||||
|
/SD IDOK
|
||||||
|
SetErrorLevel 13
|
||||||
|
Abort
|
||||||
|
|
||||||
|
install_location_safe:
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Section -ValidateInstallLocation
|
||||||
|
Call AssertSafeInstallLocation
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section -MicrosoftRuntime
|
||||||
|
SetOutPath "$PLUGINSDIR"
|
||||||
|
File /oname=vc_redist.x64.exe "${VC_REDIST_PATH}"
|
||||||
|
DetailPrint "Installing or repairing the Microsoft Visual C++ 2015-2022 x64 runtime."
|
||||||
|
ExecWait '"$PLUGINSDIR\vc_redist.x64.exe" /install /quiet /norestart' $0
|
||||||
|
|
||||||
|
${If} $0 == 3010
|
||||||
|
DetailPrint "The Microsoft runtime requested a restart."
|
||||||
|
SetRebootFlag true
|
||||||
|
${ElseIf} $0 == 1638
|
||||||
|
DetailPrint "A compatible or newer Microsoft runtime is already installed."
|
||||||
|
${ElseIf} $0 != 0
|
||||||
|
MessageBox MB_OK|MB_ICONSTOP \
|
||||||
|
"Microsoft Visual C++ runtime setup failed with exit code $0. HyperTwist was not installed." \
|
||||||
|
/SD IDOK
|
||||||
|
SetErrorLevel 20
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "!HyperTwist application" SEC_CORE
|
||||||
|
SectionIn RO
|
||||||
|
AddSize ${PAYLOAD_SIZE_KB}
|
||||||
|
|
||||||
|
; Do not disturb a working prior install until every bundled prerequisite succeeds.
|
||||||
|
Call CleanOwnedPayloadForUpgrade
|
||||||
|
|
||||||
|
SetOutPath "$INSTDIR"
|
||||||
|
File /r \
|
||||||
|
/x "*.pdb" \
|
||||||
|
/x "Manifest_DebugFiles_Win64.txt" \
|
||||||
|
"${PAYLOAD_ROOT}\*"
|
||||||
|
|
||||||
|
SetOutPath "$INSTDIR\Installer"
|
||||||
|
File /oname=payload-manifest.json "${PAYLOAD_MANIFEST}"
|
||||||
|
File /oname=Test-HyperTwistWindowsReadiness.ps1 "${READINESS_SCRIPT}"
|
||||||
|
|
||||||
|
FileOpen $0 "$INSTDIR\Installer\${INSTALL_MARKER}" w
|
||||||
|
FileWrite $0 "product=HyperTwist$\r$\n"
|
||||||
|
FileWrite $0 "release=${RELEASE_ID}$\r$\n"
|
||||||
|
FileWrite $0 "version=${DISPLAY_VERSION}$\r$\n"
|
||||||
|
FileClose $0
|
||||||
|
|
||||||
|
WriteUninstaller "$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
|
||||||
|
WriteRegStr HKLM "${PRODUCT_REG_KEY}" "InstallLocation" "$INSTDIR"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_REG_KEY}" "ReleaseId" "${RELEASE_ID}"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_REG_KEY}" "DisplayVersion" "${DISPLAY_VERSION}"
|
||||||
|
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "DisplayName" "${PRODUCT_NAME} ${PRODUCT_CHANNEL}"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "DisplayVersion" "${DISPLAY_VERSION}"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "InstallLocation" "$INSTDIR"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\UnrealHyperTwist.exe,0"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "URLInfoAbout" "${PRODUCT_WEBSITE}"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "HelpLink" "${PRODUCT_SUPPORT}"
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "UninstallString" "$\"$INSTDIR\Uninstall HyperTwist.exe$\""
|
||||||
|
WriteRegStr HKLM "${PRODUCT_UNINSTALL_KEY}" "QuietUninstallString" "$\"$INSTDIR\Uninstall HyperTwist.exe$\" /S"
|
||||||
|
WriteRegDWORD HKLM "${PRODUCT_UNINSTALL_KEY}" "EstimatedSize" ${PAYLOAD_SIZE_KB}
|
||||||
|
WriteRegDWORD HKLM "${PRODUCT_UNINSTALL_KEY}" "NoModify" 1
|
||||||
|
WriteRegDWORD HKLM "${PRODUCT_UNINSTALL_KEY}" "NoRepair" 1
|
||||||
|
|
||||||
|
SetShellVarContext all
|
||||||
|
CreateDirectory "$SMPROGRAMS\HyperTwist"
|
||||||
|
CreateShortCut "$SMPROGRAMS\HyperTwist\HyperTwist.lnk" \
|
||||||
|
"$INSTDIR\UnrealHyperTwist.exe" "" "$INSTDIR\UnrealHyperTwist.exe" 0
|
||||||
|
CreateShortCut "$SMPROGRAMS\HyperTwist\System Readiness Report.lnk" \
|
||||||
|
"$SYSDIR\WindowsPowerShell\v1.0\powershell.exe" \
|
||||||
|
"-NoProfile -ExecutionPolicy Bypass -File $\"$INSTDIR\Installer\Test-HyperTwistWindowsReadiness.ps1$\" -PayloadRoot $\"$INSTDIR$\" -TargetInstallRoot $\"$INSTDIR$\" -ExpectedPayloadManifestPath $\"$INSTDIR\Installer\payload-manifest.json$\" -WaitForUser" \
|
||||||
|
"$INSTDIR\UnrealHyperTwist.exe" 0
|
||||||
|
CreateShortCut "$SMPROGRAMS\HyperTwist\Uninstall HyperTwist.lnk" \
|
||||||
|
"$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Desktop shortcut" SEC_DESKTOP
|
||||||
|
SetShellVarContext all
|
||||||
|
CreateShortCut "$DESKTOP\HyperTwist.lnk" \
|
||||||
|
"$INSTDIR\UnrealHyperTwist.exe" "" "$INSTDIR\UnrealHyperTwist.exe" 0
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
LangString DESC_SEC_CORE ${LANG_ENGLISH} \
|
||||||
|
"The complete HyperTwist desktop Alpha, puzzle runtimes, learning studio, browser shell, and local solver data."
|
||||||
|
LangString DESC_SEC_DESKTOP ${LANG_ENGLISH} \
|
||||||
|
"Create an all-users HyperTwist shortcut on the desktop."
|
||||||
|
|
||||||
|
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||||
|
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_CORE} $(DESC_SEC_CORE)
|
||||||
|
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_DESKTOP} $(DESC_SEC_DESKTOP)
|
||||||
|
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||||
|
|
||||||
|
Section "Uninstall"
|
||||||
|
SetRegView 64
|
||||||
|
${GetFileName} "$INSTDIR" $1
|
||||||
|
StrCmp $1 "HyperTwist" uninstall_leaf_safe uninstall_refused
|
||||||
|
|
||||||
|
uninstall_leaf_safe:
|
||||||
|
ReadRegStr $0 HKLM "${PRODUCT_REG_KEY}" "InstallLocation"
|
||||||
|
StrCmp $0 $INSTDIR uninstall_registry_owned uninstall_refused
|
||||||
|
|
||||||
|
uninstall_registry_owned:
|
||||||
|
IfFileExists "$INSTDIR\Installer\${INSTALL_MARKER}" uninstall_owned uninstall_refused
|
||||||
|
|
||||||
|
uninstall_refused:
|
||||||
|
MessageBox MB_OK|MB_ICONSTOP \
|
||||||
|
"HyperTwist registry ownership or the install marker is missing. The uninstaller will not delete an unverified directory." \
|
||||||
|
/SD IDOK
|
||||||
|
SetErrorLevel 30
|
||||||
|
Abort
|
||||||
|
|
||||||
|
uninstall_owned:
|
||||||
|
SetShellVarContext all
|
||||||
|
Delete "$DESKTOP\HyperTwist.lnk"
|
||||||
|
RMDir /r "$SMPROGRAMS\HyperTwist"
|
||||||
|
|
||||||
|
DeleteRegKey HKLM "${PRODUCT_UNINSTALL_KEY}"
|
||||||
|
DeleteRegKey HKLM "${PRODUCT_REG_KEY}"
|
||||||
|
DeleteRegKey /ifempty HKLM "Software\HyperTwist"
|
||||||
|
|
||||||
|
RMDir /r "$INSTDIR\Content"
|
||||||
|
RMDir /r "$INSTDIR\Engine"
|
||||||
|
RMDir /r "$INSTDIR\UnrealHyperTwist"
|
||||||
|
Delete "$INSTDIR\Manifest_DebugFiles_Win64.txt"
|
||||||
|
Delete "$INSTDIR\Manifest_NonUFSFiles_Win64.txt"
|
||||||
|
Delete "$INSTDIR\Manifest_UFSFiles_Win64.txt"
|
||||||
|
Delete "$INSTDIR\UnrealHyperTwist.exe"
|
||||||
|
Delete "$INSTDIR\Installer\payload-manifest.json"
|
||||||
|
Delete "$INSTDIR\Installer\Test-HyperTwistWindowsReadiness.ps1"
|
||||||
|
Delete "$INSTDIR\Installer\${INSTALL_MARKER}"
|
||||||
|
RMDir "$INSTDIR\Installer"
|
||||||
|
Delete "$INSTDIR\Uninstall HyperTwist.exe"
|
||||||
|
RMDir "$INSTDIR"
|
||||||
|
SectionEnd
|
||||||
464
scripts/Build-HyperTwistWindowsInstaller.ps1
Normal file
464
scripts/Build-HyperTwistWindowsInstaller.ps1
Normal file
|
|
@ -0,0 +1,464 @@
|
||||||
|
param(
|
||||||
|
[string]$PackageRoot = 'C:\HyperTwist_worktrees\phase10validate_packaged_alpha_release19_shipping_20260723',
|
||||||
|
[string]$OutputDirectory = 'C:\HyperTwist_worktrees\installer-release19-20260726',
|
||||||
|
[string]$InstallerFileName = 'HyperTwist-Alpha-Test-20260723-R19-Setup.exe',
|
||||||
|
[string]$ProductVersion = '0.19.0.0',
|
||||||
|
[string]$DisplayVersion = 'Alpha R19',
|
||||||
|
[string]$ReleaseId = '20260723-R19',
|
||||||
|
[string]$MakensisPath = 'C:\Program Files (x86)\NSIS\makensis.exe',
|
||||||
|
[string]$VcRedistPath = '',
|
||||||
|
[string]$ReportPath = '',
|
||||||
|
[switch]$KeepBuildContext
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$ExpectedSolverTableSizeBytes = 676207080
|
||||||
|
$ExpectedSolverTableSha256 = 'dc6de3d909a37afe2ba7f1f978543a13eae215bd20d954d66813524a8ca20034'
|
||||||
|
|
||||||
|
function Write-Utf8JsonFile {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Path,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[object]$Value
|
||||||
|
)
|
||||||
|
|
||||||
|
$ParentPath = Split-Path -Parent $Path
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($ParentPath))
|
||||||
|
{
|
||||||
|
New-Item -ItemType Directory -Force -Path $ParentPath | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$Json = $Value | ConvertTo-Json -Depth 12
|
||||||
|
$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||||||
|
[System.IO.File]::WriteAllText($Path, $Json, $Utf8NoBom)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Resolve-WindowsPayloadRoot {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RootPath
|
||||||
|
)
|
||||||
|
|
||||||
|
$ResolvedRootPath = (Resolve-Path -LiteralPath $RootPath).Path
|
||||||
|
$WindowsCandidate = Join-Path $ResolvedRootPath 'Windows'
|
||||||
|
if (Test-Path -LiteralPath (Join-Path $WindowsCandidate 'UnrealHyperTwist.exe') -PathType Leaf)
|
||||||
|
{
|
||||||
|
return $WindowsCandidate
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -LiteralPath (Join-Path $ResolvedRootPath 'UnrealHyperTwist.exe') -PathType Leaf)
|
||||||
|
{
|
||||||
|
return $ResolvedRootPath
|
||||||
|
}
|
||||||
|
|
||||||
|
throw "No packaged Windows payload was found beneath '$RootPath'."
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-NormalizedRelativePath {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RootPath,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$FilePath
|
||||||
|
)
|
||||||
|
|
||||||
|
$RootPrefix = $RootPath.TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
|
||||||
|
$ResolvedFilePath = [System.IO.Path]::GetFullPath($FilePath)
|
||||||
|
if (-not $ResolvedFilePath.StartsWith(
|
||||||
|
$RootPrefix,
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
throw "File '$ResolvedFilePath' is outside payload root '$RootPath'."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ResolvedFilePath.Substring($RootPrefix.Length).Replace('\', '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
function Assert-RequiredPayloadFile {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$PayloadRoot,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RelativePath,
|
||||||
|
[Int64]$ExpectedSizeBytes = -1,
|
||||||
|
[string]$ExpectedSha256 = ''
|
||||||
|
)
|
||||||
|
|
||||||
|
$RequiredPath = Join-Path $PayloadRoot $RelativePath
|
||||||
|
if (-not (Test-Path -LiteralPath $RequiredPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "Required payload file '$RelativePath' was not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
$RequiredItem = Get-Item -LiteralPath $RequiredPath
|
||||||
|
if ($RequiredItem.Length -le 0)
|
||||||
|
{
|
||||||
|
throw "Required payload file '$RelativePath' is empty."
|
||||||
|
}
|
||||||
|
if ($ExpectedSizeBytes -ge 0 -and $RequiredItem.Length -ne $ExpectedSizeBytes)
|
||||||
|
{
|
||||||
|
throw "Required payload file '$RelativePath' has an unexpected size."
|
||||||
|
}
|
||||||
|
|
||||||
|
$ActualSha256 = (Get-FileHash -LiteralPath $RequiredPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($ExpectedSha256) `
|
||||||
|
-and $ActualSha256 -ne $ExpectedSha256.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
throw "Required payload file '$RelativePath' has an unexpected SHA-256."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Resolve-VcRedistPath {
|
||||||
|
param(
|
||||||
|
[string]$RequestedPath
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($RequestedPath))
|
||||||
|
{
|
||||||
|
if (-not (Test-Path -LiteralPath $RequestedPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "Requested VC++ redistributable '$RequestedPath' was not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Resolve-Path -LiteralPath $RequestedPath).Path
|
||||||
|
}
|
||||||
|
|
||||||
|
$CandidateRoots = @(
|
||||||
|
'C:\Program Files\Epic Games\UE_5.7\Engine\Extras\Redist',
|
||||||
|
'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist',
|
||||||
|
'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Redist'
|
||||||
|
)
|
||||||
|
$Candidates = @(
|
||||||
|
foreach ($CandidateRoot in $CandidateRoots)
|
||||||
|
{
|
||||||
|
if (Test-Path -LiteralPath $CandidateRoot)
|
||||||
|
{
|
||||||
|
Get-ChildItem -LiteralPath $CandidateRoot `
|
||||||
|
-Filter 'vc_redist.x64.exe' `
|
||||||
|
-File `
|
||||||
|
-Recurse `
|
||||||
|
-ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$Candidate = $Candidates |
|
||||||
|
Sort-Object { [version]$_.VersionInfo.FileVersion } -Descending |
|
||||||
|
Select-Object -First 1
|
||||||
|
if ($null -eq $Candidate)
|
||||||
|
{
|
||||||
|
throw 'No Microsoft Visual C++ 2015-2022 x64 redistributable was found.'
|
||||||
|
}
|
||||||
|
|
||||||
|
return $Candidate.FullName
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $PackageRoot -PathType Container))
|
||||||
|
{
|
||||||
|
throw "Package root '$PackageRoot' was not found."
|
||||||
|
}
|
||||||
|
if (-not (Test-Path -LiteralPath $MakensisPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "NSIS compiler '$MakensisPath' was not found."
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$ParsedProductVersion = [version]$ProductVersion
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw "ProductVersion '$ProductVersion' is not a valid numeric Windows file version."
|
||||||
|
}
|
||||||
|
if ($ParsedProductVersion.Build -lt 0 -or $ParsedProductVersion.Revision -lt 0)
|
||||||
|
{
|
||||||
|
throw 'ProductVersion must contain exactly four numeric components.'
|
||||||
|
}
|
||||||
|
if ($InstallerFileName -ne [System.IO.Path]::GetFileName($InstallerFileName) `
|
||||||
|
-or [System.IO.Path]::GetExtension($InstallerFileName) -ne '.exe')
|
||||||
|
{
|
||||||
|
throw "InstallerFileName '$InstallerFileName' must be a leaf .exe filename."
|
||||||
|
}
|
||||||
|
foreach ($MetadataValue in @($DisplayVersion, $ReleaseId))
|
||||||
|
{
|
||||||
|
if ([string]::IsNullOrWhiteSpace($MetadataValue) `
|
||||||
|
-or $MetadataValue -notmatch '^[A-Za-z0-9][A-Za-z0-9 ._-]{0,63}$')
|
||||||
|
{
|
||||||
|
throw "Installer metadata value '$MetadataValue' contains unsupported characters or length."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResolvedPackageRoot = (Resolve-Path -LiteralPath $PackageRoot).Path
|
||||||
|
$ResolvedPayloadRoot = Resolve-WindowsPayloadRoot -RootPath $ResolvedPackageRoot
|
||||||
|
$ResolvedOutputDirectory = [System.IO.Path]::GetFullPath($OutputDirectory)
|
||||||
|
$ResolvedInstallerPath = Join-Path $ResolvedOutputDirectory $InstallerFileName
|
||||||
|
$PayloadRootPrefix = $ResolvedPayloadRoot.TrimEnd('\') + '\'
|
||||||
|
if ($ResolvedInstallerPath.StartsWith(
|
||||||
|
$PayloadRootPrefix,
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
throw 'Installer output must not be written inside its source payload.'
|
||||||
|
}
|
||||||
|
$RepositoryRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '..')).Path
|
||||||
|
$NsiScriptPath = Join-Path $RepositoryRoot 'packaging\windows\HyperTwistInstaller.nsi'
|
||||||
|
$ReadinessScriptPath = Join-Path $RepositoryRoot 'scripts\Test-HyperTwistWindowsReadiness.ps1'
|
||||||
|
if (-not (Test-Path -LiteralPath $NsiScriptPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "Installer definition '$NsiScriptPath' was not found."
|
||||||
|
}
|
||||||
|
if (-not (Test-Path -LiteralPath $ReadinessScriptPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "Readiness script '$ReadinessScriptPath' was not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResolvedVcRedistPath = Resolve-VcRedistPath -RequestedPath $VcRedistPath
|
||||||
|
$VcRedistSignature = Get-AuthenticodeSignature -LiteralPath $ResolvedVcRedistPath
|
||||||
|
if ($VcRedistSignature.Status -ne [System.Management.Automation.SignatureStatus]::Valid)
|
||||||
|
{
|
||||||
|
throw "VC++ redistributable '$ResolvedVcRedistPath' does not have a valid Authenticode signature."
|
||||||
|
}
|
||||||
|
|
||||||
|
$RequiredRelativePaths = @(
|
||||||
|
'UnrealHyperTwist.exe',
|
||||||
|
'UnrealHyperTwist\Binaries\Win64\UnrealHyperTwist-Win64-Shipping.exe',
|
||||||
|
'UnrealHyperTwist\Binaries\Win64\tbb12.dll',
|
||||||
|
'UnrealHyperTwist\Binaries\Win64\tbbmalloc.dll',
|
||||||
|
'UnrealHyperTwist\Content\Paks\UnrealHyperTwist-Windows.pak',
|
||||||
|
'UnrealHyperTwist\Content\Paks\UnrealHyperTwist-Windows.utoc',
|
||||||
|
'UnrealHyperTwist\Content\Paks\UnrealHyperTwist-Windows.ucas',
|
||||||
|
'Content\Browser\index.html',
|
||||||
|
'Content\Browser\src\browser-runtime-bootstrap.js',
|
||||||
|
'Content\Browser\src\browser-spatial-runtime-fallback.js',
|
||||||
|
'Content\Browser\dist\browser-spatial-runtime.js'
|
||||||
|
)
|
||||||
|
foreach ($RequiredRelativePath in $RequiredRelativePaths)
|
||||||
|
{
|
||||||
|
Assert-RequiredPayloadFile `
|
||||||
|
-PayloadRoot $ResolvedPayloadRoot `
|
||||||
|
-RelativePath $RequiredRelativePath
|
||||||
|
}
|
||||||
|
Assert-RequiredPayloadFile `
|
||||||
|
-PayloadRoot $ResolvedPayloadRoot `
|
||||||
|
-RelativePath 'UnrealHyperTwist\Saved\twophase-ht.tbl' `
|
||||||
|
-ExpectedSizeBytes $ExpectedSolverTableSizeBytes `
|
||||||
|
-ExpectedSha256 $ExpectedSolverTableSha256
|
||||||
|
|
||||||
|
$ReparsePoints = @(
|
||||||
|
Get-ChildItem -LiteralPath $ResolvedPayloadRoot -Force -Recurse |
|
||||||
|
Where-Object {
|
||||||
|
$_.Attributes -band [System.IO.FileAttributes]::ReparsePoint
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if ($ReparsePoints.Count -gt 0)
|
||||||
|
{
|
||||||
|
throw (
|
||||||
|
"The payload contains reparse points, which are not permitted in an installer source: " +
|
||||||
|
(($ReparsePoints | Select-Object -ExpandProperty FullName) -join ', ')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Force -Path $ResolvedOutputDirectory | Out-Null
|
||||||
|
$ValidationDirectory = Join-Path $ResolvedOutputDirectory 'validation'
|
||||||
|
$BuildContextDirectory = Join-Path $ResolvedOutputDirectory 'build-context'
|
||||||
|
New-Item -ItemType Directory -Force -Path $ValidationDirectory | Out-Null
|
||||||
|
if (Test-Path -LiteralPath $BuildContextDirectory)
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $BuildContextDirectory -Recurse -Force
|
||||||
|
}
|
||||||
|
New-Item -ItemType Directory -Force -Path $BuildContextDirectory | Out-Null
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($ReportPath))
|
||||||
|
{
|
||||||
|
$ReportPath = Join-Path $ValidationDirectory 'windows-installer-build-report.json'
|
||||||
|
}
|
||||||
|
$PayloadManifestPath = Join-Path $ValidationDirectory 'windows-installer-payload-manifest.json'
|
||||||
|
$SourceReadinessReportPath = Join-Path $ValidationDirectory 'windows-installer-source-readiness-report.json'
|
||||||
|
$MakensisLogPath = Join-Path $ValidationDirectory 'makensis.log'
|
||||||
|
$InstallerIconPath = Join-Path $BuildContextDirectory 'HyperTwist.ico'
|
||||||
|
|
||||||
|
$BuildReport = [ordered]@{
|
||||||
|
reportVersion = 'ht-windows-installer-build/v1'
|
||||||
|
generatedAtUtc = [DateTime]::UtcNow.ToString('o')
|
||||||
|
result = 'failed'
|
||||||
|
releaseId = $ReleaseId
|
||||||
|
displayVersion = $DisplayVersion
|
||||||
|
productVersion = $ProductVersion
|
||||||
|
packageRoot = $ResolvedPackageRoot
|
||||||
|
payloadRoot = $ResolvedPayloadRoot
|
||||||
|
installerPath = $ResolvedInstallerPath
|
||||||
|
payloadManifestPath = $PayloadManifestPath
|
||||||
|
sourceReadinessReportPath = $SourceReadinessReportPath
|
||||||
|
makensisPath = (Resolve-Path -LiteralPath $MakensisPath).Path
|
||||||
|
makensisLogPath = $MakensisLogPath
|
||||||
|
vcRedist = $null
|
||||||
|
excludedPatterns = @('*.pdb', 'Manifest_DebugFiles_Win64.txt')
|
||||||
|
payloadFileCount = 0
|
||||||
|
payloadSizeBytes = 0
|
||||||
|
installerSizeBytes = 0
|
||||||
|
installerSha256 = $null
|
||||||
|
installerSignatureStatus = $null
|
||||||
|
incompleteInstallerRemoved = $false
|
||||||
|
error = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$VcRedistItem = Get-Item -LiteralPath $ResolvedVcRedistPath
|
||||||
|
$BuildReport.vcRedist = [pscustomobject][ordered]@{
|
||||||
|
path = $ResolvedVcRedistPath
|
||||||
|
version = [string]$VcRedistItem.VersionInfo.FileVersion
|
||||||
|
sizeBytes = [Int64]$VcRedistItem.Length
|
||||||
|
sha256 = (Get-FileHash -LiteralPath $ResolvedVcRedistPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
signatureStatus = $VcRedistSignature.Status.ToString()
|
||||||
|
signer = [string]$VcRedistSignature.SignerCertificate.Subject
|
||||||
|
}
|
||||||
|
|
||||||
|
$PayloadFiles = @(
|
||||||
|
Get-ChildItem -LiteralPath $ResolvedPayloadRoot -Force -File -Recurse |
|
||||||
|
Where-Object {
|
||||||
|
$_.Extension -ne '.pdb' `
|
||||||
|
-and $_.Name -ne 'Manifest_DebugFiles_Win64.txt'
|
||||||
|
} |
|
||||||
|
Sort-Object FullName
|
||||||
|
)
|
||||||
|
$PayloadManifestEntries = @(
|
||||||
|
foreach ($PayloadFile in $PayloadFiles)
|
||||||
|
{
|
||||||
|
[pscustomobject][ordered]@{
|
||||||
|
relativePath = Get-NormalizedRelativePath `
|
||||||
|
-RootPath $ResolvedPayloadRoot `
|
||||||
|
-FilePath $PayloadFile.FullName
|
||||||
|
sizeBytes = [Int64]$PayloadFile.Length
|
||||||
|
sha256 = (Get-FileHash -LiteralPath $PayloadFile.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$PayloadSizeBytes = [Int64](($PayloadFiles | Measure-Object Length -Sum).Sum)
|
||||||
|
$PayloadManifest = [pscustomobject][ordered]@{
|
||||||
|
manifestVersion = 'ht-windows-installer-payload/v1'
|
||||||
|
generatedAtUtc = [DateTime]::UtcNow.ToString('o')
|
||||||
|
releaseId = $ReleaseId
|
||||||
|
sourcePayloadRoot = $ResolvedPayloadRoot
|
||||||
|
excludedPatterns = @('*.pdb', 'Manifest_DebugFiles_Win64.txt')
|
||||||
|
fileCount = $PayloadManifestEntries.Count
|
||||||
|
totalSizeBytes = $PayloadSizeBytes
|
||||||
|
files = $PayloadManifestEntries
|
||||||
|
}
|
||||||
|
Write-Utf8JsonFile -Path $PayloadManifestPath -Value $PayloadManifest
|
||||||
|
$BuildReport.payloadFileCount = $PayloadManifestEntries.Count
|
||||||
|
$BuildReport.payloadSizeBytes = $PayloadSizeBytes
|
||||||
|
|
||||||
|
$ReadinessReport = & $ReadinessScriptPath `
|
||||||
|
-PayloadRoot $ResolvedPayloadRoot `
|
||||||
|
-TargetInstallRoot (Join-Path ([Environment]::GetFolderPath('ProgramFiles')) 'HyperTwist') `
|
||||||
|
-ExpectedPayloadManifestPath $PayloadManifestPath `
|
||||||
|
-ReportPath $SourceReadinessReportPath `
|
||||||
|
-VerifyPayloadHashes `
|
||||||
|
-PassThru
|
||||||
|
if ($ReadinessReport.result -eq 'blocked')
|
||||||
|
{
|
||||||
|
throw 'Source payload or Windows host readiness is blocked.'
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Type -AssemblyName System.Drawing
|
||||||
|
$PayloadExecutablePath = Join-Path $ResolvedPayloadRoot 'UnrealHyperTwist.exe'
|
||||||
|
$InstallerIcon = [System.Drawing.Icon]::ExtractAssociatedIcon($PayloadExecutablePath)
|
||||||
|
if ($null -eq $InstallerIcon)
|
||||||
|
{
|
||||||
|
throw "No application icon could be extracted from '$PayloadExecutablePath'."
|
||||||
|
}
|
||||||
|
$IconStream = [System.IO.File]::Open(
|
||||||
|
$InstallerIconPath,
|
||||||
|
[System.IO.FileMode]::Create,
|
||||||
|
[System.IO.FileAccess]::Write,
|
||||||
|
[System.IO.FileShare]::None
|
||||||
|
)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$InstallerIcon.Save($IconStream)
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
$IconStream.Dispose()
|
||||||
|
$InstallerIcon.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -LiteralPath $ResolvedInstallerPath)
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $ResolvedInstallerPath -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
$PayloadSizeKilobytes = [Math]::Ceiling($PayloadSizeBytes / 1KB)
|
||||||
|
$MakensisArguments = @(
|
||||||
|
'/V4',
|
||||||
|
"/DPRODUCT_VERSION=$ProductVersion",
|
||||||
|
"/DDISPLAY_VERSION=$DisplayVersion",
|
||||||
|
"/DRELEASE_ID=$ReleaseId",
|
||||||
|
"/DOUTPUT_FILE=$ResolvedInstallerPath",
|
||||||
|
"/DPAYLOAD_ROOT=$ResolvedPayloadRoot",
|
||||||
|
"/DPAYLOAD_MANIFEST=$PayloadManifestPath",
|
||||||
|
"/DREADINESS_SCRIPT=$ReadinessScriptPath",
|
||||||
|
"/DVC_REDIST_PATH=$ResolvedVcRedistPath",
|
||||||
|
"/DINSTALLER_ICON=$InstallerIconPath",
|
||||||
|
"/DPAYLOAD_SIZE_KB=$PayloadSizeKilobytes",
|
||||||
|
$NsiScriptPath
|
||||||
|
)
|
||||||
|
|
||||||
|
$MakensisOutput = @(
|
||||||
|
& $MakensisPath @MakensisArguments 2>&1 |
|
||||||
|
ForEach-Object {
|
||||||
|
$Line = $_.ToString()
|
||||||
|
[Console]::Out.WriteLine($Line)
|
||||||
|
$Line
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$MakensisExitCode = $LASTEXITCODE
|
||||||
|
[System.IO.File]::WriteAllLines(
|
||||||
|
$MakensisLogPath,
|
||||||
|
$MakensisOutput,
|
||||||
|
(New-Object System.Text.UTF8Encoding($false))
|
||||||
|
)
|
||||||
|
if ($MakensisExitCode -ne 0)
|
||||||
|
{
|
||||||
|
throw "NSIS compilation failed with exit code $MakensisExitCode."
|
||||||
|
}
|
||||||
|
if (-not (Test-Path -LiteralPath $ResolvedInstallerPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "NSIS did not create '$ResolvedInstallerPath'."
|
||||||
|
}
|
||||||
|
|
||||||
|
$InstallerItem = Get-Item -LiteralPath $ResolvedInstallerPath
|
||||||
|
if ($InstallerItem.Length -le 0)
|
||||||
|
{
|
||||||
|
throw 'The generated installer is empty.'
|
||||||
|
}
|
||||||
|
$InstallerSignature = Get-AuthenticodeSignature -LiteralPath $ResolvedInstallerPath
|
||||||
|
$BuildReport.installerSizeBytes = [Int64]$InstallerItem.Length
|
||||||
|
$BuildReport.installerSha256 = (Get-FileHash -LiteralPath $ResolvedInstallerPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
$BuildReport.installerSignatureStatus = $InstallerSignature.Status.ToString()
|
||||||
|
$BuildReport.result = 'passed'
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
$BuildReport.error = $_.Exception.Message
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if ($BuildReport.result -ne 'passed' `
|
||||||
|
-and (Test-Path -LiteralPath $ResolvedInstallerPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $ResolvedInstallerPath -Force
|
||||||
|
$BuildReport.incompleteInstallerRemoved = $true
|
||||||
|
}
|
||||||
|
Write-Utf8JsonFile -Path $ReportPath -Value $BuildReport
|
||||||
|
if (-not $KeepBuildContext -and (Test-Path -LiteralPath $BuildContextDirectory))
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $BuildContextDirectory -Recurse -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Console]::Out.WriteLine('HyperTwist Windows installer built successfully.')
|
||||||
|
[Console]::Out.WriteLine("Installer: $ResolvedInstallerPath")
|
||||||
|
[Console]::Out.WriteLine("SHA-256: $($BuildReport.installerSha256)")
|
||||||
|
[Console]::Out.WriteLine("Report: $([System.IO.Path]::GetFullPath($ReportPath))")
|
||||||
707
scripts/Test-HyperTwistWindowsInstaller.ps1
Normal file
707
scripts/Test-HyperTwistWindowsInstaller.ps1
Normal file
|
|
@ -0,0 +1,707 @@
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$InstallerPath,
|
||||||
|
[string]$ValidationRoot = 'C:\HyperTwistInstallerValidation',
|
||||||
|
[string]$ReportPath = '',
|
||||||
|
[int]$LaunchSmokeSeconds = 20,
|
||||||
|
[switch]$KeepInstalled
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
function Write-Utf8JsonFile {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Path,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[object]$Value
|
||||||
|
)
|
||||||
|
|
||||||
|
$ParentPath = Split-Path -Parent $Path
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($ParentPath))
|
||||||
|
{
|
||||||
|
New-Item -ItemType Directory -Force -Path $ParentPath | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$Json = $Value | ConvertTo-Json -Depth 12
|
||||||
|
$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||||||
|
[System.IO.File]::WriteAllText($Path, $Json, $Utf8NoBom)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-InstallerProcess {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ExecutablePath,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string[]]$Arguments,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Label
|
||||||
|
)
|
||||||
|
|
||||||
|
$Process = Start-Process `
|
||||||
|
-FilePath $ExecutablePath `
|
||||||
|
-ArgumentList $Arguments `
|
||||||
|
-PassThru `
|
||||||
|
-Wait
|
||||||
|
if ($Process.ExitCode -notin @(0, 3010))
|
||||||
|
{
|
||||||
|
throw "$Label failed with exit code $($Process.ExitCode)."
|
||||||
|
}
|
||||||
|
|
||||||
|
return [int]$Process.ExitCode
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-InstallerProcessForExitCode {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ExecutablePath,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string[]]$Arguments
|
||||||
|
)
|
||||||
|
|
||||||
|
$Process = Start-Process `
|
||||||
|
-FilePath $ExecutablePath `
|
||||||
|
-ArgumentList $Arguments `
|
||||||
|
-PassThru `
|
||||||
|
-Wait
|
||||||
|
return [int]$Process.ExitCode
|
||||||
|
}
|
||||||
|
|
||||||
|
function Resolve-PayloadRelativeFilePath {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RootPath,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RelativePath
|
||||||
|
)
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($RelativePath))
|
||||||
|
{
|
||||||
|
throw 'A payload-relative path cannot be empty.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$WindowsRelativePath = $RelativePath.Replace('/', '\')
|
||||||
|
if ([System.IO.Path]::IsPathRooted($WindowsRelativePath))
|
||||||
|
{
|
||||||
|
throw "Payload-relative path '$RelativePath' must not be rooted."
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResolvedRootPath = [System.IO.Path]::GetFullPath($RootPath)
|
||||||
|
$RootPrefix = $ResolvedRootPath.TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
|
||||||
|
$ResolvedFilePath = [System.IO.Path]::GetFullPath(
|
||||||
|
(Join-Path $ResolvedRootPath $WindowsRelativePath)
|
||||||
|
)
|
||||||
|
if (-not $ResolvedFilePath.StartsWith(
|
||||||
|
$RootPrefix,
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
throw "Payload-relative path '$RelativePath' escapes root '$RootPath'."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ResolvedFilePath
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-PayloadManifest {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$InstallRoot,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ManifestPath
|
||||||
|
)
|
||||||
|
|
||||||
|
$Manifest = Get-Content -LiteralPath $ManifestPath -Raw | ConvertFrom-Json
|
||||||
|
$Failures = New-Object System.Collections.ArrayList
|
||||||
|
$ExpectedPaths = @{}
|
||||||
|
foreach ($Entry in @($Manifest.files))
|
||||||
|
{
|
||||||
|
$EntryRelativePath = [string]$Entry.relativePath
|
||||||
|
$EntryPathKey = $EntryRelativePath.Replace('\', '/').ToLowerInvariant()
|
||||||
|
if ($ExpectedPaths.ContainsKey($EntryPathKey))
|
||||||
|
{
|
||||||
|
[void]$Failures.Add("duplicate:$EntryRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$ExpectedPaths[$EntryPathKey] = $true
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$InstalledPath = Resolve-PayloadRelativeFilePath `
|
||||||
|
-RootPath $InstallRoot `
|
||||||
|
-RelativePath $EntryRelativePath
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
[void]$Failures.Add("invalid-path:$EntryRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $InstalledPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
[void]$Failures.Add("missing:$EntryRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$InstalledItem = Get-Item -LiteralPath $InstalledPath
|
||||||
|
if ($InstalledItem.Length -ne [Int64]$Entry.sizeBytes)
|
||||||
|
{
|
||||||
|
[void]$Failures.Add("size:$EntryRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$InstalledHash = (Get-FileHash -LiteralPath $InstalledPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
if ($InstalledHash -ne ([string]$Entry.sha256).ToLowerInvariant())
|
||||||
|
{
|
||||||
|
[void]$Failures.Add("sha256:$EntryRelativePath")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$AllowedInstallerPaths = @{}
|
||||||
|
@(
|
||||||
|
'Installer/payload-manifest.json',
|
||||||
|
'Installer/Test-HyperTwistWindowsReadiness.ps1',
|
||||||
|
'Installer/HyperTwist.install-marker',
|
||||||
|
'Uninstall HyperTwist.exe'
|
||||||
|
) | ForEach-Object { $AllowedInstallerPaths[$_.ToLowerInvariant()] = $true }
|
||||||
|
$InstallRootPrefix = [System.IO.Path]::GetFullPath($InstallRoot).TrimEnd('\') + '\'
|
||||||
|
$UnexpectedFiles = @(
|
||||||
|
Get-ChildItem -LiteralPath $InstallRoot -File -Force -Recurse |
|
||||||
|
ForEach-Object {
|
||||||
|
$RelativePath = $_.FullName.Substring($InstallRootPrefix.Length).Replace('\', '/')
|
||||||
|
$RelativePathKey = $RelativePath.ToLowerInvariant()
|
||||||
|
if (-not $ExpectedPaths.ContainsKey($RelativePathKey) `
|
||||||
|
-and -not $AllowedInstallerPaths.ContainsKey($RelativePathKey))
|
||||||
|
{
|
||||||
|
$RelativePath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$UnexpectedPdbFiles = @(
|
||||||
|
Get-ChildItem -LiteralPath $InstallRoot -Filter '*.pdb' -File -Recurse -ErrorAction SilentlyContinue
|
||||||
|
)
|
||||||
|
return [pscustomobject][ordered]@{
|
||||||
|
passed = $Failures.Count -eq 0 `
|
||||||
|
-and $UnexpectedPdbFiles.Count -eq 0 `
|
||||||
|
-and $UnexpectedFiles.Count -eq 0
|
||||||
|
manifestEntryCount = @($Manifest.files).Count
|
||||||
|
failureCount = $Failures.Count
|
||||||
|
failures = @($Failures)
|
||||||
|
unexpectedFiles = $UnexpectedFiles
|
||||||
|
unexpectedPdbFiles = @($UnexpectedPdbFiles | Select-Object -ExpandProperty FullName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-OwnedProcessRecords {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$InstallRoot
|
||||||
|
)
|
||||||
|
|
||||||
|
$InstallPrefix = $InstallRoot.TrimEnd('\') + '\'
|
||||||
|
return @(
|
||||||
|
Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object {
|
||||||
|
-not [string]::IsNullOrWhiteSpace([string]$_.ExecutablePath) `
|
||||||
|
-and ([string]$_.ExecutablePath).StartsWith(
|
||||||
|
$InstallPrefix,
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Stop-OwnedProcesses {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$InstallRoot
|
||||||
|
)
|
||||||
|
|
||||||
|
$StoppedProcessIds = New-Object 'System.Collections.Generic.HashSet[int]'
|
||||||
|
for ($Attempt = 0; $Attempt -lt 8; $Attempt += 1)
|
||||||
|
{
|
||||||
|
$OwnedProcesses = @(Get-OwnedProcessRecords -InstallRoot $InstallRoot)
|
||||||
|
if ($OwnedProcesses.Count -eq 0)
|
||||||
|
{
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($OwnedProcess in $OwnedProcesses)
|
||||||
|
{
|
||||||
|
Stop-Process -Id ([int]$OwnedProcess.ProcessId) -Force -ErrorAction SilentlyContinue
|
||||||
|
[void]$StoppedProcessIds.Add([int]$OwnedProcess.ProcessId)
|
||||||
|
}
|
||||||
|
Start-Sleep -Milliseconds 250
|
||||||
|
}
|
||||||
|
|
||||||
|
return @($StoppedProcessIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-InstalledLaunchSmoke {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$InstallRoot,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$EvidenceDirectory,
|
||||||
|
[int]$SmokeSeconds
|
||||||
|
)
|
||||||
|
|
||||||
|
$ExecutablePath = Join-Path $InstallRoot 'UnrealHyperTwist.exe'
|
||||||
|
$RuntimeLogPath = Join-Path $EvidenceDirectory 'installed-runtime.log'
|
||||||
|
$DiagnosticsPath = Join-Path $EvidenceDirectory 'installed-runtime.hyperdiagnostics.log'
|
||||||
|
$UserDirectory = Join-Path $EvidenceDirectory 'isolated-user'
|
||||||
|
New-Item -ItemType Directory -Force -Path $UserDirectory | Out-Null
|
||||||
|
|
||||||
|
$Arguments = @(
|
||||||
|
'-NullRHI',
|
||||||
|
'-nosound',
|
||||||
|
'-windowed',
|
||||||
|
'-ResX=1280',
|
||||||
|
'-ResY=720',
|
||||||
|
'-log',
|
||||||
|
'-FORCELOGFLUSH',
|
||||||
|
"-abslog=$RuntimeLogPath",
|
||||||
|
"-HyperTwistDiagnosticsLog=`"$DiagnosticsPath`"",
|
||||||
|
"-UserDir=`"$UserDirectory`""
|
||||||
|
)
|
||||||
|
$StartedAtUtc = [DateTime]::UtcNow
|
||||||
|
$LaunchProcess = Start-Process `
|
||||||
|
-FilePath $ExecutablePath `
|
||||||
|
-ArgumentList $Arguments `
|
||||||
|
-PassThru
|
||||||
|
Start-Sleep -Seconds $SmokeSeconds
|
||||||
|
|
||||||
|
$OwnedProcesses = @(Get-OwnedProcessRecords -InstallRoot $InstallRoot)
|
||||||
|
$OwnedProcessIds = @($OwnedProcesses | Select-Object -ExpandProperty ProcessId)
|
||||||
|
$ListeningEndpoints = @(
|
||||||
|
if ($OwnedProcessIds.Count -gt 0)
|
||||||
|
{
|
||||||
|
Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $OwnedProcessIds -contains [int]$_.OwningProcess } |
|
||||||
|
ForEach-Object {
|
||||||
|
[pscustomobject][ordered]@{
|
||||||
|
processId = [int]$_.OwningProcess
|
||||||
|
localAddress = [string]$_.LocalAddress
|
||||||
|
localPort = [int]$_.LocalPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$FatalPatterns = @(
|
||||||
|
'Fatal error:',
|
||||||
|
'LowLevelFatalError',
|
||||||
|
'Assertion failed:',
|
||||||
|
'Critical error:',
|
||||||
|
'Unhandled Exception:',
|
||||||
|
'StaticShutdownAfterError'
|
||||||
|
)
|
||||||
|
$RuntimeLines = @(
|
||||||
|
if (Test-Path -LiteralPath $RuntimeLogPath)
|
||||||
|
{
|
||||||
|
Get-Content -LiteralPath $RuntimeLogPath
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$DiagnosticsLines = @(
|
||||||
|
if (Test-Path -LiteralPath $DiagnosticsPath)
|
||||||
|
{
|
||||||
|
Get-Content -LiteralPath $DiagnosticsPath
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$FatalLines = @(
|
||||||
|
@($RuntimeLines + $DiagnosticsLines) |
|
||||||
|
Where-Object {
|
||||||
|
$Line = $_.ToString()
|
||||||
|
@($FatalPatterns | Where-Object { $Line -like "*$_*" }).Count -gt 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$Initialized = @(
|
||||||
|
$DiagnosticsLines |
|
||||||
|
Where-Object {
|
||||||
|
$_.ToString().IndexOf(
|
||||||
|
'[Process] HyperTwist runtime module initialized.',
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase
|
||||||
|
) -ge 0
|
||||||
|
}
|
||||||
|
).Count -gt 0
|
||||||
|
|
||||||
|
$StoppedProcessIds = @(Stop-OwnedProcesses -InstallRoot $InstallRoot)
|
||||||
|
$Passed = $OwnedProcessIds.Count -gt 0 `
|
||||||
|
-and (Test-Path -LiteralPath $DiagnosticsPath -PathType Leaf) `
|
||||||
|
-and $Initialized `
|
||||||
|
-and $FatalLines.Count -eq 0 `
|
||||||
|
-and @($ListeningEndpoints | Where-Object { $_.localPort -eq 1985 }).Count -eq 0
|
||||||
|
return [pscustomobject][ordered]@{
|
||||||
|
passed = $Passed
|
||||||
|
startedAtUtc = $StartedAtUtc.ToString('o')
|
||||||
|
launcherProcessId = [int]$LaunchProcess.Id
|
||||||
|
ownedProcessIds = $OwnedProcessIds
|
||||||
|
stoppedProcessIds = $StoppedProcessIds
|
||||||
|
runtimeLogPath = $RuntimeLogPath
|
||||||
|
diagnosticsPath = $DiagnosticsPath
|
||||||
|
diagnosticsInitialized = $Initialized
|
||||||
|
fatalLines = $FatalLines
|
||||||
|
listeningEndpoints = $ListeningEndpoints
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-ShortcutEvidence {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $Path -PathType Leaf))
|
||||||
|
{
|
||||||
|
return [pscustomobject][ordered]@{
|
||||||
|
path = $Path
|
||||||
|
exists = $false
|
||||||
|
targetPath = $null
|
||||||
|
arguments = $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Shell = New-Object -ComObject WScript.Shell
|
||||||
|
$Shortcut = $null
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$Shortcut = $Shell.CreateShortcut($Path)
|
||||||
|
return [pscustomobject][ordered]@{
|
||||||
|
path = $Path
|
||||||
|
exists = $true
|
||||||
|
targetPath = [string]$Shortcut.TargetPath
|
||||||
|
arguments = [string]$Shortcut.Arguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if ($null -ne $Shortcut)
|
||||||
|
{
|
||||||
|
[void][System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($Shortcut)
|
||||||
|
}
|
||||||
|
[void][System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($Shell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$CurrentIdentity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||||
|
$CurrentPrincipal = New-Object Security.Principal.WindowsPrincipal($CurrentIdentity)
|
||||||
|
if (-not $CurrentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
|
||||||
|
{
|
||||||
|
throw 'Installer lifecycle validation requires an elevated Windows session.'
|
||||||
|
}
|
||||||
|
if (-not (Test-Path -LiteralPath $InstallerPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "Installer '$InstallerPath' was not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResolvedInstallerPath = (Resolve-Path -LiteralPath $InstallerPath).Path
|
||||||
|
$ResolvedValidationRoot = [System.IO.Path]::GetFullPath($ValidationRoot)
|
||||||
|
$RunId = [DateTime]::UtcNow.ToString('yyyyMMddTHHmmssZ')
|
||||||
|
$RunDirectory = Join-Path $ResolvedValidationRoot $RunId
|
||||||
|
$InstallRoot = Join-Path $RunDirectory 'HyperTwist'
|
||||||
|
$EvidenceDirectory = Join-Path $RunDirectory 'evidence'
|
||||||
|
New-Item -ItemType Directory -Force -Path $EvidenceDirectory | Out-Null
|
||||||
|
if ([string]::IsNullOrWhiteSpace($ReportPath))
|
||||||
|
{
|
||||||
|
$ReportPath = Join-Path $EvidenceDirectory 'windows-installer-lifecycle-report.json'
|
||||||
|
}
|
||||||
|
|
||||||
|
$RepositoryRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '..')).Path
|
||||||
|
$ReadinessScriptPath = Join-Path $RepositoryRoot 'scripts\Test-HyperTwistWindowsReadiness.ps1'
|
||||||
|
$UninstallRegistryPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\HyperTwist'
|
||||||
|
$ProductRegistryPath = 'HKLM:\SOFTWARE\HyperTwist\HyperTwist'
|
||||||
|
$CommonProgramsPath = [Environment]::GetFolderPath('CommonPrograms')
|
||||||
|
$CommonDesktopPath = [Environment]::GetFolderPath('CommonDesktopDirectory')
|
||||||
|
$StartMenuDirectory = Join-Path $CommonProgramsPath 'HyperTwist'
|
||||||
|
$DesktopShortcutPath = Join-Path $CommonDesktopPath 'HyperTwist.lnk'
|
||||||
|
|
||||||
|
if (Test-Path -LiteralPath $UninstallRegistryPath)
|
||||||
|
{
|
||||||
|
throw 'A registered HyperTwist installation already exists; validation will not replace it.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$InstallerItem = Get-Item -LiteralPath $ResolvedInstallerPath
|
||||||
|
$Report = [ordered]@{
|
||||||
|
reportVersion = 'ht-windows-installer-lifecycle/v1'
|
||||||
|
generatedAtUtc = [DateTime]::UtcNow.ToString('o')
|
||||||
|
result = 'failed'
|
||||||
|
validationClass = 'isolated-current-host'
|
||||||
|
cleanMachineAvailable = $false
|
||||||
|
cleanMachineBoundary = 'No Windows Sandbox, clean Hyper-V VM, or base VHD was available on the validation host.'
|
||||||
|
installerPath = $ResolvedInstallerPath
|
||||||
|
installerSizeBytes = [Int64]$InstallerItem.Length
|
||||||
|
installerSha256 = (Get-FileHash -LiteralPath $ResolvedInstallerPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
installerSignatureStatus = (Get-AuthenticodeSignature -LiteralPath $ResolvedInstallerPath).Status.ToString()
|
||||||
|
installRoot = $InstallRoot
|
||||||
|
unownedNonEmptyRefusal = $null
|
||||||
|
firstInstallExitCode = $null
|
||||||
|
upgradeInstallExitCode = $null
|
||||||
|
payloadParityAfterFirstInstall = $null
|
||||||
|
payloadParityAfterUpgrade = $null
|
||||||
|
readiness = $null
|
||||||
|
launchSmoke = $null
|
||||||
|
uninstallExitCode = $null
|
||||||
|
registrationVerified = $false
|
||||||
|
shortcutsVerified = $false
|
||||||
|
shortcutDetails = $null
|
||||||
|
userDataPreserved = $false
|
||||||
|
installRootRemoved = $false
|
||||||
|
registrationRemoved = $false
|
||||||
|
shortcutsRemoved = $false
|
||||||
|
cleanupCompleted = $false
|
||||||
|
error = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
$UninstallerPath = Join-Path $InstallRoot 'Uninstall HyperTwist.exe'
|
||||||
|
$SentinelDirectory = Join-Path $env:LOCALAPPDATA 'UnrealHyperTwist\Saved\InstallerValidation'
|
||||||
|
$SentinelPath = Join-Path $SentinelDirectory "$RunId.txt"
|
||||||
|
$Installed = $false
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
||||||
|
$UnownedSentinelPath = Join-Path $InstallRoot 'unrelated-owner-sentinel.txt'
|
||||||
|
[System.IO.File]::WriteAllText(
|
||||||
|
$UnownedSentinelPath,
|
||||||
|
"Unowned install-root refusal sentinel $RunId",
|
||||||
|
(New-Object System.Text.UTF8Encoding($false))
|
||||||
|
)
|
||||||
|
$UnownedRefusalExitCode = Invoke-InstallerProcessForExitCode `
|
||||||
|
-ExecutablePath $ResolvedInstallerPath `
|
||||||
|
-Arguments @('/S', "/D=$InstallRoot")
|
||||||
|
if ($UnownedRefusalExitCode -eq 0)
|
||||||
|
{
|
||||||
|
$Installed = Test-Path -LiteralPath $UninstallerPath -PathType Leaf
|
||||||
|
}
|
||||||
|
$Report.unownedNonEmptyRefusal = [pscustomobject][ordered]@{
|
||||||
|
passed = $UnownedRefusalExitCode -eq 14 `
|
||||||
|
-and (Test-Path -LiteralPath $UnownedSentinelPath -PathType Leaf) `
|
||||||
|
-and -not (Test-Path -LiteralPath $UninstallRegistryPath) `
|
||||||
|
-and -not (Test-Path -LiteralPath $ProductRegistryPath)
|
||||||
|
exitCode = $UnownedRefusalExitCode
|
||||||
|
expectedExitCode = 14
|
||||||
|
sentinelPreserved = Test-Path -LiteralPath $UnownedSentinelPath -PathType Leaf
|
||||||
|
registrationAbsent = `
|
||||||
|
-not (Test-Path -LiteralPath $UninstallRegistryPath) `
|
||||||
|
-and -not (Test-Path -LiteralPath $ProductRegistryPath)
|
||||||
|
}
|
||||||
|
if (-not $Report.unownedNonEmptyRefusal.passed)
|
||||||
|
{
|
||||||
|
throw 'The installer did not safely refuse an unowned non-empty installation root.'
|
||||||
|
}
|
||||||
|
Remove-Item -LiteralPath $InstallRoot -Recurse -Force
|
||||||
|
|
||||||
|
$Report.firstInstallExitCode = Invoke-InstallerProcess `
|
||||||
|
-ExecutablePath $ResolvedInstallerPath `
|
||||||
|
-Arguments @('/S', "/D=$InstallRoot") `
|
||||||
|
-Label 'Silent installer'
|
||||||
|
$Installed = $true
|
||||||
|
|
||||||
|
$ManifestPath = Join-Path $InstallRoot 'Installer\payload-manifest.json'
|
||||||
|
if (-not (Test-Path -LiteralPath $ManifestPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw 'The installed payload manifest is missing.'
|
||||||
|
}
|
||||||
|
$Report.payloadParityAfterFirstInstall = Test-PayloadManifest `
|
||||||
|
-InstallRoot $InstallRoot `
|
||||||
|
-ManifestPath $ManifestPath
|
||||||
|
if (-not $Report.payloadParityAfterFirstInstall.passed)
|
||||||
|
{
|
||||||
|
throw 'Installed payload parity failed after first install.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$RegisteredProduct = Get-ItemProperty -LiteralPath $UninstallRegistryPath
|
||||||
|
$RegisteredOwner = Get-ItemProperty -LiteralPath $ProductRegistryPath
|
||||||
|
$Report.registrationVerified = `
|
||||||
|
[System.IO.Path]::GetFullPath([string]$RegisteredProduct.InstallLocation) -eq $InstallRoot `
|
||||||
|
-and [System.IO.Path]::GetFullPath([string]$RegisteredOwner.InstallLocation) -eq $InstallRoot
|
||||||
|
if (-not $Report.registrationVerified)
|
||||||
|
{
|
||||||
|
throw 'Add/Remove Programs or product registration does not match the isolated install root.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$ExpectedApplicationPath = Join-Path $InstallRoot 'UnrealHyperTwist.exe'
|
||||||
|
$ExpectedReadinessScriptPath = Join-Path $InstallRoot 'Installer\Test-HyperTwistWindowsReadiness.ps1'
|
||||||
|
$ExpectedManifestPath = Join-Path $InstallRoot 'Installer\payload-manifest.json'
|
||||||
|
$ExpectedUninstallerPath = Join-Path $InstallRoot 'Uninstall HyperTwist.exe'
|
||||||
|
$ApplicationShortcut = Get-ShortcutEvidence `
|
||||||
|
-Path (Join-Path $StartMenuDirectory 'HyperTwist.lnk')
|
||||||
|
$ReadinessShortcut = Get-ShortcutEvidence `
|
||||||
|
-Path (Join-Path $StartMenuDirectory 'System Readiness Report.lnk')
|
||||||
|
$UninstallShortcut = Get-ShortcutEvidence `
|
||||||
|
-Path (Join-Path $StartMenuDirectory 'Uninstall HyperTwist.lnk')
|
||||||
|
$DesktopShortcut = Get-ShortcutEvidence -Path $DesktopShortcutPath
|
||||||
|
$Report.shortcutDetails = [pscustomobject][ordered]@{
|
||||||
|
application = $ApplicationShortcut
|
||||||
|
readiness = $ReadinessShortcut
|
||||||
|
uninstall = $UninstallShortcut
|
||||||
|
desktop = $DesktopShortcut
|
||||||
|
}
|
||||||
|
$Report.shortcutsVerified = `
|
||||||
|
$ApplicationShortcut.exists `
|
||||||
|
-and $ApplicationShortcut.targetPath -eq $ExpectedApplicationPath `
|
||||||
|
-and $ReadinessShortcut.exists `
|
||||||
|
-and $ReadinessShortcut.targetPath.EndsWith(
|
||||||
|
'\WindowsPowerShell\v1.0\powershell.exe',
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase
|
||||||
|
) `
|
||||||
|
-and $ReadinessShortcut.arguments.Contains($ExpectedReadinessScriptPath) `
|
||||||
|
-and $ReadinessShortcut.arguments.Contains($ExpectedManifestPath) `
|
||||||
|
-and $ReadinessShortcut.arguments.Contains('-WaitForUser') `
|
||||||
|
-and $UninstallShortcut.exists `
|
||||||
|
-and $UninstallShortcut.targetPath -eq $ExpectedUninstallerPath `
|
||||||
|
-and $DesktopShortcut.exists `
|
||||||
|
-and $DesktopShortcut.targetPath -eq $ExpectedApplicationPath
|
||||||
|
if (-not $Report.shortcutsVerified)
|
||||||
|
{
|
||||||
|
throw 'One or more installer-managed shortcuts are missing or have incorrect targets or arguments.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$ReadinessReportPath = Join-Path $EvidenceDirectory 'installed-readiness-report.json'
|
||||||
|
$Report.readiness = & $ReadinessScriptPath `
|
||||||
|
-PayloadRoot $InstallRoot `
|
||||||
|
-TargetInstallRoot $InstallRoot `
|
||||||
|
-ExpectedPayloadManifestPath $ManifestPath `
|
||||||
|
-ReportPath $ReadinessReportPath `
|
||||||
|
-VerifyPayloadHashes `
|
||||||
|
-PassThru
|
||||||
|
if ($Report.readiness.result -eq 'blocked')
|
||||||
|
{
|
||||||
|
throw 'Installed-host readiness validation is blocked.'
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Force -Path $SentinelDirectory | Out-Null
|
||||||
|
[System.IO.File]::WriteAllText(
|
||||||
|
$SentinelPath,
|
||||||
|
"HyperTwist installer validation sentinel $RunId",
|
||||||
|
(New-Object System.Text.UTF8Encoding($false))
|
||||||
|
)
|
||||||
|
|
||||||
|
$Report.launchSmoke = Invoke-InstalledLaunchSmoke `
|
||||||
|
-InstallRoot $InstallRoot `
|
||||||
|
-EvidenceDirectory $EvidenceDirectory `
|
||||||
|
-SmokeSeconds $LaunchSmokeSeconds
|
||||||
|
if (-not $Report.launchSmoke.passed)
|
||||||
|
{
|
||||||
|
throw 'Installed executable launch smoke failed.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$Report.upgradeInstallExitCode = Invoke-InstallerProcess `
|
||||||
|
-ExecutablePath $ResolvedInstallerPath `
|
||||||
|
-Arguments @('/S', "/D=$InstallRoot") `
|
||||||
|
-Label 'Silent in-place upgrade'
|
||||||
|
$ManifestPath = Join-Path $InstallRoot 'Installer\payload-manifest.json'
|
||||||
|
$Report.payloadParityAfterUpgrade = Test-PayloadManifest `
|
||||||
|
-InstallRoot $InstallRoot `
|
||||||
|
-ManifestPath $ManifestPath
|
||||||
|
if (-not $Report.payloadParityAfterUpgrade.passed)
|
||||||
|
{
|
||||||
|
throw 'Installed payload parity failed after in-place upgrade.'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $KeepInstalled)
|
||||||
|
{
|
||||||
|
$Report.uninstallExitCode = Invoke-InstallerProcess `
|
||||||
|
-ExecutablePath $UninstallerPath `
|
||||||
|
-Arguments @('/S') `
|
||||||
|
-Label 'Silent uninstaller'
|
||||||
|
$Installed = $false
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
|
||||||
|
$Report.userDataPreserved = Test-Path -LiteralPath $SentinelPath -PathType Leaf
|
||||||
|
$Report.installRootRemoved = -not (Test-Path -LiteralPath $InstallRoot)
|
||||||
|
$Report.registrationRemoved = `
|
||||||
|
-not (Test-Path -LiteralPath $UninstallRegistryPath) `
|
||||||
|
-and -not (Test-Path -LiteralPath $ProductRegistryPath)
|
||||||
|
$Report.shortcutsRemoved = `
|
||||||
|
-not (Test-Path -LiteralPath $StartMenuDirectory) `
|
||||||
|
-and -not (Test-Path -LiteralPath $DesktopShortcutPath)
|
||||||
|
|
||||||
|
if (-not $Report.userDataPreserved)
|
||||||
|
{
|
||||||
|
throw 'Default uninstall removed current-user data unexpectedly.'
|
||||||
|
}
|
||||||
|
if (-not $Report.installRootRemoved)
|
||||||
|
{
|
||||||
|
throw 'The isolated install root remains after uninstall.'
|
||||||
|
}
|
||||||
|
if (-not $Report.registrationRemoved)
|
||||||
|
{
|
||||||
|
throw 'Installer registry state remains after uninstall.'
|
||||||
|
}
|
||||||
|
if (-not $Report.shortcutsRemoved)
|
||||||
|
{
|
||||||
|
throw 'Installer-managed shortcuts remain after uninstall.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Report.cleanupCompleted = -not $KeepInstalled
|
||||||
|
$Report.result = 'passed'
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
$Report.error = $_.Exception.Message
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
[void](Stop-OwnedProcesses -InstallRoot $InstallRoot)
|
||||||
|
if ($Installed -and -not $KeepInstalled -and (Test-Path -LiteralPath $UninstallerPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
[void](Invoke-InstallerProcess `
|
||||||
|
-ExecutablePath $UninstallerPath `
|
||||||
|
-Arguments @('/S') `
|
||||||
|
-Label 'Failure-cleanup uninstaller')
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
$Installed = $false
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
if ([string]::IsNullOrWhiteSpace([string]$Report.error))
|
||||||
|
{
|
||||||
|
$Report.error = $_.Exception.Message
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$Report.error = "$($Report.error) | Cleanup: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $KeepInstalled `
|
||||||
|
-and (Test-Path -LiteralPath $InstallRoot) `
|
||||||
|
-and -not (Test-Path -LiteralPath $UninstallRegistryPath) `
|
||||||
|
-and -not (Test-Path -LiteralPath $ProductRegistryPath))
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $InstallRoot -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -LiteralPath $SentinelPath)
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $SentinelPath -Force
|
||||||
|
}
|
||||||
|
if ((Test-Path -LiteralPath $SentinelDirectory) `
|
||||||
|
-and @(Get-ChildItem -LiteralPath $SentinelDirectory -Force).Count -eq 0)
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $SentinelDirectory -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $KeepInstalled)
|
||||||
|
{
|
||||||
|
$Report.installRootRemoved = -not (Test-Path -LiteralPath $InstallRoot)
|
||||||
|
$Report.registrationRemoved = `
|
||||||
|
-not (Test-Path -LiteralPath $UninstallRegistryPath) `
|
||||||
|
-and -not (Test-Path -LiteralPath $ProductRegistryPath)
|
||||||
|
$Report.shortcutsRemoved = `
|
||||||
|
-not (Test-Path -LiteralPath $StartMenuDirectory) `
|
||||||
|
-and -not (Test-Path -LiteralPath $DesktopShortcutPath)
|
||||||
|
$Report.cleanupCompleted = `
|
||||||
|
-not $Installed `
|
||||||
|
-and $Report.installRootRemoved `
|
||||||
|
-and $Report.registrationRemoved `
|
||||||
|
-and $Report.shortcutsRemoved
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Utf8JsonFile -Path $ReportPath -Value $Report
|
||||||
|
}
|
||||||
|
|
||||||
|
[Console]::Out.WriteLine('HyperTwist Windows installer lifecycle validation passed.')
|
||||||
|
[Console]::Out.WriteLine("Report: $([System.IO.Path]::GetFullPath($ReportPath))")
|
||||||
617
scripts/Test-HyperTwistWindowsReadiness.ps1
Normal file
617
scripts/Test-HyperTwistWindowsReadiness.ps1
Normal file
|
|
@ -0,0 +1,617 @@
|
||||||
|
param(
|
||||||
|
[string]$PayloadRoot = '',
|
||||||
|
[string]$TargetInstallRoot = '',
|
||||||
|
[string]$ExpectedPayloadManifestPath = '',
|
||||||
|
[string]$ReportPath = '',
|
||||||
|
[Int64]$MinimumMemoryBytes = 8589934592,
|
||||||
|
[Int64]$MinimumFreeSpaceBytes = 4294967296,
|
||||||
|
[int]$MinimumWindowsBuild = 19045,
|
||||||
|
[switch]$VerifyPayloadHashes,
|
||||||
|
[switch]$WaitForUser,
|
||||||
|
[switch]$PassThru
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$ExpectedSolverTableSizeBytes = 676207080
|
||||||
|
$ExpectedSolverTableSha256 = 'dc6de3d909a37afe2ba7f1f978543a13eae215bd20d954d66813524a8ca20034'
|
||||||
|
$RequiredVcRuntimeVersion = [version]'14.44.35211.0'
|
||||||
|
|
||||||
|
function Write-Utf8JsonFile {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Path,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[object]$Value
|
||||||
|
)
|
||||||
|
|
||||||
|
$ParentPath = Split-Path -Parent $Path
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($ParentPath))
|
||||||
|
{
|
||||||
|
New-Item -ItemType Directory -Force -Path $ParentPath | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$Json = $Value | ConvertTo-Json -Depth 12
|
||||||
|
$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||||||
|
[System.IO.File]::WriteAllText($Path, $Json, $Utf8NoBom)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-NormalizedRelativePath {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RootPath,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$FilePath
|
||||||
|
)
|
||||||
|
|
||||||
|
$RootPrefix = $RootPath.TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
|
||||||
|
$ResolvedFilePath = [System.IO.Path]::GetFullPath($FilePath)
|
||||||
|
if (-not $ResolvedFilePath.StartsWith(
|
||||||
|
$RootPrefix,
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
throw "File '$ResolvedFilePath' is outside payload root '$RootPath'."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ResolvedFilePath.Substring($RootPrefix.Length).Replace('\', '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
function Resolve-PayloadRelativeFilePath {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RootPath,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$RelativePath
|
||||||
|
)
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($RelativePath))
|
||||||
|
{
|
||||||
|
throw 'A payload-relative path cannot be empty.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$WindowsRelativePath = $RelativePath.Replace('/', '\')
|
||||||
|
if ([System.IO.Path]::IsPathRooted($WindowsRelativePath))
|
||||||
|
{
|
||||||
|
throw "Payload-relative path '$RelativePath' must not be rooted."
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResolvedRootPath = [System.IO.Path]::GetFullPath($RootPath)
|
||||||
|
$RootPrefix = $ResolvedRootPath.TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
|
||||||
|
$ResolvedFilePath = [System.IO.Path]::GetFullPath(
|
||||||
|
(Join-Path $ResolvedRootPath $WindowsRelativePath)
|
||||||
|
)
|
||||||
|
if (-not $ResolvedFilePath.StartsWith(
|
||||||
|
$RootPrefix,
|
||||||
|
[System.StringComparison]::OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
throw "Payload-relative path '$RelativePath' escapes root '$RootPath'."
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ResolvedFilePath
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-ExistingPathRoot {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$CandidatePath = [System.IO.Path]::GetFullPath($Path)
|
||||||
|
while (-not (Test-Path -LiteralPath $CandidatePath))
|
||||||
|
{
|
||||||
|
$ParentPath = Split-Path -Parent $CandidatePath
|
||||||
|
if ([string]::IsNullOrWhiteSpace($ParentPath) -or $ParentPath -eq $CandidatePath)
|
||||||
|
{
|
||||||
|
throw "No existing parent could be resolved for '$Path'."
|
||||||
|
}
|
||||||
|
|
||||||
|
$CandidatePath = $ParentPath
|
||||||
|
}
|
||||||
|
|
||||||
|
return $CandidatePath
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-VcRuntimeEvidence {
|
||||||
|
$RegistryPaths = @(
|
||||||
|
'HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64',
|
||||||
|
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64'
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($RegistryPath in $RegistryPaths)
|
||||||
|
{
|
||||||
|
if (-not (Test-Path -LiteralPath $RegistryPath))
|
||||||
|
{
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$Runtime = Get-ItemProperty -LiteralPath $RegistryPath
|
||||||
|
$VersionText = ([string]$Runtime.Version).TrimStart('v')
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$ParsedVersion = [version]$VersionText
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return [pscustomobject][ordered]@{
|
||||||
|
registryPath = $RegistryPath
|
||||||
|
installed = [int]$Runtime.Installed -eq 1
|
||||||
|
version = $ParsedVersion.ToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($TargetInstallRoot))
|
||||||
|
{
|
||||||
|
$TargetInstallRoot = Join-Path ([Environment]::GetFolderPath('ProgramFiles')) 'HyperTwist'
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($ReportPath))
|
||||||
|
{
|
||||||
|
$ReportPath = Join-Path $env:TEMP 'HyperTwist-readiness.json'
|
||||||
|
}
|
||||||
|
|
||||||
|
$Checks = New-Object System.Collections.ArrayList
|
||||||
|
function Add-ReadinessCheck {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Id,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet('required', 'optional', 'informational')]
|
||||||
|
[string]$Class,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[bool]$Passed,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Summary,
|
||||||
|
[object]$Evidence = $null
|
||||||
|
)
|
||||||
|
|
||||||
|
[void]$Checks.Add([pscustomobject][ordered]@{
|
||||||
|
id = $Id
|
||||||
|
class = $Class
|
||||||
|
passed = $Passed
|
||||||
|
summary = $Summary
|
||||||
|
evidence = $Evidence
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$OperatingSystem = Get-CimInstance Win32_OperatingSystem
|
||||||
|
$ComputerSystem = Get-CimInstance Win32_ComputerSystem
|
||||||
|
$WindowsBuild = [int]$OperatingSystem.BuildNumber
|
||||||
|
$Is64BitOperatingSystem = [Environment]::Is64BitOperatingSystem
|
||||||
|
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'windows-x64' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed $Is64BitOperatingSystem `
|
||||||
|
-Summary 'HyperTwist requires a 64-bit Windows operating system.' `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
architecture = [string]$OperatingSystem.OSArchitecture
|
||||||
|
processArchitecture = [string]$env:PROCESSOR_ARCHITECTURE
|
||||||
|
})
|
||||||
|
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'windows-supported-build' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed ($WindowsBuild -ge $MinimumWindowsBuild) `
|
||||||
|
-Summary "HyperTwist requires Windows build $MinimumWindowsBuild or newer." `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
caption = [string]$OperatingSystem.Caption
|
||||||
|
version = [string]$OperatingSystem.Version
|
||||||
|
build = $WindowsBuild
|
||||||
|
minimumBuild = $MinimumWindowsBuild
|
||||||
|
})
|
||||||
|
|
||||||
|
$TotalMemoryBytes = [Int64]$ComputerSystem.TotalPhysicalMemory
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'system-memory' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed ($TotalMemoryBytes -ge $MinimumMemoryBytes) `
|
||||||
|
-Summary 'At least 8 GiB of physical memory is required for the desktop Alpha.' `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
totalBytes = $TotalMemoryBytes
|
||||||
|
minimumBytes = $MinimumMemoryBytes
|
||||||
|
})
|
||||||
|
|
||||||
|
$ExistingInstallPathRoot = Get-ExistingPathRoot -Path $TargetInstallRoot
|
||||||
|
$TargetDriveName = [System.IO.Path]::GetPathRoot($ExistingInstallPathRoot).TrimEnd('\').TrimEnd(':')
|
||||||
|
$TargetDrive = Get-PSDrive -Name $TargetDriveName
|
||||||
|
$AvailableFreeSpaceBytes = [Int64]$TargetDrive.Free
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'install-volume-free-space' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed ($AvailableFreeSpaceBytes -ge $MinimumFreeSpaceBytes) `
|
||||||
|
-Summary 'The target volume must have enough free space for installation and first-run caches.' `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
targetInstallRoot = [System.IO.Path]::GetFullPath($TargetInstallRoot)
|
||||||
|
availableBytes = $AvailableFreeSpaceBytes
|
||||||
|
minimumBytes = $MinimumFreeSpaceBytes
|
||||||
|
})
|
||||||
|
|
||||||
|
$VcRuntime = Get-VcRuntimeEvidence
|
||||||
|
$VcRuntimeReady = $null -ne $VcRuntime `
|
||||||
|
-and $VcRuntime.installed `
|
||||||
|
-and [version]$VcRuntime.version -ge $RequiredVcRuntimeVersion
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'vc-runtime-x64' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed $VcRuntimeReady `
|
||||||
|
-Summary "Microsoft Visual C++ 2015-2022 x64 runtime $RequiredVcRuntimeVersion or newer is required and is bundled by the installer." `
|
||||||
|
-Evidence $VcRuntime
|
||||||
|
|
||||||
|
$SystemDirectory = [Environment]::SystemDirectory
|
||||||
|
$RequiredSystemLibraries = @(
|
||||||
|
'd3d11.dll',
|
||||||
|
'd3d12.dll',
|
||||||
|
'dxgi.dll',
|
||||||
|
'mf.dll',
|
||||||
|
'mfplat.dll',
|
||||||
|
'mfreadwrite.dll',
|
||||||
|
'xinput1_4.dll'
|
||||||
|
)
|
||||||
|
$MissingSystemLibraries = @(
|
||||||
|
$RequiredSystemLibraries |
|
||||||
|
Where-Object { -not (Test-Path -LiteralPath (Join-Path $SystemDirectory $_)) }
|
||||||
|
)
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'windows-media-and-graphics-libraries' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed ($MissingSystemLibraries.Count -eq 0) `
|
||||||
|
-Summary 'Windows DirectX, XInput, and Media Foundation runtime libraries must be available.' `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
systemDirectory = $SystemDirectory
|
||||||
|
requiredLibraries = $RequiredSystemLibraries
|
||||||
|
missingLibraries = $MissingSystemLibraries
|
||||||
|
})
|
||||||
|
|
||||||
|
$VideoControllers = @(
|
||||||
|
Get-CimInstance Win32_VideoController -ErrorAction SilentlyContinue |
|
||||||
|
ForEach-Object {
|
||||||
|
[pscustomobject][ordered]@{
|
||||||
|
name = [string]$_.Name
|
||||||
|
driverVersion = [string]$_.DriverVersion
|
||||||
|
driverDate = if ($null -eq $_.DriverDate) { $null } else { $_.DriverDate.ToString('o') }
|
||||||
|
adapterRamBytes = [Int64]$_.AdapterRAM
|
||||||
|
status = [string]$_.Status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'graphics-adapter' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed ($VideoControllers.Count -gt 0) `
|
||||||
|
-Summary 'At least one Windows graphics adapter must be visible.' `
|
||||||
|
-Evidence $VideoControllers
|
||||||
|
|
||||||
|
$SoundDevices = @(
|
||||||
|
Get-CimInstance Win32_SoundDevice -ErrorAction SilentlyContinue |
|
||||||
|
ForEach-Object {
|
||||||
|
[pscustomobject][ordered]@{
|
||||||
|
name = [string]$_.Name
|
||||||
|
status = [string]$_.Status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'audio-device' `
|
||||||
|
-Class 'optional' `
|
||||||
|
-Passed ($SoundDevices.Count -gt 0) `
|
||||||
|
-Summary 'An audio device is optional for puzzle play and recommended for narration and speech features.' `
|
||||||
|
-Evidence $SoundDevices
|
||||||
|
|
||||||
|
$OpenXrRegistryPaths = @(
|
||||||
|
'HKLM:\SOFTWARE\Khronos\OpenXR\1',
|
||||||
|
'HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenXR\1'
|
||||||
|
)
|
||||||
|
$OpenXrRuntime = $null
|
||||||
|
foreach ($OpenXrRegistryPath in $OpenXrRegistryPaths)
|
||||||
|
{
|
||||||
|
if (Test-Path -LiteralPath $OpenXrRegistryPath)
|
||||||
|
{
|
||||||
|
$OpenXrRuntime = Get-ItemProperty -LiteralPath $OpenXrRegistryPath
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'openxr-runtime' `
|
||||||
|
-Class 'optional' `
|
||||||
|
-Passed ($null -ne $OpenXrRuntime -and -not [string]::IsNullOrWhiteSpace([string]$OpenXrRuntime.ActiveRuntime)) `
|
||||||
|
-Summary 'An active OpenXR runtime is optional for keyboard/mouse play and required only for live headset sessions.' `
|
||||||
|
-Evidence $(if ($null -eq $OpenXrRuntime) {
|
||||||
|
$null
|
||||||
|
} else {
|
||||||
|
[pscustomobject][ordered]@{ activeRuntime = [string]$OpenXrRuntime.ActiveRuntime }
|
||||||
|
})
|
||||||
|
|
||||||
|
$ResolvedPayloadRoot = $null
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($PayloadRoot))
|
||||||
|
{
|
||||||
|
if (-not (Test-Path -LiteralPath $PayloadRoot -PathType Container))
|
||||||
|
{
|
||||||
|
throw "Payload root '$PayloadRoot' was not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResolvedPayloadRoot = (Resolve-Path -LiteralPath $PayloadRoot).Path
|
||||||
|
$RequiredPayloadFiles = @(
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist.exe'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist\Binaries\Win64\UnrealHyperTwist-Win64-Shipping.exe'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist\Binaries\Win64\tbb12.dll'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist\Binaries\Win64\tbbmalloc.dll'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist\Content\Paks\UnrealHyperTwist-Windows.pak'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist\Content\Paks\UnrealHyperTwist-Windows.utoc'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist\Content\Paks\UnrealHyperTwist-Windows.ucas'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'UnrealHyperTwist\Saved\twophase-ht.tbl'; size = $ExpectedSolverTableSizeBytes; sha256 = $ExpectedSolverTableSha256 },
|
||||||
|
[pscustomobject]@{ path = 'Content\Browser\index.html'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'Content\Browser\src\browser-runtime-bootstrap.js'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'Content\Browser\src\browser-spatial-runtime-fallback.js'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'Content\Browser\dist\browser-spatial-runtime.js'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'Engine\Binaries\ThirdParty\Windows\XAudio2_9\x64\XAudio2_9Redist.dll'; size = -1; sha256 = '' },
|
||||||
|
[pscustomobject]@{ path = 'Engine\Binaries\ThirdParty\OpenXR\win64\openxr_loader.dll'; size = -1; sha256 = '' }
|
||||||
|
)
|
||||||
|
|
||||||
|
$PayloadFailures = New-Object System.Collections.ArrayList
|
||||||
|
foreach ($RequiredPayloadFile in $RequiredPayloadFiles)
|
||||||
|
{
|
||||||
|
$RequiredPath = Join-Path $ResolvedPayloadRoot $RequiredPayloadFile.path
|
||||||
|
if (-not (Test-Path -LiteralPath $RequiredPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
[void]$PayloadFailures.Add("missing:$($RequiredPayloadFile.path)")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$RequiredItem = Get-Item -LiteralPath $RequiredPath
|
||||||
|
if ($RequiredItem.Length -le 0)
|
||||||
|
{
|
||||||
|
[void]$PayloadFailures.Add("empty:$($RequiredPayloadFile.path)")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([Int64]$RequiredPayloadFile.size -ge 0 `
|
||||||
|
-and $RequiredItem.Length -ne [Int64]$RequiredPayloadFile.size)
|
||||||
|
{
|
||||||
|
[void]$PayloadFailures.Add("size:$($RequiredPayloadFile.path)")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace([string]$RequiredPayloadFile.sha256))
|
||||||
|
{
|
||||||
|
$ActualHash = (Get-FileHash -LiteralPath $RequiredPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
if ($ActualHash -ne ([string]$RequiredPayloadFile.sha256).ToLowerInvariant())
|
||||||
|
{
|
||||||
|
[void]$PayloadFailures.Add("sha256:$($RequiredPayloadFile.path)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$CefRuntimeFiles = @(
|
||||||
|
Get-ChildItem `
|
||||||
|
-LiteralPath (Join-Path $ResolvedPayloadRoot 'Engine\Binaries\ThirdParty\CEF3\Win64') `
|
||||||
|
-Filter 'libcef.dll' `
|
||||||
|
-File `
|
||||||
|
-Recurse `
|
||||||
|
-ErrorAction SilentlyContinue
|
||||||
|
)
|
||||||
|
if ($CefRuntimeFiles.Count -eq 0)
|
||||||
|
{
|
||||||
|
[void]$PayloadFailures.Add('missing:Engine/Binaries/ThirdParty/CEF3/Win64/*/libcef.dll')
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'required-payload-files' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed ($PayloadFailures.Count -eq 0) `
|
||||||
|
-Summary 'The installed payload must contain every required executable, runtime, cooked-data, browser, solver, and OpenXR file.' `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
payloadRoot = $ResolvedPayloadRoot
|
||||||
|
requiredFileCount = $RequiredPayloadFiles.Count + 1
|
||||||
|
cefRuntimeFiles = @(
|
||||||
|
$CefRuntimeFiles |
|
||||||
|
ForEach-Object {
|
||||||
|
Get-NormalizedRelativePath `
|
||||||
|
-RootPath $ResolvedPayloadRoot `
|
||||||
|
-FilePath $_.FullName
|
||||||
|
}
|
||||||
|
)
|
||||||
|
failures = @($PayloadFailures)
|
||||||
|
})
|
||||||
|
|
||||||
|
$OuterExecutablePath = Join-Path $ResolvedPayloadRoot 'UnrealHyperTwist.exe'
|
||||||
|
if (Test-Path -LiteralPath $OuterExecutablePath -PathType Leaf)
|
||||||
|
{
|
||||||
|
$Signature = Get-AuthenticodeSignature -LiteralPath $OuterExecutablePath
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'desktop-code-signature' `
|
||||||
|
-Class 'optional' `
|
||||||
|
-Passed ($Signature.Status -eq [System.Management.Automation.SignatureStatus]::Valid) `
|
||||||
|
-Summary 'The Alpha payload is currently unsigned; production distribution requires Authenticode signing.' `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
status = $Signature.Status.ToString()
|
||||||
|
signer = if ($null -eq $Signature.SignerCertificate) {
|
||||||
|
$null
|
||||||
|
} else {
|
||||||
|
[string]$Signature.SignerCertificate.Subject
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($ExpectedPayloadManifestPath))
|
||||||
|
{
|
||||||
|
if ($null -eq $ResolvedPayloadRoot)
|
||||||
|
{
|
||||||
|
throw 'ExpectedPayloadManifestPath requires PayloadRoot.'
|
||||||
|
}
|
||||||
|
if (-not (Test-Path -LiteralPath $ExpectedPayloadManifestPath -PathType Leaf))
|
||||||
|
{
|
||||||
|
throw "Payload manifest '$ExpectedPayloadManifestPath' was not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
$Manifest = Get-Content -LiteralPath $ExpectedPayloadManifestPath -Raw | ConvertFrom-Json
|
||||||
|
$ManifestFailures = New-Object System.Collections.ArrayList
|
||||||
|
$SeenManifestPaths = @{}
|
||||||
|
$ManifestEntries = @($Manifest.files)
|
||||||
|
if ([string]$Manifest.manifestVersion -ne 'ht-windows-installer-payload/v1')
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("manifest-version:$($Manifest.manifestVersion)")
|
||||||
|
}
|
||||||
|
|
||||||
|
$DeclaredFileCount = 0
|
||||||
|
if (-not [int]::TryParse([string]$Manifest.fileCount, [ref]$DeclaredFileCount) `
|
||||||
|
-or $DeclaredFileCount -ne $ManifestEntries.Count)
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("manifest-file-count:$($Manifest.fileCount)")
|
||||||
|
}
|
||||||
|
|
||||||
|
$DeclaredTotalSizeBytes = 0L
|
||||||
|
if (-not [Int64]::TryParse(
|
||||||
|
[string]$Manifest.totalSizeBytes,
|
||||||
|
[ref]$DeclaredTotalSizeBytes
|
||||||
|
) -or $DeclaredTotalSizeBytes -lt 0)
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("manifest-total-size:$($Manifest.totalSizeBytes)")
|
||||||
|
}
|
||||||
|
|
||||||
|
$ComputedTotalSizeBytes = 0L
|
||||||
|
foreach ($ManifestEntry in $ManifestEntries)
|
||||||
|
{
|
||||||
|
$ManifestRelativePath = [string]$ManifestEntry.relativePath
|
||||||
|
$ManifestPathKey = $ManifestRelativePath.Replace('\', '/').ToLowerInvariant()
|
||||||
|
if ($SeenManifestPaths.ContainsKey($ManifestPathKey))
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("duplicate:$ManifestRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$SeenManifestPaths[$ManifestPathKey] = $true
|
||||||
|
|
||||||
|
$ManifestEntrySizeBytes = 0L
|
||||||
|
if (-not [Int64]::TryParse(
|
||||||
|
[string]$ManifestEntry.sizeBytes,
|
||||||
|
[ref]$ManifestEntrySizeBytes
|
||||||
|
) -or $ManifestEntrySizeBytes -lt 0)
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("invalid-size:$ManifestRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$ComputedTotalSizeBytes += $ManifestEntrySizeBytes
|
||||||
|
|
||||||
|
$ExpectedManifestHash = ([string]$ManifestEntry.sha256).ToLowerInvariant()
|
||||||
|
if ($ExpectedManifestHash -notmatch '^[0-9a-f]{64}$')
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("invalid-sha256:$ManifestRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$ManifestFilePath = Resolve-PayloadRelativeFilePath `
|
||||||
|
-RootPath $ResolvedPayloadRoot `
|
||||||
|
-RelativePath $ManifestRelativePath
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("invalid-path:$ManifestRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $ManifestFilePath -PathType Leaf))
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("missing:$ManifestRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$ManifestItem = Get-Item -LiteralPath $ManifestFilePath
|
||||||
|
if ($ManifestItem.Length -ne $ManifestEntrySizeBytes)
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("size:$ManifestRelativePath")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($VerifyPayloadHashes)
|
||||||
|
{
|
||||||
|
$ManifestHash = (Get-FileHash -LiteralPath $ManifestFilePath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
if ($ManifestHash -ne $ExpectedManifestHash)
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add("sha256:$ManifestRelativePath")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($DeclaredTotalSizeBytes -ne $ComputedTotalSizeBytes)
|
||||||
|
{
|
||||||
|
[void]$ManifestFailures.Add(
|
||||||
|
"manifest-total-size-parity:$DeclaredTotalSizeBytes/$ComputedTotalSizeBytes"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-ReadinessCheck `
|
||||||
|
-Id 'payload-manifest-parity' `
|
||||||
|
-Class 'required' `
|
||||||
|
-Passed ($ManifestFailures.Count -eq 0) `
|
||||||
|
-Summary 'The installed payload must match the release manifest without missing, truncated, or altered files.' `
|
||||||
|
-Evidence ([pscustomobject][ordered]@{
|
||||||
|
manifestPath = (Resolve-Path -LiteralPath $ExpectedPayloadManifestPath).Path
|
||||||
|
manifestVersion = [string]$Manifest.manifestVersion
|
||||||
|
manifestEntryCount = $ManifestEntries.Count
|
||||||
|
declaredFileCount = $DeclaredFileCount
|
||||||
|
declaredTotalSizeBytes = $DeclaredTotalSizeBytes
|
||||||
|
computedTotalSizeBytes = $ComputedTotalSizeBytes
|
||||||
|
hashesVerified = [bool]$VerifyPayloadHashes
|
||||||
|
failures = @($ManifestFailures)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$RequiredFailures = @(
|
||||||
|
$Checks |
|
||||||
|
Where-Object { $_.class -eq 'required' -and -not $_.passed }
|
||||||
|
)
|
||||||
|
$OptionalWarnings = @(
|
||||||
|
$Checks |
|
||||||
|
Where-Object { $_.class -eq 'optional' -and -not $_.passed }
|
||||||
|
)
|
||||||
|
$Result = if ($RequiredFailures.Count -gt 0) {
|
||||||
|
'blocked'
|
||||||
|
} elseif ($OptionalWarnings.Count -gt 0) {
|
||||||
|
'ready-with-warnings'
|
||||||
|
} else {
|
||||||
|
'ready'
|
||||||
|
}
|
||||||
|
|
||||||
|
$Report = [pscustomobject][ordered]@{
|
||||||
|
reportVersion = 'ht-windows-readiness/v1'
|
||||||
|
generatedAtUtc = [DateTime]::UtcNow.ToString('o')
|
||||||
|
result = $Result
|
||||||
|
payloadRoot = $ResolvedPayloadRoot
|
||||||
|
targetInstallRoot = [System.IO.Path]::GetFullPath($TargetInstallRoot)
|
||||||
|
requiredFailureCount = $RequiredFailures.Count
|
||||||
|
optionalWarningCount = $OptionalWarnings.Count
|
||||||
|
checks = @($Checks)
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Utf8JsonFile -Path $ReportPath -Value $Report
|
||||||
|
[Console]::Out.WriteLine((
|
||||||
|
"HyperTwist Windows readiness: {0} ({1} required failure(s), {2} optional warning(s))." -f
|
||||||
|
$Result,
|
||||||
|
$RequiredFailures.Count,
|
||||||
|
$OptionalWarnings.Count
|
||||||
|
))
|
||||||
|
[Console]::Out.WriteLine("Report: $([System.IO.Path]::GetFullPath($ReportPath))")
|
||||||
|
|
||||||
|
if ($PassThru)
|
||||||
|
{
|
||||||
|
return $Report
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($WaitForUser)
|
||||||
|
{
|
||||||
|
[void](Read-Host 'Press Enter to close the HyperTwist readiness report')
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Result -eq 'blocked')
|
||||||
|
{
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
exit 0
|
||||||
Loading…
Add table
Reference in a new issue