@azure-id/orc 1.9.1 → 2.0.2

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 (224) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/README-id.md +20 -36
  3. package/README.md +24 -34
  4. package/bin/build-agents.js +206 -109
  5. package/bin/cli.js +760 -62
  6. package/bin/gotcha-import.js +1081 -0
  7. package/bin/gotcha.js +1286 -0
  8. package/bin/graph-query.js +1 -1
  9. package/bin/graph.js +717 -717
  10. package/bin/habit.js +1453 -0
  11. package/bin/mockrun-catalog.js +281 -276
  12. package/bin/onboarding-content.js +4 -4
  13. package/bin/pricing.json +207 -200
  14. package/bin/run-undo.js +398 -0
  15. package/bin/trace-write.js +657 -0
  16. package/bin/verify-contracts.js +527 -81
  17. package/bin/verify-package.js +58 -11
  18. package/bin/webui/api.js +26 -0
  19. package/bin/webui/app.html +239 -232
  20. package/bin/webui/css/00-tokens.css +110 -92
  21. package/bin/webui/css/04-motion.css +249 -152
  22. package/bin/webui/css/06-responsive.css +203 -178
  23. package/bin/webui/css/panels/behaviour.css +205 -0
  24. package/bin/webui/css/panels/knowledge.css +563 -116
  25. package/bin/webui/fixtures/behaviour.js +532 -0
  26. package/bin/webui/fixtures/extra.js +2036 -2036
  27. package/bin/webui/fixtures/hookui.js +5 -5
  28. package/bin/webui/fixtures/index.js +34 -0
  29. package/bin/webui/fixtures/knowledge.js +7 -1
  30. package/bin/webui/fixtures/settings.js +305 -305
  31. package/bin/webui/fixtures/stats.js +16 -0
  32. package/bin/webui/i18n/en/behaviour.json +143 -0
  33. package/bin/webui/i18n/en/knowledge.json +117 -2
  34. package/bin/webui/i18n/en/nav.json +25 -24
  35. package/bin/webui/i18n/en/tour.json +37 -35
  36. package/bin/webui/i18n/id/behaviour.json +143 -0
  37. package/bin/webui/i18n/id/knowledge.json +117 -2
  38. package/bin/webui/i18n/id/nav.json +25 -24
  39. package/bin/webui/i18n/id/tour.json +37 -35
  40. package/bin/webui/js/01-i18n.js +155 -154
  41. package/bin/webui/js/90-tour.js +498 -494
  42. package/bin/webui/js/91-shortcuts.js +126 -126
  43. package/bin/webui/js/99-boot.js +121 -118
  44. package/bin/webui/js/panels/behaviour.js +1022 -0
  45. package/bin/webui/js/panels/knowledge.js +552 -7
  46. package/bin/webui/js/panels/overview.js +13 -4
  47. package/mock-run/INDEX.md +109 -107
  48. package/mock-run/context-combiner.md +100 -100
  49. package/mock-run/gotcha-import.md +118 -0
  50. package/mock-run/habits.md +129 -0
  51. package/mock-run/orc-budget.md +534 -534
  52. package/mock-run/orc-challenge-council.md +262 -262
  53. package/mock-run/orc-quick.md +6 -1
  54. package/mock-run/orc-ultra.md +103 -103
  55. package/package.json +1 -1
  56. package/templates/agents/MODEL-MAPPING.md +49 -49
  57. package/templates/agents/orc-advisor-opus-5-xhigh.md +50 -56
  58. package/templates/agents/orc-analyze-mini-opus-5-med.md +55 -60
  59. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +55 -58
  60. package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -75
  61. package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -110
  62. package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -114
  63. package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -112
  64. package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -132
  65. package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -109
  66. package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -109
  67. package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -90
  68. package/templates/agents/orc-claude-writer-opus-4-8-high.md +48 -53
  69. package/templates/agents/orc-claude-writer-opus-5-med.md +48 -55
  70. package/templates/agents/orc-context-combiner-opus-5-high.md +78 -88
  71. package/templates/agents/orc-doc-checker-opus-5-low.md +108 -108
  72. package/templates/agents/orc-doc-writer-opus-5-med.md +134 -134
  73. package/templates/agents/orc-executor-haiku-4-5.md +14 -6
  74. package/templates/agents/orc-executor-opus-4-7-high.md +14 -6
  75. package/templates/agents/orc-executor-opus-4-7-med.md +14 -6
  76. package/templates/agents/orc-executor-opus-4-8-high.md +14 -6
  77. package/templates/agents/orc-executor-opus-5-high.md +15 -7
  78. package/templates/agents/orc-executor-opus-5-low.md +15 -7
  79. package/templates/agents/orc-executor-opus-5-med.md +15 -7
  80. package/templates/agents/orc-executor-sonnet-4-6-high.md +14 -6
  81. package/templates/agents/orc-executor-sonnet-4-6-med.md +14 -6
  82. package/templates/agents/orc-executor-sonnet-5-high.md +14 -6
  83. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -10
  84. package/templates/agents/orc-judge-opus-5-xhigh.md +81 -85
  85. package/templates/agents/orc-learn-writer-opus-5-low.md +67 -73
  86. package/templates/agents/orc-pattern-codifier-opus-5-med.md +58 -65
  87. package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +58 -63
  88. package/templates/agents/orc-planner-mini-opus-5-med.md +4 -7
  89. package/templates/agents/orc-planner-mini-sonnet-5-high.md +2 -3
  90. package/templates/agents/orc-planner-opus-5-med.md +157 -160
  91. package/templates/agents/orc-recon-opus-5-low.md +3 -10
  92. package/templates/agents/orc-recon-sonnet-4-6-med.md +1 -8
  93. package/templates/agents/orc-retro-opus-5-med.md +8 -10
  94. package/templates/agents/orc-retro-sonnet-5-high.md +6 -7
  95. package/templates/agents/orc-reviewer-opus-5-med.md +96 -60
  96. package/templates/agents/orc-scout-opus-5-low.md +35 -40
  97. package/templates/agents/orc-scout-sonnet-4-6-high.md +35 -39
  98. package/templates/agents/orc-system-analyst-opus-5-high.md +115 -120
  99. package/templates/agents/orc-test-author-opus-5-med.md +70 -71
  100. package/templates/agents/orc-test-designer-opus-5-high.md +158 -158
  101. package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -130
  102. package/templates/agents/orc-trace-writer-haiku-4-5.md +3 -7
  103. package/templates/agents/orc-verifier-opus-5-med.md +77 -69
  104. package/templates/agents/orc-wiki-scanner-opus-4-8-high.md +74 -79
  105. package/templates/agents/orc-wiki-scanner-opus-5-med.md +74 -81
  106. package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +97 -106
  107. package/templates/commands/orc-analyze.md +13 -21
  108. package/templates/commands/orc-fast.md +10 -15
  109. package/templates/commands/orc-poly.md +12 -21
  110. package/templates/commands/orc-pr-driver.md +11 -30
  111. package/templates/commands/orc-pr-setup.md +10 -31
  112. package/templates/commands/orc-route.md +11 -41
  113. package/templates/commands/orc-test.md +5 -60
  114. package/templates/commands/orc-ultra.md +17 -17
  115. package/templates/commands/orc-verify.md +11 -11
  116. package/templates/hooks/README.md +36 -2
  117. package/templates/hooks/orc-effort-guard.js +178 -178
  118. package/templates/hooks/orc-session-hook.js +264 -0
  119. package/templates/hooks/orc-statusline.js +9 -7
  120. package/templates/skills/_shared/README.md +9 -0
  121. package/templates/skills/_shared/code-graph.md +48 -56
  122. package/templates/skills/_shared/config-precedence.md +200 -198
  123. package/templates/skills/_shared/extra-dispatch.md +1331 -1346
  124. package/templates/skills/_shared/gotchas.md +228 -177
  125. package/templates/skills/_shared/habits.md +101 -0
  126. package/templates/skills/_shared/lane-contract.md +84 -0
  127. package/templates/skills/_shared/opus5-only.md +8 -8
  128. package/templates/skills/_shared/phases/README.md +142 -83
  129. package/templates/skills/_shared/phases/analyst-gates.md +125 -136
  130. package/templates/skills/_shared/phases/execution.md +8 -14
  131. package/templates/skills/_shared/phases/house-rules.md +27 -32
  132. package/templates/skills/_shared/phases/intake.md +127 -133
  133. package/templates/skills/_shared/phases/mock-example.md +46 -56
  134. package/templates/skills/_shared/phases/plan-handoff.md +91 -97
  135. package/templates/skills/_shared/phases/planning.md +7 -17
  136. package/templates/skills/_shared/phases/preflight.md +19 -42
  137. package/templates/skills/_shared/phases/review.md +23 -27
  138. package/templates/skills/_shared/phases/rules.md +18 -42
  139. package/templates/skills/_shared/phases/scoring.md +55 -65
  140. package/templates/skills/_shared/phases/security-checklist.md +46 -50
  141. package/templates/skills/_shared/phases/security.md +45 -55
  142. package/templates/skills/_shared/phases/ship.md +6 -15
  143. package/templates/skills/_shared/phases/stop-resume.md +2 -5
  144. package/templates/skills/_shared/phases/summary.md +73 -48
  145. package/templates/skills/_shared/phases/testgen.md +41 -51
  146. package/templates/skills/_shared/phases/trace-verbs.md +433 -0
  147. package/templates/skills/_shared/phases/trace.md +136 -367
  148. package/templates/skills/_shared/phases/verify.md +62 -70
  149. package/templates/skills/_shared/phases/wave-grouping.md +128 -133
  150. package/templates/skills/_shared/phases/wiki-consult.md +10 -6
  151. package/templates/skills/_shared/read-ladder.md +2 -55
  152. package/templates/skills/_shared/return-validation.md +17 -70
  153. package/templates/skills/_shared/review-slice.md +79 -0
  154. package/templates/skills/_shared/smoke-gate.md +46 -28
  155. package/templates/skills/context-combiner/SKILL.md +16 -45
  156. package/templates/skills/context-combiner/schemas/combined-report.md +78 -78
  157. package/templates/skills/orc/README.md +2 -2
  158. package/templates/skills/orc/SKILL.md +41 -69
  159. package/templates/skills/orc/config.md +9 -9
  160. package/templates/skills/orc/examples/full-run-mock.md +73 -73
  161. package/templates/skills/orc/references/effort-and-mode.md +222 -222
  162. package/templates/skills/orc/references/pattern-gate.md +89 -89
  163. package/templates/skills/orc/references/phases/intake.md +41 -47
  164. package/templates/skills/orc/references/phases/integration.md +13 -19
  165. package/templates/skills/orc/references/preflight-report.md +10 -11
  166. package/templates/skills/orc/references/ultra-mode.md +11 -9
  167. package/templates/skills/orc/subskills/orc-execution/SKILL.md +27 -73
  168. package/templates/skills/orc/subskills/orc-execution/core.md +12 -99
  169. package/templates/skills/orc/subskills/orc-execution/subagent.md +14 -13
  170. package/templates/skills/orc/subskills/orc-planner/SKILL.md +2 -2
  171. package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -121
  172. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +35 -76
  173. package/templates/skills/orc/subskills/orc-review-verify/core.md +52 -135
  174. package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -7
  175. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +34 -45
  176. package/templates/skills/orc/subskills/orc-testgen/core.md +20 -59
  177. package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -7
  178. package/templates/skills/orc-advisor/SKILL.md +56 -60
  179. package/templates/skills/orc-analyze/SKILL.md +32 -68
  180. package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -42
  181. package/templates/skills/orc-analyze/schemas/report-audit.md +84 -83
  182. package/templates/skills/orc-analyze/schemas/report-prose.md +64 -63
  183. package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -78
  184. package/templates/skills/orc-analyze-mini/SKILL.md +35 -70
  185. package/templates/skills/orc-challenge/README.md +142 -142
  186. package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -273
  187. package/templates/skills/orc-challenge/references/council.md +315 -315
  188. package/templates/skills/orc-challenge/references/intake.md +171 -171
  189. package/templates/skills/orc-claude/SKILL.md +14 -14
  190. package/templates/skills/orc-diy/README.md +174 -143
  191. package/templates/skills/orc-diy/SKILL.md +23 -74
  192. package/templates/skills/orc-diy/references/blocks/pattern.md +18 -18
  193. package/templates/skills/orc-diy/references/flow-schema.md +1 -1
  194. package/templates/skills/orc-doc/README.md +229 -229
  195. package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -325
  196. package/templates/skills/orc-doc/references/chunking.md +527 -527
  197. package/templates/skills/orc-fast/SKILL.md +45 -73
  198. package/templates/skills/orc-judge/SKILL.md +77 -82
  199. package/templates/skills/orc-learn/SKILL.md +14 -14
  200. package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -61
  201. package/templates/skills/orc-mini/SKILL.md +65 -113
  202. package/templates/skills/orc-pattern/SKILL.md +27 -48
  203. package/templates/skills/orc-poly/SKILL.md +32 -61
  204. package/templates/skills/orc-pr-driver/SKILL.md +25 -51
  205. package/templates/skills/orc-pr-driver/references/green-gate.md +113 -105
  206. package/templates/skills/orc-pr-setup/SKILL.md +20 -45
  207. package/templates/skills/orc-quick/README.md +43 -2
  208. package/templates/skills/orc-quick/SKILL.md +76 -107
  209. package/templates/skills/orc-quick/references/dispatch-gate.md +16 -5
  210. package/templates/skills/orc-quick/references/gh-mode.md +48 -1
  211. package/templates/skills/orc-quick/references/look.md +3 -1
  212. package/templates/skills/orc-retro/SKILL.md +19 -18
  213. package/templates/skills/orc-retro/examples/retro-mock.md +1 -1
  214. package/templates/skills/orc-route/SKILL.md +25 -45
  215. package/templates/skills/orc-test/SKILL.md +16 -37
  216. package/templates/skills/orc-verify/SKILL.md +21 -39
  217. package/templates/skills/orc-verify/examples/verify-mock.md +33 -33
  218. package/templates/skills/orc-wait/SKILL.md +156 -163
  219. package/templates/skills/orc-wiki/references/extra.md +1 -1
  220. package/templates/skills/orc-wiki/references/phases/phase-0.md +1 -6
  221. package/templates/skills/orc-wiki/references/phases/phase-1.md +1 -6
  222. package/templates/skills/orc-wiki/references/phases/phase-2.md +1 -6
  223. package/templates/skills/orc-wiki/references/phases/phase-3.md +1 -6
  224. package/templates/skills/orc-wiki/references/phases/phase-3c.md +1 -6
@@ -1,222 +1,222 @@
1
- # Reference — Effort, Dispatch Style, and Task Scoring
2
-
3
- **Subagents ALWAYS do the work — the orchestrator never implements** (hard
4
- rule 1). The orchestrator is Opus 4.8 high: it doing implementation is the most
5
- costly way possible, and it burns the context that must survive the whole run.
6
- Spawning keeps orchestrator context lean so runs last longer before any pause.
7
-
8
- Two INDEPENDENT axes. Never conflate them:
9
- - **Run-level effort** (low/medium/high) → picks the **dispatch style**
10
- (sequential vs parallel), which controls only **intra-wave concurrency** —
11
- never WHO does the work, and never WHETHER waves exist.
12
- - **Per-task score** (0–100) → picks each **worker's model**. Always applies.
13
-
14
- A medium run can contain a 30-score task and a 95-score task in the same wave.
15
-
16
- ## Waves always exist; dispatch style is intra-wave only
17
-
18
- **Wave computation runs for every run with ≥2 tasks, sequential included**
19
- (dependency layers + conflict graph + `max_wave_tasks` cap — see
20
- `wave-grouping.md`). Dispatch style does NOT decide whether there are waves; it
21
- decides how a wave's tasks fire:
22
-
23
- - **sequential** → a wave's tasks dispatch one at a time, in order; the wave
24
- closes when all its tasks close;
25
- - **parallel** → a wave's non-conflicting tasks dispatch at once (up to
26
- `max_wave_tasks`).
27
-
28
- The **wave-boundary batch pause binds to wave numbers, identically in both
29
- styles** — a sequential run is NOT "no waves / per-task pauses". Show the wave
30
- plan (wave → tasks → pause marks) to the user BEFORE wave 1 in both styles.
31
-
32
- ## Run-level effort → dispatch style (recommend, user confirms)
33
-
34
- - **Low**, or heavy shared data/code → **sequential**: one scored subagent at a
35
- time, in dependency order (still grouped into waves). Even a single trivial
36
- task = one cheap subagent (typically Sonnet 4.6 medium), never the
37
- orchestrator itself.
38
- - **Medium** → sequential by default; **parallel** intra-wave if 3+ genuinely
39
- independent areas.
40
- - **High** with independent areas → **parallel** waves; consider worktrees for
41
- isolation (merge at end).
42
-
43
- Always RECOMMEND with a one-line why, and let the user pick. Tell them the
44
- agent/task/wave counts, each task's scored model, and where batch pauses fall
45
- BEFORE dispatching.
46
-
47
- ## Per-task scoring — facet-scored, arithmetic, two-writer
48
-
49
- The score is **not judged** from a task title. The **planner** — the one party
50
- that globbed and read every declared file — emits per-task `facets` (facts). The
51
- **orchestrator** — who never read the code — computes the number arithmetically
52
- and audits the facts. No vibes anywhere. Every task is scored, including tiny ones.
53
-
54
- **1. Planner-emitted facets** (`planning-output.md` `facets` block, filled during
55
- grounding — zero extra passes):
56
-
57
- | Facet | Values |
58
- |---|---|
59
- | `breadth` | `len(declared_files)` — computed, not judged |
60
- | `novelty` | mechanical · imitate · new-surface · novel-algorithm |
61
- | `logic` | none · branching · stateful · algorithmic |
62
- | `test_surface` | none · update-existing · new-tests |
63
- | `risk` | `[]` or `[{class, cite}]` — class ∈ auth·money·migration·security·concurrency·data-integrity; **each entry MUST cite the file/requirement** |
64
- | `uncertainty` | low · medium · high (+ one-line reason if not low) |
65
-
66
- `fan_in`/`fan_out` are NOT emitted — the orchestrator computes them from
67
- `depends_on` (forward = fan_in, reverse = fan_out).
68
-
69
- **2. Orchestrator validation gate (Phase 2, deterministic — same bounce
70
- mechanics as grounding):** emit `GATE facet pass|bounce`. Three checks:
71
-
72
- - **Recompute** `breadth` (= `len(declared_files)`) and `fan_in`/`fan_out` from
73
- the plan itself — a mismatch bounces.
74
- - **MEMBERSHIP (v0.34.4):** `novelty`, `logic`, `test_surface` and `uncertainty`
75
- must each be a member of their CLOSED set above, and every `risk[].class` must
76
- be one of the six risk classes. A set lookup, as deterministic as the grounding
77
- Glob. This is the check that was missing: the gate validated only the two
78
- facets it could recompute and TRUSTED the four it could not, so a planner that
79
- invented a `low|medium|high` scale produced an **arithmetically unscorable**
80
- plan that passed the stated gate. There is no `N("low")` — and an orchestrator
81
- applying `risk != [] -> floor 70` to prose risk strings floors EVERY task, a
82
- two-band overshoot caused by a field's shape rather than by the work.
83
- - **Cite check:** a `risk` entry with no `cite` bounces (unchanged).
84
-
85
- A facet-vocabulary miss is a **FIELD-SHAPE bounce**: hand back the miss list and
86
- say *do not re-plan* — the planner corrects only the offending `facets` blocks.
87
- (It may also legitimately DROP a risk entry on the correction pass: implementation
88
- hazards like test seeding or dependency discipline are not risk CLASSES. That
89
- judgment is the planner's to make and is worth accepting.) Without this clause a
90
- shape bounce risks costing a correct plan. A plan with no `facets` at all
91
- (pre-v0.31.0) resumes on the legacy path — never bounced for the missing block.
92
-
93
- **3. The fixed formula (the ONLY scoring text — this replaces base+adjusters):**
94
-
95
- ```
96
- score = B(breadth) + N(novelty) + L(logic) + T(test_surface)
97
- + 5*min(fan_in,3) + 3*min(fan_out,3) + U(uncertainty)
98
-
99
- B: 1f=2 2-3f=6 4-5f=10 6+f=15
100
- N: mechanical=0 imitate=8 new-surface=18 novel-algorithm=30
101
- L: none=0 branching=8 stateful=16 algorithmic=24
102
- T: none=0 update-existing=4 new-tests=8
103
- U: low=0 medium=6 high=12
104
-
105
- risk ≠ [] → floor 70 (DERIVED from a cited risk facet, never remembered).
106
- clamp 0..100 → the RESOLVED table (below).
107
- ```
108
-
109
- **Which table (highest wins):** `opus5_only: true` (the 2-band Opus-5-only
110
- preset: `[0,90)` low · `[90,100]` medium) → `rubric_bands_override`
111
- (hand-written rows) → the default 6-band table. All three are in `config.md`.
112
- The formula, the facets and the risk floor are IDENTICAL in every case — only
113
- the score→agent mapping changes. Three consequences worth stating so nobody
114
- re-derives them per run:
115
-
116
- - **The risk floor still applies** — it raises the SCORE, then the resolved table
117
- maps it. A floored task (≥70) lands `opus-5-low` in the default table and
118
- `opus-5-low` under the Opus-5-only preset too: since v1.0.0 both tables answer
119
- the floor with the same agent, and only a score of 90+ moves it to `opus-5-med`.
120
- - **`opus5_only` FORCES** — while on, a hand-written `rubric_bands_override` is
121
- ignored. It is the one selector that can shadow another; that is deliberate.
122
-
123
- Show the user the full table (task, the facet vector, the arithmetic
124
- `B+N+L+T+fan+U = raw`, any risk floor, final, override+reason if any, dispatched
125
- model) BEFORE dispatching — an un-shown number is not a scored number. **Head it
126
- with the RESOLVED table's name** (`6-band default` / `Opus-5-only ladder
127
- (opus5_only)` / `custom (rubric_bands_override)`): the same logic
128
- applies to the mapping as to the number.
129
-
130
- **Extra (v0.50.0, `extra_enabled`) adds a `via` column and can make the head a
131
- PAIR.** An Extra route row is an OVERLAY that outranks the tables above **only
132
- for the scores it covers**, so a run can genuinely be running two tables at once
133
- and the head names both (`6-band default + extra rows [0,30) [30,70)`). The
134
- column reads `claude` or `extra:<profile> (<engine>)` and comes from
135
- `orc extra resolve --json` — the formula, the facets and the risk floor are
136
- untouched, and **the score is computed before the routing, never after it**. Two
137
- consequences the table has to show rather than imply: a cited `risk[]` HOLDS THE
138
- TASK BACK to its Claude band whatever the row says (`extra_risk_tasks: off`), and
139
- the `model` for a foreign task is the FOREIGN model id, not a Claude tier.
140
- Canonical: `../../_shared/extra-dispatch.md`.
141
-
142
- **4. Consistency check:** two tasks whose facet vectors differ in **≤1 facet must
143
- land in the same band** — or the SCORE line for the outlier **cites the one
144
- differing facet**. This is the specific fix for sibling tasks in the same domain
145
- drifting into three different bands.
146
-
147
- **5. Override protocol** (unchanged): you may override the computed score. Record
148
- `{computed_score, override_score, reason}` in the dispatch log. An override
149
- without a reason is invalid.
150
-
151
- ## EVERY dispatch is scored — the fix-cycle rule
152
-
153
- Fix-cycle dispatches — review-fix, verify-fix, the Phase-7 P2-batch, and any
154
- requeue — are scored through the **same formula**, with two floors that stop a
155
- fix in a risk area from silently dropping to a cheap model:
156
-
157
- - **Inherit the ORIGINAL task's `risk` facets** when the fix touches its files —
158
- a fix in a risk-floor area keeps the ≥70 floor (a userID/context-key fix can
159
- never dispatch below `opus-5-low` again);
160
- - a **P0/P1 fix never dispatches below the band of the task that produced the
161
- finding.**
162
-
163
- Emit a `SCORE task=fix-<n> …` line for each (they appear in the dispatch log and
164
- the completion table like any task).
165
-
166
- ## Worked scoring examples (facet vectors — compare facet-by-facet, not by vibes)
167
-
168
- Each row is the facet vector run through the formula. The number is arithmetic;
169
- the band is what matters. Compare a new task to these facet-by-facet.
170
-
171
- | Task | breadth·novelty·logic·test · fan_in/out · unc | Arithmetic | Band |
172
- |---|---|---|---|
173
- | Rename a config key across 4 files + its test | 5·mechanical·none·update-existing · 0/0 · low | 10+0+0+4 = **14** | haiku [0,30) |
174
- | New CRUD endpoint following a sibling route | 3·imitate·branching·new-tests · 1/0 · low | 6+8+8+8+5 = **35** | sonnet-4-6-med [30,40) |
175
- | Bug fix across 2 files with a repro test | 3·imitate·branching·new-tests · 0/0 · medium | 6+8+8+8+6 = **36** | sonnet-4-6-med [30,40) |
176
- | Isolated component from the design system | 3·new-surface·branching·new-tests · 0/0 · low | 6+18+8+8 = **40** | sonnet-4-6-high [40,55) |
177
- | Notification model + enum other tasks consume | 3·new-surface·stateful·new-tests · 0/3 · low | 6+18+16+8+9 = **57** | sonnet-5-high [55,65) |
178
- | Service-layer refactor behind a stable interface | 5·imitate·stateful·update-existing · 0/3 · medium | 10+8+16+4+9+6 = **53** | sonnet-4-6-high [40,55) |
179
- | Add role check to payment-refund endpoint | 3·imitate·branching·new-tests · 0/0 · low · **risk=[auth,money]** | 30 raw → **floor 70** | opus-5-low [65,90) |
180
- | Migrate orders table to split-name + backfill | 6·new-surface·stateful·new-tests · 1/3 · high · **risk=[migration,data-integrity]** | 15+18+16+8+5+9+12 = 83 (floor 70) → **83** | opus-5-low [65,90) |
181
-
182
- Two disciplines the vectors encode: (1) a small diff is NOT a low score when a
183
- cited `risk` facet forces the floor (the refund row — 30 raw, floored to 70); (2)
184
- a big-looking task IS low when its facets are mechanical (the rename). The risk
185
- floor is always DERIVED from a cited facet — the SCORE line names it, never
186
- applies it silently.
187
-
188
- ## Model ladder → the single score→model table
189
-
190
- The score→model mapping is NOT hardcoded here — it lives in `config.md` as ONE
191
- canonical 6-band table (there is no longer a narrow/wide preset). Read config at
192
- run start and map each task's final score through that table (or
193
- `rubric_bands_override`). The orchestrator dispatches the executor agent BY NAME;
194
- it does not request a raw model. `rubric_bands` sets only how many bands the
195
- rubric REPORTS (score granularity), never which table is used.
196
-
197
- The 6 bands (see config.md for the exact edges): `haiku-4-5` [0,30) ·
198
- `sonnet-4-6-med` [30,40) · `sonnet-4-6-high` [40,55) · `sonnet-5-high` [55,65) ·
199
- `opus-5-low` [65,90) · `opus-5-med` [90,100]. Effort tiers rank
200
- `low < medium < high < xhigh < max`.
201
-
202
- ## Fixed model assignments (not scored)
203
-
204
- - **Orchestrator (you):** Opus 4.8 high — or Opus 5 / Fable 5 at medium+, the
205
- two models that clear the guard from medium up. Never downgrade yourself.
206
- - **Review** — Superpowers path: Sonnet 4.6, medium. OpenSpec/self path:
207
- Opus 5, medium (`orc-reviewer-opus-5-med`).
208
- - **Verify:** Opus 5, medium (`orc-verifier-opus-5-med`).
209
- - **Analyst:** Opus 5, high. **Planner:** Opus 5, medium. **Test author:**
210
- Opus 5, medium. **Combiner:** Opus 5, high. **Ultra advisor/judge:** Opus 5,
211
- xhigh — every core fixed role is pinned to Opus 5 as of v0.34.0.
212
- - **Merge-conflict resolver:** Opus 4.8, medium.
213
-
214
- Note: every band in the table above is a real dispatch target (haiku through
215
- opus-5). If a model tier is unavailable in the environment, fall back UP to the
216
- next capable tier (never silently substitute a different family/effort).
217
-
218
- ## Dispatch log (lives in the checkpoint)
219
-
220
- Every spawn records: `{task_id, computed_score, override_score|null,
221
- override_reason|null, model, effort, spawned_at}`. Feeds the usage report at
222
- every stop.
1
+ # Reference — Effort, Dispatch Style, and Task Scoring
2
+
3
+ **Subagents ALWAYS do the work — the orchestrator never implements** (hard
4
+ rule 1). The orchestrator is Opus 4.8 high: it doing implementation is the most
5
+ costly way possible, and it burns the context that must survive the whole run.
6
+ Spawning keeps orchestrator context lean so runs last longer before any pause.
7
+
8
+ Two INDEPENDENT axes. Never conflate them:
9
+ - **Run-level effort** (low/medium/high) → picks the **dispatch style**
10
+ (sequential vs parallel), which controls only **intra-wave concurrency** —
11
+ never WHO does the work, and never WHETHER waves exist.
12
+ - **Per-task score** (0–100) → picks each **worker's model**. Always applies.
13
+
14
+ A medium run can contain a 30-score task and a 95-score task in the same wave.
15
+
16
+ ## Waves always exist; dispatch style is intra-wave only
17
+
18
+ **Wave computation runs for every run with ≥2 tasks, sequential included**
19
+ (dependency layers + conflict graph + `max_wave_tasks` cap — see
20
+ `wave-grouping.md`). Dispatch style does NOT decide whether there are waves; it
21
+ decides how a wave's tasks fire:
22
+
23
+ - **sequential** → a wave's tasks dispatch one at a time, in order; the wave
24
+ closes when all its tasks close;
25
+ - **parallel** → a wave's non-conflicting tasks dispatch at once (up to
26
+ `max_wave_tasks`).
27
+
28
+ The **wave-boundary batch pause binds to wave numbers, identically in both
29
+ styles** — a sequential run is NOT "no waves / per-task pauses". Show the wave
30
+ plan (wave → tasks → pause marks) to the user BEFORE wave 1 in both styles.
31
+
32
+ ## Run-level effort → dispatch style (recommend, user confirms)
33
+
34
+ - **Low**, or heavy shared data/code → **sequential**: one scored subagent at a
35
+ time, in dependency order (still grouped into waves). Even a single trivial
36
+ task = one cheap subagent (typically Sonnet 4.6 medium), never the
37
+ orchestrator itself.
38
+ - **Medium** → sequential by default; **parallel** intra-wave if 3+ genuinely
39
+ independent areas.
40
+ - **High** with independent areas → **parallel** waves; consider worktrees for
41
+ isolation (merge at end).
42
+
43
+ Always RECOMMEND with a one-line why, and let the user pick. Tell them the
44
+ agent/task/wave counts, each task's scored model, and where batch pauses fall
45
+ BEFORE dispatching.
46
+
47
+ ## Per-task scoring — facet-scored, arithmetic, two-writer
48
+
49
+ The score is **not judged** from a task title. The **planner** — the one party
50
+ that globbed and read every declared file — emits per-task `facets` (facts). The
51
+ **orchestrator** — who never read the code — computes the number arithmetically
52
+ and audits the facts. No vibes anywhere. Every task is scored, including tiny ones.
53
+
54
+ **1. Planner-emitted facets** (`planning-output.md` `facets` block, filled during
55
+ grounding — zero extra passes):
56
+
57
+ | Facet | Values |
58
+ |---|---|
59
+ | `breadth` | `len(declared_files)` — computed, not judged |
60
+ | `novelty` | mechanical · imitate · new-surface · novel-algorithm |
61
+ | `logic` | none · branching · stateful · algorithmic |
62
+ | `test_surface` | none · update-existing · new-tests |
63
+ | `risk` | `[]` or `[{class, cite}]` — class ∈ auth·money·migration·security·concurrency·data-integrity; **each entry MUST cite the file/requirement** |
64
+ | `uncertainty` | low · medium · high (+ one-line reason if not low) |
65
+
66
+ `fan_in`/`fan_out` are NOT emitted — the orchestrator computes them from
67
+ `depends_on` (forward = fan_in, reverse = fan_out).
68
+
69
+ **2. Orchestrator validation gate (Phase 2, deterministic — same bounce
70
+ mechanics as grounding):** emit `GATE facet pass|bounce`. Three checks:
71
+
72
+ - **Recompute** `breadth` (= `len(declared_files)`) and `fan_in`/`fan_out` from
73
+ the plan itself — a mismatch bounces.
74
+ - **MEMBERSHIP (v0.34.4):** `novelty`, `logic`, `test_surface` and `uncertainty`
75
+ must each be a member of their CLOSED set above, and every `risk[].class` must
76
+ be one of the six risk classes. A set lookup, as deterministic as the grounding
77
+ Glob. This is the check that was missing: the gate validated only the two
78
+ facets it could recompute and TRUSTED the four it could not, so a planner that
79
+ invented a `low|medium|high` scale produced an **arithmetically unscorable**
80
+ plan that passed the stated gate. There is no `N("low")` — and an orchestrator
81
+ applying `risk != [] -> floor 70` to prose risk strings floors EVERY task, a
82
+ two-band overshoot caused by a field's shape rather than by the work.
83
+ - **Cite check:** a `risk` entry with no `cite` bounces (unchanged).
84
+
85
+ A facet-vocabulary miss is a **FIELD-SHAPE bounce**: hand back the miss list and
86
+ say *do not re-plan* — the planner corrects only the offending `facets` blocks.
87
+ (It may also legitimately DROP a risk entry on the correction pass: implementation
88
+ hazards like test seeding or dependency discipline are not risk CLASSES. That
89
+ judgment is the planner's to make and is worth accepting.) Without this clause a
90
+ shape bounce risks costing a correct plan. A plan with no `facets` at all
91
+ (pre-v0.31.0) resumes on the legacy path — never bounced for the missing block.
92
+
93
+ **3. The fixed formula (the ONLY scoring text — this replaces base+adjusters):**
94
+
95
+ ```
96
+ score = B(breadth) + N(novelty) + L(logic) + T(test_surface)
97
+ + 5*min(fan_in,3) + 3*min(fan_out,3) + U(uncertainty)
98
+
99
+ B: 1f=2 2-3f=6 4-5f=10 6+f=15
100
+ N: mechanical=0 imitate=8 new-surface=18 novel-algorithm=30
101
+ L: none=0 branching=8 stateful=16 algorithmic=24
102
+ T: none=0 update-existing=4 new-tests=8
103
+ U: low=0 medium=6 high=12
104
+
105
+ risk ≠ [] → floor 70 (DERIVED from a cited risk facet, never remembered).
106
+ clamp 0..100 → the RESOLVED table (below).
107
+ ```
108
+
109
+ **Which table (highest wins):** `opus5_only: true` (the 2-band Opus-5-only
110
+ preset: `[0,90)` low · `[90,100]` medium) → `rubric_bands_override`
111
+ (hand-written rows) → the default 6-band table. All three are in `config.md`.
112
+ The formula, the facets and the risk floor are IDENTICAL in every case — only
113
+ the score→agent mapping changes. Three consequences worth stating so nobody
114
+ re-derives them per run:
115
+
116
+ - **The risk floor still applies** — it raises the SCORE, then the resolved table
117
+ maps it. A floored task (≥70) lands `opus-5-low` in the default table and
118
+ `opus-5-low` under the Opus-5-only preset too: since v1.0.0 both tables answer
119
+ the floor with the same agent, and only a score of 90+ moves it to `opus-5-med`.
120
+ - **`opus5_only` FORCES** — while on, a hand-written `rubric_bands_override` is
121
+ ignored. It is the one selector that can shadow another; that is deliberate.
122
+
123
+ Show the user the full table (task, the facet vector, the arithmetic
124
+ `B+N+L+T+fan+U = raw`, any risk floor, final, override+reason if any, dispatched
125
+ model) BEFORE dispatching — an un-shown number is not a scored number. **Head it
126
+ with the RESOLVED table's name** (`6-band default` / `Opus-5-only ladder
127
+ (opus5_only)` / `custom (rubric_bands_override)`): the same logic
128
+ applies to the mapping as to the number.
129
+
130
+ **Extra (v0.50.0, `extra_enabled`) adds a `via` column and can make the head a
131
+ PAIR.** An Extra route row is an OVERLAY that outranks the tables above **only
132
+ for the scores it covers**, so a run can genuinely be running two tables at once
133
+ and the head names both (`6-band default + extra rows [0,30) [30,70)`). The
134
+ column reads `claude` or `extra:<profile> (<engine>)` and comes from
135
+ `orc extra resolve --json` — the formula, the facets and the risk floor are
136
+ untouched, and **the score is computed before the routing, never after it**. Two
137
+ consequences the table has to show rather than imply: a cited `risk[]` HOLDS THE
138
+ TASK BACK to its Claude band whatever the row says (`extra_risk_tasks: off`), and
139
+ the `model` for a foreign task is the FOREIGN model id, not a Claude tier.
140
+ Canonical: `../../_shared/extra-dispatch.md`.
141
+
142
+ **4. Consistency check:** two tasks whose facet vectors differ in **≤1 facet must
143
+ land in the same band** — or the SCORE line for the outlier **cites the one
144
+ differing facet**. This is the specific fix for sibling tasks in the same domain
145
+ drifting into three different bands.
146
+
147
+ **5. Override protocol** (unchanged): you may override the computed score. Record
148
+ `{computed_score, override_score, reason}` in the dispatch log. An override
149
+ without a reason is invalid.
150
+
151
+ ## EVERY dispatch is scored — the fix-cycle rule
152
+
153
+ Fix-cycle dispatches — review-fix, verify-fix, the Phase-7 P2-batch, and any
154
+ requeue — are scored through the **same formula**, with two floors that stop a
155
+ fix in a risk area from silently dropping to a cheap model:
156
+
157
+ - **Inherit the ORIGINAL task's `risk` facets** when the fix touches its files —
158
+ a fix in a risk-floor area keeps the ≥70 floor (a userID/context-key fix can
159
+ never dispatch below `opus-5-low` again);
160
+ - a **P0/P1 fix never dispatches below the band of the task that produced the
161
+ finding.**
162
+
163
+ Emit a `SCORE task=fix-<n> …` line for each (they appear in the dispatch log and
164
+ the completion table like any task).
165
+
166
+ ## Worked scoring examples (facet vectors — compare facet-by-facet, not by vibes)
167
+
168
+ Each row is the facet vector run through the formula. The number is arithmetic;
169
+ the band is what matters. Compare a new task to these facet-by-facet.
170
+
171
+ | Task | breadth·novelty·logic·test · fan_in/out · unc | Arithmetic | Band |
172
+ |---|---|---|---|
173
+ | Rename a config key across 4 files + its test | 5·mechanical·none·update-existing · 0/0 · low | 10+0+0+4 = **14** | haiku [0,30) |
174
+ | New CRUD endpoint following a sibling route | 3·imitate·branching·new-tests · 1/0 · low | 6+8+8+8+5 = **35** | sonnet-4-6-med [30,40) |
175
+ | Bug fix across 2 files with a repro test | 3·imitate·branching·new-tests · 0/0 · medium | 6+8+8+8+6 = **36** | sonnet-4-6-med [30,40) |
176
+ | Isolated component from the design system | 3·new-surface·branching·new-tests · 0/0 · low | 6+18+8+8 = **40** | sonnet-4-6-high [40,55) |
177
+ | Notification model + enum other tasks consume | 3·new-surface·stateful·new-tests · 0/3 · low | 6+18+16+8+9 = **57** | sonnet-5-high [55,65) |
178
+ | Service-layer refactor behind a stable interface | 5·imitate·stateful·update-existing · 0/3 · medium | 10+8+16+4+9+6 = **53** | sonnet-4-6-high [40,55) |
179
+ | Add role check to payment-refund endpoint | 3·imitate·branching·new-tests · 0/0 · low · **risk=[auth,money]** | 30 raw → **floor 70** | opus-5-low [65,90) |
180
+ | Migrate orders table to split-name + backfill | 6·new-surface·stateful·new-tests · 1/3 · high · **risk=[migration,data-integrity]** | 15+18+16+8+5+9+12 = 83 (floor 70) → **83** | opus-5-low [65,90) |
181
+
182
+ Two disciplines the vectors encode: (1) a small diff is NOT a low score when a
183
+ cited `risk` facet forces the floor (the refund row — 30 raw, floored to 70); (2)
184
+ a big-looking task IS low when its facets are mechanical (the rename). The risk
185
+ floor is always DERIVED from a cited facet — the SCORE line names it, never
186
+ applies it silently.
187
+
188
+ ## Model ladder → the single score→model table
189
+
190
+ The score→model mapping is NOT hardcoded here — it lives in `config.md` as ONE
191
+ canonical 6-band table (there is no longer a narrow/wide preset). Read config at
192
+ run start and map each task's final score through that table (or
193
+ `rubric_bands_override`). The orchestrator dispatches the executor agent BY NAME;
194
+ it does not request a raw model. `rubric_bands` sets only how many bands the
195
+ rubric REPORTS (score granularity), never which table is used.
196
+
197
+ The 6 bands (see config.md for the exact edges): `haiku-4-5` [0,30) ·
198
+ `sonnet-4-6-med` [30,40) · `sonnet-4-6-high` [40,55) · `sonnet-5-high` [55,65) ·
199
+ `opus-5-low` [65,90) · `opus-5-med` [90,100]. Effort tiers rank
200
+ `low < medium < high < xhigh < max`.
201
+
202
+ ## Fixed model assignments (not scored)
203
+
204
+ - **Orchestrator (you):** Opus 4.8 high — or Opus 5.5 / Fable 5 at medium+, the
205
+ two models that clear the guard from medium up. Never downgrade yourself.
206
+ - **Review** — Superpowers path: Sonnet 4.6, medium. OpenSpec/self path:
207
+ Opus 5.5, medium (`orc-reviewer-opus-5-med`).
208
+ - **Verify:** Opus 5.5, medium (`orc-verifier-opus-5-med`).
209
+ - **Analyst:** Opus 5.5, high. **Planner:** Opus 5.5, medium. **Test author:**
210
+ Opus 5.5, medium. **Combiner:** Opus 5.5, high. **Ultra advisor/judge:** Opus 5.5,
211
+ xhigh — every core fixed role is pinned to Opus 5.5 as of v0.34.0.
212
+ - **Merge-conflict resolver:** Opus 4.8, medium.
213
+
214
+ Note: every band in the table above is a real dispatch target (haiku through
215
+ opus-5). If a model tier is unavailable in the environment, fall back UP to the
216
+ next capable tier (never silently substitute a different family/effort).
217
+
218
+ ## Dispatch log (lives in the checkpoint)
219
+
220
+ Every spawn records: `{task_id, computed_score, override_score|null,
221
+ override_reason|null, model, effort, spawned_at}`. Feeds the usage report at
222
+ every stop.
@@ -1,89 +1,89 @@
1
- # Reference — Code-Pattern Gate (orchestrator side)
2
-
3
- How the full lane resolves, injects, and enforces per-language code-patterns so
4
- executors MATCH the existing codebase instead of writing generic-template code.
5
- The engine (playbooks, codifier slice, reconcile rules) is the sibling skill
6
- `../../orc-pattern/SKILL.md`; this file is the orchestrator's gate + wiring.
7
- Load at Phase 2 (tagging) and Phase 3 (resolve gate + slice injection).
8
-
9
- Principle: **conventions defer to the project; security/correctness invariants
10
- are always enforced.**
11
-
12
- ## Phase 2 — Tag each task while scoring
13
-
14
- From its `declared_files` extensions + repo deps (see
15
- `../../orc-pattern/references/INDEX.md`):
16
- `{domain: FE|BE|null, lang: react|nextjs|vue|fastapi|nestjs|go|…|null}`.
17
- Tasks with no FE/BE language need no pattern.
18
-
19
- **Postgres secondary tag:** on a Postgres project (`pg`/`psycopg`/`asyncpg`/
20
- `pgx`/`lib/pq`/`Npgsql`/Prisma `postgresql`/`postgrex` in deps), add
21
- `db: postgres` to any task whose `declared_files` touch the data-access layer
22
- (repositories/dao/models/queries, `*.sql`, ORM entities/migrations). `db`
23
- co-applies WITH the framework `lang`, never instead of it — it pulls the
24
- cross-cutting `postgres` playbook into the same resolve gate.
25
-
26
- ## Phase 3 — Resolve gate (once, before the first wave)
27
-
28
- For each distinct tagged language (including `postgres` when any task is
29
- `db`-tagged), resolve against the cache `.claude/orc/patterns/<lang>-pattern.md`
30
- — test existence with the deterministic probe `orc pattern status <lang>`
31
- (exit 0 = cached; see `../../_shared/detecting-artifacts.md`), never an ad-hoc
32
- `find`, so a codified pattern is never missed:
33
-
34
- Every resolved language prints exactly ONE user-visible line (no cost, no ask —
35
- visibility only, so the user always knows which house style is in force):
36
-
37
- - **Cache hit, no drift** → no ask, no cost, but print
38
- `pattern: <lang>-pattern.md applied (cached)`.
39
- - **Cache miss** → apply config `pattern_findings` (default `ask`):
40
- - `ask` → ONE P0 prompt batched across ALL missing languages ("Learn
41
- conventions for {…} via orc-pattern, or proceed language-agnostic?");
42
- - `on` → codify without asking; print `pattern: <lang> — codifying (cache miss)`;
43
- - `off` → agnostic; print `pattern: <lang> — running language-agnostic (no cached pattern)`.
44
- - **On learn/`on`** → dispatch `orc-pattern-codifier-sonnet-5-high` per missing
45
- language (`orc-pattern-codifier-opus-5-med` when `opus5_only` — see
46
- `../../_shared/opus5-only.md`; slice per `../../orc-pattern/SKILL.md`
47
- Phase 1); YOU write the returned pattern to the cache.
48
- - **Agnostic fallback** (declined / `off` / no playbook for the language): no
49
- codifier, no scan — the executor enforces the universal invariants and
50
- imitates the neighbor files it already reads. ~Zero added cost.
51
-
52
- Hold the resolved pattern per language in run state (survives
53
- checkpoint/resume) — it is injected at dispatch and reused at Phase 5/6.
54
-
55
- ## Slice injection (anti-skip layer 1)
56
-
57
- Inject the resolved conventions + blocking invariants + the enforceable
58
- `validation_gate[]` lines LITERALLY into each FE/BE task's slice as `pattern` —
59
- never a file pointer. Agnostic tasks get the universal invariants only.
60
-
61
- **Gotchas ride BESIDE the pattern block, never inside it** (config `gotchas`;
62
- canonical `../../_shared/gotchas.md`). Same slice, same literal injection, one
63
- hard difference: the pattern applies to a LANGUAGE, so it goes to every task
64
- tagged with that language — a gotcha applies to a `scope` GLOB, so it goes only to
65
- tasks whose `declared_files` match it, capped at 3, highest `hits` first. Zero
66
- matches = no gotcha block at all. Never inject unfiltered: a pattern is what this
67
- project always does, a gotcha is what it got wrong ONCE, somewhere specific.
68
-
69
- For a `db:postgres`-tagged task, ALSO merge the resolved `postgres` pattern's
70
- Conventions + Invariants + gate lines into the SAME `pattern` block (appended
71
- to the framework pattern, or standalone if the task has no framework lang) —
72
- query invariants (bound params only, pooled connections, transactional
73
- multi-writes) ride the same anti-skip path. Record the postgres
74
- `pattern_version` in run state/log too.
75
-
76
- ## Return validation (anti-skip layer 2)
77
-
78
- A task that was given a `pattern` must return `invariants_checked: true` + a
79
- `pattern_version` matching what you injected — the single attestation covers a
80
- merged block. Missing/false attestation = malformed return (requeue). Record
81
- the applied `pattern_version` in the trace.
82
-
83
- ## Review/verify re-check (anti-skip layer 3)
84
-
85
- - **Phase 5 (review):** pass the resolved pattern as `code_pattern` AND its
86
- blocking `invariants[]` + `validation_gate[]` lines for the re-check — don't
87
- re-ask the user. An invariant violation or unmet gate line is P0.
88
- - **Phase 6 (verify):** pass the `validation_gate[]` lines in the slice — each
89
- line is an acceptance criterion; an unmet line is P0.
1
+ # Reference — Code-Pattern Gate (orchestrator side)
2
+
3
+ How the full lane resolves, injects, and enforces per-language code-patterns so
4
+ executors MATCH the existing codebase instead of writing generic-template code.
5
+ The engine (playbooks, codifier slice, reconcile rules) is the sibling skill
6
+ `../../orc-pattern/SKILL.md`; this file is the orchestrator's gate + wiring.
7
+ Load at Phase 2 (tagging) and Phase 3 (resolve gate + slice injection).
8
+
9
+ Principle: **conventions defer to the project; security/correctness invariants
10
+ are always enforced.**
11
+
12
+ ## Phase 2 — Tag each task while scoring
13
+
14
+ From its `declared_files` extensions + repo deps (see
15
+ `../../orc-pattern/references/INDEX.md`):
16
+ `{domain: FE|BE|null, lang: react|nextjs|vue|fastapi|nestjs|go|…|null}`.
17
+ Tasks with no FE/BE language need no pattern.
18
+
19
+ **Postgres secondary tag:** on a Postgres project (`pg`/`psycopg`/`asyncpg`/
20
+ `pgx`/`lib/pq`/`Npgsql`/Prisma `postgresql`/`postgrex` in deps), add
21
+ `db: postgres` to any task whose `declared_files` touch the data-access layer
22
+ (repositories/dao/models/queries, `*.sql`, ORM entities/migrations). `db`
23
+ co-applies WITH the framework `lang`, never instead of it — it pulls the
24
+ cross-cutting `postgres` playbook into the same resolve gate.
25
+
26
+ ## Phase 3 — Resolve gate (once, before the first wave)
27
+
28
+ For each distinct tagged language (including `postgres` when any task is
29
+ `db`-tagged), resolve against the cache `.claude/orc/patterns/<lang>-pattern.md`
30
+ — test existence with the deterministic probe `orc pattern status <lang>`
31
+ (exit 0 = cached; see `../../_shared/detecting-artifacts.md`), never an ad-hoc
32
+ `find`, so a codified pattern is never missed:
33
+
34
+ Every resolved language prints exactly ONE user-visible line (no cost, no ask —
35
+ visibility only, so the user always knows which house style is in force):
36
+
37
+ - **Cache hit, no drift** → no ask, no cost, but print
38
+ `pattern: <lang>-pattern.md applied (cached)`.
39
+ - **Cache miss** → apply config `pattern_findings` (default `ask`):
40
+ - `ask` → ONE P0 prompt (H `orc.phase-3.pattern`) batched across ALL missing languages ("Learn
41
+ conventions for {…} via orc-pattern, or proceed language-agnostic?");
42
+ - `on` → codify without asking; print `pattern: <lang> — codifying (cache miss)`;
43
+ - `off` → agnostic; print `pattern: <lang> — running language-agnostic (no cached pattern)`.
44
+ - **On learn/`on`** → dispatch `orc-pattern-codifier-sonnet-5-high` per missing
45
+ language (`orc-pattern-codifier-opus-5-med` when `opus5_only` — see
46
+ `../../_shared/opus5-only.md`; slice per `../../orc-pattern/SKILL.md`
47
+ Phase 1); YOU write the returned pattern to the cache.
48
+ - **Agnostic fallback** (declined / `off` / no playbook for the language): no
49
+ codifier, no scan — the executor enforces the universal invariants and
50
+ imitates the neighbor files it already reads. ~Zero added cost.
51
+
52
+ Hold the resolved pattern per language in run state (survives
53
+ checkpoint/resume) — it is injected at dispatch and reused at Phase 5/6.
54
+
55
+ ## Slice injection (anti-skip layer 1)
56
+
57
+ Inject the resolved conventions + blocking invariants + the enforceable
58
+ `validation_gate[]` lines LITERALLY into each FE/BE task's slice as `pattern` —
59
+ never a file pointer. Agnostic tasks get the universal invariants only.
60
+
61
+ **Gotchas ride BESIDE the pattern block, never inside it** (config `gotchas`;
62
+ canonical `../../_shared/gotchas.md`). Same slice, same literal injection, one
63
+ hard difference: the pattern applies to a LANGUAGE, so it goes to every task
64
+ tagged with that language — a gotcha applies to a `scope` GLOB, so it goes only to
65
+ tasks whose `declared_files` match it, capped at 3, highest `hits` first. Zero
66
+ matches = no gotcha block at all. Never inject unfiltered: a pattern is what this
67
+ project always does, a gotcha is what it got wrong ONCE, somewhere specific.
68
+
69
+ For a `db:postgres`-tagged task, ALSO merge the resolved `postgres` pattern's
70
+ Conventions + Invariants + gate lines into the SAME `pattern` block (appended
71
+ to the framework pattern, or standalone if the task has no framework lang) —
72
+ query invariants (bound params only, pooled connections, transactional
73
+ multi-writes) ride the same anti-skip path. Record the postgres
74
+ `pattern_version` in run state/log too.
75
+
76
+ ## Return validation (anti-skip layer 2)
77
+
78
+ A task that was given a `pattern` must return `invariants_checked: true` + a
79
+ `pattern_version` matching what you injected — the single attestation covers a
80
+ merged block. Missing/false attestation = malformed return (requeue). Record
81
+ the applied `pattern_version` in the trace.
82
+
83
+ ## Review/verify re-check (anti-skip layer 3)
84
+
85
+ - **Phase 5 (review):** pass the resolved pattern as `code_pattern` AND its
86
+ blocking `invariants[]` + `validation_gate[]` lines for the re-check — don't
87
+ re-ask the user. An invariant violation or unmet gate line is P0.
88
+ - **Phase 6 (verify):** pass the `validation_gate[]` lines in the slice — each
89
+ line is an acceptance criterion; an unmet line is P0.