strikethroo 3.14.2 → 3.15.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.
Files changed (74) hide show
  1. package/README.md +15 -6
  2. package/dist/__tests__/fixtures/review-gate.d.ts +59 -0
  3. package/dist/__tests__/fixtures/review-gate.d.ts.map +1 -0
  4. package/dist/__tests__/fixtures/review-gate.js +150 -0
  5. package/dist/__tests__/fixtures/review-gate.js.map +1 -0
  6. package/dist-web/assets/{arc-3h4SrJcP.js → arc-DXuQKY5O.js} +1 -1
  7. package/dist-web/assets/{architectureDiagram-3BPJPVTR-CHXVDgZv.js → architectureDiagram-3BPJPVTR-DaQd1Ie5.js} +1 -1
  8. package/dist-web/assets/{blockDiagram-GPEHLZMM-ByT2aIDh.js → blockDiagram-GPEHLZMM-BTAxxxkx.js} +1 -1
  9. package/dist-web/assets/{c4Diagram-AAUBKEIU-BpSMEH5T.js → c4Diagram-AAUBKEIU-DHuDwl7F.js} +1 -1
  10. package/dist-web/assets/channel-CKed0YrQ.js +1 -0
  11. package/dist-web/assets/{chunk-2J33WTMH-B00rt2rz.js → chunk-2J33WTMH-BD4uHGPG.js} +1 -1
  12. package/dist-web/assets/{chunk-4BX2VUAB-CUD0iXK7.js → chunk-4BX2VUAB-BqVSB0Q4.js} +1 -1
  13. package/dist-web/assets/{chunk-55IACEB6-KUROX5a_.js → chunk-55IACEB6-F-aB1oSz.js} +1 -1
  14. package/dist-web/assets/{chunk-727SXJPM-DdA9k_le.js → chunk-727SXJPM-iIr2R3ax.js} +1 -1
  15. package/dist-web/assets/{chunk-AQP2D5EJ-B4lS13Tr.js → chunk-AQP2D5EJ-UpIWfDiq.js} +1 -1
  16. package/dist-web/assets/{chunk-FMBD7UC4-C6DHs6Wv.js → chunk-FMBD7UC4-DeG5uTRD.js} +1 -1
  17. package/dist-web/assets/{chunk-ND2GUHAM-Nia1N7VP.js → chunk-ND2GUHAM-Tkl5amOh.js} +1 -1
  18. package/dist-web/assets/{chunk-QZHKN3VN-BKYt-ImO.js → chunk-QZHKN3VN-B3Af5I7v.js} +1 -1
  19. package/dist-web/assets/classDiagram-4FO5ZUOK-CD2fBLcy.js +1 -0
  20. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-CD2fBLcy.js +1 -0
  21. package/dist-web/assets/{cose-bilkent-S5V4N54A-uxuOqDzC.js → cose-bilkent-S5V4N54A-uuts3r-t.js} +1 -1
  22. package/dist-web/assets/{dagre-BM42HDAG-CUr1pLbj.js → dagre-BM42HDAG-CHrjnY3X.js} +1 -1
  23. package/dist-web/assets/{diagram-2AECGRRQ-BCeBLzM-.js → diagram-2AECGRRQ-BjEnf2q8.js} +1 -1
  24. package/dist-web/assets/{diagram-5GNKFQAL-DuM6xmJY.js → diagram-5GNKFQAL-BzvzvRAO.js} +1 -1
  25. package/dist-web/assets/{diagram-KO2AKTUF-Cf1eoQYh.js → diagram-KO2AKTUF-DNx6lZaA.js} +1 -1
  26. package/dist-web/assets/{diagram-LMA3HP47-Buo60yAm.js → diagram-LMA3HP47-BQUKKiM4.js} +1 -1
  27. package/dist-web/assets/{diagram-OG6HWLK6-D54wh40p.js → diagram-OG6HWLK6-MgImJXDh.js} +1 -1
  28. package/dist-web/assets/{erDiagram-TEJ5UH35-59J8tJG_.js → erDiagram-TEJ5UH35-D79fXG1m.js} +1 -1
  29. package/dist-web/assets/{flowDiagram-I6XJVG4X-DfDuK7uP.js → flowDiagram-I6XJVG4X-DQDtqM9F.js} +1 -1
  30. package/dist-web/assets/{ganttDiagram-6RSMTGT7-CbA5p8Mi.js → ganttDiagram-6RSMTGT7-rbAdz41p.js} +1 -1
  31. package/dist-web/assets/{gitGraphDiagram-PVQCEYII-1WxXLmxX.js → gitGraphDiagram-PVQCEYII-C-ppoVQN.js} +1 -1
  32. package/dist-web/assets/{index-Cao1t6Aj.js → index-BpEA2dcR.js} +1 -1
  33. package/dist-web/assets/{index-DHgmc9MH.js → index-COfqZ5qw.js} +4 -4
  34. package/dist-web/assets/{index-CyyNP5mv.js → index-D8Y-LZu5.js} +1 -1
  35. package/dist-web/assets/{infoDiagram-5YYISTIA-C5SUQ2SF.js → infoDiagram-5YYISTIA-DVx4rmpa.js} +1 -1
  36. package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-dU3aWKbh.js → ishikawaDiagram-YF4QCWOH-Bwo2Fe41.js} +1 -1
  37. package/dist-web/assets/{journeyDiagram-JHISSGLW-CMDkGbgV.js → journeyDiagram-JHISSGLW-Cpk1cbVU.js} +1 -1
  38. package/dist-web/assets/{kanban-definition-UN3LZRKU-mD1rJCc5.js → kanban-definition-UN3LZRKU-DT5hIyrL.js} +1 -1
  39. package/dist-web/assets/{linear-CUGnyMnk.js → linear-BHILOJgo.js} +1 -1
  40. package/dist-web/assets/{mermaid.core-Cpmiqmbf.js → mermaid.core-BYlMWjDD.js} +4 -4
  41. package/dist-web/assets/{mindmap-definition-RKZ34NQL-CDfl1B-m.js → mindmap-definition-RKZ34NQL-CjhPuIMr.js} +1 -1
  42. package/dist-web/assets/{pieDiagram-4H26LBE5-Cuo3mXQK.js → pieDiagram-4H26LBE5-BzD5r6aw.js} +1 -1
  43. package/dist-web/assets/{quadrantDiagram-W4KKPZXB-DnFnsvpl.js → quadrantDiagram-W4KKPZXB-ieE6W8Lz.js} +1 -1
  44. package/dist-web/assets/{requirementDiagram-4Y6WPE33-DCIMxgro.js → requirementDiagram-4Y6WPE33-B6Z6Nlwn.js} +1 -1
  45. package/dist-web/assets/{sankeyDiagram-5OEKKPKP-DfxERVIc.js → sankeyDiagram-5OEKKPKP-BAz2Fhdr.js} +1 -1
  46. package/dist-web/assets/{sequenceDiagram-3UESZ5HK-vKVzidDz.js → sequenceDiagram-3UESZ5HK-Dce-js6I.js} +1 -1
  47. package/dist-web/assets/{stateDiagram-AJRCARHV-OMYutbra.js → stateDiagram-AJRCARHV-DGx4tUMu.js} +1 -1
  48. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-kMJLTVIN.js +1 -0
  49. package/dist-web/assets/{timeline-definition-PNZ67QCA-Ca2z9OPS.js → timeline-definition-PNZ67QCA-B8KWHkBS.js} +1 -1
  50. package/dist-web/assets/{vennDiagram-CIIHVFJN-DBrJv-N8.js → vennDiagram-CIIHVFJN-ByWUGcRD.js} +1 -1
  51. package/dist-web/assets/{wardley-L42UT6IY-C80ot0sX.js → wardley-L42UT6IY-C1B0dt0L.js} +1 -1
  52. package/dist-web/assets/{wardleyDiagram-YWT4CUSO-CzvhVwCG.js → wardleyDiagram-YWT4CUSO-BrCqwemc.js} +1 -1
  53. package/dist-web/assets/{xychartDiagram-2RQKCTM6-DFrhJySN.js → xychartDiagram-2RQKCTM6-Br_yjZmA.js} +1 -1
  54. package/dist-web/index.html +1 -1
  55. package/package.json +1 -1
  56. package/templates/harness/skills/st-code-review/SKILL.md +309 -0
  57. package/templates/harness/skills/st-code-review/scripts/code-review.cjs +1539 -0
  58. package/templates/harness/skills/st-code-review/scripts/find-strikethroo-root.cjs +116 -0
  59. package/templates/harness/skills/st-code-review/scripts/validate-plan-blueprint.cjs +429 -0
  60. package/templates/harness/skills/st-execute-blueprint/SKILL.md +49 -2
  61. package/templates/harness/skills/st-execute-blueprint/scripts/capture-base-commit.cjs +325 -0
  62. package/templates/harness/skills/st-execute-blueprint/scripts/create-feature-branch.cjs +9 -7
  63. package/templates/harness/skills/st-execute-blueprint/scripts/dispatch-task-execution.cjs +46 -26
  64. package/templates/harness/skills/st-execute-task/scripts/dispatch-task-execution.cjs +46 -26
  65. package/templates/harness/skills/st-full-workflow/SKILL.md +49 -2
  66. package/templates/harness/skills/st-full-workflow/scripts/capture-base-commit.cjs +325 -0
  67. package/templates/harness/skills/st-full-workflow/scripts/create-feature-branch.cjs +9 -7
  68. package/templates/harness/skills/st-full-workflow/scripts/dispatch-task-execution.cjs +46 -26
  69. package/templates/strikethroo/config/hooks/CODE_REVIEW.md +60 -0
  70. package/templates/strikethroo/config/schemas/self-review-v2.xsd +437 -0
  71. package/dist-web/assets/channel-DVGz7-Ij.js +0 -1
  72. package/dist-web/assets/classDiagram-4FO5ZUOK-BuW_hD8R.js +0 -1
  73. package/dist-web/assets/classDiagram-v2-Q7XG4LA2-BuW_hD8R.js +0 -1
  74. package/dist-web/assets/stateDiagram-v2-BHNVJYJU-2bqmqQl-.js +0 -1
@@ -0,0 +1,309 @@
1
+ ---
2
+ name: st-code-review
3
+ description: Use when the blueprint execution gate asks for an independent second-harness review of a Strikethroo plan's cumulative diff in this repository — triggers include code review gate, review the plan diff, second-model review, CODE_REVIEW hook, review gate round. Do not use to review a single task, to review code outside a Strikethroo plan, or to give general code-quality or style opinions.
4
+ ---
5
+
6
+ <!--
7
+ Review-category modelling and false-positive suppression heuristics in this
8
+ prompt draw on PR-Agent (https://github.com/The-PR-Agent/pr-agent), used
9
+ under its permissive licence. No PR-Agent code is vendored. Conformance-only
10
+ scope filters out most of its deliberately broad rubric.
11
+ -->
12
+
13
+ # st-code-review
14
+
15
+ Critique a Strikethroo plan's cumulative diff as an independent reviewer running
16
+ on a different harness than the one that wrote the code, and emit the findings as
17
+ a schema-validated `review.xml`.
18
+
19
+ `<root>` below is the Strikethroo workspace root (`.ai/strikethroo`) supplied
20
+ with this dispatch.
21
+
22
+ ## Role
23
+
24
+ You **detect**. You never fix.
25
+
26
+ - Do not edit, create, or delete source files. Do not run formatters. Do not
27
+ commit.
28
+ - Fixes are dispatched separately, on the implementer route. The implementer sees
29
+ a finding, never your reasoning about it.
30
+ - Your entire output is one `review.xml` plus a short report.
31
+
32
+ ## Critical Rules
33
+
34
+ 1. **Conformance and defects only.** Check the diff against the plan's stated
35
+ requirements and for demonstrable defects. Nothing else.
36
+ 2. **Every finding cites evidence.** A file, a line range, and the concrete input
37
+ or state that produces the failure.
38
+ 3. **Every finding traces.** To an explicit requirement written in the plan, or
39
+ to a defect demonstrable in the code as written.
40
+ 4. **Emit `severity` and `confidence` on every comment.** Both attributes,
41
+ always, judged by the tests below.
42
+ 5. **The hook is authoritative.** `<root>/config/hooks/CODE_REVIEW.md` carries the
43
+ mandate, the floors, and the categories in scope. Where it and this prompt
44
+ disagree, the hook wins.
45
+ 6. **Findings do not accumulate power by volume.** Zero findings above the floor
46
+ is a correct and common outcome. Report it and stop.
47
+
48
+ ## Mandate: Conformance and Defects Only
49
+
50
+ ### In scope — exactly two categories
51
+
52
+ | `<category>` value | What it means |
53
+ | --- | --- |
54
+ | `requirement-conformance` | The code does not implement what the plan explicitly asked for. |
55
+ | `defect` | The code fails at runtime, produces wrong behaviour, violates a contract it declares, opens a security hole, causes data loss, or breaks something else the plan built. |
56
+
57
+ Emit no other category value.
58
+
59
+ ### Out of mandate — record nothing
60
+
61
+ - Style, naming, formatting, import order. The linter owns these.
62
+ - Design and abstraction opinions. "This works, but I would have structured it
63
+ differently" is not a finding.
64
+ - Requirements the plan does not state. The YAGNI posture that binds a planner to
65
+ explicit requirements binds your demands equally.
66
+ - Speculative hardening for inputs no stated requirement admits.
67
+ - Missing tests the plan did not ask for.
68
+
69
+ ### The accepted cost, stated plainly
70
+
71
+ A conformance-only reviewer will not catch *"this works and matches the plan but
72
+ the abstraction is wrong"* — a real category a second model is unusually good at
73
+ spotting. That is a deliberate trade against false-positive rate, and it is the
74
+ right trade only because this gate is unattended and auto-applies fixes. It is
75
+ not an oversight. Do not widen scope to cover it.
76
+
77
+ ## Anti-rationalization
78
+
79
+ Read `<root>/config/shared/anti-rationalization.md` and apply it to this table.
80
+ Every row points at you, the reviewer.
81
+
82
+ | You catch yourself thinking… | The binding rule |
83
+ | --- | --- |
84
+ | "This could theoretically fail if…" | Speculative failure scenario with no evidence cited. Do not emit it above the floor. A finding names a concrete input or state that produces the failure, or it is not a finding. |
85
+ | "The plan does not say this, but it should have." | Out of scope. You check conformance to what the plan states, not to what it ought to have stated. |
86
+ | "This works, but the abstraction is wrong." | Design opinion. Out of mandate. Record nothing. |
87
+ | "I am not certain, so I will explain at length to be safe." | Length is not evidence. Prompts demanding detailed justification show measurably higher misjudgment rates. Lower the `confidence` attribute instead. |
88
+ | "The caller probably handles this." / "The caller probably does not handle this." | An unread caller is an assumption, not evidence. Read it, or mark the finding `confidence="medium"` and state the assumption in the body. |
89
+ | "This is only `minor`, but it is real, so I will call it `major` so it gets fixed." | Severity is impact if real, never a lever for clearing the floor. Inflating it is the failure this gate is built to resist. Grade it honestly and let it be recorded. |
90
+ | "I have found nothing above the floor; I should look harder so this round produces something." | A clean diff is a valid result. Manufacturing a finding to justify the round is the exact defect — an over-rejecting reviewer injecting speculative changes into working code. Report zero and stop. |
91
+
92
+ ## Confidence and Severity
93
+
94
+ These are independent. Severity says how bad it is **if the finding is real**.
95
+ Confidence says **how sure you are that it is real**. An automated consumer
96
+ thresholds on both and relies on you lowering `confidence` honestly. LLM
97
+ reviewers systematically overstate certainty here.
98
+
99
+ ### `confidence` — judged by an evidentiary test, never by feel
100
+
101
+ | `confidence` | The test that earns it |
102
+ | --- | --- |
103
+ | `high` | Traceable entirely from the diff and the files you read. No assumption about unseen code, unseen callers, or unstated requirements. |
104
+ | `medium` | Exactly one unverified assumption, and that assumption is written out explicitly in the finding body. |
105
+ | `low` | The failure was imagined rather than traced, or the finding rests on more than one unverified assumption, or on a constraint you invented. |
106
+
107
+ How strongly the prose is worded changes nothing. A confident sentence resting on
108
+ an unread caller is `medium`.
109
+
110
+ ### `severity` — impact if real, never confidence and never fix cost
111
+
112
+ | `severity` | Meaning |
113
+ | --- | --- |
114
+ | `critical` | Causes data loss, a security hole, or a crash or corruption on a path real usage reaches. |
115
+ | `major` | Produces wrong behaviour or breaks a documented contract on a path real usage reaches, or leaves a stated requirement unmet. Nothing destroyed, no security impact. |
116
+ | `minor` | Real but bounded — an unlikely edge case, a maintenance hazard. Behaviour is correct today. |
117
+ | `info` | No defect. A recorded observation. Never actionable. |
118
+
119
+ ### The floors
120
+
121
+ Default floors: severity `major`, confidence `high`. The hook is authoritative if
122
+ it names different ones.
123
+
124
+ - Findings below either floor are **recorded in `review.xml` and never
125
+ auto-applied**. Recording them is useful; that is where they belong.
126
+ - A comment that **omits** `severity` or `confidence` falls below every floor.
127
+ Omission is never a route to getting a finding applied.
128
+ - A finding that lacks concrete evidence, or lacks a trace to an explicit plan
129
+ requirement or a demonstrable defect, is not emitted above the floor. Grade it
130
+ `info`/`low` or leave it out.
131
+
132
+ ## Scope: Cumulative Diff and Blast Radius
133
+
134
+ - The dispatch supplies the recorded **base commit** for this plan. Review
135
+ everything that changed between that commit and the **current working tree**.
136
+ - **Uncommitted changes are in scope.** Post-execution cleanup and any fix
137
+ applied by an earlier round are not committed by the time you run.
138
+ - Review the **cumulative** diff every round. Never the incremental fix diff. The
139
+ scope never narrows between rounds.
140
+ - Prior findings arrive marked **adjudicated**. Do not re-litigate them. Their
141
+ presence does not narrow what you look at.
142
+ - The default round budget is 3. Rounds are counted and terminated in code, not
143
+ by you. Review this round, emit, report, and stop. Do not schedule, request, or
144
+ simulate another round.
145
+ - **Blast radius.** For each symbol the diff changed — renamed, resignatured,
146
+ deleted, or given different behaviour — locate references **outside** the diff
147
+ and read those callsites. This is targeted expansion, not whole-codebase
148
+ review, and it is a partial mitigation rather than a complete one.
149
+
150
+ <details>
151
+ <summary>Obtaining the diff and running the blast-radius pass</summary>
152
+
153
+ When the dispatch hands you the diff, review what it hands you. When it hands you
154
+ only the base commit id, produce the cumulative diff yourself — `git diff <base>`
155
+ compares the base against the working tree and therefore includes uncommitted
156
+ changes, which `git diff <base>..HEAD` would omit.
157
+
158
+ For the blast-radius pass, list the symbols whose declaration or behaviour the
159
+ diff changed, then search the repository for each one and read every hit that is
160
+ not in a file the diff touched. A hit that still type-checks and still receives
161
+ what it expects needs no finding. A hit that now receives a different shape, a
162
+ different arity, or a different error contract is a `defect` finding with the
163
+ callsite's file and line as its evidence.
164
+
165
+ </details>
166
+
167
+ ## Output: `review.xml`
168
+
169
+ Emit exactly one XML document in the `urn:self-review:v2` namespace, at the path
170
+ the dispatch names. It must validate against the vendored schema at
171
+ `<root>/config/schemas/self-review-v2.xsd`.
172
+
173
+ Required shape:
174
+
175
+ - `<review>` — root. Requires `timestamp` (ISO 8601 with timezone). Set
176
+ `git-diff-args` to the base commit id and `repository` to the absolute
177
+ repository root.
178
+ - `<file>` — one per file in the diff, **including files you reviewed and had no
179
+ comment on**. Requires `path` (relative to the repository root),
180
+ `change-type` (`added`, `modified`, `deleted`, `renamed`), and `viewed`
181
+ (`true` when you read it).
182
+ - `<comment>` — zero or more per file, in child order `<body>`, `<category>`,
183
+ then an optional `<suggestion>`. Carry `severity` and `confidence` on every
184
+ one. For a line-level comment give **exactly one** pair: `new-line-start` and
185
+ `new-line-end` for added or context lines, or `old-line-start` and
186
+ `old-line-end` for deleted lines. Both pairs absent means a file-level
187
+ comment. Single-line comments set start equal to end.
188
+ - `<suggestion>` — optional, at most one per comment, containing
189
+ `<original-code>` then `<proposed-code>`.
190
+
191
+ ```xml
192
+ <?xml version="1.0" encoding="UTF-8"?>
193
+ <review xmlns="urn:self-review:v2"
194
+ timestamp="2026-07-27T09:41:00Z"
195
+ git-diff-args="a1b2c3d4"
196
+ repository="/abs/path/to/repo">
197
+ <file path="src/parse.ts" change-type="modified" viewed="true">
198
+ <comment new-line-start="42" new-line-end="44"
199
+ severity="major" confidence="high">
200
+ <body>Plan requirement "reject an empty id" is unmet: parseId("") returns
201
+ `{ ok: true }` because the length guard runs after the early return on
202
+ line 42.</body>
203
+ <category>requirement-conformance</category>
204
+ <suggestion>
205
+ <original-code> if (!raw) return { ok: true };</original-code>
206
+ <proposed-code> if (!raw) return { ok: false };</proposed-code>
207
+ </suggestion>
208
+ </comment>
209
+ </file>
210
+ <file path="src/index.ts" change-type="added" viewed="true" />
211
+ </review>
212
+ ```
213
+
214
+ ### The `<suggestion>` rule
215
+
216
+ A `<suggestion>` carries `original-code` copied **verbatim** from the file,
217
+ because it is applied by exact text matching. A finding whose fix cannot be
218
+ expressed as a local text replacement carries **no** suggestion — record the
219
+ finding and stop. Do not restructure a fix to fit the element.
220
+
221
+ Why, once: this is what blocks broad speculative refactors structurally rather
222
+ than by request. It must not be designed away.
223
+
224
+ ## Operating Procedure
225
+
226
+ ### 1. Read the mandate
227
+
228
+ Read `<root>/config/hooks/CODE_REVIEW.md`.
229
+
230
+ **Exit criterion:** you can state the severity floor, the confidence floor, and
231
+ the finding categories in scope from that file. Those values govern this round.
232
+
233
+ ### 2. Read the plan
234
+
235
+ Read the plan document named in the dispatch, in full.
236
+
237
+ **Exit criterion:** you have written down the list of explicit requirements this
238
+ diff is answerable to. A requirement not on that list cannot produce a
239
+ `requirement-conformance` finding.
240
+
241
+ ### 3. Read the cumulative diff
242
+
243
+ Take the base commit from the dispatch and review base against the working tree.
244
+
245
+ **Exit criterion:** every changed file is enumerated, and each one will receive a
246
+ `<file>` element — including the ones you have no comment on.
247
+
248
+ ### 4. Run the blast-radius pass
249
+
250
+ For each symbol the diff changed, read the references outside the diff.
251
+
252
+ **Exit criterion:** each changed symbol has been searched, and each out-of-diff
253
+ callsite has been read or explicitly noted as unread in the body of any finding
254
+ that depends on it.
255
+
256
+ ### 5. Critique under the mandate
257
+
258
+ <details>
259
+ <summary>Per-candidate procedure</summary>
260
+
261
+ For each candidate finding, in order:
262
+
263
+ 1. Name the category — `requirement-conformance` or `defect`. No third option;
264
+ if neither fits, discard the candidate.
265
+ 2. Cite the evidence — file, line range, and the concrete input or state that
266
+ produces the failure.
267
+ 3. Trace it — to a requirement on your step 2 list, or to a defect demonstrable
268
+ in the code as written.
269
+ 4. Grade `severity` by impact if real.
270
+ 5. Grade `confidence` by the evidentiary test. Count your unverified
271
+ assumptions: zero is `high`, exactly one is `medium` and must be written into
272
+ the body, more than one is `low`.
273
+ 6. Check the anti-rationalization table against the sentence you just wrote.
274
+ 7. Attach a `<suggestion>` only when the fix is a local text replacement, with
275
+ `original-code` copied verbatim.
276
+
277
+ </details>
278
+
279
+ **Exit criterion:** every finding carries a category, evidence, a trace, and both
280
+ attributes. Findings that fail any of those are dropped or graded `info`/`low`.
281
+
282
+ ### 6. Emit `review.xml`
283
+
284
+ Write the document to the path the dispatch names, in the shape above.
285
+
286
+ **Exit criterion:** the file exists, declares `urn:self-review:v2`, has one
287
+ `<file>` per changed file, and every `<comment>` carries `severity` and
288
+ `confidence`.
289
+
290
+ ### 7. Report
291
+
292
+ State the counts: total findings, findings at or above both floors, and findings
293
+ recorded below a floor. Name the floors you applied.
294
+
295
+ **Exit criterion:** the report's above-floor count matches the comments in
296
+ `review.xml` that clear both floors. Do not claim a clean review without having
297
+ emitted the document.
298
+
299
+ ## Failure Modes
300
+
301
+ - **The plan document cannot be read.** Stop and report. Do not review against a
302
+ reconstructed idea of the requirements.
303
+ - **The diff is empty.** Emit a `<review>` with no `<file>` children and report
304
+ zero findings. This is not an error.
305
+ - **A finding will not fit the schema.** Fix the finding's shape, never the
306
+ schema. A fix that cannot be a local text replacement is recorded without a
307
+ suggestion.
308
+ - **You are tempted to apply a fix yourself.** Stop. Detection and remediation
309
+ run on different routes on purpose — nobody marks their own homework.