@@ -363,3 +363,110 @@ re-established: the lane outputs were consumed as-is and never rebuilt or edited
363363** Next unit:** T010, the freeze supersession. It inherits a parity claim that is real but
364364shallow, plus one named finding — any pigallery2 claim past the loading shell needs the
365365live-backend seam, not another static serve.
366+
367+ ---
368+
369+ ## T009d — pigallery2 on its own live backend: the two lanes are ** not** the same
370+
371+ ` pigallery2-live-witness.json ` · schema ` versionless.angular-13cell-live-witness.v1 ` ·
372+ sha256 ` b2318d0a42f51bcd4fba43c94907d0a2a8c2ea20fcc354c51fa29e583b41fa12 `
373+
374+ T009c named the seam and this unit walked through it. pigallery2's ** own Express
375+ backend** — ` backend/index.js ` , copied byte-for-byte out of the frozen baseline checkout
376+ and run at its ** era Node v10.24.1** (x64 under Rosetta; the Node-16 fallback the packet
377+ allowed was never needed) — was stood up on ` 127.0.0.1:32701 ` , pointed at one built lane
378+ at a time, and witnessed in real Chromium through the pipeline's witness host.
379+ ` successfulNonLoopback: 0 ` on both lanes, structurally.
380+
381+ ** The answer is no, and the reason is a real migration defect.**
382+
383+ | | baseline (Angular 8.1.2) | migrated (Angular 13.4.0) |
384+ | ---| ---| ---|
385+ | bundles served | all 200 | all 200 |
386+ | ` ServerInject ` rendered | yes | yes |
387+ | application bootstrapped | ** yes** | ** no** |
388+ | route it settled on | ` /gallery/ ` (its own redirect) | ` / ` (it never navigated) |
389+ | API calls made | ` GET /api/notifications ` , ` GET /api/gallery/content/ ` — both 200 | ** none** |
390+ | gallery grid | ` app-gallery-grid ` with ** 3** ` app-gallery-grid-photo ` tiles, text "3 Images / 3 items" | absent, ` <app-pi-gallery2> ` empty, no visible text |
391+
392+ Chromium's verbatim console error on the migrated lane:
393+
394+ ```
395+ ERROR Error: Uncaught (in promise): ReferenceError: $localize is not defined
396+ ReferenceError: $localize is not defined
397+ at consts (http://127.0.0.1:32701/main.4b2fa472bc230245.js:1:241772)
398+ ```
399+
400+ The Angular 13 build emits ` $localize ` -tagged i18n constants and the lane loads no
401+ ` @angular/localize ` polyfill; the Angular 8 lane never needed one because its build
402+ substituted translations at compile time. ** Nothing was repaired** — rebuilding or
403+ hand-editing an emitted lane is a separate unit.
404+
405+ Read the two differing outcome strings the right way round: the migrated lane's * higher*
406+ ` route-reached-1-of-3 ` is the * worse* lane. The baseline lane scores 0 because the
407+ running application routed itself off the declared ` / ` ; the migrated lane "reached" ` / `
408+ only by never leaving it.
409+
410+ ** Why the earlier units could not see this.** T009b measured that both lanes build, twice,
411+ byte-identically — and a build that emits ` $localize ` calls and omits its polyfill is a
412+ perfectly deterministic build. T009c measured a static serve in which * neither* lane
413+ bootstrapped, and two lanes that both fail to start look identical. It took the live
414+ backend for the lanes to differ, because it took the live backend for either of them to
415+ run at all. T009c's ` parity.identical: true ` is hereby ** superseded** as a claim about
416+ behaviour; its finding and its ` notEstablished ` stand unchanged.
417+
418+ ### Media
419+
420+ Three 64×48 solid-colour PNGs, ** generated locally** by
421+ ` .versionless/work/angular-pigallery2/logs/t009d-gen-media.cjs ` (zlib + a hand-written
422+ CRC32, no image library, nothing fetched), identical for both lanes. The backend really
423+ indexed them: ` GET /api/gallery/content/ ` returned ` mediaCount: 3 ` with exactly those
424+ names.
425+
426+ ### The seam, operated rather than extended
427+
428+ ` witness:real-app --journeys synthesized ` takes lane ** directories** and serves them
429+ itself; the live-backend path (` AppSpec.backend ` → ` packages/cli/src/witness/live-backend.ts ` )
430+ is reachable only from a registered AppSpec whose name is in the closed
431+ ` WITNESS_REAL_APP_STATEFUL_NAMES ` / ` WITNESS_REAL_APP_PROJECTED_HOLDOUT_NAMES ` lists.
432+ Admitting pigallery2 there is a ` packages/** ` change this unit was forbidden to make, so
433+ the crawl reader, the outcome vocabulary, the emitter and the Playwright witness host
434+ were ** imported and driven unchanged** against the live origin. No ` packages/** ` file was
435+ written.
436+
437+ ### Reproduce
438+
439+ ``` sh
440+ node .versionless/work/angular-pigallery2/logs/t009d-gen-media.cjs < repo> /.versionless/work/angular-pigallery2/serve/media
441+ sh .versionless/work/angular-pigallery2/logs/t009d-backend.sh setup baseline < repo> /.versionless/work/angular-pigallery2/baseline/t009b-baseline-run1
442+ sh .versionless/work/angular-pigallery2/logs/t009d-backend.sh start baseline
443+ node --experimental-strip-types .versionless/work/angular-pigallery2/logs/t009d-live-witness.mjs \
444+ baseline http://127.0.0.1:32701 < logs> /t009d-plan.json derive < logs> /t009d-lane-baseline.json
445+ sh .versionless/work/angular-pigallery2/logs/t009d-backend.sh stop baseline
446+ # ... then the same three steps for `migrated`, with `replay` instead of `derive`
447+ T009D_HEAD=$( git rev-parse HEAD) node .versionless/work/angular-pigallery2/logs/t009d-emit-live-witness.cjs
448+ ```
449+
450+ One lane at a time; the backend is stopped (and any survivor ` pkill ` ed) between lanes,
451+ because a stale process holding the port would serve the wrong lane and mask exactly the
452+ difference this unit found. Each lane's served ` main.*.js ` filename was checked against
453+ that lane's build before witnessing it.
454+
455+ ### What T009d does not establish
456+
457+ ` notEstablished ` in the JSON is the binding list. In short: a ** three-image generated
458+ gallery is not the fleet's media diversity** — no EXIF, GPS, faces, video, sidecars or
459+ nested directories, so nothing here speaks about metadata, map, person or transcoding
460+ surfaces. ** Auth was off** (` authenticationRequired: false ` , unauthenticated role Admin),
461+ so login, sessions and every role boundary are untested. The database was the
462+ ** in-memory** backend, not SQLite — identical on both lanes, so it cannot explain the lane
463+ difference, but the application itself disabled search, sharing and faces and said so in
464+ two "Server error" notices. The baseline lane is ** not certified working** : it mounts,
465+ routes, calls its API and renders three tiles; ` photoImages ` is 0, so no thumbnail is
466+ claimed to have loaded, and nothing was clicked. The migrated lane's defect is ** named,
467+ not diagnosed to its root** — no build with the polyfill was attempted. One journey, one
468+ pass, one host; no screenshots, pixels, accessibility or performance readings. Both lanes
469+ ran the ** era backend** : nothing here speaks about a migrated backend, which does not exist.
470+
471+ ** Next unit:** T010, the freeze supersession — now inheriting a live-backend parity claim
472+ that is real and ** negative** .
0 commit comments