Property-page callback invocation ownership

2026-10-18. Source prerequisite for the Circus Linux CRTDLL jump pair; no jump API is enabled. propsheet_page_callback is an explicit example in the setjmp audit because it restores an interrupted guest context after nested execution. Its PSPCB_CREATE and PSPCB_RELEASE callers share this runner.

The runner now allocates its child before writing the guest frame and retains the expected child, root and synchronous depth in invocation-local WAT locals. Before popping or restoring any caller register it checks those values. A completed three-argument stdcall must also restore the exact entry ESP. Missing callbacks still return one without allocating a child. The existing bounded incomplete-call behavior remains zero with ordinary caller restoration when the original owner remains current; that behavior is not nonlocal-jump proof.

test/test-propsheet-invocation-ownership.js authors real x86 callbacks using an imported GetTickCount and RET 12. It exercises nested and sibling callbacks, with guest instructions capturing all three stdcall arguments in separate records and asserting NULL hwnd, CREATE/RELEASE message and guest page pointer; multiple run slices, missing flag/function, malformed RET, bounded timeout, guest trap, host exception, leaked child, equal-depth sibling substitution, changed synchronous depth and process retirement. Capacity and ID exhaustion assert unchanged registers, stack bytes and private ownership state. The test exposes the actual internal runner, reduces only its run budget, and supports both normal and --no-tail-calls compilation. It does not exercise the entire property-sheet UI or actual OS Worker scheduling.

Source validation: changed fragment parser, census (396 records, one reviewed record changed), census mutation tests, JS syntax and diff whitespace checks passed. The new guest test has not run and no build was performed. Run both dispatch variants under the root's exclusive runtime grant, followed by normal build and existing property-sheet, synchronous-window, token and lifecycle regressions before integration. Sparse dependencies must be restored by exact closure with the usual 2 GiB floor; no binaries are part of this commit.

Traps retain the child until explicit host-quiescent reset. Concurrent process or slot replacement is not made safe. Other synchronous runners, retained CACA families, cross-thread send, JS COM, timer/wave/APC paths, SEH, saved-buffer validation and the dispatcher nonlocal restore exception remain separate prerequisites. The inventory continues to mark all ownership pending.

Granted compiled validation

The source-only status above was superseded by root-granted validation on 6f8e31979c0a31381f7018db37311e4b5b96ae70, incorporating reviewed main ea57e62de. Both dispatch variants of the actual-x86 fixture passed, including the explicit guest-captured CREATE/RELEASE argument values and nested records. The normal gated build, existing property-sheet page-handles, wide and main-hwnd regressions, synchronous-window ownership, private token and production PE/NE/thread-lifecycle tests all passed. No game was run.

The candidate is 1,870,624 bytes, SHA-256 da72a16f9551cb2cd8bc2f0ee636eb966ec9c7cde9a56931201bb6d1fb11a2c7. The root canonical artifact remained SHA-256 203163dda45d61b905a53bfbe2ad0128d006092b087a73d48a776bafd330ead0. All nine process groups exited; no disk, deadline or log guard fired. Minimum sampled free space was 3,250,712,576 bytes. Guards admitted above 2 GiB + 128 MiB, stopped below 2 GiB + 64 MiB, and capped each command at 180 seconds and 8 MiB.

Evidence remains in the isolated worktree under scratch/runs/20261018-propsheet-ownership-validation/: per-command receipts and logs, artifact hashes, prior canonical/combined copies, source pins, preflight and guard. The granted preflight's actual free space was 3,316,080,640 bytes (the initial board claim quoted an earlier reading). Restore its exact build-closure-paths.txt with sparse-checkout before reproduction; restore the verified 94,208-byte test/binaries/calc.exe from the fixture source recorded in granted-preflight.json. Use the existing /tmp/wa-local-runtime-deps/node_modules through NODE_PATH, without installs. Run the nine commands recorded in the JSON receipts under guard.js and a fresh disk admission. Git does not preserve these ignored artifacts; keep the evidence directory and fixture separately. The task checkout is narrowed after validation, preserving its ignored build and evidence. Remaining ownership and jump prerequisites above are unchanged.