step.24.diff.txt -- narrative retro for step.24 (U5.3: the SCB validation tier). Companion: step.24.gdiff.txt via ../scripts/step_gdiff (machine half). Executed: 2026-07-22, same session as steps 22-23. WORK commit d4ca480. ## Plan vs actual +---+--------------------------------------+--------------------------------------+ | # | Planned (brief) | Actual | +---+--------------------------------------+--------------------------------------+ | 1 | "Quartet byte-identity where the | The b3u first-run precedent scoped | | | workspace consumes SCB APIs" | it honestly: V0 = the interpreted | | | | pair (py+js), byte-identical over | | | | delivered bundles; cpp/rust = named | | | | toolchain-gated future (Q-24-A -- | | | | integrity-only on the b3u side too). | | 2 | The check's runtimes | CLIENT POSTURE WON (Q-24-D): fetched | | | | through the port's NEW package() op | | | | (already frozen in contract v1 -- | | | | zero new server surface), cached in | | | | the data home; sibling checkouts | | | | rejected as a posture violation. | | 3 | (implied) tool-surface fit | Two named extensions: node in the | | | | default allowlist + engine-only | | | | extra_env on run_shell (PYTHONPATH | | | | for the delivered runtime), both | | | | secret-name-filtered, both tested. | +---+--------------------------------------+--------------------------------------+ ## Surprises / genuine findings 1. **Stub runtimes made the arc hermetic.** The identity check's green AND fail paths seemed live-only until the inversion: ship tiny copy-input-to-output py/js "decompilers" as replay package fixtures -- identity then holds iff the two halves' .bfgr bytes agree, so divergence is arranged by data, not by runtimes. Zero CCS anywhere in the hermetic suite. 2. **The contract paid for itself again**: the runtime fetch needed NOTHING new on the b3u side -- GET /packages/{lang} was frozen at UB.2 before this consumer existed. package() on the port is purely additive (the port's own C-52-B-style law, recorded at U5.1). 3. **extra_env stayed narrow by writing the lock first** (C-24-D): the parameter is the exact hole Q-15-B closed, so it ships engine-only, secret-name-filtered even for the engine, and key-name-trailed -- the falsifier lives in the shell suite. 4. The live leg is the SCB isomorphism at full client distance: plane-generated bundle -> plane-delivered runtimes -> byte-equal. Nothing local, nothing sibling, nothing simulated. ## Scope discipline In: the U5.3 row + the two tool-surface extensions it forced (named, locked, tested). Out and named: cpp/rust identity legs (Q-24-A), .fgr-vs-.bfgr cross-format identity, cache invalidation (delete-the- dir is the named manual remedy), U5.4/U5.4a/U5.5. Zero b3u-repo changes; zero CLI changes. ## Numbers - New: app/ccs/scb.py (discovery/cache/builders), package() on the port + client + replay, the scb_identity handler branch, 2 tool- surface extensions, 11 tests (10 hermetic + 1 live), 3 shipped stub-fixture builders (in-test). - Suite: 616 -> 629 collected (11 new + 2 own-corpus step.24.txt); 608 passed + 21 skipped (20 + the scb live leg), 0 failed. - p5_gates: live 9 -> 10 legs; hermetic twin 33+9 -> 43+10; ALL PASS first post-extension run. Numbers measured with the step file in the corpus. End of retro.