← Files Unbounce - Classic BuilderARCHIVED FILE

skills/mcp-modernize/rules/verification.md

5.7 KB · Oct 4, 2026 · 12:22 UTC

↓ Download file

# Verification — audit completion, hard stops, delivery

There is no screenshot step: verification is deterministic checks you run
against your own output, plus the human's eyes on the preview. The act of
looking up actual values and counting things in your output IS the check —
"looks right" without evidence is the failure mode this file prevents.

## Audit completion check (before writing back)

Walk every row of the Step-4 audit and name the specific element in your output
that satisfies it. An audit row without a matching output element means the
rewrite is incomplete — add the element, don't rationalize.

- **Text walk** — grep your output for every audited source string
  (whitespace-insensitive). Any miss without a recorded phase-2 substitution
  pair is a fail.
- **Count walk** — per hint row, output items must equal `rows[i].length`;
  form field count and order must match; `<form>` count must match.
- **Multi-role assets** — the same image used as both a background and an inset,
  or the same string in two CTAs, needs BOTH uses. Dedupe by
  (source + role + position), never by source alone.

## Closure checks against the extracted signals

`get_layout_hints` hands you machine-checkable inventories; close each set
(exact string match) and show the counts:

- **Image-src closure** — the set of `src` values in your output equals the
  hints' `images[].src` set plus any background-image URLs from the audit. A
  hand-transcribed URL that dropped a path segment fails this; skimming does
  not catch it.
- **Link-href closure** — your `href` set equals the hints' `links[].href` set.
- **Palette closure** — every color literal in your CSS appears in the hints'
  `palette` (or carries an audit justification). See
  [color.md](color.md).
- **Font closure** — every `font-family` you declare is in `loaded_fonts` (plus
  generic fallbacks).
- **Structure** — section count and order match the hints' sections; per-row
  output item counts match `row_stats[].columns`.
- **Contrast table** — the per-section (background, text color) WCAG ratios
  from [color.md](color.md), with any background-image cases marked
  indeterminate. A ratio below threshold is a hard stop.
- **Hidden elements** — everything in `hidden_elements` is present in your
  output and still hidden.

If the hints came back without these fields (an older render service), fall
back to deriving the inventories from the source body by grep — the closure
checks still run, just against hand-extracted sets.

## Hard stops — countable checks on your output

Run these literally (grep/count your own HTML/CSS). Any failure ⇒ fix before
delivery, no exceptions:

- `position:absolute` count > 5 ⇒ FAIL (legitimate uses: overlays and genuine
  overlaps only). You carried the positioning model through — restructure from
  the hint rows.
- `display: flex` + `display: grid` declarations = 0 ⇒ FAIL. Not a
  modernization, however it looks at canvas width.
- Any `cbc-`-prefixed (or `lp-pom-`) class/id in markup or selectors YOU
  authored ⇒ FAIL — you copied source CSS instead of writing fresh. Content
  preserved verbatim as a black box is exempt: the `cfm-*` form-confirmation
  overlay + its script, and user custom-HTML embeds / custom scripts (which may
  legitimately reference old-namespace ids — those now-dead selectors get
  FLAGGED in the delivery summary per
  [replication.md](replication.md), never rewritten).
- No per-section inner wrapper with `max-width: <design_width>` ⇒ FAIL; a
  page-level max-width wrapper ⇒ FAIL (both invisible at canvas-width preview —
  see [layout.md](layout.md)).
- `cross_section_overlays` non-empty AND no shared structure reserving each
  overlay's space across the sections it spans ⇒ FAIL.
- Any source `srcset`/`image-set`/`@font-face`/`<ub:dynamic>` dropped ⇒ FAIL.
- Form fields: any name missing, retyped, or reordered ⇒ FAIL.
- Any closure check above (image-src, href, palette, font, contrast) failing
  without a recorded audit justification ⇒ FAIL.
- Page default text color not taken from `page_defaults.color` (e.g. promoted
  from one band's styling) ⇒ FAIL — see [color.md](color.md).

## Write-back

`update_variant_from_html` is a true full replace: pass the COMPLETE artifact
set (html + every css + every js) on every call — an omitted stream is
deleted, not kept. After writing, fetch a fresh `get_variant` and use its
`preview_ref` for the handover.

## Empty or missing layout hints

If `get_layout_hints` returns an empty structure for a variant whose body
plainly carries a positioned (`cbc-*`) tree, do NOT fall back to deriving
structure from coordinates — stop and report it (a stale render service
returns empty hints indistinguishably from a genuinely empty page). An empty
result for a variant authored as responsive HTML is truthful: there is nothing
to modernize; tell the user.

## Delivery summary (what the user sees)

Brief, product-voice, evidence-backed:

- What you did: "Made variant A responsive — an editable copy of your page;
  the original is untouched." (Adjust to the actual flow.)
- Phase-2 changes applied, each with the user's quoted request.
- Genuine differences from the original — concrete and specific ("hero heading
  wraps to 3 lines at 1280px vs 2 in the original"), or "none".
- One structural line: "position:absolute uses: 2 (overlays); flex/grid
  declarations: 47; all N text strings verified."
- The preview link(s), and the reminder that edits now go through MCP (never
  the Unbounce builder), and that publishing/traffic is their call.

**Prohibited:** "pixel-faithful match" / "no meaningful differences" without
having run the checks above; paraphrased text in difference reports (quote
verbatim); skipping the counts because they "feel structural".

SHA-256: eb19690f14b6b71ff5418428b100db2a33a93970244742e7491f19d17aba82ca