Skip to content

Session handover — 2026-07-14 pt2

A follow-on to pt1. It began as "are we using a vision model to score our near-final output?" and ended by rejecting the vision model and fixing the gate instead — because the scorecard was never blind. It measured the owner's defects and threw them away.

ADR-0011 — Accepted. Slices 1a and 1b shipped. Both reference sites now HOLD, for real reasons.

The finding that inverted the decision

I drafted an ADR for a "vision editor" — a VLM proposing schema-legal config changes. An adversarial review ran the scorecard instead of reasoning from my brief. Every claim verified:

variantMismatch.count  (the HEADLINE) : 0
variantMismatch.items  (the DETAIL)   : 38
   x19  faq    tone: default → brand      <- the owner's "the FAQ is the wrong colour"
   x14  ribbon tone: brand   → default
   x 5  content tone: brand  → default

The FAQ defect was measured nineteen times and reported as zero. It had been sitting in fidelity-scorecard.json the whole time.

Cause: one constant. critical is tagged iff ROLE_WEIGHT >= criticalRoleWeight (1.3) — but ROLE_WEIGHT is a visual-importance number (faq 0.75, ribbon 0.5, content 1.0), so those roles could never be critical by arithmetic. And four of the five defects were already computed elsewhere: globals-diff and asset-manifest are literally "mode": "reporting-only"; lib/verify-content.js (10 KB) already detected destroyed intra-block content and had never been wired in.

Zero of the five needed a VLM. A gating and aggregation failure, misdiagnosed (by me) as a perception failure.

What shipped

Slice 1a — the systematic veto (26c026f). Role-agnostic, weight-agnostic; fires on SYSTEMATICNESS: the same (role, dim, live→ours) across ≥5 sections and ≥3 pages is a broken producer — one bug, N symptoms, not N tickets. structural-diff.js untouched, S byte-identical (the conflation was a policy bug, fixed where policy lives). Gate validate 29 → 41.

Slice 1b — the C axis (9222fc8). verify-content.js never landed because it had its own bespoke aligner — two instruments that align differently cannot be reconciled. So the signal moved into the capture (content census, schemaVersion 5 → 6) and lib/content-diff.js reuses structural-diff#alignPage, so C and S agree by construction. Vetoes contentDestroyed + fabricatedLink. C is deliberately NOT in calibration.weights — an unfitted 4th weight would re-scale S/T/G_det and silently re-rank the portfolio; the vetoes gate, scoring waits for Slice 6. S/T/G_det byte-identical, proven twice. +38 checks.

Where the two sites now stand

site verdict why — all real, all documented
WCP HOLD systematicVariantMismatch (faq tone ×19 / ribbon ×14 / content ×5) + contentDestroyed
garvanbay HOLD criticalSectionDropped/contact has no hero at all (renders only fcr.map + fcr.contact; the known pre-canonical page). Surfaced by pt1's isJunk fix.

The numbers got worse. The sites did not change. The instrument stopped lying.

Three new bugs, found by the new instruments on their first run

  • fcr.gallery has NO TEXT FIELD — live's 218-char gallery intro is destroyed on every site that has one. The block cannot carry it; S scored the section a clean match. Found by contentDestroyed on run 1.
  • tone is an INERT LEVER on cta-wcp — it accepts tone and then hard-paints an inline background: that beats any tone rule. All 19 WCP cta-strips already carry tone: "brand" and the ribbon still measures wrong. The bounded dimensions are unaudited, and this one would have silently defeated any config-writing agent.
  • imagesDropped is representation drift — Wix paints a full-bleed background as an <img>; we paint it as a CSS background-image. Reported, deliberately not scored or gated (it ranked garvanbay below WCP).

Also this session

  • A fix you did not EXECUTE is a HYPOTHESIS — a new protocol rule, plus its reading-side corollary in session-start. The wiki's measurements have been reliable; its untested fix proposals were wrong three for three (they would have broken garvanbay, collapsed zero pairs, and hidden the video debt). 4 entries in known-issues are now marked Fix candidate — UNTESTED HYPOTHESIS; chores were deliberately not marked, because a marker applied everywhere means nothing.

Next

  1. Slice 1c — promote globals-diff + asset-manifest to vetoing. globals-diff must compare chrome PALETTE, not just structure (it reported 7/7 agree on a site whose topbar was another client's cyan — a null-vs-null match checks nothing). 45 of 46 videos missing is a veto, full stop. Plus an ours-side background-image probe so imagesDropped can gate.
  2. Slice 1d — the lever audit. For every (block, select, value), prove the render changes. Fix tone on cta-wcp — very likely the producer behind 1a's 14 ribbon tone rows.
  3. Then honestly re-ask whether ADR-0011 Slice 2 (the VLM) is worth building at all. Its only structural justification is correlated blindness — S re-measures OUR output with the SAME probe that measured live, so a dimension the probe misses is invisible on both sides and they agree in the blind spot (exactly how globals reported the topbar as "agree": null vs null). If Slice 1's punch-list already matches an owner's read of the page, the VLM's marginal value is small.
  4. Still untouched from pt1: garvanbay's clean-room rebuild, the live-asset harvest, the FAQ container split, FAQPage JSON-LD, video segmentation.

The through-line

pt1: check the artifact before believing the INSTRUMENT. This run: check whether the instrument's finding ever reaches the VERDICT.

The scorecard was not blind. It saw 38 mis-renders and rolled them up to 0. verify-content.js saw the destroyed content and was never plugged in. globals-diff and asset-manifest saw the chrome and the missing videos and were both marked reporting-only. The pipeline knew. Nothing asked it.

And my instinct — buy a better instrument — was the expensive wrong answer, arrived at without reading the artifact the existing instrument had already written. The adversarial review's first move was to run the scorecard. That is the whole lesson, again.