Skip to content

Session handover — 2026-07-13 pt4

The clean-room rebuild ran. WCP is now a pure product of the pipeline — and the headline is that it scored the same as the site it replaced, while the operator rated the result 4/10. Both facts are true, and the gap between them is the finding.

Four portfolio-wide bugs were fixed on the way, none of them WCP-specific.

What happened

1. The rebuild proved the pipeline — and proved the scorecard doesn't measure fidelity

WCP was rebuilt from inception (fresh crawl → theme → capture → seed → image migration → deploy → reseed) and re-scored across all 25 pages for the first time (every prior number was 3 cherry-picked slugs):

S T G_det composite verdict
baseline, hand-patched (3 slugs) 70.8 100 74.3 79.0 MANUAL-POLISH
rebuilt (same 3 slugs) 69.4 100 75.1 78.5 MANUAL-POLISH
rebuilt (all 25 pages) 72.5 100 72 79.3 MANUAL-POLISH

~20 sessions of hand-patches bought nothing measurable. The pipeline alone lands in the same place — and now it is reproducible. The regen independently produced the floating CTA, the SERVICE AREAS header CTA, split-center, and the topbar contact run, matching the committed seed exactly: six globals in, six out, nothing invented. Every value a previous session had to hand-type is now measured.

Then Cathal opened the deployed site and called it 4/10, listing four defects — and the scorecard could not see any of them. It said 79.3, no vetoes, globals 7/7 agree, 0 loud-fail placeholders. Green instruments over a visibly broken page. That is the fifth artifact-that-looks-like-success in this repo's run, and this session produced it.

The blind spots are enumerable — chrome, intra-block content, links, assets — and are now filed as known-issues: "The scorecard scored 79.3 on a site the operator rated 4/10" + known-patterns "The near-match scorecard is BLIND to content destroyed INSIDE a matched block". A verdict means "no structural regression", not "this site is good", and must not be reported as the latter. Arguably this precedes Slice 6 calibration: fitting thresholds on axes that cannot see the dominant defects fits the wrong model.

2. Four portfolio-wide bugs, each found by looking at the artifact

All four are fleet-wide, not WCP-specific. All are deployed (worker 51891396).

  • Brand nondeterminism — and the wiki's proposed fix would have broken garvanbay. known-issues said "the ranker isn't purely score-ordered""make it prefer the logo". The observation was right; the inference was wrong twice. It is not a ranking bug (the surface-over-logo rule is deliberate, and is the only thing getting garvanbay right — garvanbay's dominant logo cluster is yellow-green and outscores the cyan its brand actually is). And the proposed fix would have inverted it. The real defect: the rule was an absolute override, so it fired between two families that were the same colour (hueDist 2.71°, rgbDist 32 — one navy the clusterer split in two), letting a 9.22-point candidate depose a 16.97-point one. Now a two-condition tie-break (different hue and genuinely painted) that can only depose, never block. WCP restored to #183a6f; garvanbay byte-identical; old and new crawls now agree. Locked by lib/brand-palette.validate.mjs (11 checks). Two traps recorded — rgbDist/lightness runs backwards on the real data, and a score margin is structurally biased by logoAgreement. → known-issues (CLOSED + corrected), known-patterns.

  • The topbar was every CMS site's, not WCP's. topbar-wcp.astro falls back to a hardcoded cyan; the static lane passed the measured colour, the CMS adapter passed nothing — so the whole CMS fleet rendered the same cyan strip regardless of brand. Fixed in the shared theme emitter (emitGlobalCss--topbar-bg/--topbar-text), so both lanes inherit it. → ADR-0009 Slice 3.

  • The nav fabricated its links. Header.js: $label.attr('href') || '/'. On live, FARMING/COMMERCIAL/RESIDENTIAL are toggles with no <a>, children JS-mounted and invisible to the static crawl. The matcher invented /; every menu item went home. The render was already correct — a pure data-plane fabrication, produced by a matcher instead of a human. Fixed with a capture-plane probe (chrome.navRaw, schemaVersion 4 → 5), grouping by DOM containment (URL-prefix grouping provably fails on WCP). Overlay REPLACES rather than fills-if-empty — a fabricated / reads as "already set".

  • The icon cards' text was destroyed — and the pt6 fix is what did it. fromUspBar split on imagery, so an icon+text CARD (which has both) took the logo branch and lost its text, silently (the src was present, so nothing loud-failed). Corrected to split on TEXT. fcr.usp-bar gains imageUrl — pt6 had dropped the scraped icon rather than give it a home. → known-patterns "One emitter, two item shapes" (Correction).

3. Preconditions landed

  • Baked-seed identity assertion — now in astro.config.mjs at config load, so npx astro build cannot bypass it (prebuild could be). A mismatched .emdash/seed.json refuses to build. Closes the hard blocker on ADR-0008 Slice 3 fleet provisioning. → ADR-0008.
  • Safety — both live D1s exported + Time Travel bookmarks → rebuild-2026-07-13-restore-path. Verified by reading them (WCP's operator-authored native block is in the dump; it is an empty paragraph, so the reseed was allowed to drop it).
  • r2-basename-map.mjs graduated from the scratchpad to a committed per-site helper — though it did no work: the scope's "must re-use the map" premise is false, corrected in place. R2 keys are sha256(bytes)-derived and a rebuild re-crawls the bytes (idempotent: 299). → scope correction.
  • transform-seed-images was still calling searchFiles — the contract ADR-0010's second amendment superseded that morning. Now mediaPool.
  • quick-crawl.js un-hardcoded from its EC2 path. (Bonus: the original AWS S3 crawler is real, but it lives in the superseded replatform-dev repo — the current crawler never wrote to S3 or R2.)

Verification

  • WCP: all 25 pages HTTP 200, 0 loud-fail placeholders, 0 raw /assets/ paths, globals 7/7 agree with live, hero carousel 8/8 + video, phantom social rail gone.
  • Nav: 3 <button> toggles + 10 dropdown children; only HOME has href="/".
  • Topbar: serves --topbar-bg: oklch(92.6% .002 17) (WCP grey), not the cyan.
  • Icon cards: all four render text + icon from R2.
  • Shared-surface regression checks: garvanbay theme.json unchanged, its emitted global.css same md5, its regenerated header byte-identical (its capture is v4 → the nav dim is skipped with a loud warning, exactly as designed).
  • Validators: brand-palette 11, section-style 159, check-renderers green.

Next session

  1. The scorecard's blind spots — chrome / intra-block content / links / assets. This is the highest-value work in the repo right now: without it, no number can be trusted as a fidelity claim, and Slice 6 would calibrate the wrong model.
  2. insertedOurs: 51 (47 content) — we render 51 sections live doesn't have. The single largest structural drag; likely the known responsive-double re-match over-production.
  3. garvanbay's clean-room rebuild + the live-asset harvest (§5 of the scope, never run) — the instrument that splits at-source-never-pulled: 298 into real capture debt vs library cruft, and the 45-video question.
  4. FAQ renders navy where live is white — 19 of 25 pages, the dominant G_det drag.
  5. Home page drops the client-logo strip entirely.
  6. Audit the fleet for other fabrications — still open, and this session found two more (Header.js's || '/', and pt6's dropped icon). A fabrication does not need a human hand.

The through-line

pt7: check the producer before believing a capture gap. pt2: check the artifact before believing a detector shipped. pt3: check the artifact before believing LIVE is the truth.

This run: check the artifact before believing the INSTRUMENT. Every green light this session was, at some point, wrong:

  • the scorecard said 79.3 over a page the operator rated 4/10;
  • globals reported the topbar as agree — because null matched null;
  • an R2 enumeration keyed by domain returned a confident zero objects;
  • a pgrep liveness check "completed" instantly (it cannot see node.exe on Windows), so twenty minutes of analysis ran against an artifact hours stale — and then propagated it;
  • a probe reported the ribbon as icon-less because it filtered on non-empty alt;
  • and the wiki itself proposed a brand fix that would have broken the other reference site.

The four bugs that mattered were all found the same way — by looking at the thing: the live DOM, the persisted JSON, the rendered page. The operator's screenshot caught what six of my probes did not. The instruments are not the site. The next slice is making them able to see it.