@open-agent-toolkit/cli 0.2.26 → 0.2.28

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.
Files changed (76) hide show
  1. package/assets/NOTICES.md +156 -0
  2. package/assets/agents/oat-phase-implementer.md +312 -7
  3. package/assets/docs/contributing/explainer-kit-verification.md +125 -0
  4. package/assets/docs/contributing/index.md +1 -0
  5. package/assets/docs/reference/troubleshooting.md +47 -0
  6. package/assets/docs/workflows/projects/artifacts.md +24 -6
  7. package/assets/docs/workflows/projects/implementation-execution.md +151 -1
  8. package/assets/docs/workflows/skills/explainer-kit-providers.md +144 -0
  9. package/assets/docs/workflows/skills/explainer-kit.md +121 -69
  10. package/assets/docs/workflows/skills/index.md +1 -0
  11. package/assets/public-package-versions.json +4 -4
  12. package/assets/skills/explainer-kit/SKILL.md +18 -3
  13. package/assets/skills/explainer-kit/recipes/project-recap.json +43 -16
  14. package/assets/skills/explainer-kit/references/contracts.md +167 -20
  15. package/assets/skills/explainer-kit/references/golden-conformance.md +80 -0
  16. package/assets/skills/explainer-kit/references/visual-authoring.md +92 -0
  17. package/assets/skills/explainer-kit/references/visual-review.md +57 -0
  18. package/assets/skills/explainer-kit/schemas/author-request.v2.schema.json +172 -1
  19. package/assets/skills/explainer-kit/schemas/build-record.schema.json +7 -1
  20. package/assets/skills/explainer-kit/schemas/fact-base.schema.json +38 -2
  21. package/assets/skills/explainer-kit/schemas/manifest.schema.json +25 -1
  22. package/assets/skills/explainer-kit/schemas/run-request.schema.json +4 -0
  23. package/assets/skills/explainer-kit/schemas/set-plan.v1.schema.json +149 -0
  24. package/assets/skills/explainer-kit/schemas/visual-review-request.v1.schema.json +117 -0
  25. package/assets/skills/explainer-kit/schemas/visual-review-result.v1.schema.json +80 -0
  26. package/assets/skills/explainer-kit/scripts/lib/browser-runtime.mjs +148 -4
  27. package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +243 -0
  28. package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +586 -8
  29. package/assets/skills/explainer-kit/scripts/lib/diagram.mjs +285 -8
  30. package/assets/skills/explainer-kit/scripts/lib/durability.mjs +35 -0
  31. package/assets/skills/explainer-kit/scripts/lib/fact-base.mjs +144 -8
  32. package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +379 -0
  33. package/assets/skills/explainer-kit/scripts/lib/png.mjs +287 -0
  34. package/assets/skills/explainer-kit/scripts/lib/qa.mjs +280 -8
  35. package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +132 -3
  36. package/assets/skills/explainer-kit/scripts/lib/records.mjs +513 -21
  37. package/assets/skills/explainer-kit/scripts/lib/render.mjs +67 -3
  38. package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +43 -1
  39. package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +208 -0
  40. package/assets/skills/explainer-kit/scripts/lib/source-backlinks.mjs +218 -0
  41. package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +380 -0
  42. package/assets/skills/explainer-kit/scripts/render-qa.mjs +48 -10
  43. package/assets/skills/explainer-kit/scripts/run.mjs +859 -134
  44. package/assets/skills/oat-dispatch-subagents/SKILL.md +16 -3
  45. package/assets/skills/oat-explainer-kit/SKILL.md +40 -12
  46. package/assets/skills/oat-explainer-kit/references/author-callback.md +12 -10
  47. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +40 -2
  48. package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +72 -0
  49. package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +167 -5
  50. package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +92 -5
  51. package/assets/skills/oat-explainer-kit/scripts/run.mjs +324 -2
  52. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
  53. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
  54. package/assets/skills/oat-project-implement/SKILL.md +5 -4
  55. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +21 -0
  56. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
  57. package/assets/skills/oat-project-implement/references/phase-execution.md +359 -12
  58. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
  59. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
  60. package/assets/templates/state.md +7 -0
  61. package/dist/commands/project/archive/archive-utils.d.ts +1 -0
  62. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  63. package/dist/commands/project/archive/archive-utils.js +109 -42
  64. package/dist/commands/project/archive/explainer-package-coverage.d.ts +14 -0
  65. package/dist/commands/project/archive/explainer-package-coverage.d.ts.map +1 -0
  66. package/dist/commands/project/archive/explainer-package-coverage.js +27 -0
  67. package/dist/commands/project/archive/explainer-source-backlinks.d.ts +18 -0
  68. package/dist/commands/project/archive/explainer-source-backlinks.d.ts.map +1 -0
  69. package/dist/commands/project/archive/explainer-source-backlinks.js +27 -0
  70. package/dist/commands/project/archive/push-runner.d.ts +2 -1
  71. package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
  72. package/dist/commands/project/archive/push-runner.js +5 -1
  73. package/dist/release/public-package-contract.d.ts +6 -0
  74. package/dist/release/public-package-contract.d.ts.map +1 -1
  75. package/dist/release/public-package-contract.js +75 -0
  76. package/package.json +2 -2
@@ -113,9 +113,56 @@ oat tools has <pack> --scope user
113
113
  - Reconcile `state.md`, `plan.md` review table, and `implementation.md`.
114
114
  - Ensure phase/review status has been updated after reviews and fix cycles.
115
115
 
116
+ ## An Explainer Kit recap ends as `built-needs-review`
117
+
118
+ `built-needs-review` means the required unattended visual-review chain did not
119
+ reach a valid `pass`. The run retains available output for diagnosis, but OAT
120
+ will not finalize, archive, attest, publish, or push it as a successful recap.
121
+ Do not bypass the review gate by copying the package into a durable location.
122
+
123
+ Inspect:
124
+
125
+ 1. `build-record.json` and `manifest.json` for the terminal outcome and warning.
126
+ 2. `qa/browser/` for all required mobile, tablet, and desktop PNG/metrics pairs.
127
+ 3. `qa/visual-review/attempt-*/request.json` and `result.json` for request
128
+ binding, critic disposition, and findings.
129
+ 4. `qa/visual-review/revision.json` when a correction was requested.
130
+ 5. Adapter logs for missing or invalid `browserSession`, `visualCritic`, or
131
+ correction-provider modules.
132
+
133
+ Common causes include unavailable Chromium, a fixture or unbranded session,
134
+ missing screenshots, invalid decoded PNG dimensions, runtime/capture identity
135
+ drift, critic exceptions, evidence mutation, `fail`, and an unresolved
136
+ correction. Fix the provider or artifact problem and rebuild the recap; partial
137
+ evidence is diagnostic only.
138
+
139
+ See
140
+ [Explainer Provider Integration](../workflows/skills/explainer-kit-providers.md)
141
+ for the trusted-session and critic contracts.
142
+
143
+ ## Explainer Kit resume fails with `E_APPROVAL_RESUME`
144
+
145
+ Interactive resume is same-request only. Keep the opaque `ekrt2` token returned
146
+ as `approval.resumeToken` outside the package and provide it as
147
+ `reviewedSource.resumeToken` with the complete original request.
148
+
149
+ The error is expected when:
150
+
151
+ - the token is missing, malformed, or not `ekrt2`;
152
+ - the configured output root or retained run root moved;
153
+ - `run-request.json` or a retained set-plan record changed;
154
+ - the current request differs in source binding, recipe, mode, theme, render
155
+ strategy, privacy, public URL, durability, or publish destination; or
156
+ - the package contains a legacy `ekrt1` token.
157
+
158
+ Do not edit retained files or weaken the current request to force a match.
159
+ Restore the exact original request and package bytes. Legacy paused runs cannot
160
+ be upgraded in place; restart them to receive an authenticated `ekrt2` token.
161
+
116
162
  ## Reference artifacts
117
163
 
118
164
  - `.oat/projects/<scope>/<project>/implementation.md`
119
165
  - `.oat/projects/<scope>/<project>/reviews/`
166
+ - `.oat/projects/<scope>/<project>/explainers/<slug>/qa/`
120
167
  - `packages/cli/src/commands/doctor/index.ts`
121
168
  - `packages/cli/src/commands/instructions/`
@@ -57,12 +57,30 @@ The archive exports at most one selected recap package. It preserves structured
57
57
  failure outcomes and successful intermediates, rejects an existing dated
58
58
  destination, and requires the selected path to stay under the project's
59
59
  `explainers/` directory with a `project-recap` manifest. Verification covers
60
- the exact retained bytes for the privacy-safe request, content approval, fact
61
- base JSON and Markdown, declared author results, authored content, resolved
62
- theme, and every built artifact. Canonical fact-base and theme hashes remain
63
- normalized-object identities; `manifest.immutableHashes` independently covers
64
- serialized file bytes. Missing, stale, or tampered coverage fails before the
65
- active project is deleted.
60
+ the complete mode-aware package:
61
+
62
+ - privacy-safe request and content approval;
63
+ - fact-base JSON and Markdown;
64
+ - the five immutable set-plan records and authored drafts;
65
+ - declared author results and authored content;
66
+ - resolved theme and every built artifact;
67
+ - canonical mobile, tablet, and desktop screenshots;
68
+ - paired `browser-evidence/v2` metrics with launched Chromium name, version,
69
+ and capture identity;
70
+ - cohesion observations and each visual-review request/result; and
71
+ - the bounded revision record when a correction occurred.
72
+
73
+ Canonical object hashes identify normalized fact-base, theme, runtime, and
74
+ capture objects; `manifest.immutableHashes` independently covers serialized file
75
+ bytes. The archive requires one complete, internally consistent browser and
76
+ review chain for a successful unattended recap. Missing, stale, forged,
77
+ cross-record-mismatched, or tampered coverage fails before the active project is
78
+ deleted.
79
+
80
+ `built-needs-review` is a terminal review-gate outcome, not a non-durable
81
+ success. Its partial evidence remains available for diagnosis, but it cannot be
82
+ finalized, exported, attested, archived, or pushed. Review and rebuild the recap
83
+ to a passing visual-review outcome first.
66
84
 
67
85
  Local-scope projects are not archived through this export path. Their explainer
68
86
  packages inherit the local project's untracked posture and remain
@@ -16,6 +16,10 @@ and updates project state.
16
16
  in dependency order.
17
17
  - **Task boundary:** each task still produces exactly one bounded, verified
18
18
  commit.
19
+ - **Prevention boundary:** formatting, declared task verification, and
20
+ applicable cheap checks run before the task commit.
21
+ - **Recovery boundary:** an eligible post-commit defect may produce a separate
22
+ same-target recovery commit under the phase's bounded recovery authority.
19
23
  - **Review boundary:** the root dispatches one independent reviewer after the
20
24
  phase report.
21
25
  - **Fix boundary:** blocking findings return to the original phase handle when
@@ -78,7 +82,138 @@ once, and directly executes each task in plan order. For every task it:
78
82
  6. verifies the commit, file boundary, tests, and clean worktree.
79
83
 
80
84
  After all tasks, it runs phase-wide verification and returns a compact report.
81
- It does not dispatch the phase reviewer or mutate project bookkeeping.
85
+ It does not dispatch the phase reviewer or mutate general project bookkeeping.
86
+ While it owns the worktree, it may atomically update only the active phase's
87
+ authoritative `oat_phase_recovery_policy.phase_attempt_usage.<pNN>` entry. The
88
+ phase returns with a matching committed `completed` or `failed` terminal marker
89
+ still present. The root validates that marker against the report, recovery
90
+ event, immutable history, attempt accounting, exact target, and verification
91
+ before clearing it. Only the post-validation null marker is the settled ledger
92
+ state; a premature clear or contradictory marker fails closed.
93
+
94
+ ## Prevent Defects Before Commit
95
+
96
+ Prevention is the first recovery control. Before each planned task commit, the
97
+ phase implementer runs checks in this order:
98
+
99
+ 1. format every changed file;
100
+ 2. run the task's declared verification;
101
+ 3. run every repository-discovered cheap check that applies to the changed
102
+ surface and is proportionate to the task; and
103
+ 4. run a discoverable scoped build or test when the task changes emitted
104
+ output, build or test configuration, packaging, or equivalent behavior.
105
+
106
+ Broad repository tests and builds may remain phase-level when running them for
107
+ every task would be disproportionate. These broader checks verify that the
108
+ phase's task outputs compose correctly. A correction made before the planned
109
+ task commit is prevention and does not consume a recovery attempt.
110
+
111
+ ## Recover After Commit
112
+
113
+ When declared task, transition, or phase verification finds a post-commit
114
+ defect, OAT classifies it before editing. Automatic recovery proceeds only when
115
+ the correction is mechanically bounded, unambiguous, in phase, non-destructive,
116
+ and verifiable, and when the exact launcher-owned implementation target and
117
+ original-request provenance remain intact. Architecture, security, product,
118
+ requirements, public-behavior, credential, protected-branch, destructive, or
119
+ non-mechanical scope changes require operator direction.
120
+
121
+ The accepted task commit remains immutable. For an eligible defect, the phase
122
+ implementer reserves an attempt in the authoritative phase ledger, applies the
123
+ bounded correction, and runs focused and phase checks before a candidate commit.
124
+ After those checks pass, the implementer commits the correction with a
125
+ `completed` pre-bookkeeping marker and immediately reruns both checks against
126
+ the committed HEAD. Those post-commit reruns are authoritative. A pass makes
127
+ the candidate the successful recovery commit; a failure durably transitions the
128
+ marker to `failed` in ledger-only terminal evidence and stops without claiming
129
+ a successful recovery. Mechanically related failures from one verification
130
+ command may share one atomic attempt and successful commit; independent defects
131
+ require separate attempts.
132
+
133
+ Append-only history protects accepted work by requiring a new, auditable commit;
134
+ it does not require repeated approval for a mechanical repair already covered
135
+ by the phase's standing authority. The important distinctions are:
136
+
137
+ - a **defect** is a post-commit failure discovered by declared verification;
138
+ - an **authorization prompt** is required only at a direction-required
139
+ boundary, not for every eligible defect;
140
+ - a **continuation** preserves the original request and exact target, either in
141
+ the accepted handle or through an explicitly linked fresh same-target
142
+ recovery launch; and
143
+ - a **successful repair** produces one immutable append-only recovery commit.
144
+
145
+ This recovery is not accepted-launch fallback. After a launch is accepted,
146
+ completion, failure, timeout, interruption, `BLOCKED`, or contract refusal never
147
+ makes another model, provider, route, or worker eligible. A fresh launch is
148
+ permitted only when the caller-specific lifecycle contract already authorized
149
+ bounded recovery, the accepted handle cannot resume, the exact original target
150
+ remains bindable, a pending attempt is reconciled, and the existing
151
+ `continuation_events` record links it to the original request.
152
+
153
+ ### Recovery Budget
154
+
155
+ `oat_phase_recovery_policy` is dedicated to implementation recovery and is
156
+ independent of `oat_orchestration_retry_limit`, which continues to govern
157
+ review-fix and gate loops. The project default is `10` attempts per phase.
158
+ Project defaults and phase-specific overrides accept integers from `0` through
159
+ `20`; `0` disables automatic post-commit repair for that scope.
160
+
161
+ Attempt usage is monotonic and durable per phase. A new attempt is consumed
162
+ before the bounded edit begins, so a failed edit, commit, or re-verification
163
+ cannot retry for free. An already-reconciled pending attempt may finish without
164
+ another reservation, even when usage equals the limit. Evidence of an
165
+ infrastructure or flaky failure permits one no-edit rerun without consuming an
166
+ attempt; a repeated unexplained failure is ambiguous and stops without editing.
167
+ A direction-required boundary reached before reservation leaves the pending
168
+ marker null and usage unchanged, emits its required event, and records no edit
169
+ or recovery commit.
170
+
171
+ At three recovery events, the phase report warns about elevated recovery volume
172
+ but may continue while every eligibility condition and the budget remain valid.
173
+ At exhaustion, OAT stops for one explicit operator outcome:
174
+
175
+ 1. **Add N attempts:** set that phase's total limit to `used_attempts + N`,
176
+ capped at `20`, without resetting prior usage.
177
+ 2. **Authorize changed scope:** record a separate consequential or
178
+ scope-expanding action outside automatic recovery.
179
+ 3. **Stop:** preserve the worktree, immutable history, and evidence.
180
+
181
+ ### Recovery Event
182
+
183
+ Every recovered, direction-required, or failed-attempt disposition emits
184
+ exactly one event with this heading, label order, and vocabulary:
185
+
186
+ ```markdown
187
+ ### Recovery Event {event-id}
188
+
189
+ - Phase/task: {phase and originating task when known}
190
+ - Original request: {original_request_id}
191
+ - Original commit: {immutable task commit}
192
+ - Defect class: lint | type | test | build | composition | other
193
+ - Discovered by: {exact verification command or transition check}
194
+ - Disposition: recovered | direction-required | failed-attempt
195
+ - Authorization: phase-standing | operator-extension | operator-scope
196
+ - Attempt: {used}/{phase_recovery_limit}
197
+ - Dispatch target: {exact launcher-owned implementation target}
198
+ - Recovery commit: {sha or -}
199
+ - Verification: {focused and relevant phase result}
200
+ - Reason: {eligibility or stop-boundary evidence}
201
+ ```
202
+
203
+ The event ledger keeps defect volume, authorization-prompt volume, continuation
204
+ volume, and successful repair commits measurable as separate facts. A failed
205
+ attempt still produces one event even when it produces no recovery commit.
206
+
207
+ ### Pre-Change Baseline
208
+
209
+ The recorded pre-change baseline is nine recovery events plus two
210
+ operator-recovery continuations. Known failures included lint, composition, and
211
+ test-fixture defects; exact per-class counts are unavailable. The repeated
212
+ prompts exposed a latent policy under integration-heavy verification rather
213
+ than a recent regression. In particular, PR #176 changed phase-base anchoring
214
+ and is explicitly excluded from causation: the root still captures a fresh
215
+ phase base immediately before each launch, so earlier recovery commits are
216
+ already part of the next phase's base.
82
217
 
83
218
  ### Phase reviewer
84
219
 
@@ -155,6 +290,21 @@ Only an allowed and fresh gate disposition can enter the pre-approval sequence,
155
290
  cross final HiLL, run the post-approval sequence, mark implementation complete,
156
291
  or emit success.
157
292
 
293
+ ## Update Installed Recovery Contracts
294
+
295
+ Bounded phase recovery ships in OAT `0.2.28`. After upgrading to that release or
296
+ later, update the installed OAT tools and then regenerate provider views from
297
+ the canonical contracts:
298
+
299
+ ```bash
300
+ oat tools update
301
+ oat sync --scope all
302
+ ```
303
+
304
+ Run the commands in that order before expecting global Claude, Codex, or Cursor
305
+ phase agents to use the new contract. Provider assets are generated views, not
306
+ independently maintained policy forks.
307
+
158
308
  ## Phase Scope
159
309
 
160
310
  The root supplies one scope for the whole phase:
@@ -0,0 +1,144 @@
1
+ ---
2
+ title: Explainer Provider Integration
3
+ description: 'Provider-neutral planner, author, browser-session, and visual-critic contracts for Explainer Kit integrators.'
4
+ ---
5
+
6
+ # Explainer Provider Integration
7
+
8
+ Explainer Kit keeps model and browser providers outside its retained request
9
+ contracts. Integrators supply executable seams in process or through validated
10
+ module exports; the core owns schemas, evidence binding, and terminal outcomes.
11
+
12
+ For recipes, authoring behavior, themes, and lifecycle policy, start with
13
+ [Explainer Kit](explainer-kit.md).
14
+
15
+ ## Provider boundaries
16
+
17
+ Use exactly one form for each required role:
18
+
19
+ | Role | Direct input | Module-path input | Required export |
20
+ | ------------------ | ---------------- | -------------------------- | ----------------------------------- |
21
+ | Set planning | `planSet` | `planSetModulePath` | `planSet` function |
22
+ | Artifact authoring | `author` | `authorModulePath` | `author` function |
23
+ | Browser evidence | `browserSession` | `browserSessionModulePath` | branded `browserSession` descriptor |
24
+ | Whole-set review | `visualCritic` | `visualCriticModulePath` | `visualCritic` function |
25
+
26
+ `project-recap` requires all four roles. Other recipes require the author and
27
+ use their recipe-specific planning behavior. Direct-plus-module conflicts,
28
+ missing files, and invalid exports fail at the adapter boundary before core
29
+ execution.
30
+
31
+ Do not place browser or visual-review providers in `coreOptions`. Executable
32
+ callbacks, descriptors, and module paths are transient and never enter
33
+ `ExplainerRunRequestV1`, `run-request.json`, or immutable package hashes.
34
+
35
+ ## Set planner
36
+
37
+ The provider-neutral `planSet` callback runs once after fact reconciliation and
38
+ before any author callback. It returns the complete portfolio and one shared
39
+ claim ledger.
40
+
41
+ For a project recap, the portfolio must contain the required hub, architecture
42
+ view, and deck. Optional entries must use a recipe-licensed profile, remain
43
+ inside recipe and per-profile limits, and carry source-backed justification.
44
+ Duplicate identities, undeclared sources, conflicting shared terms, and
45
+ unjustified optionals fail validation.
46
+
47
+ Every author request receives the immutable set context and its matching planned
48
+ artifact. Authors cannot add, remove, replace, or rename portfolio entries.
49
+
50
+ ## Artifact author
51
+
52
+ The core invokes `author` once per planned artifact with
53
+ `explainer-kit.author-request/v2`. The request contains:
54
+
55
+ - artifact identity, type, and authoring path;
56
+ - the versioned brief and bundled medium-specific guidance;
57
+ - reconciled facts and the shared set context;
58
+ - the matching planned artifact;
59
+ - the resolved theme; and
60
+ - the bundled shell for artistic HTML.
61
+
62
+ Return `explainer-kit.author-result/v2` with exactly one of
63
+ `content.markdown` or `content.html` and non-secret provenance. The core
64
+ validates source overlap, path ownership, script identity, and structural
65
+ contracts after the callback returns.
66
+
67
+ The author, fact critic, browser probe, and visual critic must have distinct
68
+ callback identities. One provider implementation may back multiple roles, but
69
+ the adapter still requires separate executable boundaries.
70
+
71
+ ## Trusted browser session
72
+
73
+ Create a direct session with the compatible core:
74
+
75
+ ```js
76
+ const browserSession = await core.createBrowserProbeSession();
77
+
78
+ try {
79
+ await runOatExplainer(request, {
80
+ planSet,
81
+ author,
82
+ browserSession,
83
+ visualCritic,
84
+ });
85
+ } finally {
86
+ await browserSession.close();
87
+ }
88
+ ```
89
+
90
+ The factory launches Chromium and derives the runtime name and version from the
91
+ actual browser instance. A private in-memory brand prevents a plain object with
92
+ caller-authored `{name, version}` metadata from impersonating a trusted
93
+ session. Module providers export the already branded descriptor as
94
+ `browserSession`, not a bare callback.
95
+
96
+ For unattended project recaps, the core chooses 320, 768, and 1440 widths and
97
+ requires default-scenario PNGs. It validates the PNG signature, decoded
98
+ dimensions, and pixel payload, then writes paired
99
+ `explainer-kit.browser-evidence/v2` metrics. Every record retains:
100
+
101
+ - launched Chromium name and version;
102
+ - fixed capture settings;
103
+ - one derived capture identity;
104
+ - viewport and scenario;
105
+ - screenshot path and byte binding; and
106
+ - measured overflow, clipping, readability, motion, keyboard, deck, and theme
107
+ behavior.
108
+
109
+ All records in one review chain must carry the same runtime and capture
110
+ identity. Deterministic fixture sessions are explicit test helpers and are
111
+ rejected by unattended production recap paths.
112
+
113
+ ## Whole-set visual critic
114
+
115
+ The `visualCritic` receives one
116
+ `explainer-kit.visual-review-request/v1` plus a confined evidence reader. The
117
+ request binds:
118
+
119
+ - every rendered artifact and its exact content hash;
120
+ - every viewport-matched screenshot and metrics hash;
121
+ - cohesion observations from the shared ledger; and
122
+ - the trusted browser runtime and capture identity.
123
+
124
+ Return `explainer-kit.visual-review-result/v1` with the exact request identity,
125
+ all reviewed artifact IDs, structured findings, and one disposition:
126
+
127
+ - `pass` completes the review gate;
128
+ - `correct` requests one bounded correction and one final review; or
129
+ - `fail` terminates the gate.
130
+
131
+ The critic must not mutate rendered files or evidence. The core revalidates all
132
+ bound bytes after each callback.
133
+
134
+ ## Terminal behavior
135
+
136
+ There is never a second correction or third review. Missing, malformed, forged,
137
+ stale, cross-record-mismatched, or mutated evidence; a thrown callback; a
138
+ `fail`; or an unresolved correction produces `built-needs-review`.
139
+
140
+ That outcome retains available artifacts and review evidence for diagnosis, but
141
+ invokes neither durability nor publication. It cannot be finalized, archived,
142
+ attested, or pushed as a successful recap.
143
+
144
+ See [Troubleshooting](../../reference/troubleshooting.md) for recovery steps.