page-foundry 2.9.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,21 @@
1
1
  # Ship Gates
2
2
 
3
- Run every gate. Report results as a pass/fail table plus the MECLABS score. A failed gate means fix and re-run, not ship with a caveat.
3
+ Run every gate. Report results as a pass/fail table plus the MECLABS score. A failed gate means fix and re-run, not ship with a caveat. The one sanctioned caveat is an **enhancer** running on its reference-file fallback: that degrades a phase and is recorded on the `degraded` line, and the run still ships. A missing or skipped **core** companion is not a caveat, it is a Gate 0 failure (or, when the user overrode it in chat at preflight, an explicit PARTIAL that the report banners loudly). So "no shipping with a caveat" holds for gates and for core companions; enhancer degradation is the named exception, and nothing else is.
4
4
 
5
- Handoff mode: gates 1, 2, and 8 run before the package is delivered; gates 3, 4, 5, 6, and 7 become acceptance criteria in the package and run in full when the built asset comes back, along with a re-run of 1 and 2 on the rendered page. Details in `references/handoff.md`.
5
+ One doctrine, adopted whole from impeccable, binds every mechanical check in this file (the voice scanner at Gate 2, the design detector at Gate 5, the on-page audit at Gate 6, a Lighthouse run at Gate 4): a clean scan is a floor, never a verdict. Zero findings means no known tell fired, and the judgment lines that sit beside each scan still run in full.
6
+
7
+ Handoff mode: gates 0, 1, 2, and 8 run before the package is delivered; gates 3, 4, 5, 6, and 7 become acceptance criteria in the package and run in full when the built asset comes back, along with a re-run of 1 and 2 on the rendered page. Details in `references/handoff.md`.
8
+
9
+ ## Gate 0: Orchestration
10
+
11
+ This gate answers a question no other gate asks: did the pipeline actually run, or did an agent write a good-looking page from its own knowledge and fill the evidence lines with plausible sentences? Every other gate audits the page; this one audits the run that produced it. It exists because without it a run that invokes zero companions passes all the others and reports "all companions present".
12
+
13
+ - [ ] **Run the mechanical audit.** `python3 scripts/run_audit.py --mode <mode> --archetype <archetype> .agents/foundry/<product>/` exits 0. It checks that each phase's OUTPUT artifact exists on disk, is non-trivial, and carries the structure its consumer needs (voc.md quotes each with a source, a ranked Themes section; message-architecture.md with a hierarchy and objection map; persuasion-map.md with levers and where each lands; conversion-audit.md with two scores and the divergence; the copy snapshot; the token plans; the comp record; foundry-log.md in the documented format). A non-zero exit is a FAIL: the named artifact is missing or malformed, and the phase that owns it did not really run. The script is stdlib-only and reads only these files; it cannot judge whether an artifact's content is any good, only that it is present and shaped right (see its limits block). It is the floor, the same way the voice scanner is the floor for Gate 2.
14
+ - [ ] **Present-but-uninvoked is a failure, not a silent pass.** Read `.agents/foundry/<product>/preflight.md`. For every companion that resolved PRESENT there, its phase's OUTPUT artifact must exist. A core companion present at preflight whose artifact is absent means the phase skipped a skill that was available: the run is PARTIAL at best, and unless the user overrode that companion in chat (recorded on the preflight `override:` line), it is a FAIL. This closes the gap the two-tier policy left open: the old rule gated companions at install time, the moment of lowest information; this gates them at ship time, when the artifacts either exist or they do not.
15
+ - [ ] **Every `degraded` claim is checked against the sweep.** A phase reported as degraded because its companion was "missing" is a FAIL if that companion resolves PRESENT in `preflight.md`. The fallback path is only legitimate for a companion the sweep recorded as missing or the user declined; claiming it for a present companion is the honor-system failure this gate replaces.
16
+ - [ ] **The evidence block is derived, not asserted.** The companion evidence lines in the gate report (below) are filled from the artifacts on disk, not from memory of what ran. A line with no artifact behind it is deleted, not written.
17
+
18
+ Gate 0 runs first because the rest of the report is only meaningful if the run behind it was real. In handoff mode it runs before delivery on the artifacts that exist pre-build. A page cannot ship on a failed Gate 0 any more than on a failed Gate 2.
6
19
 
7
20
  ## Gate 1: Conversion audit
8
21
 
@@ -11,68 +24,93 @@ Handoff mode: gates 1, 2, and 8 run before the package is delivered; gates 3, 4,
11
24
  - [ ] Exactly one primary CTA action on the page; repeats are identical in wording and destination.
12
25
  - [ ] Every CTA instance has a proof element within one viewport.
13
26
  - [ ] campaign-landing only: no site navigation, hero language matches the traffic source.
14
- - [ ] Forms: every field beyond name/email has a written justification in the spec.
15
- - [ ] MECLABS heuristic scored (rubric in conversion-rules.md); flagged factors (M/V/I low, F/A high) addressed or explicitly accepted.
16
- - [ ] Red-team read: one simulated skeptical reader per segment x entry state from the brief walks the page; every reader must reach the CTA. Any "not for me" exit by a qualified reader is a failure (conversion rule 10). Log bounce points and fix.
27
+ - [ ] Forms: every field beyond name/email has a written justification in the spec. On the form-centric archetypes (newsletter-capture, waitlist-coming-soon, event-webinar, campaign-landing, and any other page converting at a form) the spec's form entry holds cro's form design from Phase 2, and the built form is audited against it: the field set and order match the entry or carry a recorded amendment, the single-step or multi-step call was honored, labels stay visible rather than placeholder-only, each field's error message exists and typed input survives an error, and the button carries the entry's copy. A form-centric page whose spec never held a form design fails this line at the spec, before the built form is read.
28
+ - [ ] MECLABS heuristic scored independently. The builder records its own score first, from full context. The score of record then comes from a fresh agent given exactly two inputs: the page as a visitor meets it (build mode: the rendered page; handoff mode: the package's verbatim copy pre-delivery, the returned build on the re-run) and the brief. Never the spec, the drafting context, or the self-score. The fresh agent invokes cro when installed, and scores from the rubric in conversion-rules.md otherwise; either way it works cold, which is the condition the visitor is in. `conversion-audit.md` records both scores and the divergence. A page that scores well only for its own author depends on context a cold visitor lacks, which is the exact failure the heuristic measures, so a wide gap is a finding about the page. When the environment offers no way to open a fresh context, the self-score stands and the Notes column says the audit was not independent.
29
+ - [ ] Flagged factors in the independent score (M/V/I low, F/A high) resolved. Two failure floors, not just a diagnosis: a severe flag in the independent score (M, V, or I at 1, or F or A at 5) is a FAIL that blocks ship unless the page is fixed. Acceptance of any lesser flag is the **user's** call in chat, never the builder's or the agent's own; an author accepting their own page's flag is the self-grading this gate exists to stop. `conversion-audit.md` must exist and carry both scores (Gate 0 already requires the file; this line requires the flags in it to be resolved, not merely recorded).
30
+ - [ ] Divergence interpreted, not just measured (the [TK] question). A wide self-versus-cold gap has two causes and they are handled differently. For each divergent factor, the audit says which: **recoverable** — the gap closes when a specific deferred `[TK]` artifact lands at build (name the TK: "I and F recover when the real install command replaces `[TK: install command]`"), so the factor is re-scored on the rendered page at the build-time Gate 1 re-run and only the residual counts; or **unexplained** — no deferred artifact accounts for it, so the builder scored optimistically and the gap is a real finding now, subject to the failure floors above. A divergence left un-attributed is treated as unexplained. On the rendered-page re-run, a factor tagged recoverable whose `[TK]` filled but whose score did not recover becomes an unexplained finding: the prediction was wrong, and the page owns the gap.
31
+ - [ ] Message hierarchy carried onto the page. Every claim in `message-architecture.md`'s hierarchy appears on the built page, in the priority order the hierarchy set, or the spec records the deviation with a reason (a claim cut for length, two claims merged in one section). The lead claim is in the hero. A page that drops or reorders the hierarchy without a recorded reason is not the page the message architecture specified; the fix is the page or a spec amendment, not a silent divergence. Mechanical aid: the claims are short and checkable by string presence, the same shape as the Gate 2 quote search.
32
+ - [ ] Red-team read: one simulated skeptical reader per segment x entry state from the brief walks the page, each carrying the brief's Switching Dynamics (the Habit force as their reason to leave, the Anxiety force as their doubt at the CTA); every reader must reach the CTA. Any "not for me" exit by a qualified reader is a failure (conversion rule 10). One more reader built from the brief's anti-persona walks the page and should self-select out; an anti-persona reaching the CTA convinced means the page promises something the product does not do for them, and that is a failure too. Log bounce points and fix.
33
+ - [ ] Rewrite leaks answered (rewrites only). When the run began from an existing page, `rewrite-diagnosis.md` recorded where that page lost visitors and which conversion factors leaked. Each leak is answered on the new page, or listed in the run's open items with a reason it was not, and the ones the diagnosis said the current page kept because they worked are still present. A leak that the diagnosis named and the new page neither fixed nor consciously carried forward means the rewrite reproduced the old page's failure; that is the point of writing the diagnosis down. Greenfield build: N/A, no diagnosis exists.
34
+ - [ ] Anti-template check: this page's skeleton (the job order plus axis settings the spec records) compared against the `skeleton` lines of the property's last three runs in `foundry-log.md`. A match backed by `conversion data` on the matched run passes: converged because it converts. A match with no conversion data behind it is flagged, and the flag resolves one of two ways: the spec shows why this buyer's objection map landed on the same structure, or the skeleton goes back to Phase 2. No prior log for the property: N/A.
17
35
 
18
36
  ## Gate 2: Voice
19
37
 
20
38
  - [ ] `python3 scripts/voice_scan.py <files>` returns zero FAILs (banned phrases, em/en dashes in prose).
21
- - [ ] Pattern pass done: every `AI language pattern` WARN resolved (negative parallelism "not X, it's Y", copula avoidance "serves as", tailing negation "no X, no Y", significance inflation, authority trope, three-verb-clause runs, parallel-list uniformity). **The humanizer skill was invoked on the final copy, its rewrites applied, and that is recorded on the `humanizer` line below.** The scanner passing is necessary but not sufficient: structural uniformity across separate elements (a parallel roster) is beyond regex, so a scanner PASS with no humanizer pass is an incomplete Gate 2, not a clean one.
39
+ - [ ] Pattern pass done: every `AI language pattern` WARN resolved or accepted with a recorded reason (negative parallelism "not X, it's Y", copula avoidance "serves as", tailing negation "no X, no Y", significance inflation, authority trope, three-verb-clause runs, parallel-list uniformity). The patterns are deliberately WARN, not FAIL; an accepted WARN carries its reason on the `humanizer` line. **The humanizer skill was invoked once on the final copy, the rewrites that survived meaning arbitration applied, and that is recorded on the `humanizer` line below.** Humanizer proposes; meaning arbitrates: a rewrite that changes what a sentence claims is a defect, not a fix, and a second humanizer pass chasing zero tells is over-processing, not rigor. The scanner passing is necessary but not sufficient: structural uniformity across separate elements (a parallel roster) is beyond regex, so a scanner PASS with no humanizer pass is a Gate 2 **FAIL**, not a clean pass and not a footnote. humanizer is a core companion; on a full run it must run once on the final copy, and "not run" fails this gate the same way a missing core artifact fails Gate 0. The only way a full run reaches PASS with humanizer not run is the preflight override, which makes the whole run PARTIAL. Final copy means final: any copy edit after the pattern pass (a red-team fix from Gate 1, a build-time cut, a late rewrite) re-triggers the scan and the humanizer on the edited sections before this gate reports PASS.
40
+ - [ ] Verbatim-copy diff done: the built page's rendered text diffed against the approved-copy snapshot (build mode: `copy-approved.md`, frozen at the end of the copy-fit pass; handoff mode: the package's `01-copy.md`, when the built asset comes back). Every snapshot sentence appears in the build verbatim; any wording change went back through the Phase 3 re-trigger and the snapshot was rewritten from the re-scanned copy; prose the build introduced (button labels, microcopy, alt text) was scanned the same way. Drift that ships, or a snapshot edited to match a drifted build, fails this gate.
22
41
  - [ ] Read-aloud pass done: no sentence the owner would not say to a client across a table.
23
- - [ ] No fabricated specificity: every number, name, and quote traces to the proof inventory.
42
+ - [ ] No fabricated specificity: every number and name traces to the proof inventory, and every quote is checked by search, not by memory. Extract each quoted string and testimonial from the rendered page and search `voc.md` for it: the quote must appear character for character in the Verbatim section, or in the brief's proof inventory for proof the buyer handed over directly. A quote the search cannot find does not go on the page.
24
43
 
25
44
  ## Gate 3: Accessibility (WCAG 2.2 AA spot checks)
26
45
 
46
+ With the webapp-testing skill installed, walk the interactive checks below (focus visibility, tab order, form error states) in a real browser through its Playwright toolkit; a static read of the markup and CSS is the fallback, and Gate 5's screenshot line names the same executor.
47
+
27
48
  - [ ] One `h1`; heading levels do not skip.
28
49
  - [ ] Landmarks present (`nav`, `main`, `footer`); links and buttons are real `a`/`button` elements; icon-only controls carry an `aria-label`.
29
50
  - [ ] Text contrast 4.5:1 (3:1 for large text and UI components); CTA buttons included.
30
- - [ ] Visible keyboard focus on all interactive elements (`:focus-visible`), logical tab order, and focus never obscured (WCAG 2.2 SC 2.4.11).
51
+ - [ ] Interactive-state completeness: every interactive element has a visible focus state and a hover state. Focus is `:focus-visible` with a real ring, 2 to 3px, offset outside the element, at 3:1 contrast against its surroundings; `outline: none` with no replacement fails this line. Nothing on the page is hover-only, since keyboard and touch users never see hover, and a state change never signals by color alone. Logical tab order; focus never obscured (WCAG 2.2 SC 2.4.11). The craft rule behind the numbers is in `references/design-direction.md`.
31
52
  - [ ] Touch targets at least 24x24px (WCAG 2.2 SC 2.5.8); 44px preferred for primary actions.
32
53
  - [ ] Every informative image has real alt text and explicit `width`/`height` (CLS); decorative images have empty alt.
33
54
  - [ ] No content conveyed by color alone; `prefers-reduced-motion` respected; motion animates only `transform`/`opacity`, never `transition: all`.
34
55
  - [ ] Form inputs have programmatic labels plus correct `type`/`inputmode`/`autocomplete`; async status changes use `aria-live`.
35
56
  - [ ] If the page has auth, no step forces a memory or transcription test with no easier alternative (WCAG 2.2 SC 3.3.8).
57
+ - [ ] Reflow at 320px (WCAG 2.2 SC 1.4.10): render the page at a 320px viewport width and confirm no content is lost and no horizontal scroll appears (except for parts that legitimately need two-dimensional layout, such as a wide data table or a code block, which may scroll within their own container). 320 is narrower than the 390 render width and catches the smallest real phones; a page that only holds together at 390 is not reflow-safe. When no render tool exists, read the CSS for fixed pixel widths wider than 320 on layout containers and flag them, and tell the user to check 320 by hand.
36
58
 
37
59
  ## Gate 4: Performance
38
60
 
39
61
  - [ ] Total transfer under ~1MB; CSS+JS under ~200KB.
40
62
  - [ ] Images sized to display dimensions, modern formats (WebP/AVIF), lazy-loaded below the fold.
41
- - [ ] Fonts: system stack, or at most two self-hosted files, preloaded, `font-display: swap`.
63
+ - [ ] Fonts: system stack, or at most two self-hosted files, preloaded, `font-display: swap` with a metric-matched fallback (`size-adjust`/`ascent-override`) so the swap reflows nothing.
42
64
  - [ ] No render-blocking third-party scripts; analytics deferred.
43
- - [ ] Target: LCP under ~2s on a mid-range phone. If a Lighthouse run is possible in the environment, run it and record the score.
65
+ - [ ] Layout stability (CLS): everything that loads late reserves its space. Images and embeds carry explicit `width`/`height` or `aspect-ratio` (Gate 3 checks images for the same attributes; this line covers every late-loading element), and nothing injects content above existing content after first paint.
66
+ - [ ] LCP mechanics: name the LCP element in the report; it is the hero image or text block, never a script-injected element. A hero image loads eagerly with `fetchpriority="high"`; lazy-loading stays below the fold. Target: LCP under ~2s on a mid-range phone. If a Lighthouse run is possible in the environment, run it and record the score.
44
67
 
45
68
  ## Gate 5: Render review
46
69
 
47
- - [ ] Render the page and look at it: screenshot at 390px and 1440px via Playwright, headless Chrome, or gstack `/design-review` when available. Critique the screenshots against the chosen design direction, the anti-slop list, and (when installed) the web-design-guidelines rules; fix anything a cold viewer would flag in five seconds (cramped hero, wall of gray, broken wrap, invisible CTA).
48
- - [ ] If no render tool exists in the environment, mark this gate N/A in the report and tell the user to eyeball both widths before deploy. Never silently skip it; an unrendered page is unreviewed design.
70
+ - [ ] Render the page and look at it: screenshot at 390px and 1440px via the webapp-testing skill when installed (its Playwright toolkit is this line's Playwright option, and its emulation renders a true 390 viewport), plain Playwright, headless Chrome, or gstack `/design-review` when available. The 390 capture must be a true 390 layout: desktop Chrome floors its window width near 500, so a bare `--window-size=390 --screenshot` renders a 500px layout cropped to 390, and the fake right-edge clipping it produces fabricates overflow findings. Use real viewport emulation (Playwright's default) or render inside a 390px iframe wrapper page, and distrust any narrow capture whose text clips uniformly at the right edge. Critique the screenshots against the chosen design direction, the anti-slop list, and (when installed) the web-design-guidelines rules; fix anything a cold viewer would flag in five seconds (cramped hero, wall of gray, broken wrap, invisible CTA).
71
+ - [ ] Squint test on the captures: blur each screenshot (or squint at it) and the primary element, the secondary element, and the groupings must still be identifiable within 2 seconds, the hero first, then section by section. A page that fails blurred has a hierarchy problem, and the fix is composition (weight, scale, spacing) inside the committed tokens, not a palette change. The craft rule and its criterion live in `references/design-direction.md`; this line is where the built page faces it.
72
+ - [ ] Design-to-research trace: the design direction's scene sentence names the ICP segment and entry state it was drawn from (`references/design-direction.md`), and that segment exists in the brief or `voc.md`. A scene sentence that could describe any page for any buyer means the aesthetic was chosen without the research, which is the failure Phase 4's required reads exist to prevent; send it back to write the scene from the actual reader. Handoff mode: the manifest carries the scene sentence, checked pre-delivery.
73
+ - [ ] Grid and recomposition check: read the built CSS against the token plan's grid spec. Container max-widths, the column structure of the densest section, and gutter values must match the spec'd custom properties in `theme.css`; a mismatch is fixed in the page, or the spec is amended with the reason recorded in the token plan file, and silent divergence between spec and build fails. Then walk the recomposition notes: at each breakpoint a note names, the hero and the densest section re-form as written, and when a named breakpoint falls between the standard screenshot widths, screenshot that width too instead of inferring the layout from the CSS. Handoff mode: the external tool owns the grid within the manifest geometry (`references/handoff.md`), so on the returned build this line reads N/A with that reason.
74
+ - [ ] Design detect scan (impeccable is core, so this always runs on a full run): run its detector over the built HTML and CSS (`node <impeccable skill dir>/scripts/detect.mjs --json pages/<product>/`, or `npx impeccable detect --json`), from the product's repo root so the property's `.impeccable/config.json` ignores and `DESIGN.md` token enforcement apply; a persisted `DESIGN.md` makes off-palette colors, radii, and fonts findings, which is why Phase 4 step 8 wrote it. The scan prints an empty JSON array and exits 0 when clean, a findings array and a non-zero exit otherwise; the findings list is the array. Resolve every entry one of two ways: fix the page, or accept the finding into the product's `.impeccable/config.json` under `detector.ignoreValues` with a `reason`. That file is the per-property accepted-findings record, and an ignore without a reason is a suppressed finding, not an accepted one. The `impeccable` evidence line carries the finding count, what was fixed, and each accepted finding with its reason. The only run that skips the detector is one where the user overrode impeccable at preflight: that run is already PARTIAL, its design was never mechanically checked, and the anti-slop critique in `references/design-direction.md` is the acknowledged-weaker stand-in, not an equal substitute.
75
+ - [ ] The header doctrine, applied to the detect scan: zero findings means no known visual tell fired, not that the design is good. The screenshot critique and the squint test above still run in full, and an accepted finding is a recorded style choice, not a waived check.
76
+ - [ ] Imagery was designed, not defaulted. `imagery-plan.md` exists and every image on the built page traces to a slot in it, at the treatment the plan specifies (crop, aspect ratio, grade, frame); a set of images that do not share the plan's consistency rules reads as a scatter, not art direction, and fails. A page the plan declared intentionally image-light passes only if the typographic and layout treatment it named carries the visual load; a page that fell back to an unplanned wall of text and CSS boxes fails, because that default is the visual AI tell the plan exists to prevent. Product screenshots are real captures of real use (Gate 8 owns that check; this line owns whether the imagery was art-directed at all).
77
+ - [ ] States and motion walk, not just render. `states-motion.md` exists, and the built page's designed states are present: with a render tool, drive the primary form to its error state and confirm the designed error (not the browser default) shows and announces via `aria-live`, then to its success state; trigger any copy-button, accordion, or interactive element and confirm its designed state. Focus and hover match the personality the file specifies, not the UA default. Page-level motion respects `prefers-reduced-motion` with the static fallback the file names. A page whose states are browser defaults ships the behavioral equivalent of the generic look and fails; the fix is designing the states in Phase 4, not adding them at the gate. Without a render tool, read the CSS and markup for the state styles and the reduced-motion query and flag any the plan named but the build omitted.
78
+ - [ ] Render breadth beyond one engine at two widths. The 390/1440 Chromium pair is the floor, not the whole review. When webapp-testing or a Playwright install is present, also capture the two mid widths a real audience uses (768 tablet, 1024 small laptop) and one non-Chromium engine (WebKit or Firefox) at 390 and 1440, and diff the non-Chromium captures against the Chromium ones: a layout that only holds in Chromium is a real defect, since the audience does not all use Chrome. Fix anything the extra widths or the second engine surface, or record why a difference is acceptable. When only Chromium is available, capture 768 and 1024 there and note in the report that cross-engine was not run rather than claiming a breadth the environment could not deliver.
79
+ - [ ] Comp record present (build mode): the comp stage ran and left its record, `comp/rounds.md` or the critique snapshots under the product's `.impeccable/critique/`, with the league verdict answered (SKILL.md Phase 4.5). The ceiling question lives there, and this gate checks it was faced: a league-level weakness surfacing here that no round recorded means the stage was skipped or shallow, and the fix is comp rounds against the direction's scene sentence and anchors, not patching at the gate. A build-mode run with no comp record fails this line. Handoff mode: N/A, the tool's revision rounds own comp iteration per `references/handoff.md`.
80
+ - [ ] Fix loop, when any line above failed: with impeccable installed, run its `critique` on the built page, then hand the result to `polish`. The critique persists a scored snapshot (heuristic scores, issues tagged P0 to P3) under the product's `.impeccable/critique/`; `polish` opens by pulling the latest snapshot for the target and folding its P0 and P1 items into the pass as its backlog. That pairing is impeccable's designed loop, and a critique whose snapshot nothing consumes is ceremony. The contract still arbitrates: when a polish move collides with a conversion requirement (a demoted CTA, a cut of a repetition the contract requires, a thinned proof section), the conversion rules win, and the deferral is recorded with a reason like any accepted finding. Copy stays out of polish's hands; drift the pass introduces fails Gate 2's verbatim diff. After the pass, re-run the failed lines above. Without impeccable, work the screenshot critique's findings directly under the same re-run rule.
81
+ - [ ] If no render tool exists in the environment, mark the screenshot review N/A in the report and tell the user to eyeball both widths before deploy; the detect scan is static and runs regardless. Never silently skip either; an unrendered page is unreviewed design.
49
82
 
50
83
  ## Gate 6: AI discovery and meta
51
84
 
52
85
  - [ ] JSON-LD schema present and valid for the archetype (templates below).
53
86
  - [ ] `llms.txt` present at the site root (template below).
87
+ - [ ] Site placement honored (multi-page properties only). When `site-context.md` exists, this page's role in the site architecture is honored: its canonical URL, its place in the internal link graph (the parent and sibling links `site-context.md` assigns it), and its non-overlapping scope with the property's other pages. A page that duplicates another page's job, or that `site-context.md` placed in the nav but the build orphaned, fails this line. Single-page property: N/A, no site context exists.
54
88
  - [ ] `robots.txt` does not `Disallow` the AI crawlers that drive citations: `GPTBot`, `ChatGPT-User`, `PerplexityBot`, `ClaudeBot`, `anthropic-ai`, `Google-Extended`, `Bingbot`. Blocking one loses that engine's citation; only `CCBot` is safe to block. An AI-discovery gate that passes while `ClaudeBot` is disallowed is a false pass.
55
- - [ ] Page copy is machine-extractable: the primary answer sits in a self-contained 40 to 60 word block near the top, key facts are in real text (not baked into images), and comparisons/FAQs use plain markup.
56
- - [ ] For archetypes with public pricing (saas-homepage, course-sales, membership-community), a machine-readable `/pricing.md` (or `/pricing.txt`) is present for agentic buyers.
57
- - [ ] `<title>` and meta description written to the same standard as page copy (voice rules apply), and short enough not to truncate.
58
- - [ ] Open Graph + Twitter card meta complete, with a real OG image (1200x630).
59
- - [ ] Canonical URL set; favicon present.
89
+ - [ ] Page copy is machine-extractable: the answer block the Phase 2 spec placed survived the build as a self-contained 40 to 60 word block near the top, key facts are in real text (not baked into images), and comparisons/FAQs use plain markup. This gate verifies the spec's block; discovering at ship time that no block was specced is a Phase 2 defect, not something to retrofit here.
90
+ - [ ] For archetypes with public pricing (pricing-page, saas-homepage, course-sales, membership-community, docs-dev-tool-landing), the machine-readable `/pricing.md` (or `/pricing.txt`) the Phase 2 spec drafted is present for agentic buyers.
91
+ - [ ] `<title>` and meta description match the labeled entries in the approved-copy snapshot exactly (build mode: `copy-approved.md`; handoff mode: `01-copy.md`, criterion G6.5). Phase 3 drafted them through the full voice chain, so this gate diffs, it does not judge wording: a head entry that matches nothing in the snapshot is copy that skipped the voice gate, and it goes through the Phase 3 step 5 re-trigger and a re-snapshot before this gate reports. Also verify neither element truncates in a search result; the length budget was a Phase 3 drafting constraint, and this line checks it held.
92
+ - [ ] Open Graph + Twitter card meta complete, with a real OG image (1200x630). Mechanical, since Phase 5 produces the file: the `og:image` URL is absolute and its filename resolves to a file the build shipped in `assets/`; the file measures 1200x630; any text on the card appears in the approved-copy snapshot, because card text is rendered copy. A meta tag pointing at a file the build never produced fails this line, and a run arriving here with no OG image and no recorded open-item gap is a Phase 5 defect: the asset is produced there and only checked here. Handoff mode: criterion G6.6 puts production on the tool, checked when the build returns.
93
+ - [ ] Canonical URL set; favicon present and linked in the head: the brand mark when the brief supplied one, otherwise the token-derived `favicon.svg` Phase 5 wrote.
94
+ - [ ] On-page audit: with the seo-audit skill installed, invoke it on the built page. Its on-page framework reads the `<title>` and meta description against search intent (the snapshot diff above checks fidelity to the voice chain; this reads whether the entries earn the click for the queries the brief expects), the heading structure as crawlers parse it, image alt coverage, link text, and indexability. Findings are floors, same doctrine as the Gate 5 detector: each one fixed, or accepted on the gate report with a reason. Two dedup boundaries hold: the skill's ai-writing-detection vocabulary already lives in `references/voice.md`, so prose tells belong to Gate 2, and structured data belongs to the schema line above. Without seo-audit this line reads N/A degraded; the mechanical head checks above still run.
60
95
 
61
96
  Note: Google does not consume `llms.txt`; it helps ChatGPT, Claude, and Perplexity. Keep it, and do not rely on it for Google.
62
97
 
63
98
  ## Gate 7: Measurement
64
99
 
65
- - [ ] Conversion event defined: the form destination (ESP, endpoint) records source/medium, or the user has consciously declined measurement.
66
- - [ ] UTM convention stated for every planned traffic source, so campaign performance is attributable from day one.
100
+ - [ ] Conversion event wired as the Phase 2 spec defined it: the form destination (ESP, endpoint) records source/medium, or the user has consciously declined measurement. A spec with no measurement plan is a Phase 2 defect; this gate verifies, it does not invent measurement after the build.
101
+ - [ ] The spec's UTM convention stated for every planned traffic source, so campaign performance is attributable from day one.
67
102
  - [ ] Analytics: privacy-respecting option (Plausible, GoatCounter, or server logs) wired or consciously declined. A gauge-interest page without measurement cannot gauge interest.
103
+ - [ ] One real submit, end to end (form-centric archetypes). Verifying the form renders is not verifying it works: with webapp-testing or Playwright present, actually submit the primary form once with test input and confirm the destination received it and the measurement event fired (the success state showed, the endpoint or ESP recorded the row, the conversion event landed where Gate 7's wiring says it should). A form that looks wired but silently drops submissions is the worst failure a capture page has, and only a real submit catches it. When no browser tool can drive the submit, mark this line "not executed, submit-path read statically" and tell the user to submit once themselves before they drive traffic.
104
+ - [ ] Post-deploy live check (when a deploy happens this run). After the page is deployed, open the live URL and confirm the deployed version is the one built: the page loads with no console errors, the hero and primary CTA are present, and the measurement snippet is live on the production page, not just in the source. This is the Interceptor VerifyDeploy pattern; a green build is not a live page. Not deployed this run (handing back static files or a package): N/A.
68
105
 
69
106
  ## Gate 8: Integrity
70
107
 
71
- - [ ] Zero fabricated testimonials, logos, counts, or statistics.
108
+ - [ ] Zero fabricated testimonials, logos, counts, or statistics. For quotes this check is mechanical: rerun the Gate 2 search with integrity's question. A page quote matching a `voc.md` Paraphrase entry is a paraphrase wearing quotation marks; a quote matching nothing was invented. Both are fabricated attribution, whoever wrote the words.
72
109
  - [ ] Zero fabricated technical artifacts or staged scenarios: (a) every command, terminal output, code snippet, config, and file path is real and runnable exactly as shown, or removed; and (b) every terminal, screenshot, console, or UI depicts a real action the user takes and real output they see. Real data in a styled card (the page's own gate report) is fine; a terminal of a script the user never runs is not, even if the script is real. A demo of the product is held to this.
73
110
  - [ ] All `[TK]` placeholders resolved: filled with real material, or the section cut.
74
111
  - [ ] Any urgency element (deadline, cap) verified real with the user.
75
112
  - [ ] Security/privacy claims substantiated by the brief.
113
+ - [ ] External-project claims re-verified against the live source at build. When the page makes checkable factual claims about a live external thing the run does not own — an open-source repo, another product, a public API, a pricing or licensing fact — those claims are re-checked against that source at build time, not trusted from the brief, because external facts drift between intake and ship. The dogfood caught exactly this: a repo renamed (`slop-browser` to `Interceptor`), an install model changed (a signed `.pkg`, not a shell command), a license, and OS support (browser-only shipped on Windows and Linux while the page marked them `[TK]`). Each such claim on the page is confirmed against the live README, repo metadata, or API, and a drifted claim is corrected or cut before ship. The `integrity` line records which external claims were re-verified and what changed. No external claim to check (a page about the run owner's own product with no outside dependencies): N/A, and the report says so.
76
114
 
77
115
  ---
78
116
 
@@ -168,7 +206,7 @@ Omit `aggregateRating` entirely unless the numbers are real and public.
168
206
 
169
207
  FAQ schema must mirror the visible page content exactly; do not add schema-only Q&A.
170
208
 
171
- **course-sales / membership-community / dated webinar campaign-landing** (`Event`; use for a page selling a scheduled cohort, workshop, or live event):
209
+ **event-webinar / course-sales / membership-community / dated campaign-landing** (`Event`; use for a page registering or selling a scheduled session, cohort, workshop, or live event; the event-webinar contract's Phase 2 spec supplies these values, real only):
172
210
 
173
211
  ```json
174
212
  {
@@ -194,6 +232,34 @@ FAQ schema must mirror the visible page content exactly; do not add schema-only
194
232
 
195
233
  Omit `endDate` and `offers` fields you cannot fill with real values; never invent a date, price, or seat count.
196
234
 
235
+ **ecommerce-product** (`Product`; the buy box's machine-readable twin; the Phase 2 spec supplies real values only):
236
+
237
+ ```json
238
+ {
239
+ "@context": "https://schema.org",
240
+ "@type": "Product",
241
+ "name": "{Product}",
242
+ "description": "{factual one-liner}",
243
+ "image": ["{real product photo urls}"],
244
+ "sku": "{sku}",
245
+ "brand": { "@type": "Brand", "name": "{Brand}" },
246
+ "offers": {
247
+ "@type": "Offer",
248
+ "price": "{price}",
249
+ "priceCurrency": "USD",
250
+ "availability": "https://schema.org/InStock",
251
+ "url": "{product url}"
252
+ },
253
+ "aggregateRating": {
254
+ "@type": "AggregateRating",
255
+ "ratingValue": "{real only}",
256
+ "reviewCount": "{real only}"
257
+ }
258
+ }
259
+ ```
260
+
261
+ Omit `aggregateRating` unless the store's review system produced the numbers; `availability` states the actual stock state, and the schema price always matches the visible buy box.
262
+
197
263
  **homepage / personal-home** (optional, add alongside the primary type): a `WebSite` with `potentialAction` SearchAction when the site has search, and a standalone `Organization` (name, url, logo, sameAs social links) so the brand resolves as an entity.
198
264
 
199
265
  ### Gate report format
@@ -201,24 +267,46 @@ Omit `endDate` and `offers` fields you cannot fill with real values; never inven
201
267
  ```
202
268
  ## Ship gates: {product} / {archetype}
203
269
 
270
+ {when any core companion was overridden at preflight, open with the banner: "PARTIAL RUN: built without {names}; this output is a draft, not a page-foundry page". Omit the line entirely on full runs.}
271
+
204
272
  | Gate | Result | Notes |
205
273
  |---|---|---|
206
- | Conversion audit | PASS | MECLABS C = {n} (M{n} V{n} I{n} F{n} A{n}) |
274
+ | Orchestration | PASS | run_audit.py exit 0; {n} core artifacts present; preflight override: {none / names} |
275
+ | Conversion audit | PASS | MECLABS C = {n} (M{n} V{n} I{n} F{n} A{n}), independent; self C = {n}, divergence {n}; skeleton {new / matched, converged with data / flagged, with how the flag resolved} |
207
276
  | Voice scan | PASS | 0 hits across {n} files |
208
277
  | Accessibility | PASS | |
209
278
  | Performance | PASS | {transfer size}, {LCP if measured} |
210
- | Render review | PASS / N/A | {widths checked, or why N/A} |
279
+ | Render review | PASS / N/A | {widths checked; detect findings fixed/accepted; or why the screenshot half was N/A} |
211
280
  | AI discovery | PASS | schema valid, llms.txt present |
212
281
  | Measurement | PASS | {conversion event, UTM, analytics or declined} |
213
282
  | Integrity | PASS | {n} TK items resolved/cut |
214
283
 
215
- Humanizer: {invoked on final copy yes/no; one line on what it changed (e.g. "broke two three-verb runs, varied a 6-item roster"), or "not run" which makes Gate 2 incomplete}
216
-
217
- Degraded phases: {any phase that ran on a reference-file fallback because its companion was missing or declined, named with the companion it lacked; "none, all companions present" otherwise. A degraded run is a partial execution, and the owner is told which skill would improve it.}
284
+ Companion evidence — one line per companion in scope this run, each filling the EVIDENCE
285
+ column of its table row: what ran, the artifact it wrote, what changed because of it.
286
+ A companion with no line here and no artifact on disk was not invoked, whatever the
287
+ transcript says. This is no longer honor-system: Gate 0 runs `run_audit.py` over the
288
+ run artifact directory and cross-checks these lines against `preflight.md`, so a line
289
+ claimed for a companion whose OUTPUT artifact is absent fails the run. Each line is
290
+ written FROM the artifact on disk, not from memory of what ran. The eight core lines
291
+ always appear; an overridden core companion's line reads "PARTIAL: overridden at
292
+ preflight" and must match the preflight `override:` field.
293
+
294
+ - product-marketing: {invoked, brief written, fields the interview still had to supply}
295
+ - customer-research: {invoked, voc.md written, {n} verbatim quotes, every one carrying a source; {k} themes ranked, the top theme named with its confidence}
296
+ - marketing-psychology: {invoked, persuasion-map.md written, levers applied and where}
297
+ - cro: {invoked at spec and at Gate 1; Gate 1 run in a fresh context on the rendered page and brief alone; conversion-audit.md written with both scores and the divergence; on the form-centric archetypes, the form entry written at spec and the built form audited against it; spec changes applied}
298
+ - copywriting: {invoked, sections drafted, headline candidates scored}
299
+ - frontend-design: {invoked, tokens persisted, grid specced and checked at Gate 5, alternatives considered}
300
+ - impeccable: {core; `document` wrote the property's DESIGN.md at Phase 4; `detect` ran at Gate 5 with the finding count, the fixes, and each accepted finding with its reason; `critique`/`polish` at the comp stage and the fix loop; or "PARTIAL: overridden at preflight", meaning the design was never mechanically checked}
301
+ - humanizer: {invoked once on final copy — yes/no; one line on what it changed (e.g. "broke two three-verb runs, varied a 6-item roster"); accepted WARNs, each with its reason; re-runs triggered by post-pass edits, if any; or "not run" which fails Gate 2 unless overridden at preflight, in which case the run is PARTIAL}
302
+ - copy-editing: {changelog summary — what was cut, what was tightened, what the So-What and Specificity sweeps sharpened; or "skipped (degraded)"}
303
+ - {one line per enhancer whose seam was in scope: analytics, ai-seo, schema, seo-audit (finding count and each disposition), site-architecture (multi-page properties: site-context.md written), competitor-profiling (when the brief named alternatives), ab-testing (repeat runs where a prior experiment's result fed this run's decisions, or a new experiment was designed at close), web-design-guidelines (live ruleset or frozen fallback), webapp-testing (when it executed Gates 3 and 5: widths captured, console state), image and canvas-design (the asset slots each produced), algorithmic-art (when a proposal was made, with the user's call), the remotion stack (which of its four ran), vercel-react-view-transitions (React builds only), gstack (which commands ran, `/diagram` included when a diagram shape shipped), the archetype companions (pricing, competitors, aso, launch, lead-magnets, popups, signup, onboarding, free-tools, paywalls) when their section is on the page, and the post-ship seams when the user requested them: deploy-to-vercel (the deployed URL) and `distribution:` (which channels ran and the artifacts each consumed). In scope but skipped reads "skipped (degraded: missing)" or "skipped (declined at preflight)"}
304
+
305
+ Degraded phases: {any phase that ran on a reference-file fallback because its companion was missing or declined, named with the companion it lacked; core-tier overrides prefixed PARTIAL:; "none, all companions present" otherwise. A degraded run is a partial execution, and the owner is told which skill would improve it.}
218
306
 
219
307
  Open items for the owner: {real proof to collect, urgency to verify, etc.}
220
308
  ```
221
309
 
222
310
  ---
223
311
 
224
- _Provenance: reconciled 2026-07-07 against marketingskills 2.3.0 (ai-seo, schema, cro) and web-design-guidelines (vercel-labs, live ruleset). JSON-LD templates verified current against schema.org; accessibility bumped to WCAG 2.2 AA. The MECLABS heuristic is external (rubric in conversion-rules.md), not from the cro companion. Re-reconcile when those companions or the schema.org / WCAG baselines change._
312
+ _Provenance: reconciled 2026-07-24 (v3.1) against marketingskills 2.3.0 (ai-seo, schema, cro, image) and web-design-guidelines (vercel-labs, live ruleset); impeccable (pbakaus) integrated at Phases 4-6 and the shared clean-scan doctrine. JSON-LD templates verified current against schema.org; accessibility at WCAG 2.2 AA (SC 1.4.10 reflow, 2.4.11 focus-not-obscured, 2.5.8 target size, 3.3.8 accessible auth). The MECLABS heuristic is external (rubric in conversion-rules.md), not from the cro companion. Re-reconcile per `MAINTENANCE.md` when those companions or the schema.org / WCAG baselines change._
@@ -172,6 +172,8 @@ Patterns to kill on sight (from Wikipedia's "Signs of AI writing" and the seo-au
172
172
  - **Terse noun-pair fragments.** "Seven phases, eight gates." A punchy fragment pairing two counts. Make it a sentence.
173
173
  - **Three parallel verb-clauses.** "It runs the skills, gates the result, and hands back a page." Three present-tense verb clauses in a row read as generated. Break the rhythm: two sentences, or vary the verbs and shapes. (Caught by the `three parallel verb-clauses` regex.)
174
174
  - **Parallel-list uniformity.** A list where every item opens the same way ("Finds... / Pulls... / Structures... / Writes..."). Uniform openings across a set read as machine-made even when each item is fine alone. Vary the grammatical shape item to item. (The scanner flags a plain prose run of these; a list spread across separate DOM elements with labels is beyond regex, which is why the humanizer pass is a hard gate, not a suggestion.)
175
+ - **Aphoristic contrast.** `Not a feature. A platform.` Two clipped sentences manufacturing a contrast. One on a page can be a choice; the cadence is the tell, and three or more is a rewrite, not a review. (Caught by the `aphoristic contrast` regex.)
176
+ - **Aphoristic rebuttal.** A sentence answered by a short `No ...` or `Just ...` sentence: `You ship the page. No guessing.` Same threshold: once reads as voice, a page that keeps landing on the rebuttal reads as generated. The scanner flags every instance; Phase 3 applies the three-per-page line when deciding rewrite versus accept-with-reason. (Caught by the `aphoristic rebuttal` regex.)
175
177
 
176
178
  <!-- scan:patterns -->
177
179
  # AI language patterns, WARN-level. Format: NAME|||REGEX (case-insensitive). Reviewed and fixed in Phase 3.
@@ -183,6 +185,9 @@ authority trope|||\b(the point is|what really matters|the real question is|the h
183
185
  significance inflation|||\b(marks|marking|represents|signals) a (pivotal|key|defining|turning|significant) (moment|point|shift|role)\b
184
186
  superficial -ing|||,\s+(highlighting|underscoring|emphasizing|showcasing|reflecting|symbolizing|ensuring|fostering|cultivating)\b
185
187
  three parallel verb-clauses|||\b[a-z]+s\b[^,.;:!?]{2,60},\s+[a-z]+s\b[^,.;:!?]{2,60},\s+(?:and|then)\s+[a-z]+s\b
188
+ # The two aphoristic patterns keep their case sensitivity inside (?-i:...) because sentence casing is the signal.
189
+ aphoristic contrast|||(?-i:\bNot an? [a-z][^.!?]{1,40}[.!]\s+[A-Z][^.!?]{1,60}[.!])
190
+ aphoristic rebuttal|||(?-i:\b[A-Z][^.!?]{4,80}[.!]\s+(?:No|Just)\s+[a-z][^.!?]{2,60}[.!])
186
191
  <!-- /scan:patterns -->
187
192
 
188
193
  ## Replacement strategy
@@ -201,4 +206,4 @@ After the mechanical scan passes, read the page top to bottom once and ask of ea
201
206
 
202
207
  ---
203
208
 
204
- _Provenance: banned and judgment lists reconciled 2026-07-07 against marketingskills 2.3.0 (copywriting, copy-editing) and the seo-audit ai-writing-detection list, which copywriting itself defers to. Re-reconcile when those companions change; keep this list a superset of the AI-writing-detection vocabulary._
209
+ _Provenance: banned and judgment lists reconciled 2026-07-07 against marketingskills 2.3.0 (copywriting, copy-editing) and the seo-audit ai-writing-detection list, which copywriting itself defers to. The two aphoristic patterns and the scanner's repeated-section-kicker check are absorbed from impeccable 3.9.1's detector (clone `8967edc`, rules `aphoristic-cadence` and `repeated-section-kickers`) under the v3.0 capability-ownership split: voice_scan owns the mechanical text scan, so these fire with or without impeccable installed. Re-reconcile when those companions change; keep this list a superset of the AI-writing-detection vocabulary._