@azure-id/orc 1.9.2 → 2.1.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 (228) hide show
  1. package/CHANGELOG.md +722 -0
  2. package/README-id.md +56 -42
  3. package/README.md +58 -41
  4. package/bin/build-agents.js +125 -29
  5. package/bin/clear-logs.js +620 -0
  6. package/bin/cli.js +1873 -180
  7. package/bin/fix.js +459 -0
  8. package/bin/gotcha-import.js +1081 -0
  9. package/bin/gotcha.js +1566 -0
  10. package/bin/graph-query.js +1 -1
  11. package/bin/graph.js +717 -717
  12. package/bin/habit.js +1538 -0
  13. package/bin/mockrun-catalog.js +284 -276
  14. package/bin/onboarding-content.js +2 -1
  15. package/bin/pricing.json +28 -21
  16. package/bin/run-undo.js +398 -0
  17. package/bin/trace-write.js +869 -0
  18. package/bin/verify-contracts.js +627 -100
  19. package/bin/verify-package.js +68 -10
  20. package/bin/webui/api.js +151 -6
  21. package/bin/webui/app.html +239 -232
  22. package/bin/webui/css/00-tokens.css +110 -92
  23. package/bin/webui/css/04-motion.css +87 -0
  24. package/bin/webui/css/06-responsive.css +203 -178
  25. package/bin/webui/css/panels/behaviour.css +205 -0
  26. package/bin/webui/css/panels/hookui.css +79 -0
  27. package/bin/webui/fixtures/behaviour.js +562 -0
  28. package/bin/webui/fixtures/extra.js +9 -9
  29. package/bin/webui/fixtures/flow.js +81 -81
  30. package/bin/webui/fixtures/hookui.js +506 -431
  31. package/bin/webui/fixtures/index.js +66 -3
  32. package/bin/webui/fixtures/knowledge.js +9 -3
  33. package/bin/webui/fixtures/maintenance.js +123 -42
  34. package/bin/webui/fixtures/rules.js +1007 -1002
  35. package/bin/webui/fixtures/settings.js +6 -7
  36. package/bin/webui/fixtures/stats.js +25 -6
  37. package/bin/webui/fixtures/wait.js +98 -97
  38. package/bin/webui/i18n/en/behaviour.json +156 -0
  39. package/bin/webui/i18n/en/hookui.json +290 -194
  40. package/bin/webui/i18n/en/maintenance.json +71 -52
  41. package/bin/webui/i18n/en/nav.json +25 -24
  42. package/bin/webui/i18n/en/settings.json +60 -60
  43. package/bin/webui/i18n/en/tour.json +37 -35
  44. package/bin/webui/i18n/id/behaviour.json +156 -0
  45. package/bin/webui/i18n/id/hookui.json +290 -194
  46. package/bin/webui/i18n/id/maintenance.json +71 -52
  47. package/bin/webui/i18n/id/nav.json +25 -24
  48. package/bin/webui/i18n/id/settings.json +60 -60
  49. package/bin/webui/i18n/id/tour.json +37 -35
  50. package/bin/webui/js/01-i18n.js +155 -154
  51. package/bin/webui/js/05-banners.js +181 -172
  52. package/bin/webui/js/06-edit.js +193 -183
  53. package/bin/webui/js/90-tour.js +498 -494
  54. package/bin/webui/js/91-shortcuts.js +126 -126
  55. package/bin/webui/js/99-boot.js +121 -118
  56. package/bin/webui/js/panels/behaviour.js +1087 -0
  57. package/bin/webui/js/panels/hookui.js +2196 -1691
  58. package/bin/webui/js/panels/maintenance.js +336 -235
  59. package/bin/webui/js/panels/settings.js +726 -719
  60. package/mock-run/INDEX.md +110 -107
  61. package/mock-run/extra-slots.md +1 -1
  62. package/mock-run/gotcha-import.md +118 -0
  63. package/mock-run/habits.md +129 -0
  64. package/mock-run/orc-aftermath.md +392 -392
  65. package/mock-run/orc-budget.md +29 -33
  66. package/mock-run/orc-cli.md +200 -200
  67. package/mock-run/orc-explain.md +86 -86
  68. package/mock-run/orc-extra.md +389 -392
  69. package/mock-run/orc-fix.md +87 -0
  70. package/mock-run/orc-pattern.md +112 -112
  71. package/mock-run/orc-quick.md +6 -1
  72. package/mock-run/orc.md +157 -157
  73. package/package.json +1 -1
  74. package/templates/agents/MODEL-MAPPING.md +37 -34
  75. package/templates/agents/orc-advisor-opus-5-xhigh.md +1 -7
  76. package/templates/agents/orc-analyze-mini-opus-5-med.md +1 -6
  77. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +2 -5
  78. package/templates/agents/{orc-claude-writer-opus-4-8-high.md → orc-claude-writer-opus-5-low.md} +48 -53
  79. package/templates/agents/orc-context-combiner-opus-5-high.md +1 -11
  80. package/templates/agents/orc-executor-haiku-4-5.md +14 -6
  81. package/templates/agents/orc-executor-opus-4-7-high.md +14 -6
  82. package/templates/agents/orc-executor-opus-4-7-med.md +14 -6
  83. package/templates/agents/orc-executor-opus-4-8-high.md +14 -6
  84. package/templates/agents/orc-executor-opus-5-high.md +14 -6
  85. package/templates/agents/orc-executor-opus-5-low.md +14 -6
  86. package/templates/agents/orc-executor-opus-5-med.md +14 -6
  87. package/templates/agents/orc-executor-sonnet-4-6-high.md +14 -6
  88. package/templates/agents/orc-executor-sonnet-4-6-med.md +14 -6
  89. package/templates/agents/orc-executor-sonnet-5-high.md +15 -7
  90. package/templates/agents/orc-executor-sonnet-5-low.md +155 -0
  91. package/templates/agents/orc-executor-sonnet-5-med.md +155 -0
  92. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -10
  93. package/templates/agents/orc-judge-opus-5-xhigh.md +5 -9
  94. package/templates/agents/orc-learn-writer-opus-5-low.md +1 -7
  95. package/templates/agents/orc-pattern-codifier-opus-5-med.md +1 -8
  96. package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +58 -63
  97. package/templates/agents/orc-planner-mini-opus-5-med.md +1 -4
  98. package/templates/agents/orc-planner-mini-sonnet-5-high.md +2 -3
  99. package/templates/agents/orc-planner-opus-5-med.md +1 -4
  100. package/templates/agents/orc-recon-opus-5-low.md +1 -8
  101. package/templates/agents/orc-recon-sonnet-4-6-med.md +1 -8
  102. package/templates/agents/orc-retro-opus-5-med.md +6 -8
  103. package/templates/agents/orc-retro-sonnet-5-high.md +7 -8
  104. package/templates/agents/orc-reviewer-opus-5-low.md +96 -0
  105. package/templates/agents/orc-scout-opus-5-low.md +1 -6
  106. package/templates/agents/orc-scout-sonnet-4-6-high.md +35 -39
  107. package/templates/agents/orc-system-analyst-opus-5-high.md +1 -6
  108. package/templates/agents/orc-test-author-opus-5-med.md +4 -5
  109. package/templates/agents/orc-trace-writer-haiku-4-5.md +3 -7
  110. package/templates/agents/orc-verifier-opus-5-med.md +16 -8
  111. package/templates/agents/{orc-wiki-scanner-opus-4-8-high.md → orc-wiki-scanner-opus-5-low.md} +74 -79
  112. package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +97 -106
  113. package/templates/commands/orc-analyze.md +13 -21
  114. package/templates/commands/orc-fast.md +10 -15
  115. package/templates/commands/orc-fix.md +18 -0
  116. package/templates/commands/orc-poly.md +12 -21
  117. package/templates/commands/orc-pr-driver.md +11 -30
  118. package/templates/commands/orc-pr-setup.md +10 -31
  119. package/templates/commands/orc-route.md +11 -41
  120. package/templates/commands/orc-test.md +5 -60
  121. package/templates/commands/orc-wiki.md +64 -64
  122. package/templates/hooks/README.md +109 -7
  123. package/templates/hooks/orc-session-hook.js +339 -0
  124. package/templates/hooks/orc-statusline-render.js +317 -23
  125. package/templates/hooks/orc-statusline.js +165 -50
  126. package/templates/hooks/orc-subagent-line.js +23 -5
  127. package/templates/hooks/orc-weather-fetch.js +123 -0
  128. package/templates/skills/_shared/README.md +9 -0
  129. package/templates/skills/_shared/code-graph.md +47 -55
  130. package/templates/skills/_shared/config-precedence.md +3 -1
  131. package/templates/skills/_shared/extra-dispatch.md +78 -93
  132. package/templates/skills/_shared/gotchas.md +248 -177
  133. package/templates/skills/_shared/habits.md +101 -0
  134. package/templates/skills/_shared/lane-contract.md +84 -0
  135. package/templates/skills/_shared/opus5-only.md +14 -14
  136. package/templates/skills/_shared/phases/README.md +142 -83
  137. package/templates/skills/_shared/phases/analyst-gates.md +10 -21
  138. package/templates/skills/_shared/phases/execution.md +8 -14
  139. package/templates/skills/_shared/phases/house-rules.md +27 -32
  140. package/templates/skills/_shared/phases/intake.md +127 -133
  141. package/templates/skills/_shared/phases/mock-example.md +46 -56
  142. package/templates/skills/_shared/phases/plan-handoff.md +91 -97
  143. package/templates/skills/_shared/phases/planning.md +7 -17
  144. package/templates/skills/_shared/phases/preflight.md +19 -42
  145. package/templates/skills/_shared/phases/review.md +24 -28
  146. package/templates/skills/_shared/phases/rules.md +18 -42
  147. package/templates/skills/_shared/phases/scoring.md +55 -65
  148. package/templates/skills/_shared/phases/security-checklist.md +46 -50
  149. package/templates/skills/_shared/phases/security.md +45 -55
  150. package/templates/skills/_shared/phases/ship.md +6 -15
  151. package/templates/skills/_shared/phases/stop-resume.md +2 -5
  152. package/templates/skills/_shared/phases/summary.md +73 -48
  153. package/templates/skills/_shared/phases/testgen.md +41 -51
  154. package/templates/skills/_shared/phases/trace-verbs.md +447 -0
  155. package/templates/skills/_shared/phases/trace.md +66 -297
  156. package/templates/skills/_shared/phases/verify.md +62 -70
  157. package/templates/skills/_shared/phases/wave-grouping.md +128 -133
  158. package/templates/skills/_shared/phases/wiki-consult.md +10 -6
  159. package/templates/skills/_shared/read-ladder.md +2 -55
  160. package/templates/skills/_shared/return-validation.md +17 -70
  161. package/templates/skills/_shared/review-slice.md +106 -0
  162. package/templates/skills/_shared/smoke-gate.md +46 -28
  163. package/templates/skills/_shared/wait.md +1 -0
  164. package/templates/skills/context-combiner/SKILL.md +15 -44
  165. package/templates/skills/orc/README.md +2 -2
  166. package/templates/skills/orc/SKILL.md +35 -63
  167. package/templates/skills/orc/config.md +25 -27
  168. package/templates/skills/orc/examples/full-run-mock.md +2 -1
  169. package/templates/skills/orc/references/effort-and-mode.md +17 -17
  170. package/templates/skills/orc/references/pattern-gate.md +89 -89
  171. package/templates/skills/orc/references/phases/intake.md +41 -47
  172. package/templates/skills/orc/references/phases/integration.md +13 -19
  173. package/templates/skills/orc/references/preflight-report.md +11 -12
  174. package/templates/skills/orc/references/ultra-mode.md +9 -7
  175. package/templates/skills/orc/schemas/checkpoint.md +122 -122
  176. package/templates/skills/orc/subskills/orc-execution/SKILL.md +27 -73
  177. package/templates/skills/orc/subskills/orc-execution/core.md +12 -99
  178. package/templates/skills/orc/subskills/orc-execution/subagent.md +14 -13
  179. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +12 -53
  180. package/templates/skills/orc/subskills/orc-review-verify/core.md +52 -135
  181. package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -7
  182. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +11 -22
  183. package/templates/skills/orc/subskills/orc-testgen/core.md +20 -59
  184. package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -7
  185. package/templates/skills/orc-advisor/SKILL.md +56 -60
  186. package/templates/skills/orc-analyze/SKILL.md +33 -67
  187. package/templates/skills/orc-analyze/schemas/report-audit.md +2 -1
  188. package/templates/skills/orc-analyze/schemas/report-prose.md +2 -1
  189. package/templates/skills/orc-analyze-mini/SKILL.md +35 -70
  190. package/templates/skills/orc-claude/SKILL.md +14 -14
  191. package/templates/skills/orc-claude/examples/claude-run-mock.md +65 -65
  192. package/templates/skills/orc-diy/README.md +31 -0
  193. package/templates/skills/orc-diy/SKILL.md +27 -78
  194. package/templates/skills/orc-diy/references/blocks/pattern.md +18 -18
  195. package/templates/skills/orc-fast/SKILL.md +49 -75
  196. package/templates/skills/orc-fix/SKILL.md +110 -0
  197. package/templates/skills/orc-judge/SKILL.md +77 -82
  198. package/templates/skills/orc-mini/SKILL.md +64 -112
  199. package/templates/skills/orc-mini/examples/mini-run-mock.md +4 -2
  200. package/templates/skills/orc-pattern/SKILL.md +27 -48
  201. package/templates/skills/orc-poly/SKILL.md +32 -61
  202. package/templates/skills/orc-pr-driver/SKILL.md +25 -51
  203. package/templates/skills/orc-pr-driver/references/green-gate.md +113 -105
  204. package/templates/skills/orc-pr-setup/SKILL.md +20 -45
  205. package/templates/skills/orc-quick/README.md +44 -3
  206. package/templates/skills/orc-quick/SKILL.md +77 -108
  207. package/templates/skills/orc-quick/references/dispatch-gate.md +18 -6
  208. package/templates/skills/orc-quick/references/gh-mode.md +50 -1
  209. package/templates/skills/orc-quick/references/look.md +3 -1
  210. package/templates/skills/orc-retro/SKILL.md +20 -19
  211. package/templates/skills/orc-retro/examples/retro-mock.md +17 -17
  212. package/templates/skills/orc-route/SKILL.md +25 -45
  213. package/templates/skills/orc-test/SKILL.md +16 -37
  214. package/templates/skills/orc-verify/SKILL.md +14 -32
  215. package/templates/skills/orc-wait/SKILL.md +156 -163
  216. package/templates/skills/orc-wiki/README.md +325 -325
  217. package/templates/skills/orc-wiki/SKILL.md +195 -195
  218. package/templates/skills/orc-wiki/examples/wiki-run-mock.md +37 -37
  219. package/templates/skills/orc-wiki/references/extra.md +2 -2
  220. package/templates/skills/orc-wiki/references/partial-refresh.md +276 -271
  221. package/templates/skills/orc-wiki/references/phases/phase-0.md +2 -7
  222. package/templates/skills/orc-wiki/references/phases/phase-1.md +1 -6
  223. package/templates/skills/orc-wiki/references/phases/phase-2.md +4 -9
  224. package/templates/skills/orc-wiki/references/phases/phase-3.md +1 -6
  225. package/templates/skills/orc-wiki/references/phases/phase-3c.md +4 -8
  226. package/templates/agents/orc-claude-writer-opus-5-med.md +0 -55
  227. package/templates/agents/orc-reviewer-opus-5-med.md +0 -60
  228. package/templates/agents/orc-wiki-scanner-opus-5-med.md +0 -81
@@ -1,133 +1,128 @@
1
- # Phase — Wave grouping (id: `wave-grouping`)
2
-
3
- > **Library file.** Canonical since v1.0.0 W12; it was under the `orc` skill's
4
- > private `references/`, and another lane already reached across into it. Read
5
- > by `orc`, `orc-diy`. Layers declared: `core` only — single-layer because the
6
- > conflict graph is arithmetic, and a lane that groups waves at all groups
7
- > them this way. `orc lane phases <lane> --json` names the file and the layers
8
- > to read.
9
-
10
- <!-- orc:layer core -->
11
- ## Reference — Wave Grouping & Conflict Graph
12
-
13
- Turn the tagged task list into conflict-free waves. Load during Phase 3.
14
-
15
- ## Waves are computed for EVERY run — dispatch style is intra-wave only
16
-
17
- Wave computation is NOT a parallel-mode concern. It runs for **every run with ≥2
18
- tasks, sequential included** (dependency layers + conflict graph +
19
- `max_wave_tasks` cap). **Dispatch style controls only INTRA-WAVE concurrency:**
20
-
21
- - **parallel** → a wave's non-conflicting tasks dispatch at once (up to
22
- `max_wave_tasks`);
23
- - **sequential** → the SAME waves, but a wave's tasks dispatch one at a time, in
24
- order; the wave still closes only when all its tasks close.
25
-
26
- Either way the **wave-boundary gate fires identically** (the deterministic batch
27
- pause below binds to wave numbers, not to a dispatch style). A sequential run
28
- therefore never degenerates to "no waves / per-task pauses" — a 5-task plan
29
- becomes e.g. `[T1] [T2 T3 T4] [T5]`, not five ad-hoc stops. **Show the wave plan
30
- (wave → tasks → pause marks) to the user BEFORE wave 1 in BOTH styles.**
31
-
32
- ## The principle
33
-
34
- Two tasks may share a wave ONLY if their `declared_files` don't overlap AND
35
- neither depends on the other. Conflicts are designed out by scheduling — never
36
- negotiated at runtime.
37
-
38
- ## Algorithm
39
-
40
- 1. **Dependency edges:** a task's earliest wave = max(wave of its deps) + 1.
41
- 2. **Conflict edges:** for every pair, mark conflict if `declared_files` globs
42
- intersect (expand against the repo tree; unresolvable globs conflict on
43
- their literal prefix).
44
- 3. **Assign greedily in topological order:** place each task in the earliest
45
- wave where (a) all deps are earlier and (b) nothing in that wave conflicts.
46
- Otherwise open a new wave.
47
- 4. **Cap concurrency at `config.max_wave_tasks`** (default 3): a wave NEVER
48
- exceeds this many tasks, even if more are conflict-free. Overflow moves to the
49
- next wave. This is the efficiency cap — 3 parallel subagents by default.
50
- 5. **Mark batch pauses:** compute the pause schedule from the user's Phase 2
51
- answer — mark `is_batch_pause: true` on wave W when `W % N == 0` AND a later
52
- wave exists (`W < total_waves`); the last wave is NEVER a pause (nothing
53
- remains to gate). The resulting wave indices are the `pause_schedule` stored
54
- in the checkpoint. A pause so marked is a HARD gate (stop-resume.md), not
55
- an orchestrator judgment call.
56
-
57
- ## Same-feature collision
58
-
59
- If two tasks own the same feature/files with no dependency between them, the
60
- graph auto-serializes them — but that's a planning smell. Surface it: suggest
61
- merging them into one task rather than silently serializing duplicate work.
62
-
63
- ## TDD tasks are ORDINARY tasks (v0.41.0)
64
-
65
- TDD red proofs are **planner-emitted tasks**, not an orchestrator-synthesized
66
- Wave 0. Each one materializes the `tdd_spec` entries of the implementation task
67
- it guards, and that task lists it in `depends_on`. Nothing here special-cases
68
- them:
69
-
70
- - they enter the same conflict graph via their `declared_files` (their test
71
- files), so **independent TDD tasks share a wave and run in parallel** — the
72
- red proofs for two unrelated features are one wave, not two;
73
- - `depends_on` guarantees **a red proof is always in an earlier wave than the
74
- code it proves** — a proof can never land beside its implementation;
75
- - they are scored from **their own planner-emitted `facets`**, like any task, so
76
- no derived-vector rule is needed;
77
- - `max_wave_tasks`, `is_batch_pause` and `pause_schedule` bind to them unchanged.
78
-
79
- **A TDD task does NOT inherit the risk floor** of the task it guards: it
80
- transcribes planner-authored skeletons, writes no production code, and its output
81
- is asserted RED before anything is believed. The planner reflects that in the
82
- task's own facets (`novelty: mechanical`, `logic: none`, `risk: []`). Stated here
83
- so it is not re-litigated per run — the alternative is a Haiku-sized
84
- transcription job dispatched at floor 70 because the requirement it proves is
85
- auth-flavoured.
86
-
87
- **If no task carries `new-surface` or `behavior-change` entries, no TDD task
88
- exists and no extra wave is created.**
89
-
90
- ## Orchestrator-synthesized tasks (the mock example, any future one)
91
-
92
- Some dispatched tasks appear in no `tasks[]` because the ORCHESTRATOR synthesized
93
- them — the mock example (`_shared/drift-recovery.md`). They still obey hard rule
94
- 1: **dispatched like any other task, never done by you.** But they have no
95
- planner-emitted `facets`, and the orchestrator is by definition the party that
96
- did NOT read the code — inventing a vector for them is judgment wearing
97
- arithmetic's clothes, the exact thing the facet redesign removed.
98
-
99
- So their vector is **DERIVED, never judged**:
100
-
101
- | Facet | Value |
102
- |---|---|
103
- | `breadth` | `len(files the synthesized task will touch)` |
104
- | `novelty` | `mechanical` — it transcribes planner-authored material |
105
- | `logic` | `none` |
106
- | `test_surface` | per the task |
107
- | `risk` | `[]` — unless the synthesized task itself inherits a CITED risk |
108
-
109
- ## Post-wave worktree audit (a GATE, not a report)
110
-
111
- Declarations can be wrong, and a return can be honest and still miss what
112
- happened. Capture `git status --short` BEFORE the wave dispatches and again
113
- after every task returns, then diff the two:
114
- - **Any path whose state changed and is in NO task's `declared_files`** → name
115
- the path and the likely task, and get an explicit user decision BEFORE the
116
- wave closes. A wave never closes over an unexplained worktree delta.
117
- - **A file that became LESS modified is as much a violation as one that became
118
- more modified.** That is the revert signature — an executor made an
119
- unsatisfiable assertion true by `git checkout`-ing another task's completed
120
- work, returned a literally-true report, and left a CLEAN tree. Nothing that
121
- reads returns can see it.
122
- - **Stray files count** — a path that appears at the repo root (a stdout dump, a
123
- mangled-path artifact) is undeclared output, not noise to ignore.
124
- - Two agents in one wave touched the same undeclared file → record
125
- `failure_reason: "file-collision:<file> with <agent>"`, set the
126
- later-finishing task to `requeued`, re-dispatch in a later wave so it sees
127
- the other's committed changes.
128
- - Declarations are the plan, `actual_files` is the ATTESTATION, and
129
- `git status` is the AUDIT — same instruction → contract → attestation →
130
- spot-check pattern the plan applies to `grounding[]`.
131
- - Canonical cross-lane wording: `_shared/return-validation.md` §6.
132
-
133
- <!-- /orc:layer -->
1
+ # Phase — Wave grouping (id: `wave-grouping`)
2
+
3
+ > **Library file** (`orc`, `orc-diy`), `core` only: the conflict graph is arithmetic, and every lane that groups waves groups them this way.
4
+
5
+ <!-- orc:layer core -->
6
+ ## Reference — Wave Grouping & Conflict Graph
7
+
8
+ Turn the tagged task list into conflict-free waves. Load during Phase 3.
9
+
10
+ ## Waves are computed for EVERY run — dispatch style is intra-wave only
11
+
12
+ Wave computation is NOT a parallel-mode concern. It runs for **every run with ≥2
13
+ tasks, sequential included** (dependency layers + conflict graph +
14
+ `max_wave_tasks` cap). **Dispatch style controls only INTRA-WAVE concurrency:**
15
+
16
+ - **parallel** → a wave's non-conflicting tasks dispatch at once (up to
17
+ `max_wave_tasks`);
18
+ - **sequential** → the SAME waves, but a wave's tasks dispatch one at a time, in
19
+ order; the wave still closes only when all its tasks close.
20
+
21
+ Either way the **wave-boundary gate fires identically** (the deterministic batch
22
+ pause below binds to wave numbers, not to a dispatch style). A sequential run
23
+ therefore never degenerates to "no waves / per-task pauses" — a 5-task plan
24
+ becomes e.g. `[T1] [T2 T3 T4] [T5]`, not five ad-hoc stops. **Show the wave plan
25
+ (wave → tasks → pause marks) to the user BEFORE wave 1 in BOTH styles.**
26
+
27
+ ## The principle
28
+
29
+ Two tasks may share a wave ONLY if their `declared_files` don't overlap AND
30
+ neither depends on the other. Conflicts are designed out by scheduling — never
31
+ negotiated at runtime.
32
+
33
+ ## Algorithm
34
+
35
+ 1. **Dependency edges:** a task's earliest wave = max(wave of its deps) + 1.
36
+ 2. **Conflict edges:** for every pair, mark conflict if `declared_files` globs
37
+ intersect (expand against the repo tree; unresolvable globs conflict on
38
+ their literal prefix).
39
+ 3. **Assign greedily in topological order:** place each task in the earliest
40
+ wave where (a) all deps are earlier and (b) nothing in that wave conflicts.
41
+ Otherwise open a new wave.
42
+ 4. **Cap concurrency at `config.max_wave_tasks`** (default 3): a wave NEVER
43
+ exceeds this many tasks, even if more are conflict-free. Overflow moves to the
44
+ next wave. This is the efficiency cap — 3 parallel subagents by default.
45
+ 5. **Mark batch pauses:** compute the pause schedule from the user's Phase 2
46
+ answer — mark `is_batch_pause: true` on wave W when `W % N == 0` AND a later
47
+ wave exists (`W < total_waves`); the last wave is NEVER a pause (nothing
48
+ remains to gate). The resulting wave indices are the `pause_schedule` stored
49
+ in the checkpoint. A pause so marked is a HARD gate (stop-resume.md), not
50
+ an orchestrator judgment call.
51
+
52
+ ## Same-feature collision
53
+
54
+ If two tasks own the same feature/files with no dependency between them, the
55
+ graph auto-serializes them — but that's a planning smell. Surface it: suggest
56
+ merging them into one task rather than silently serializing duplicate work.
57
+
58
+ ## TDD tasks are ORDINARY tasks (v0.41.0)
59
+
60
+ TDD red proofs are **planner-emitted tasks**, not an orchestrator-synthesized
61
+ Wave 0. Each one materializes the `tdd_spec` entries of the implementation task
62
+ it guards, and that task lists it in `depends_on`. Nothing here special-cases
63
+ them:
64
+
65
+ - they enter the same conflict graph via their `declared_files` (their test
66
+ files), so **independent TDD tasks share a wave and run in parallel** — the
67
+ red proofs for two unrelated features are one wave, not two;
68
+ - `depends_on` guarantees **a red proof is always in an earlier wave than the
69
+ code it proves** — a proof can never land beside its implementation;
70
+ - they are scored from **their own planner-emitted `facets`**, like any task, so
71
+ no derived-vector rule is needed;
72
+ - `max_wave_tasks`, `is_batch_pause` and `pause_schedule` bind to them unchanged.
73
+
74
+ **A TDD task does NOT inherit the risk floor** of the task it guards: it
75
+ transcribes planner-authored skeletons, writes no production code, and its output
76
+ is asserted RED before anything is believed. The planner reflects that in the
77
+ task's own facets (`novelty: mechanical`, `logic: none`, `risk: []`). Stated here
78
+ so it is not re-litigated per run — the alternative is a Haiku-sized
79
+ transcription job dispatched at floor 70 because the requirement it proves is
80
+ auth-flavoured.
81
+
82
+ **If no task carries `new-surface` or `behavior-change` entries, no TDD task
83
+ exists and no extra wave is created.**
84
+
85
+ ## Orchestrator-synthesized tasks (the mock example, any future one)
86
+
87
+ Some dispatched tasks appear in no `tasks[]` because the ORCHESTRATOR synthesized
88
+ them — the mock example (`_shared/drift-recovery.md`). They still obey hard rule
89
+ 1: **dispatched like any other task, never done by you.** But they have no
90
+ planner-emitted `facets`, and the orchestrator is by definition the party that
91
+ did NOT read the code — inventing a vector for them is judgment wearing
92
+ arithmetic's clothes, the exact thing the facet redesign removed.
93
+
94
+ So their vector is **DERIVED, never judged**:
95
+
96
+ | Facet | Value |
97
+ |---|---|
98
+ | `breadth` | `len(files the synthesized task will touch)` |
99
+ | `novelty` | `mechanical` — it transcribes planner-authored material |
100
+ | `logic` | `none` |
101
+ | `test_surface` | per the task |
102
+ | `risk` | `[]` — unless the synthesized task itself inherits a CITED risk |
103
+
104
+ ## Post-wave worktree audit (a GATE, not a report)
105
+
106
+ Declarations can be wrong, and a return can be honest and still miss what
107
+ happened. Capture `git status --short` BEFORE the wave dispatches and again
108
+ after every task returns, then diff the two:
109
+ - **Any path whose state changed and is in NO task's `declared_files`** → name
110
+ the path and the likely task, and get an explicit user decision BEFORE the
111
+ wave closes. A wave never closes over an unexplained worktree delta.
112
+ - **A file that became LESS modified is as much a violation as one that became
113
+ more modified.** That is the revert signature — an executor made an
114
+ unsatisfiable assertion true by `git checkout`-ing another task's completed
115
+ work, returned a literally-true report, and left a CLEAN tree. Nothing that
116
+ reads returns can see it.
117
+ - **Stray files count** — a path that appears at the repo root (a stdout dump, a
118
+ mangled-path artifact) is undeclared output, not noise to ignore.
119
+ - Two agents in one wave touched the same undeclared file → record
120
+ `failure_reason: "file-collision:<file> with <agent>"`, set the
121
+ later-finishing task to `requeued`, re-dispatch in a later wave so it sees
122
+ the other's committed changes.
123
+ - Declarations are the plan, `actual_files` is the ATTESTATION, and
124
+ `git status` is the AUDIT — same instruction → contract → attestation →
125
+ spot-check pattern the plan applies to `grounding[]`.
126
+ - Canonical cross-lane wording: `_shared/return-validation.md` §6.
127
+
128
+ <!-- /orc:layer -->
@@ -1,11 +1,6 @@
1
1
  # Phase — Wiki consult (id: `wiki-consult`)
2
2
 
3
- > **Library file.** Canonical since v1.0.0 W12; it was under the `orc` skill's
4
- > private `references/`, and other lanes already reached across into it. Read
5
- > by `orc`, `orc-mini`, `orc-fast`, `orc-wiki`. Layers declared: `core` only —
6
- > single-layer because the precedence ladder (`code > fresh wiki > stale wiki
7
- > > model priors`) does not bend for a faster lane. `orc lane phases <lane>
8
- > --json` names the file and the layers to read.
3
+ > **Library file** (`orc`, `orc-mini`, `orc-fast`, `orc-wiki`), `core` only: the ladder `code > fresh wiki > stale wiki > model priors` does not bend for a faster lane.
9
4
 
10
5
  <!-- orc:layer core -->
11
6
  ## Reference — Wiki Consult (shared by orc / orc-mini / orc-fast)
@@ -148,6 +143,15 @@ actually read, or `none`. `none` on a slice that carried docs is a REAL signal
148
143
  It is the only thing that distinguishes a wiki that is working from one that is
149
144
  merely being shipped.
150
145
 
146
+ **orc-mini only** (moved here from its spine at v2.0.0):
147
+
148
+ **`none` is an answer — record it, never drop it.** `wiki_used: none` and
149
+ `graph_used: none` from ANY return go into the checkpoint and the ship line
150
+ (`knowledge: wiki 2 pages offered · used none · graph card 2 targets · used
151
+ none`). Two runs in a row with `wiki_used: none` on FRESH pages → one line:
152
+ `wiki: the selected pages were not used in 2 runs — check their TL;DRs
153
+ (/orc-wiki)`. A signal, never a gate, never dropped for looking null.
154
+
151
155
  ## Scoring bonus (full lane, Phase 2)
152
156
 
153
157
  If a non-empty `wiki/` is present, use its overviews' "Notes for planning" to
@@ -5,14 +5,6 @@ about to edit: scouts, wiki scan-tasks, the analyst, the reviewer, and every
5
5
  executor reading a file for context rather than for change. Load this wherever
6
6
  a slice tells an agent to go read something.
7
7
 
8
- ## Why this exists
9
-
10
- ORC's cost is dominated by parallel reading, not by thinking: up to `max_scouts`
11
- scouts at once, a wiki scan that is expensive by design, and every executor in a
12
- wave opening its declared files. A role that opens a 900-line file to learn one
13
- function's shape has spent the run's budget on bytes nobody needed. Reading more
14
- is not understanding more.
15
-
16
8
  ## The ladder
17
9
 
18
10
  Escalate one step at a time. Stop at the step that answers the question.
@@ -88,50 +80,6 @@ is a `needs_context` return, not permission to keep going.
88
80
  lint results — the smoke gate, the TDD gate, the verifier and orc-quick's
89
81
  build loop decide red vs green from those exact bytes. Read them whole.
90
82
 
91
- ## Reading ORC's own payload — the partial-read discipline (v1.0.0 W10)
92
-
93
- Everything above is about reading the PROJECT. It applies unchanged to reading
94
- ORC's own files, and it has to: a lane manifest of pointers that every lane
95
- dutifully reads whole is MORE round-trips than the prose it replaced, for the
96
- same bytes. Centralizing prose and then reading all of it is a slower payload,
97
- not a smaller one.
98
-
99
- So every pointer a lane carries declares three things.
100
-
101
- | Declaration | Values | Means |
102
- |---|---|---|
103
- | `when` | `always` · `on-phase` · `on-state` · `on-demand` · `compile-time` | WHETHER to open it at all |
104
- | `read` | `layer` · `section` · `whole` | HOW MUCH to open |
105
- | `layers` | `core` · `full` · `trim` · `composed` | WHICH part, when `read: layer` |
106
-
107
- ### The four rules that make it honest
108
-
109
- 1. **`on-phase` is the default, and `always` must be justified.** A file every
110
- lane always loads has saved nothing by moving. Each `always` pointer is
111
- named in the wave that adds it.
112
- 2. **`read: section` names a HEADING, never a line number.** A stored line
113
- number is a wrong line number one edit later; a heading anchor survives an
114
- edit above it. This is why a shared file's headings are part of its
115
- contract — renaming one breaks every pointer into it.
116
- 3. **A trimmed lane reads `core` plus its OWN layer, and never the `full`
117
- layer.** Reading a neighbouring layer "for context" is the bleed this rule
118
- exists to stop: the layer boundary is the product promise, not a suggestion.
119
- 4. **The two exceptions above carry over unchanged.** A file you will EDIT is
120
- read in full, first, always; and output a gate parses is read whole.
121
- 5. **`compile-time` is not a run-time read at all.** `orc-diy` is a declared
122
- reader of ten shared phases and opens none of them during a run: the `orc
123
- diy compile` CLI reads their `composed` layer once and stitches it into
124
- `FLOW-COMPILED.md`, which is the only spine that run then follows. Saying
125
- `on-phase` there would describe a read that never happens, and a manifest
126
- that describes a run nobody performs is the drift it exists to prevent
127
- (v1.0.0 W13).
128
-
129
- ### The honest limit
130
-
131
- A partial read saves round-trips and bytes for the lanes that SKIP a phase. It
132
- does **not** make a phase cheaper for the lane that runs it — that lane reads
133
- its layers whole. Any claim otherwise has to show the measurement.
134
-
135
83
  ## Handoff
136
84
 
137
85
  The ladder governs HOW MUCH to read. It never decides WHETHER knowledge exists —
@@ -140,6 +88,5 @@ that is `detecting-artifacts.md` — and it never overrides precedence:
140
88
  the same order gains two rungs and loses none:
141
89
  `code > graph structure (current blob) > fresh wiki > stale wiki (hints) > graph notes and doc notes > model priors`.
142
90
 
143
- What a lane INVOKES, and what each exit code means, is not here either: that is
144
- `orc lane calls <lane> --json`, whose catalogue is the one copy of every call
145
- two or more lanes share.
91
+ An orchestrator reading ORC's OWN payload follows the partial-read rules in
92
+ `phases/README.md` (§Pointer discipline).
@@ -4,22 +4,20 @@ Canonical procedure for validating a spawned agent's return. Every ORC lane
4
4
  (full, mini, fast, wiki, diy) runs this on EVERY return; a malformed return is
5
5
  a failure (requeue/re-dispatch with reason — lane sets the retry cap).
6
6
 
7
+ **Read the SECTION, not the file.** Every return: §1–§3. Then ONLY the § of
8
+ each field the slice carried — §4 `pattern`, §5 `tdd_spec`, §5b wiki, §5b.1
9
+ graph cards, §5c the rules card, §5d `repro`. §2b only for a foreign return. §0
10
+ only before a re-dispatch. §6 only after a wave. §7 only on a repair loop. The §
11
+ numbers are anchors: never renumber or rename a § heading.
12
+
7
13
  ## 0. Is the previous attempt still ALIVE? (v1.2.0) — BEFORE anything else
8
14
 
9
15
  > **`a lane that re-dispatches over a live attempt` has broken this contract.**
10
16
 
11
17
  **A Task error does not kill the agent behind it.** Claude Code's tool call can
12
18
  fail, time out, or be cut off mid-turn while the subagent it started keeps
13
- running — and keeps writing files. Every rule below this line ends in
14
- "re-dispatch", and every one of them silently assumed a failed call meant a dead
15
- agent. It does not.
16
-
17
- What that costs, measured: one graded `/orc-quick` entry put THREE
18
- `orc-executor-opus-5-low` agents on the SAME task — 50m19s, 115m22s and
19
- 100m53s, **266 minutes of Opus 5.5 for one authorised dispatch**, all editing the
20
- same files, inside a 2h04m window. The second was dispatched 4m19s after the
21
- first, while the first was still working. The hook had recorded all three; no
22
- lane had ever read that record.
19
+ running — and keeps writing files. Every rule below ends in "re-dispatch";
20
+ none of them may assume that a failed call means a dead agent.
23
21
 
24
22
  ### The rule
25
23
 
@@ -49,8 +47,7 @@ A usage limit, an API error, a dropped connection or a `Ctrl+C` between a
49
47
  dispatch and its return says **nothing** about the agent. Treat it as §0 exit 2
50
48
  and ask. A lane that classifies an interruption as a failure re-dispatches into
51
49
  a live agent, gets interrupted again sooner because it is now paying twice, and
52
- the loop tightens on itself — which is exactly how the 266-minute entry
53
- happened.
50
+ the loop tightens on itself.
54
51
 
55
52
  ### What refusing looks like
56
53
 
@@ -102,64 +99,14 @@ is on the wrong model.)
102
99
 
103
100
  ## 2b. A FOREIGN return — the SUBSTITUTION check (v0.50.0)
104
101
 
105
- A foreign worker (`orc extra dispatch`, `_shared/extra-dispatch.md`) is not a
106
- Claude subagent. It has no injected system-prompt model-id line, so **it cannot
107
- carry `actual_model`** — and §2 must not be faked for it. A foreign return that
108
- claimed an `actual_model` would be claiming evidence that does not exist.
109
-
110
- It carries instead, and every one of these is quoted from the wire rather than
111
- assumed:
112
-
113
- - `engine` (`api` | `claude-shim` | `cli`), `provider`, `profile`
114
- - `model_requested` — what the route row asked for
115
- - **`model_reported`** — the `model` field the endpoint echoed back
116
- - `usage` — the four token kinds, never blended, **or `null`**
117
-
118
- **`model_reported != model_requested` is ⛔ SUBSTITUTION**, surfaced to the user
119
- exactly as ⛔ DOWNGRADE is today and never silently accepted. It is the only
120
- defence against an aggregator quietly serving something else. `unknown` is a
121
- valid, honest value and is reported as `unknown` — **never as a match**.
122
-
123
- **A clean model check is not a clean answer.** An aggregator's *provider-level*
124
- fallback is on by default and it PRESERVES the model id, so the substitution
125
- check reads clean while the code went to a different company. Engine `api`
126
- records the response's `provider` echo and reports **⚠ REROUTE**; the other two
127
- engines cannot see it at all, and their `served_by_note` says so. An absent
128
- measurement is never a pass.
129
-
130
- **`usage: null` is not four zeros.** A worker that reported no token counts
131
- (engine `cli` frequently) returns `null` plus a note. `{0,0,0,0}` would tell
132
- `/orc-budget` the run was free. Engine `api`'s `cache_write: 0` is the opposite
133
- case — a real measurement — so the two must never be normalised together.
134
-
135
- **The fence is per-engine, and the return says which one it had.** Engine `api`
136
- ENFORCES `declared_files`; engines `claude-shim` and `cli` ASK. A return
137
- carrying `fence: {declared_files: false}` means the list was an instruction, not
138
- a rule — treat §6 below as the only real check, and say so to the user rather
139
- than reporting a constraint that was never applied.
140
-
141
- **A RESUMED foreign dispatch owes three more fields** (v0.54.0). The dispatch
142
- return sets `resume_expected: true`, so the obligation is never inferred:
143
-
144
- - **`resume_state`** — `continued` · `restarted` · `no-op`. Absent on a slice
145
- with no `resumed_from` is correct; **absent on a resume slice is MALFORMED.**
146
- A return claiming `restarted` while `preexisting[]` was non-empty is a
147
- FINDING, not a failure — it is how `/orc-retro` learns which providers ignore
148
- a resume preamble, so surface it rather than treating it as a bad return.
149
- - **`preexisting_read[]`** — which pre-existing files the worker actually
150
- opened. Quoted like `wiki_used`: **what it did, never what the dispatcher
151
- assumed.** An EMPTY list on a resume whose `preexisting[]` was not empty is an
152
- honest and informative return — it says the worker ignored the preamble — and
153
- it must be surfaced, never dropped.
154
- - **`journal_fidelity`** — relayed from the dispatch return (`per-turn` |
155
- `streamed-opaque`), so a validator never reports `streamed-opaque` evidence as
156
- if it had per-turn tool attribution.
157
-
158
- Everything else in this file applies to a foreign return unchanged: the
159
- honest-status rules, the pattern attestation, the TDD attestation, the wiki
160
- attestation, and above all **§6, the worktree delta** — which is engine-blind
161
- because it reads the worktree rather than the return, and is therefore what
162
- makes a foreign executor safe at all.
102
+ Read this § only when `extra_enabled` and the return came from `orc extra
103
+ dispatch`. A foreign worker has no system-prompt model-id line, so **it cannot
104
+ carry `actual_model`** — never fake §2 for it. **`model_reported !=
105
+ model_requested` is ⛔ SUBSTITUTION**, surfaced exactly as ⛔ DOWNGRADE. A
106
+ RESUMED foreign dispatch also owes `resume_state`, `preexisting_read[]` and
107
+ `journal_fidelity`. The full check — the wire fields, ⚠ REROUTE, `usage: null`,
108
+ the per-engine fence and the resume fields — is `extra-dispatch.md`
109
+ §The return contract delta. Every other § of this file applies unchanged.
163
110
 
164
111
  ## 3. Honest-status rules (executor returns)
165
112
 
@@ -0,0 +1,106 @@
1
+ # The review slice — the ONE shape every lane uses
2
+
3
+ > **On demand.** Read this file ONLY when a review dispatch is about to be built
4
+ > (`/orc` Phase 5 and its composed DIY layer, `orc-review-verify/core.md`, the
5
+ > `/orc-quick` review offer, the `/orc-mini` risk-high option, the `/orc-pr-driver`
6
+ > per-layer gate, `/orc-ultra` gate 3). One slice, so a review in quick is the
7
+ > same review as in `/orc`. The procedure and the return live in the agent file
8
+ > (`.claude/agents/orc-reviewer-opus-5-low.md`), never here.
9
+
10
+ ## §0 Which review — only when the project names its own (v2.1.0)
11
+
12
+ When the `review-policy` probe of the lane config (or `orc review policy
13
+ --json`) says `policy: project`, a coding lane that changed code asks this ONCE
14
+ before ship — also `/orc-fast`, and `/orc-mini` without a risk-high row (DE-8).
15
+ A CLAUDE.md line never picks the reviewer: it adds an OPTION (H `any.review.which`).
16
+
17
+ ```text
18
+ Which review for this change?
19
+ 1. ORC review — orc-reviewer-opus-5-low (traced, gotcha card, Review Quality)
20
+ 2. <name> — the review <file>:<line> asks for ← recommended
21
+ 3. Skip review (not recommended: <file>:<line> asks for one)
22
+ ```
23
+
24
+ - Write `REVIEW-WHICH chose=<orc|project|skip> name=<the named review> by=user ::
25
+ <file>:<line>` ALWAYS (habits off too) — and ONLY under `policy: project`. With habits on, also the ASK line.
26
+ - **1** → this slice, as the lane already does. **2** → run the named skill or
27
+ command (the Skill tool takes both), then §3 on its findings with
28
+ `reviewer: "<name>"` on each observation — no ORC reviewer is dispatched.
29
+ **3** → no review; the summary says the project asked for one.
30
+ - An external review has no hook trace, no gotcha card and no required
31
+ `category`/`scenario`/`pre_existing`: §3 fills `category: uncategorized` where
32
+ it cannot map one, and Review Quality counts it in its own line.
33
+
34
+ Slice fields: changed_files[] · diff_ranges[] · acceptance_criteria[] · constraints[] · code_pattern · invariants[] · validation_gate[] · fe_rules[] · security_checklist[] · graph_changes · tool_findings[] · gotcha_card · rules_card · previous_findings[] · mode
35
+
36
+ ## §1 R1 — the free check (before ANY review dispatch)
37
+
38
+ The free check always runs before the paid one. On the changed files only:
39
+
40
+ 1. Run the project's OWN lint and type check. Take the commands from
41
+ `wiki-meta.json` `commands`; else the `package.json` scripts named `lint` /
42
+ `typecheck`; else the `pyproject` / `Makefile` targets of those names; else
43
+ `sonar-scanner` when the project already has it. **Never invent a command.
44
+ Never install tooling.** No command found → `tool_findings[]` is empty; say so
45
+ in one line.
46
+ 2. Run `orc rules lint --diff` (free, zero tokens).
47
+ 3. Keep only the output lines that land on a changed file → `tool_findings[]`
48
+ (`{tool, location, message}`). **The reviewer must not re-report them.**
49
+
50
+ `/orc-ultra` gate 3 reuses this step (it does not run a second copy); a fix wave
51
+ that changed files re-runs it first.
52
+
53
+ ## §2 The fields
54
+
55
+ | Field | Source |
56
+ |---|---|
57
+ | `changed_files[]`, `diff_ranges[]` | git — `diff_ranges` are the changed line ranges per file (R2) |
58
+ | `acceptance_criteria[]`, `constraints[]` | the plan / the quick entry |
59
+ | `code_pattern`, `invariants[]`, `validation_gate[]` | the pattern cache (or null / empty) |
60
+ | `fe_rules[]`, `security_checklist[]` | FE diffs / `mode: security` only, else empty |
61
+ | `graph_changes` | `orc graph changes --if-enabled --json` — **keeps its rows: no `--brief` here** |
62
+ | `tool_findings[]` | §1 |
63
+ | `gotcha_card` | `orc gotcha card --files <changed csv> --lane <lane> --json` → `text` |
64
+ | `rules_card` | `orc rules slice --lane <lane> --json` → `text` (a lane with no rules → null) |
65
+ | `previous_findings[]` | the checkpoint, on a re-review ONLY (R9), each with its outcome |
66
+ | `mode` | `review` · `disprove` · `security` |
67
+
68
+ - **`graph_changes`** (`code-graph.md` §7): the symbols THIS diff's hunks overlap,
69
+ each with its callers, its tests and a risk word that carries its own reason.
70
+ The reviewer is handed `symbols[].caller_files` and reads them.
71
+ It replaces a whole-file `orc graph impact` here: a file card reports every symbol in
72
+ a touched file, and a symbol nobody edited is not a finding. An unchanged caller of
73
+ a changed signature is a finding candidate, anchored like any other.
74
+ - **`gotcha_card` is ALWAYS built** when anything matches — no switch removes it
75
+ (`gotcha_card_budget` is only its size). Exit 1 (no match) → null, the normal
76
+ case. Its header counts what the budget dropped; never cut it silently.
77
+ The session hook ALSO hands it to every `orc-reviewer-*`, `orc-verifier-*` and
78
+ `orc-judge-*` at `SubagentStart` (v2.0.2), so a slice that forgot it still has it.
79
+ Before the card, run `orc gotcha sync --json` (it is due at most once per
80
+ `gotcha_sync_hours`); exit 2 (a CLI that has no `sync`) or any failure → go on.
81
+ - **`mode: disprove`** carries only the P0/P1 findings to test and their files.
82
+
83
+ ## §3 After the return — the after-filter (R10)
84
+
85
+ The reviewer reports EVERY finding. Then, before the ladder acts:
86
+
87
+ 1. Pipe the findings to `orc gotcha filter --findings - --json`. It drops P2/P3
88
+ that a `suppress` gotcha names, folds P3 above 5 into `+N similar`, and applies
89
+ the category noise budget. **It never removes a P0 or P1.** Keep its `kept`;
90
+ list its `removed[]` (each with the `by` id) in the run summary — a count is
91
+ not consent.
92
+ 2. `pre_existing: true` findings (on a line outside `diff_ranges`) go to their own
93
+ bucket. They never gate.
94
+ 3. A P0/P1 with no `scenario`, or with `confidence: low`, becomes P2.
95
+ 4. Findings that share a `group` are ONE fix: the P0 fix, the P1 ask and the P2
96
+ batch are made per group (R7).
97
+
98
+ 5. At review close, record one observation per finding and emit the
99
+ `FINDING-OUTCOME` line — `gotchas.md` §10 "Review close" (`/orc` Phase 7,
100
+ `/orc-mini` after its risk option, `/orc-quick` after the review offer).
101
+ 6. In the same step, store the reviewed ranges (`diff_ranges`) with ONE
102
+ `orc gotcha observe -` call, body `{"kind": "review-scope", run, commit,
103
+ files}` (DE-13, "Review close"). The CLI computes a later fix's `miss` from it.
104
+
105
+ **Superpowers path** (DE-13): after the Superpowers review skill returns, run
106
+ this §3 on its findings too, outcomes included — never a second reviewer dispatch.