# PGM parity staged runbook (2026-07-22)

This runbook is for the designated local development Tornado2/PGM target only.
It does not replace the target, path, hash, listener, package, or `OutcomeUnknown`
stops implemented by `scripts/Invoke-LegacyPgmParityRun.ps1`.

## What is different from the older artifact scripts

- A new evidence directory captures the currently registered package, application,
  PGM, executable hashes, process IDs/start times, window handles, TCP listeners,
  the CDP target, and all 33 authoritative cut hashes exactly once. The 33rd cut is
  `6001`; `5006` remains outside this live inventory until its cube video exists.
- Live staging accepts only the registered x64 loose development package whose
  install root is the current workspace's exact
  `src/MBN_STOCK_WEBVIEW.LegacyParityApp/bin/x64/Debug/<tfm>/win-x64/AppX`
  boundary. A Release, customer-installed, or WindowsApps package is rejected.
- The exact package runtime files pinned are
  `MBN_STOCK_WEBVIEW.LegacyParityApp.exe`,
  `MBN_STOCK_WEBVIEW.LegacyParityApp.dll`, and
  `MBN_STOCK_WEBVIEW.Playout.dll`.
- The `S6001AssetIndependent` workflow additionally pins the authoritative and
  runtime copies of `images\주유기merge.png` and `images\35752913_l.jpg` by length
  and SHA-256 before any input. The 13 country videos are not silently substituted.
- The app-side PGM connection must be entirely loopback and must have exactly one
  reciprocal established row owned by the pinned PGM process. A same-numbered
  port on another host cannot pass preflight.
- Every later stage must match all captured identities before the input, after the
  input, and after read-only evidence capture.
- PGM uses a DirectX surface, so evidence capture temporarily raises only the exact
  pinned PGM or app window without activating it, captures its screen rectangle,
  and restores the original top-most state. This prevents unrelated foreground
  windows from being recorded while preserving keyboard focus.
- Every invocation performs at most one staged action. There is no command retry.
- A timeout, `OutcomeUnknown`, probe violation, identity change, or broken Network
  Monitoring anchor creates `STOPPED.json`. That run directory cannot dispatch a
  later command.
- The validation playlist uses only in-memory `legacy-*` rows. It does not load or
  save a temporary named DB playlist. The comparison build still creates and then
  deletes the same temporary comparison pairs required by the application feature.
- A fresh app instance and a fresh evidence directory are required for each primary
  workflow below. `Recovery8001`, `Recovery5077Page2`, and `ThirtyRoutes20To29` are
  constrained recovery workflows and may start only from their exact known states
  and preserved evidence.

## Static and dry checks

Static validation does not inspect or attach to the app/PGM and sends no native
message:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File `
  .\scripts\Invoke-LegacyPgmParityRun.ps1 -Action StaticAudit
```

The current accepted static result pins 33 cuts and reports workflow stage counts
`Core5001=6`, `ThirtyRoutes=125`, `PagedBoundary=24`,
`S6001AssetIndependent=18`, `Recovery8001=1`, `Recovery5077Page2=1`, and
`ThirtyRoutes20To29=41`. Static success is implementation evidence only; it is not
an actual PGM result.

After the current package app and the designated development PGM are running and
connected, a dry preflight reads identities only. It does not attach to CDP, write
evidence, or send a native message. Supply the exact local PGM executable at run
time; do not commit that machine-local path:

```powershell
$pgmExecutable = $env:MBN_STOCK_PGM_EXECUTABLE
if ([string]::IsNullOrWhiteSpace($pgmExecutable)) {
  throw 'Set MBN_STOCK_PGM_EXECUTABLE to the designated development PGM executable.'
}

powershell.exe -NoProfile -ExecutionPolicy Bypass -File `
  .\scripts\Invoke-LegacyPgmParityRun.ps1 -Action DryPreflight `
  -ExpectedPgmExecutable $pgmExecutable
```

## Start one workflow

Choose a primary workflow: `Core5001`, `ThirtyRoutes`, `PagedBoundary`, or
`S6001AssetIndependent`. Use a new, nonexistent evidence directory. Initialization
is read-only with respect to the app and PGM; it freezes the identities and captures
the baseline windows and Network Monitoring text. Do not select `Recovery8001`,
`Recovery5077Page2`, or `ThirtyRoutes20To29` unless the stop handling section's
exact recovery prerequisites are already met.

```powershell
$run = Join-Path (Resolve-Path '.').Path `
  'artifacts\pgm-evidence\MBNWEB-YYYYMMDD-PARITY-01'

powershell.exe -NoProfile -ExecutionPolicy Bypass -File `
  .\scripts\Invoke-LegacyPgmParityRun.ps1 -Action Initialize `
  -Workflow Core5001 -EvidenceDirectory $run `
  -ExpectedPgmExecutable $pgmExecutable
```

Inspect always reports the next required stage without sending input:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File `
  .\scripts\Invoke-LegacyPgmParityRun.ps1 -Action Inspect `
  -EvidenceDirectory $run
```

Dispatch exactly that one stage:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File `
  .\scripts\Invoke-LegacyPgmParityRun.ps1 -Action RunNext `
  -EvidenceDirectory $run
```

Do not loop `RunNext` blindly. Review its result and the new stage directory before
issuing the next invocation. `RunStage` is also available when the action and route
or page index should be written explicitly; it refuses anything out of order.

## Exact workflow sequences

`Core5001` contains six one-shot stages:

1. bootstrap the safety probe and confirm empty connected IDLE;
2. build in-memory 5001/5074 rows;
3. TAKE IN 5001;
4. playlist NEXT to 5074;
5. Page NEXT from 5074 page 1 to page 2;
6. TAKE OUT 5074.

`ThirtyRoutes` contains 125 stages: bootstrap, four in-memory build phases, then
four stages per route (`activate`, fast TAKE IN for the PGM frame, read-only wait
for settled PROGRAM, TAKE OUT) in this order:

```text
5016, 50160, 5078, 8067, 5086, 50860, 5023, 5024, 5077, 5082,
5083, 5084, 5085, 5088, 6067, 8035, 5011, 8003, 5037, 8001,
5026, 5087, 5029, 8032, 5032, 5076, 5079, 5080, 5081, 5025
```

`PagedBoundary` contains 24 stages: bootstrap, build 5077/5088, TAKE IN 5077,
19 individual Page NEXT inputs through page 20, playlist NEXT to 5088 page 1,
and TAKE OUT. It requires exact fresh-read boundaries of 5077 = 120 items / 6 per
page / 20 pages and 5088 = 240 items / 12 per page / 20 pages.

`S6001AssetIndependent` contains 18 stages: bootstrap, one physical double-click
build stage that creates exactly these four `6001` rows, then four stages per row
(`activate`, TAKE IN, read-only settled PROGRAM wait, TAKE OUT):

```text
fixed-072  유가 두바이 지수  DubaiCrude
fixed-073  유가 WTI 지수     WtiCrude
fixed-074  유가 브렌트유 지수 BrentCrude
fixed-075  금 지수           Gold
```

These actions use only the two globally pinned image assets. They do not exercise
or claim parity for the 13 country-video actions. The workflow's static audit and
the accepted `MBNWEB-20260722-S6001-04` actual-PGM run both pass. Record completion
only when one evidence directory contains all 18 ordered one-shot stages, no
`STOPPED.json`, final IDLE, and the limitations described below.

`Recovery8001` contains one TAKE OUT stage. It is valid only after read-only
inspection proves the interrupted `ThirtyRoutes` run stopped in the exact known,
settled `PROGRAM 8001` state with unchanged identities and
`OutcomeUnknown=false`. It must not be used to guess or repair an unclear state.

`Recovery5077Page2` contains one TAKE OUT stage. It is valid only after read-only
inspection proves the exact preserved `PagedBoundary` manifest is settled in
`PROGRAM 5077`, page 2/20, with 120 items, page size 6, one completed refresh,
no pending command, and `OutcomeUnknown=false`. It is not a general PageN repair.

`ThirtyRoutes20To29` contains 41 stages: one read-only manifest reconciliation and
four stages for each route index 20 through 29. It is valid only after the first 20
routes and the exact 30-row in-memory manifest have been preserved and reconciled.

## Completed evidence baseline

The accepted latest 2026-07-22 development PGM baseline is split across these
preserved directories:

- `MBNWEB-20260722-LATEST-CORE-01`: latest combined `Core5001` 6/6;
- `MBNWEB-20260722-THIRTY-02`: routes 0 through 18 completed and route 19 `8001`
  reached a correct PGM frame. The subsequent read-only wait hit the runner's old
  90-second limit because the original 8001 first-refresh interval is 120 seconds.
  The wait sent no SDK command; the app remained in known `PROGRAM 8001` with
  `OutcomeUnknown=false`. This is a runner timeout, not an app or scene failure;
- `MBNWEB-20260722-RECOVERY8001-01`: after read-only confirmation that the 8001
  refresh had settled, one exact TAKE OUT returned the known state to IDLE;
- `MBNWEB-20260722-THIRTY20-29-01`: constrained resume 41/41, completing routes
  20 through 29;
- `MBNWEB-20260722-LATEST-PAGED-04`: latest combined `PagedBoundary` 24/24,
  including 5077 page 1/20,
  all 19 Page NEXT inputs through 20/20, playlist NEXT to 5088 page 1/20, and
  final TAKE OUT/UNLOAD/IDLE;
- `MBNWEB-20260722-S6001-04`: `S6001AssetIndependent` 18/18. One physical build
  created the Dubai, WTI, Brent, and Gold rows; each row completed activate,
  TAKE IN, settled PROGRAM observation, and TAKE OUT exactly once. The final state
  is IDLE with no retry, timeout, `OutcomeUnknown`, probe block, or violation.

The older `CORE5001-05` and `PAGED-01` directories remain historical evidence but
are not the latest combined-code approval. The split thirty-route evidence verifies
all 30 entries in that workflow, `LATEST-CORE-01` verifies the additional
`5001`/`5074` pair, and `S6001-04` verifies the approved image-only scope of route
code `6001`. This yields 33 of 34 active runtime route codes with actual PGM evidence
within the stated action scope. `LATEST-PAGED-04` independently fixes the current
PageN/long-run boundary. `s5006` remains blocked by its cube video, and the 13
`s6001` country-video actions remain asset-blocked.

The Core, thirty-route, and Paged accepted runs have matching Network
request/success counts and zero `FAILURE`, `ERROR`, probe block, violation,
`OutcomeUnknown`, or retry. `S6001-04` has matching required LOAD 4, PREPARE 8,
PLAY 8, and UNLOAD 4 successes. Its 24 `FAILURE` lines are exactly eight each for
`VALUE_SET wonText`, `FACE_COLOR wonText`, and `VALUE_SET pattern`; the 120 `ERROR`
lines are the associated engine cause text rather than 120 distinct failures. The
authoritative `6001.t2s` lacks those helper objects, while the original `s6001.cs`
attempts the same calls and swallows their exceptions. Required movie, unit, title,
quote, direction-color, PREPARE, and PLAY operations succeed and the four PGM
captures are correct. Keep this inherited template limitation explicit rather than
claiming an error-free `s6001` Network log.

The diagnostic `S6001-01`, `S6001-02`, and `S6001-03` evidence remains preserved
and is not combined with the accepted count. The first exposed a hidden catalog
workspace, the second refused initialization while the exact PGM window was
minimized, and the third exposed a missing fixed-action probe allowlist entry. None
is an accepted partial completion. Only `S6001-04` supplies the complete 18/18
baseline.

The suspected approximately 65-second 5077 Page NEXT transition was an observation
artifact, not a runtime defect. Each of the 19 Page NEXT stages emitted exactly one
effect, PREPARE, and PLAY; `SCENE_PLAYED` followed PLAY in 144-188 ms. Immediate,
45-second, and 65-second-named captures for pages 9 and 20 are byte-identical, and
all 17 stages with delayed captures match their immediate capture hashes. The
original and packaged `5077.t2s` files also have the same SHA-256:
`845B99DFC499B5BDCD84058D68D91D849D59FB6692CB44784118A99EA68A20E2`.
Do not add waits or change fade units based on the image-view display inconsistency.

## Stop handling

If `STOPPED.json` exists, do not delete or edit it and do not start another command
from that run directory. Preserve the complete directory, inspect the last stage's
`node-stderr.json`, `node-result.json`, `pins-*.json`, Network text, and screenshots,
then diagnose from read-only state. Never resume the stopped directory itself. The
normal path is a fresh app instance and a new evidence directory after the state is
known. `Recovery8001` and `Recovery5077Page2` are the only same-app single-TAKE-OUT
exceptions; `ThirtyRoutes20To29` is the only constrained manifest continuation.
Use each only in a new evidence directory after every exact known-state prerequisite
above has been proved read-only; otherwise close normally and restart fresh.
