feat: dual-ship-smoke.ps1 offline VM A/B/C runner with optional artifact hashes
Some checks failed
windows-msi / full-msi-unsigned (push) Has been cancelled

Prints checklist steps; -VerifyArtifacts uses fill-manifest-sha256.
This commit is contained in:
George Lambert 2026-10-14 00:39:21 -04:00
commit 376bbe188a
5 changed files with 312 additions and 2 deletions

View file

@ -37,6 +37,7 @@ Repo now includes **authoring/docs scaffolds** for the two commercial gaps that
| **0.3.6 Windows NSIS+MSI placeholder rows** ([`DOWNLOADS-MANIFEST.txt`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.txt) + [`DOWNLOADS-MANIFEST.md`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.md); sha256 **TBD**) | Build/upload signed 0.3.6 blobs; replace TBD with real digests | | **0.3.6 Windows NSIS+MSI placeholder rows** ([`DOWNLOADS-MANIFEST.txt`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.txt) + [`DOWNLOADS-MANIFEST.md`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.md); sha256 **TBD**) | Build/upload signed 0.3.6 blobs; replace TBD with real digests |
| [`fill-manifest-sha256.ps1`](../platform/windows/scripts/fill-manifest-sha256.ps1) local hash → DOWNLOADS-MANIFEST rows (linked from DUAL-SHIP + manifest.md; **no upload**) | Operator still must upload first, then paste digests over TBD | | [`fill-manifest-sha256.ps1`](../platform/windows/scripts/fill-manifest-sha256.ps1) local hash → DOWNLOADS-MANIFEST rows (linked from DUAL-SHIP + manifest.md; **no upload**) | Operator still must upload first, then paste digests over TBD |
| **Printable VM A/B/C sheet** [`VM-DUAL-SHIP-CHECKLIST.md`](../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) | Operator sign-off on clean VMs (C blocked until CAs uncommented) | | **Printable VM A/B/C sheet** [`VM-DUAL-SHIP-CHECKLIST.md`](../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) | Operator sign-off on clean VMs (C blocked until CAs uncommented) |
| **Offline dual-ship smoke** [`dual-ship-smoke.ps1`](../platform/windows/scripts/dual-ship-smoke.ps1) (prints A/B/C; `-VerifyArtifacts` → existence + `fill-manifest-sha256.ps1`) | Does **not** replace clean-VM sign-off; no install/sign/upload |
**Still use for day-to-day presence (no WiX / no Apple certs):** **Still use for day-to-day presence (no WiX / no Apple certs):**
Windows `scripts/build-tray-startmenu.ps1` + `install-tray-startup.ps1`; macOS `verae-print menubar --install` / unsigned `build-menubar-app.sh`. Full product install remains NSIS (`installer-windows.nsi`) and macOS `pkg/build-pkg.sh`. Optional: `build-tray-msi.ps1` (WiX tip exit 0); `build-full-msi.ps1` (needs WiX; exit 1 if missing). Windows `scripts/build-tray-startmenu.ps1` + `install-tray-startup.ps1`; macOS `verae-print menubar --install` / unsigned `build-menubar-app.sh`. Full product install remains NSIS (`installer-windows.nsi`) and macOS `pkg/build-pkg.sh`. Optional: `build-tray-msi.ps1` (WiX tip exit 0); `build-full-msi.ps1` (needs WiX; exit 1 if missing).
@ -75,6 +76,7 @@ Related but out of scope for “done” above (still backlog-adjacent): Linux `.
| **Printable VM checklist** | [`wix/VM-DUAL-SHIP-CHECKLIST.md`](../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) | **Docs** — tick boxes for shared pre-checks + VM A/B/C + side-by-side | | **Printable VM checklist** | [`wix/VM-DUAL-SHIP-CHECKLIST.md`](../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) | **Docs** — tick boxes for shared pre-checks + VM A/B/C + side-by-side |
| **0.3.6 download placeholders** | [`site/.../DOWNLOADS-MANIFEST.md`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) + `.txt` TBD rows | **Docs** — NSIS setup + full MSI filenames reserved; digests TBD until publish | | **0.3.6 download placeholders** | [`site/.../DOWNLOADS-MANIFEST.md`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) + `.txt` TBD rows | **Docs** — NSIS setup + full MSI filenames reserved; digests TBD until publish |
| **Manifest SHA-256 row helper** | [`scripts/fill-manifest-sha256.ps1`](../platform/windows/scripts/fill-manifest-sha256.ps1) | **Tool** — local `Get-FileHash` → SHA256SUMS / MD rows; does **not** upload or rewrite site files | | **Manifest SHA-256 row helper** | [`scripts/fill-manifest-sha256.ps1`](../platform/windows/scripts/fill-manifest-sha256.ps1) | **Tool** — local `Get-FileHash` → SHA256SUMS / MD rows; does **not** upload or rewrite site files |
| **Offline dual-ship smoke** | [`scripts/dual-ship-smoke.ps1`](../platform/windows/scripts/dual-ship-smoke.ps1) | **Tool** — prints VM A/B/C checklist; optional local MSI/NSIS existence + hash via fill-manifest; does **not** install or drive VMs |
| Shared version helper | [`platform/windows/scripts/common.ps1`](../platform/windows/scripts/common.ps1) `Get-VeraePackageVersion` | Aligns tray/full MSI/NSIS drivers with `HelperVersion` | | Shared version helper | [`platform/windows/scripts/common.ps1`](../platform/windows/scripts/common.ps1) `Get-VeraePackageVersion` | Aligns tray/full MSI/NSIS drivers with `HelperVersion` |
| End-user Windows readme | [`platform/windows/README-WINDOWS.txt`](../platform/windows/README-WINDOWS.txt), [`README.txt`](../platform/windows/README.txt) | Documents NSIS flow; states **no elevated MSI** for tray | | End-user Windows readme | [`platform/windows/README-WINDOWS.txt`](../platform/windows/README-WINDOWS.txt), [`README.txt`](../platform/windows/README.txt) | Documents NSIS flow; states **no elevated MSI** for tray |
| Packaging policy doc | [PACKAGING.md](PACKAGING.md) | “**No elevated MSI**” for tray presence by design | | Packaging policy doc | [PACKAGING.md](PACKAGING.md) | “**No elevated MSI**” for tray presence by design |

View file

@ -0,0 +1,292 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Offline dual-ship smoke: print VM A/B/C checklist steps; optionally verify local MSI/NSIS + hash.
.DESCRIPTION
Operator helper for clean-VM dual-ship gates (NSIS primary + full MSI dual-ship).
Default mode prints the shared pre-checks and VM A / B / C steps from
platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md (narrative: DUAL-SHIP.md).
Does NOT install, uninstall, sign, upload, or drive a remote VM. It is a
printable offline runner for the host that built (or downloaded) artifacts.
With -VerifyArtifacts: look for NSIS setup.exe and/or full MSI under common
build paths (or -NsisPath / -MsiPath), report present/missing, then invoke
fill-manifest-sha256.ps1 for every file found (local SHA-256 only — no upload).
.EXITCODES
0 Checklist printed. If -VerifyArtifacts: at least one artifact found and hashed
(or -RequireBoth satisfied). Missing optional artifact is a warning only.
1 -VerifyArtifacts and no artifacts found; -RequireBoth and one leg missing;
fill-manifest failed; or terminating error.
.PARAMETER Version
Expected HelperVersion stamp (default: Get-VeraePackageVersion / 0.3.6).
.PARAMETER Arch
Artifact arch segment (default: amd64).
.PARAMETER NsisPath
Explicit NSIS setup.exe path. When omitted, searches dist/ and common out dirs.
.PARAMETER MsiPath
Explicit full MSI path. When omitted, searches wix/out and dist/.
.PARAMETER SearchRoot
Extra directory to search for VeraePrintStamp-windows-*-setup.exe / *.msi.
.PARAMETER VerifyArtifacts
Check local MSI/NSIS existence and hash via fill-manifest-sha256.ps1.
.PARAMETER RequireBoth
With -VerifyArtifacts: fail (exit 1) unless both NSIS and MSI are present.
.PARAMETER SkipHash
With -VerifyArtifacts: existence only (do not call fill-manifest).
.PARAMETER Format
Hash output format passed to fill-manifest (txt|md|both). Default txt.
.EXAMPLE
powershell -NoProfile -ExecutionPolicy Bypass -File dual-ship-smoke.ps1
.EXAMPLE
powershell -NoProfile -ExecutionPolicy Bypass -File dual-ship-smoke.ps1 -VerifyArtifacts
.EXAMPLE
.\dual-ship-smoke.ps1 -VerifyArtifacts -RequireBoth -NsisPath .\dist\VeraePrintStamp-windows-amd64-0.3.6-setup.exe
#>
param(
[string]$Version = "",
[string]$Arch = "amd64",
[string]$NsisPath = "",
[string]$MsiPath = "",
[string]$SearchRoot = "",
[switch]$VerifyArtifacts,
[switch]$RequireBoth,
[switch]$SkipHash,
[ValidateSet("txt", "md", "both")]
[string]$Format = "txt"
)
$ErrorActionPreference = "Stop"
$common = Join-Path $PSScriptRoot "common.ps1"
if (Test-Path -LiteralPath $common) { . $common }
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..\..")).Path
$WinDir = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$WixDir = Join-Path $WinDir "wix"
$FillScript = Join-Path $PSScriptRoot "fill-manifest-sha256.ps1"
if (-not $Version) {
if (Get-Command Get-VeraePackageVersion -ErrorAction SilentlyContinue) {
$Version = Get-VeraePackageVersion
} elseif ($env:VERSION -and $env:VERSION.Trim()) {
$Version = $env:VERSION.Trim()
} else {
$Version = "0.3.6"
}
}
$nsisLeaf = "VeraePrintStamp-windows-$Arch-$Version-setup.exe"
$msiLeaf = "VeraePrintStamp-windows-$Arch-$Version.msi"
function Write-Section([string]$Title) {
Write-Host ""
Write-Host ("==== {0} ====" -f $Title) -ForegroundColor Cyan
}
function Write-Step([string]$Id, [string]$Text) {
Write-Host (" [ ] {0} {1}" -f $Id, $Text)
}
function Write-Note([string]$Text) {
Write-Host (" {0}" -f $Text) -ForegroundColor DarkGray
}
function Resolve-FirstExisting {
param([string[]]$Candidates)
foreach ($c in $Candidates) {
if (-not $c) { continue }
if (Test-Path -LiteralPath $c) {
return (Get-Item -LiteralPath $c).FullName
}
}
return $null
}
function Find-Artifact {
param(
[string]$Explicit,
[string]$Leaf,
[string[]]$Dirs
)
if ($Explicit) {
if (Test-Path -LiteralPath $Explicit) {
return (Get-Item -LiteralPath $Explicit).FullName
}
return $null
}
$cands = @()
foreach ($d in $Dirs) {
if (-not $d) { continue }
if (-not (Test-Path -LiteralPath $d)) { continue }
$cands += (Join-Path $d $Leaf)
# Also accept any matching pattern if exact leaf missing (version drift).
Get-ChildItem -LiteralPath $d -File -ErrorAction SilentlyContinue |
Where-Object {
($Leaf -match '-setup\.exe$' -and $_.Name -like 'VeraePrintStamp-windows-*-setup.exe') -or
($Leaf -match '\.msi$' -and $_.Name -like 'VeraePrintStamp-windows-*.msi' -and $_.Name -notlike '*Tray*')
} |
ForEach-Object { $cands += $_.FullName }
}
return (Resolve-FirstExisting -Candidates $cands)
}
# --- Header ---
Write-Host "dual-ship-smoke (offline) — does not install, sign, or upload." -ForegroundColor DarkGray
Write-Host ("HelperVersion expect: {0} arch: {1}" -f $Version, $Arch)
Write-Host ("Repo: {0}" -f $RepoRoot)
Write-Host "Docs: platform/windows/wix/DUAL-SHIP.md"
Write-Host " platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md"
Write-Host "Rules: one channel per VM; receipt/CID only (never jobId-only); VM C blocked while printer CAs commented."
# --- Shared pre-checks ---
Write-Section "Shared pre-checks (every VM)"
Write-Step "0.1" "Fresh Win10/11 x64 snapshot (or sysprep-clean); admin account available"
Write-Step "0.2" "No prior Verae Print Stamp under Program Files or ARP"
Write-Step "0.3" "Spooler running (Get-Service Spooler)"
Write-Step "0.4" ("Note HelperVersion on artifact = tree (expect {0})" -f $Version)
Write-Step "0.5" "Record SmartScreen / AV prompts (unsigned expected until Authenticode live)"
# --- VM A ---
Write-Section "VM A — NSIS primary (baseline)"
Write-Note ("Install: elevated setup.exe (typical: {0})" -f $nsisLeaf)
Write-Step "A.1" "Run setup.exe elevated; key wizard complete or skip per test plan"
Write-Step "A.2" "Confirm Program Files\Verae\PrintStamp\bin\verae-print.exe + helper"
Write-Step "A.3" "Confirm printers (IPP and/or Local Port) present"
Write-Step "A.4" "Confirm scheduled task Verae Print Helper"
Write-Step "A.5" "Print one-page PDF → stamp path OK (receipt/CID; never jobId-only)"
Write-Step "A.6" "Start Menu: Setup signing key, Start print helper, Collect diagnostics"
Write-Step "A.7" "Uninstall via ARP; printers/task removed; reboot optional"
Write-Note "VM A sign-off: pass / fail · log path · initials"
# --- VM B ---
Write-Section "VM B — MSI files-only (safe today)"
Write-Note ("Install: full MSI with printers skipped (typical: {0})" -f $msiLeaf)
Write-Note "msiexec /i VeraePrintStamp-windows-amd64-<ver>.msi /qn /norestart \"
Write-Note " VERAE_SKIP_KEY_SETUP=1 VERAE_SKIP_PRINTERS=1 VERAE_CHANNEL=zapier"
Write-Step "B.1" "msiexec as above (or UI); exit code recorded"
Write-Step "B.2" "Confirm InstallDir: bin\, scripts\ (incl. install-printer.ps1), LICENSE, README"
Write-Step "B.3" "ARP entry: Publisher Verae; DisplayVersion = HelperVersion"
Write-Step "B.4" "Start Menu shortcuts resolve to helper / diag"
Write-Step "B.5" "Optional: elevated manual scripts\install-printer.ps1 -InstallDir `"…`""
Write-Step "B.6" "msiexec /x {ProductCode} /qn — files + Start Menu gone; no orphan HKLM"
Write-Note "Pass (files-only): clean install/uninstall; version match; props accepted."
Write-Note "VM B sign-off: pass / fail · ProductCode · initials"
# --- VM C ---
Write-Section "VM C — MSI printer CA (BLOCKED until CAs live)"
Write-Note "Prereq: uncomment + schedule deferred CAs in Product-Full.wxs; rebuild MSI."
Write-Step "C.0" "CAs scheduled; conditions NOT Installed + VERAE_SKIP_PRINTERS<>`"1`"; REMOVE~=`"ALL`" uninstall"
Write-Step "C.1" "Default MSI install (or VERAE_SKIP_PRINTERS=0) elevated"
Write-Step "C.2" "Program Files layout matches VM A (bin\, scripts\, docs)"
Write-Step "C.3" "IPP loopback 127.0.0.1:8631 and/or Local Port names match NSIS"
Write-Step "C.4" "Scheduled task Verae Print Helper (same principal / trigger class as A)"
Write-Step "C.5" "Start Menu OK; one-page PDF stamp path (receipt/CID evidence)"
Write-Step "C.6" "VERAE_SKIP_PRINTERS=1 skips CA; default installs printers"
Write-Step "C.7" "msiexec /x removes printers, task, files, Start Menu; no orphan HKLM"
Write-Step "C.8" "Repair / same-version upgrade smoke (AllowSameVersionUpgrades)"
Write-Note "Do not mark dual-ship complete until VM C matches VM A on a clean image."
Write-Note "VM C sign-off: pass / fail / blocked (CAs commented) · initials"
# --- Side-by-side ---
Write-Section "Side-by-side (tick when observed)"
Write-Host " Check NSIS(A) MSI-files(B) MSI+CA(C)"
Write-Host " Version = HelperVersion [ ] [ ] [ ]"
Write-Host " Program Files layout [ ] [ ] [ ]"
Write-Host " Start Menu shortcuts [ ] [ ] [ ]"
Write-Host " ARP uninstall clean [ ] [ ] [ ]"
Write-Host " IPP + Local Port printers [ ] N/A [ ]"
Write-Host " Scheduled task helper [ ] N/A [ ]"
Write-Host " Key wizard / first-run key [ ] skip prop [ ]"
Write-Host " msiexec /qn N/A [ ] [ ]"
Write-Host " Authenticode (signtool) still left still left still left"
Write-Section "After the VMs"
Write-Step "G.1" "Record logs + exit codes in release notes / dual-ship folder"
Write-Step "G.2" "Authenticode still left → SmartScreen warn is not promote-ready"
Write-Step "G.3" "Update DOWNLOADS-MANIFEST digests only after upload (hash with fill-manifest-sha256.ps1)"
Write-Step "G.4" "Thin-NSIS only when DUAL-SHIP exit checklist A–D all checked"
Write-Note "Overall dual-ship gate: open / closed"
# --- Optional local artifact verify ---
if (-not $VerifyArtifacts) {
Write-Section "Local artifacts (skipped)"
Write-Host " Pass -VerifyArtifacts to check MSI/NSIS existence and hash via fill-manifest-sha256.ps1."
Write-Host " Example:"
Write-Host " powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\dual-ship-smoke.ps1 -VerifyArtifacts"
exit 0
}
Write-Section "Local artifact verify"
$searchDirs = @(
(Join-Path $RepoRoot "dist"),
(Join-Path $RepoRoot "dist\windows"),
(Join-Path $WixDir "out"),
(Join-Path $WinDir "out"),
(Join-Path $RepoRoot "out")
)
if ($SearchRoot) { $searchDirs = @($SearchRoot) + $searchDirs }
$foundNsis = Find-Artifact -Explicit $NsisPath -Leaf $nsisLeaf -Dirs $searchDirs
$foundMsi = Find-Artifact -Explicit $MsiPath -Leaf $msiLeaf -Dirs $searchDirs
$nsisStatus = if ($foundNsis) { "FOUND $foundNsis" } else { "MISSING (expected leaf $nsisLeaf)" }
$msiStatus = if ($foundMsi) { "FOUND $foundMsi" } else { "MISSING (expected leaf $msiLeaf)" }
Write-Host (" NSIS setup.exe : {0}" -f $nsisStatus) -ForegroundColor $(if ($foundNsis) { "Green" } else { "Yellow" })
Write-Host (" Full MSI : {0}" -f $msiStatus) -ForegroundColor $(if ($foundMsi) { "Green" } else { "Yellow" })
$toHash = @()
if ($foundNsis) { $toHash += $foundNsis }
if ($foundMsi) { $toHash += $foundMsi }
if ($RequireBoth -and (-not $foundNsis -or -not $foundMsi)) {
Write-Host " FAIL: -RequireBoth set but NSIS and/or MSI missing." -ForegroundColor Red
exit 1
}
if ($toHash.Count -eq 0) {
Write-Host " FAIL: no local MSI/NSIS artifacts found under dist/, wix/out, or -NsisPath/-MsiPath." -ForegroundColor Red
Write-Host " Build first: platform\windows\build-windows.ps1 then scripts\build-full-msi.ps1" -ForegroundColor DarkGray
exit 1
}
if ($SkipHash) {
Write-Host " SkipHash: existence only (fill-manifest not invoked)." -ForegroundColor DarkGray
exit 0
}
if (-not (Test-Path -LiteralPath $FillScript)) {
Write-Host (" FAIL: fill-manifest-sha256.ps1 not found: {0}" -f $FillScript) -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host " Invoking fill-manifest-sha256.ps1 (local hash only — does not upload)…" -ForegroundColor DarkGray
& powershell -NoProfile -ExecutionPolicy Bypass -File $FillScript -Path $toHash -Format $Format
$fillExit = $LASTEXITCODE
if ($null -eq $fillExit) { $fillExit = 0 }
if ($fillExit -ne 0) {
Write-Host (" FAIL: fill-manifest-sha256.ps1 exit {0}" -f $fillExit) -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host " Hash rows above are for DOWNLOADS-MANIFEST paste only after CDN upload." -ForegroundColor DarkGray
Write-Host " dual-ship-smoke verify: OK" -ForegroundColor Green
exit 0

View file

@ -4,7 +4,7 @@
**Do not** thin or deprecate NSIS until the **thin-NSIS exit criteria checklist** (below) is fully checked — clean-VM gates, live Authenticode, silent/fleet proof, and site cutover (see [COMMERCIAL-INSTALLER-BACKLOG.md](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md), [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md)). **Do not** thin or deprecate NSIS until the **thin-NSIS exit criteria checklist** (below) is fully checked — clean-VM gates, live Authenticode, silent/fleet proof, and site cutover (see [COMMERCIAL-INSTALLER-BACKLOG.md](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md), [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md)).
**Related:** [Product-Full.wxs](Product-Full.wxs) · [SILENT_PROPS.md](SILENT_PROPS.md) · [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) (printable A/B/C) · [../installer-windows.nsi](../installer-windows.nsi) · [PACKAGING.md](../../../docs/PACKAGING.md) · site [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) (0.3.6 TBD rows) · [`fill-manifest-sha256.ps1`](../scripts/fill-manifest-sha256.ps1) (hash built MSI/NSIS → manifest row; no upload). **Related:** [Product-Full.wxs](Product-Full.wxs) · [SILENT_PROPS.md](SILENT_PROPS.md) · [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) (printable A/B/C) · [`dual-ship-smoke.ps1`](../scripts/dual-ship-smoke.ps1) (offline checklist runner + optional local MSI/NSIS hash) · [../installer-windows.nsi](../installer-windows.nsi) · [PACKAGING.md](../../../docs/PACKAGING.md) · site [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) (0.3.6 TBD rows) · [`fill-manifest-sha256.ps1`](../scripts/fill-manifest-sha256.ps1) (hash built MSI/NSIS → manifest row; no upload).
--- ---
@ -79,6 +79,13 @@ Prints `DOWNLOADS-MANIFEST.txt` lines (`<sha256> <leaf>`). `-Format md` prints
**Printable tick sheet:** [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) (shared pre-checks + VM A/B/C steps + side-by-side table). **Printable tick sheet:** [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) (shared pre-checks + VM A/B/C steps + side-by-side table).
**Offline checklist runner** (prints the same A/B/C steps; optional local artifact existence + hash via fill-manifest — does **not** install or drive a VM):
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\dual-ship-smoke.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\dual-ship-smoke.ps1 -VerifyArtifacts
```
Use two fresh Windows 10/11 **x64** VMs (or reset snapshots). Do **not** mix channels on one machine until Upgrade/ARP coexistence is explicitly tested. Use two fresh Windows 10/11 **x64** VMs (or reset snapshots). Do **not** mix channels on one machine until Upgrade/ARP coexistence is explicitly tested.
| VM | Install | Goal | | VM | Install | Goal |
@ -273,6 +280,7 @@ Do **not** put PFX bytes or passwords in git. Do not upload the PFX as a workflo
| CI unsigned MSI workflow | [../../../.github/workflows/windows-msi.yml](../../../.github/workflows/windows-msi.yml) | | CI unsigned MSI workflow | [../../../.github/workflows/windows-msi.yml](../../../.github/workflows/windows-msi.yml) |
| Silent properties | [SILENT_PROPS.md](SILENT_PROPS.md) | | Silent properties | [SILENT_PROPS.md](SILENT_PROPS.md) |
| Printable VM A/B/C checklist | [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) | | Printable VM A/B/C checklist | [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) |
| Offline dual-ship smoke (print + optional hash) | [../scripts/dual-ship-smoke.ps1](../scripts/dual-ship-smoke.ps1) |
| Sign/notary draft | [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md) | | Sign/notary draft | [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md) |
| Menubar CI notary example | [../../macos/menubar/ci-notarize.yml.example](../../macos/menubar/ci-notarize.yml.example) | | Menubar CI notary example | [../../macos/menubar/ci-notarize.yml.example](../../macos/menubar/ci-notarize.yml.example) |
| Site 0.3.6 placeholders | [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) · [DOWNLOADS-MANIFEST.txt](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.txt) | | Site 0.3.6 placeholders | [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) · [DOWNLOADS-MANIFEST.txt](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.txt) |

View file

@ -173,6 +173,8 @@ day-to-day full product. **Not** Authenticode-signed; printer CAs remain
| `../scripts/build-tray-msi.ps1` | Tray candle/light driver; WiX tip exit 0 if missing | | `../scripts/build-tray-msi.ps1` | Tray candle/light driver; WiX tip exit 0 if missing |
| `../scripts/build-full-msi.ps1` | Full StageFull + candle/light; WiX missing → exit 1 | | `../scripts/build-full-msi.ps1` | Full StageFull + candle/light; WiX missing → exit 1 |
| `../scripts/fill-manifest-sha256.ps1` | Hash built MSI/NSIS → DOWNLOADS-MANIFEST row (no upload) | | `../scripts/fill-manifest-sha256.ps1` | Hash built MSI/NSIS → DOWNLOADS-MANIFEST row (no upload) |
| `../scripts/dual-ship-smoke.ps1` | Offline dual-ship checklist runner (print A/B/C; optional local hash) |
| `VM-DUAL-SHIP-CHECKLIST.md` | Printable clean-VM A/B/C tick sheet |
### Relation to other Windows paths ### Relation to other Windows paths
@ -184,6 +186,7 @@ day-to-day full product. **Not** Authenticode-signed; printer CAs remain
| `../scripts/build-tray-msi.ps1` | Builds tray presence MSI when WiX is installed | | `../scripts/build-tray-msi.ps1` | Builds tray presence MSI when WiX is installed |
| `../scripts/build-full-msi.ps1` | Stages StageFull + builds full MSI when WiX is installed | | `../scripts/build-full-msi.ps1` | Stages StageFull + builds full MSI when WiX is installed |
| `../scripts/fill-manifest-sha256.ps1` | Local SHA-256 rows for site DOWNLOADS-MANIFEST (no upload) | | `../scripts/fill-manifest-sha256.ps1` | Local SHA-256 rows for site DOWNLOADS-MANIFEST (no upload) |
| `../scripts/dual-ship-smoke.ps1` | Offline print of dual-ship A/B/C steps + optional MSI/NSIS verify/hash |
| `../installer-windows.nsi` | Elevated **full product** setup.exe (primary until MSI validated) | | `../installer-windows.nsi` | Elevated **full product** setup.exe (primary until MSI validated) |
| **`wix/` (this folder)** | Tray skeleton + full Product-Full authoring | | **`wix/` (this folder)** | Tray skeleton + full Product-Full authoring |

View file

@ -1,6 +1,11 @@
# VM dual-ship checklist (printable) # VM dual-ship checklist (printable)
Printable operator sheet for **clean-VM A / B / C** validation while NSIS remains primary and full MSI is dual-ship only. Narrative runbook: [DUAL-SHIP.md](DUAL-SHIP.md). Silent props: [SILENT_PROPS.md](SILENT_PROPS.md). Printable operator sheet for **clean-VM A / B / C** validation while NSIS remains primary and full MSI is dual-ship only. Narrative runbook: [DUAL-SHIP.md](DUAL-SHIP.md). Silent props: [SILENT_PROPS.md](SILENT_PROPS.md). Offline runner (prints these steps; optional local MSI/NSIS existence + hash): [`../scripts/dual-ship-smoke.ps1`](../scripts/dual-ship-smoke.ps1).
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\dual-ship-smoke.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\dual-ship-smoke.ps1 -VerifyArtifacts
```
**HelperVersion:** _____________ (expect **0.3.6** unless `VERSION=` override) **HelperVersion:** _____________ (expect **0.3.6** unless `VERSION=` override)
**NSIS artifact:** `VeraePrintStamp-windows-_____-_____-setup.exe` **NSIS artifact:** `VeraePrintStamp-windows-_____-_____-setup.exe`