Session handover — 2026-07-07 pt4¶
Continues from session-2026-07-07-pt3-handover.md (ADR-0009 columns).
This session shifted from fanning out dimensions to validation: designed and
began building the ADR-0009 §6 near-match scorecard — the ship/hold metric
that was the last-session recommendation and the unblocker for Slices 4 & 6.
One code+docs commit + this wiki commit.
What changed — where to look¶
- New contract:
docs/pipeline/near-match-scorecard-contract.md— the metric design, synthesised from two blind parallel studies (deep-reasoner + Codex, briefed identically). The crux calls: a measured-feature scorecard (not a literal pixel diff — fonts are substituted, decoration stripped); three deterministic axes (S structural / T theme / G_det masked-perceptual) under a hurdle+veto gate with thresholds fit on a batch; LLM triage-only, never the gate. Load-bearing insight: fidelity = re-measuring the deployed OUTPUT, not comparing to what we stamped (an identity). Build tracker (Steps 0–5) inside. - ADR-0009 (
decisions/0009-…md) — §6 rewritten to reference the contract; Slice 4 tracker row now logs scorecard Steps 0/1/2 shipped with numbers; Slice 6 row references the calibration method. - Code — 3 axes + emitter, all deterministic,
builds/*gitignored: lib/structural-diff.js(S, Step 0) — junk-filter → canonicalise Wix dup-pairs → heading-anchored NW alignment → omit-aware per-dim agreement → role-weighted S.lib/theme-fidelity.js(T, Step 1) — wrapsfidelity-harness.jstypography+palette into a 0–100 axis + veto flags (fallbackNavy, …).lib/perceptual-diff.js(G_det, Step 2) — section-crop coarse colour+luma grid over full-page shots; reusesstructural-diff#alignPage.lib/scorecard.js— combinedfidelity-scorecard.jsonemitter (3 axes + weight-re-normalised partial composite, not yet a verdict).lib/capture-section-backgrounds.js— additive--base/--out(symmetric re-capture of the deployed output) +--shots+rect.y(default crawl unchanged).- known-patterns: one durable entry — measuring fidelity means re-measuring the deployed output; comparing a capture to what we stamped is an identity (+ canonicalise/junk-filter corollary).
- known-issues: scorecard-in-progress (Steps 3–5 pending) + the deployed-site fidelity gaps the scorecard surfaced (garvanbay muted bands not painting; WCP service-grid columns 4-vs-3 + align/imageSide) + metric-side follow-ups.
Verified¶
- All 5
lib/*.jspassnode -c. Default probe crawl path unchanged (both new flags fall back to prior hardcoded values). - Three-axis scorecard run live against both deployed CMS workers:
garvanbay (
emdash.dcathal.org) S=96 / T=100 / G_det=80.8 (composite 93.2); WCP (wcp.dcathal.org) S=59.9 / T=100 / G_det=70.9 (72.7). The known-good site ranks near the top (the sanity anchor), WCP lands "needs-polish" — a sensible spread where every deduction traces to a real gap or defensible structural difference. - G_det adds orthogonal signal (flags garvanbay hero + WCP FAQ as top visual divergences, invisible to S). Junk-filter + canonicalise validated on real data (WCP: 6/31/9 junk sections filtered per page; garvanbay: 6 dup-pairs collapsed).
Next priority — Step 3 (the GATE), then Slices 4 & 6¶
Step 3 is the next build: the full composite + the hurdle/veto gate
(verdict: ship|manual-polish|hold) in lib/scorecard.js, enforcing the veto
flags T already collects. That turns the three axes into an actual decision.
Then Slice 4 (GenericSection + matcher-gap into S) and Slice 6 (calibrate
thresholds on a 30–50-site batch — the point where the measured pass rate, not
these two anchor points, sets ship/hold). Before G_det can gate, triage the
low-sim outliers (real vs crop artifact) — see the contract follow-ups.
Second track still open (unblocked by the metric now existing): bring more already-deployed sites through capture→scorecard to grow the labelled sample.
Carried / open (see known-issues)¶
Scorecard Steps 3–5 pending; deployed-site gaps the scorecard surfaced (garvanbay
muted-tone, WCP columns/align/imageSide) unfixed by design (metric ≠ fixes this
session); G_det real-vs-artifact triage; no .validate.mjs yet for the new pure
modules; T re-measures emission not the deployed DOM; per-site static lane still
consumes no capture; plus all prior carried items (cross-account sharding,
brand-detection nondeterminism, noindex launch blocker, …).