diff --git a/dev/test/fixtures/visual-review/README.md b/dev/test/fixtures/visual-review/README.md
new file mode 100644
index 0000000..7a86d84
--- /dev/null
+++ b/dev/test/fixtures/visual-review/README.md
@@ -0,0 +1,44 @@
+# Visual finishing exercise
+
+Two synthetic regions exercise [the rendered-delivery workflow](../../../../skills/block-runner/references/VISUAL.md): a long-copy page and a shared template part. The reference uses different HTML elements from the native block tree. Its copy must survive unchanged.
+
+`styles/native.css` deliberately narrows the article and closing note and forces the highlight wider than a phone. `styles/native.corrected.css` contains the source correction, including the WordPress first-child spacing rule found during review. Keep the original fixture intact; copy it to a separate working directory before substituting corrected CSS.
+
+## Replay
+
+Build the checkout with `npm run build`. Serve this directory with a local static server and open `reference.html`. Compile the native source:
+
+```sh
+node dist/cli.js site compile dev/test/fixtures/visual-review/site.intent.json --asset-root dev/test/fixtures/visual-review --out /tmp/visual-review-before --strict --json
+```
+
+Use a new output path if that directory already exists. Install the emitted `theme/` as `visual-review-demo` on an explicitly selected disposable WordPress 7.1 site and activate it. Use the existing `site plan` / hash-confirmed `site apply` route from [SITE.md](../../../../skills/block-runner/references/SITE.md); retain the plan, journal and readback. No production target is needed.
+
+Compare the rendered reference and native homepage at 1280×900 and 390×844, with the same scale and scrollbar state. Check content, then the article, highlight and closing note. Retain paired screenshots and targeted bounding boxes; inspect the images.
+
+Copy this fixture to a working directory, replace that copy's `styles/native.css` with `styles/native.corrected.css`, then compile to a new output directory. Deploy the changed theme bytes to the same disposable target, plan/apply again and recapture the same regions. Do not patch serialized block delimiters or discard the initial evidence. Finish with a representative native editor edit, save and reopen.
+
+## Observed comparison
+
+On 2026-10-24, local WordPress 7.1 / PHP 8.4.27 and the in-app Chromium browser showed:
+
+| Region / view | Reference | Before | After |
+| --- | --- | --- | --- |
+| Article / desktop | 720px wide | 480px; extra wrapping | 720px |
+| Closing part / desktop | 960px, centred text | 440px, left-aligned | 960px, centred |
+| Highlight / mobile | 342px | 520px; document overflow to 544px | 342px; document width 390px |
+| Article top / desktop, mobile | 48px, 24px | 0px, 0px | 48px, 24px |
+
+Matched mobile viewports used 390 CSS pixels with scrollbars hidden on both sides; desktop used 1280. The corrected region text, widths, heights, positions and alignment matched the reference. The screenshots showed the same wrapping and spacing. Both strict compilations had no diagnostics; the site applies completed with readback. These are separate validity, operational and visual observations, not a universal fidelity score.
+
+No new helper, renderer, command or dependency was needed. A clean comparison ends after the paired inspection; it does not require a correction loop. Missing-reference, unavailable-browser and source-only cases remain explicitly unverified under the workflow, and do not block ordinary source delivery.
+
+## Native editing and retained evidence
+
+In Chrome 154, the page highlight paragraph was edited, saved and reopened in the native editor; the saved WordPress content and frontend both contained the test sentence. The closing-note template part passed the same edit/save/reopen and frontend check. Both original texts were then restored through the editor. The restored page also passed the existing validation gate.
+
+- Desktop: [reference](evidence/reference-desktop-matched.png), [before](evidence/before-desktop-matched.png), [after](evidence/after-desktop-matched.png).
+- Mobile: [reference](evidence/reference-mobile-matched.png), [before](evidence/before-mobile-matched.png), [after](evidence/after-mobile-matched.png).
+- Native persistence: [page reopened](evidence/editor-reopened.png), [template part reopened](evidence/part-editor-reopened.png).
+
+The paired after comparison was taken before the deliberate editor test edits. These captures show synthetic content only. The exercise was performed by one operator; independent reviewer replay remains separate.
diff --git a/dev/test/fixtures/visual-review/evidence/after-desktop-matched.png b/dev/test/fixtures/visual-review/evidence/after-desktop-matched.png
new file mode 100644
index 0000000..639611d
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/after-desktop-matched.png differ
diff --git a/dev/test/fixtures/visual-review/evidence/after-mobile-matched.png b/dev/test/fixtures/visual-review/evidence/after-mobile-matched.png
new file mode 100644
index 0000000..67f9c68
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/after-mobile-matched.png differ
diff --git a/dev/test/fixtures/visual-review/evidence/before-desktop-matched.png b/dev/test/fixtures/visual-review/evidence/before-desktop-matched.png
new file mode 100644
index 0000000..7d1b4be
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/before-desktop-matched.png differ
diff --git a/dev/test/fixtures/visual-review/evidence/before-mobile-matched.png b/dev/test/fixtures/visual-review/evidence/before-mobile-matched.png
new file mode 100644
index 0000000..f447491
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/before-mobile-matched.png differ
diff --git a/dev/test/fixtures/visual-review/evidence/editor-reopened.png b/dev/test/fixtures/visual-review/evidence/editor-reopened.png
new file mode 100644
index 0000000..c833e00
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/editor-reopened.png differ
diff --git a/dev/test/fixtures/visual-review/evidence/part-editor-reopened.png b/dev/test/fixtures/visual-review/evidence/part-editor-reopened.png
new file mode 100644
index 0000000..d4cd846
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/part-editor-reopened.png differ
diff --git a/dev/test/fixtures/visual-review/evidence/reference-desktop-matched.png b/dev/test/fixtures/visual-review/evidence/reference-desktop-matched.png
new file mode 100644
index 0000000..639611d
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/reference-desktop-matched.png differ
diff --git a/dev/test/fixtures/visual-review/evidence/reference-mobile-matched.png b/dev/test/fixtures/visual-review/evidence/reference-mobile-matched.png
new file mode 100644
index 0000000..67f9c68
Binary files /dev/null and b/dev/test/fixtures/visual-review/evidence/reference-mobile-matched.png differ
diff --git a/dev/test/fixtures/visual-review/reference.html b/dev/test/fixtures/visual-review/reference.html
new file mode 100644
index 0000000..be48442
--- /dev/null
+++ b/dev/test/fixtures/visual-review/reference.html
@@ -0,0 +1,13 @@
+
+
+
Visual review reference
+
+
A quiet place to read
+
A good reading page gives every sentence enough room. The words should feel unhurried, with a clear measure, familiar type and a useful rhythm between paragraphs. The design is modest on purpose: changes to its width are easy to see, but the content must remain exactly the same.
+
The article can be read on a large screen or on a phone. Neither reader should need to scroll sideways to finish a sentence. When a theme adds a narrower container, the extra wrapping can look like a content problem even though every word is still present.
+
+
The highlighted note is part of the article, not a picture of some text. It should fit within the available width, stay in the reading order and remain editable through the normal paragraph control. A successful correction fixes the layout without rewriting the message.
+
After checking the page, inspect the shared closing note as a separate region. It has a different purpose and a wider measure. Matching these two regions by meaning makes the comparison useful even when the reference and WordPress use different element trees.
+
+
+
diff --git a/dev/test/fixtures/visual-review/site.intent.json b/dev/test/fixtures/visual-review/site.intent.json
new file mode 100644
index 0000000..5a917e5
--- /dev/null
+++ b/dev/test/fixtures/visual-review/site.intent.json
@@ -0,0 +1,136 @@
+{
+ "version": 1,
+ "siteId": "visual-review-demo",
+ "homePageId": "home",
+ "theme": {
+ "slug": "visual-review-demo",
+ "title": "Visual Review Demo",
+ "themeJson": {
+ "version": 3,
+ "settings": {
+ "appearanceTools": true
+ },
+ "styles": {
+ "spacing": {
+ "blockGap": "0"
+ },
+ "typography": {
+ "fontFamily": "Georgia, serif",
+ "fontSize": "18px",
+ "lineHeight": "1.6"
+ },
+ "color": {
+ "background": "#f6f4ee",
+ "text": "#252c28"
+ }
+ }
+ }
+ },
+ "templates": {
+ "index": {
+ "body": {
+ "blocks": [
+ {
+ "block": "core/post-content"
+ },
+ {
+ "block": "core/template-part",
+ "attrs": {
+ "slug": "closing-note"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "parts": {
+ "closing-note": {
+ "body": {
+ "blocks": [
+ {
+ "block": "core/group",
+ "attrs": {
+ "className": "review-note"
+ },
+ "children": [
+ {
+ "block": "core/paragraph",
+ "text": "This is a shared closing note. Its text remains a native paragraph."
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "patterns": {},
+ "pages": [
+ {
+ "id": "home",
+ "route": "/",
+ "title": "Reading page",
+ "template": "index",
+ "status": "publish",
+ "body": {
+ "blocks": [
+ {
+ "block": "core/group",
+ "attrs": {
+ "className": "review-article"
+ },
+ "children": [
+ {
+ "block": "core/heading",
+ "level": 1,
+ "text": "A quiet place to read"
+ },
+ {
+ "block": "core/paragraph",
+ "text": "A good reading page gives every sentence enough room. The words should feel unhurried, with a clear measure, familiar type and a useful rhythm between paragraphs. The design is modest on purpose: changes to its width are easy to see, but the content must remain exactly the same."
+ },
+ {
+ "block": "core/paragraph",
+ "text": "The article can be read on a large screen or on a phone. Neither reader should need to scroll sideways to finish a sentence. When a theme adds a narrower container, the extra wrapping can look like a content problem even though every word is still present."
+ },
+ {
+ "block": "core/group",
+ "attrs": {
+ "className": "review-highlight"
+ },
+ "children": [
+ {
+ "block": "core/paragraph",
+ "text": "Keep the words. Correct the layout. Check the result at both sizes."
+ }
+ ]
+ },
+ {
+ "block": "core/paragraph",
+ "text": "The highlighted note is part of the article, not a picture of some text. It should fit within the available width, stay in the reading order and remain editable through the normal paragraph control. A successful correction fixes the layout without rewriting the message."
+ },
+ {
+ "block": "core/paragraph",
+ "text": "After checking the page, inspect the shared closing note as a separate region. It has a different purpose and a wider measure. Matching these two regions by meaning makes the comparison useful even when the reference and WordPress use different element trees."
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ],
+ "assets": [
+ {
+ "id": "base",
+ "path": "styles/base.css",
+ "kind": "stylesheet",
+ "role": "theme-file"
+ },
+ {
+ "id": "native",
+ "path": "styles/native.css",
+ "kind": "stylesheet",
+ "role": "theme-file"
+ }
+ ],
+ "assetUses": []
+}
diff --git a/dev/test/fixtures/visual-review/styles/base.css b/dev/test/fixtures/visual-review/styles/base.css
new file mode 100644
index 0000000..13cb063
--- /dev/null
+++ b/dev/test/fixtures/visual-review/styles/base.css
@@ -0,0 +1,14 @@
+/* Shared design vocabulary; reference and native markup deliberately differ. */
+body { margin: 0; background: #f6f4ee; color: #252c28; font: 18px/1.6 Georgia, serif; }
+.wp-site-blocks { padding: 0; }
+.reference-article, .review-article { box-sizing: border-box; width: calc(100% - 48px); max-width: 720px; margin: 48px auto; }
+.reference-article h1, .review-article h1 { font: bold 44px/1.12 Georgia, serif; margin: 0 0 24px; }
+.reference-article p, .review-article p { margin: 0 0 24px; }
+.reference-highlight, .review-highlight { box-sizing: border-box; background: #e2e8dd; padding: 24px; border-left: 4px solid #596d4e; margin: 32px 0; }
+.reference-highlight p, .review-highlight p { margin: 0; }
+.reference-note, .review-note { box-sizing: border-box; width: calc(100% - 48px); max-width: 960px; margin: 48px auto; padding: 24px; background: #252c28; color: #f6f4ee; text-align: center; }
+.reference-note p, .review-note p { margin: 0; }
+@media (max-width: 600px) {
+ .reference-article, .review-article { margin-top: 24px; }
+ .reference-article h1, .review-article h1 { font-size: 34px; }
+}
diff --git a/dev/test/fixtures/visual-review/styles/native.corrected.css b/dev/test/fixtures/visual-review/styles/native.corrected.css
new file mode 100644
index 0000000..398b036
--- /dev/null
+++ b/dev/test/fixtures/visual-review/styles/native.corrected.css
@@ -0,0 +1,8 @@
+/* Scoped source correction, after the initial comparison identifies the defects. */
+.review-article { max-width: 720px; }
+.review-highlight { min-width: 0; }
+.review-note { max-width: 960px; text-align: center; }
+
+/* Keep the authored top spacing against WordPress first-child layout defaults. */
+.wp-block-post-content > .review-article { margin-block-start: 48px; }
+@media (max-width: 600px) { .wp-block-post-content > .review-article { margin-block-start: 24px; } }
diff --git a/dev/test/fixtures/visual-review/styles/native.css b/dev/test/fixtures/visual-review/styles/native.css
new file mode 100644
index 0000000..c397f8f
--- /dev/null
+++ b/dev/test/fixtures/visual-review/styles/native.css
@@ -0,0 +1,4 @@
+/* Three intentional presentation defects; native content stays identical. */
+.review-article { max-width: 480px; }
+.review-highlight { min-width: 520px; }
+.review-note { max-width: 440px; text-align: left; }
diff --git a/skills/block-runner/SKILL.md b/skills/block-runner/SKILL.md
index 9a4421e..d890adf 100644
--- a/skills/block-runner/SKILL.md
+++ b/skills/block-runner/SKILL.md
@@ -19,7 +19,7 @@ compatibility: Requires Node.js ^22.13.0 || >=24.0.0 and shell access. An uncach
## Pick the artifact first
Choose the visible result before discovering a project. Read the named first reference, use the
-condition, and stop at its stated boundary. Do not load a construction taxonomy for a
+condition, and respect its stated boundary. Do not load a construction taxonomy for a
self-contained page-content or markup-repair task.
| Requested artifact | First reference | Use when | Completion boundary |
@@ -36,6 +36,15 @@ If “reusable section” does not say whether it is page `post_content` or a na
block, ask that one artifact question before writing. Do not use this skill for unrelated WordPress
administration, non-WordPress HTML, or frontend-scraped HTML presented as source.
+## Finish rendered delivery
+
+When the task creates or changes visible WordPress output, follow
+[VISUAL.md](references/VISUAL.md) by default before calling the delivery complete.
+Check the affected region on desktop/mobile, correct meaningful differences and verify
+the applicable native edit/save behaviour. Do not ask whether the user wants this check.
+Respect source-only delivery and explicit skips; disclose unavailable rendering or
+unverified checks. Existing CLI/API behaviour and write permissions remain unchanged.
+
## Discover only missing project facts
For a component that belongs in an existing project, use [GUIDE.md §0](references/GUIDE.md) after
diff --git a/skills/block-runner/references/GUIDE.md b/skills/block-runner/references/GUIDE.md
index dc47765..47e560f 100644
--- a/skills/block-runner/references/GUIDE.md
+++ b/skills/block-runner/references/GUIDE.md
@@ -289,6 +289,10 @@ tool is broken.
**Always say what you did** — where it went, how many blocks, and anything that fell back to
Custom HTML. A silent success is indistinguishable from a silent failure.
+For a rendered delivery, follow [VISUAL.md](VISUAL.md) by default: compare desktop/mobile,
+correct meaningful differences and check native editing/save. Source-only delivery still
+finishes normally; say when rendering or persistence has not been verified.
+
---
## 7. Matching the user's site
diff --git a/skills/block-runner/references/SITE.md b/skills/block-runner/references/SITE.md
index 72826e6..96c04d5 100644
--- a/skills/block-runner/references/SITE.md
+++ b/skills/block-runner/references/SITE.md
@@ -151,3 +151,7 @@ theme proof checks the theme's declared PHP requirement. Both routes require the
optional pinned WordPress/browser tooling. They pin the captured theme snapshot
automatically, so a separate plugin-style `--input` is unnecessary. Save proof and
visual/editor acceptance are separate claims.
+
+When delivering a rendered site or theme change, use [VISUAL.md](VISUAL.md) by default
+to compare the affected views, correct source-level differences and retain the observed
+limits. The proof commands above do not replace that comparison or authorise production writes.
diff --git a/skills/block-runner/references/VISUAL.md b/skills/block-runner/references/VISUAL.md
new file mode 100644
index 0000000..46c4b6a
--- /dev/null
+++ b/skills/block-runner/references/VISUAL.md
@@ -0,0 +1,84 @@
+# Finish rendered output
+
+Use this after creating or changing a rendered WordPress page, section, template/part,
+site or integrated block. It is the default delivery check: do not wait for a separate
+QA request. Existing CLI/library calls remain headless and unchanged.
+
+Check the changed region and surrounding layout on desktop and mobile. Reuse the
+current browser session and evidence that still matches the delivered revision.
+For a site, cover its different templates and responsive behaviour; do not revisit
+every unrelated page for a small edit. A clean first comparison needs no correction pass.
+
+## Establish the comparison
+
+Record the authored input/revision, native destination, intended regions and any
+approved design differences. Use the authored design's render or supplied screenshots
+as the reference. Rendered HTML is visual evidence, never a substitute for authored
+converter input.
+
+Match viewport, scale and UI state between reference and target. Choose desktop/mobile
+widths appropriate to the design; add a breakpoint-adjacent view when a defect needs it.
+Wait for fonts and images with a bounded timeout, and disclose missing resources.
+Freeze animation consistently for static comparison; check its behaviour separately
+when it is part of the requested result. Retain the actual browser/version and views.
+
+Without a visual reference, inspect the render against the stated content/layout
+requirements and check overflow, missing assets and obvious presentation failures.
+Say that source fidelity was not compared. An inaccessible target/browser, missing
+required reference or explicit user skip is an unverified check, never a visual pass.
+Source-only or batch work without a rendered destination still delivers normally.
+This check grants no deployment, credential or production-write authority.
+
+## Compare, explain, correct
+
+1. **Check content first:** section order, headings, body text, media, links and required
+ interactions, including fragment-link destinations and drawn/animated graphics.
+ A similar silhouette cannot compensate for lost content. A present canvas element
+ does not prove that its artwork rendered.
+2. **Compare corresponding regions:** widths/alignment, spacing, typography/wrapping,
+ image crop and mobile overflow or clipping. `overflow: hidden` can conceal broken
+ layouts while document width still looks correct. Confirm breakpoint rules still
+ affect the native regions. Match regions by meaning; source and native DOM
+ trees need not share selectors. Inspect the screenshots, not just capture success.
+3. **Measure a discrepancy:** use the browser's bounding boxes/computed styles for
+ the affected region. Record both selectors or region labels. Missing/ambiguous
+ regions block that comparison; screenshot-only references have no DOM measurements.
+ Do not collect every CSS property or require DOM/style equality. A pixel diff can
+ locate differences; it does not establish fidelity or editorial quality.
+4. **Fix the responsible input:** identify the authored selector, intent node path or
+ theme rule. Keep uncertain attribution explicit. Prioritise missing content,
+ broken interaction and overflow before decorative differences. Preserve unrelated
+ copy and native editability; never hand-patch generated block delimiters.
+5. **Regenerate and recapture:** use the existing conversion/assembly and delivery
+ route, including its gate, confirmation and drift checks. Preserve human edits.
+ Compare the same views again, keeping the original capture. Stop when the result
+ meets the brief or a real blocker/task budget is reached, not after an arbitrary
+ number of passes. Keep unresolved differences and editorial TODOs visible.
+
+A short working list is enough; it is not a required formal handoff:
+
+| Region / viewport | Expected → observed, evidence | Impact / source to inspect | Action / result |
+| --- | --- | --- | --- |
+| Article / desktop | Reference 720px → native 480px; paired capture and width | Extra wrapping; theme content width | Correct width, regenerate; resolved in recapture |
+
+Finish with the applicable native editor check: make a representative edit through
+its actual control, save and reopen, and inspect the rendered result. Keep permission
+to mutate the target and preservation of existing content explicit. If this cannot
+be exercised, record persistence as unverified rather than deriving it from a screenshot.
+
+## Reuse the existing facilities
+
+Use the harness's available browser controls for paired inspection and targeted
+measurements. The project's existing proof runners retain screenshots, errors and
+receipts and exercise native editing. `proof --theme` / `proof --site` use controlled
+sandboxes and may write fixture state: see [SITE.md](SITE.md#prove-the-right-result).
+They are not read-only capture commands for arbitrary sites.
+
+Registered-block `ProofFixture.visual` compares a render to a reviewed golden. That
+regression gate retains its own thresholds/masks; do not replace the golden to hide
+a source-to-native mismatch. Reuse captured evidence, without treating a successful
+gate as proof of a comparison it did not perform.
+
+Tell the user what was checked, what was corrected, and what remains. Distinguish
+block validity, visual observations, interaction and save persistence. No universal
+fidelity score, new CLI mode or separate report package is required.