@azure-id/orc 0.56.1 → 1.0.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 (153) hide show
  1. package/CHANGELOG.md +2367 -2218
  2. package/README-id.md +49 -107
  3. package/README.md +45 -133
  4. package/bin/build-agents.js +18 -11
  5. package/bin/cli.js +33060 -29855
  6. package/bin/onboarding-content.js +0 -3
  7. package/bin/test-run.js +491 -0
  8. package/bin/verify-contracts.js +4256 -3277
  9. package/bin/verify-package.js +563 -498
  10. package/bin/webui/api.js +1186 -1163
  11. package/bin/webui/app.html +9 -0
  12. package/bin/webui/css/06-responsive.css +120 -108
  13. package/bin/webui/css/panels/extra.css +29 -0
  14. package/bin/webui/css/panels/lanes.css +134 -0
  15. package/bin/webui/css/panels/settings.css +79 -3
  16. package/bin/webui/fixtures/extra.js +2036 -1934
  17. package/bin/webui/fixtures/flow.js +2 -2
  18. package/bin/webui/fixtures/index.js +503 -486
  19. package/bin/webui/fixtures/lanes.js +218 -0
  20. package/bin/webui/fixtures/settings.js +261 -34
  21. package/bin/webui/fixtures/stats.js +3 -3
  22. package/bin/webui/i18n/TERMS.md +135 -134
  23. package/bin/webui/i18n/en/extra.json +345 -313
  24. package/bin/webui/i18n/en/lanes.json +29 -0
  25. package/bin/webui/i18n/en/nav.json +1 -0
  26. package/bin/webui/i18n/en/overview.json +2 -0
  27. package/bin/webui/i18n/en/settings.json +16 -5
  28. package/bin/webui/i18n/id/extra.json +345 -313
  29. package/bin/webui/i18n/id/lanes.json +29 -0
  30. package/bin/webui/i18n/id/nav.json +1 -0
  31. package/bin/webui/i18n/id/overview.json +2 -0
  32. package/bin/webui/i18n/id/settings.json +15 -4
  33. package/bin/webui/js/01-i18n.js +1 -0
  34. package/bin/webui/js/panels/extra.js +3199 -3011
  35. package/bin/webui/js/panels/lanes.js +259 -0
  36. package/bin/webui/js/panels/overview.js +10 -0
  37. package/bin/webui/js/panels/settings.js +149 -3
  38. package/package.json +39 -39
  39. package/templates/agents/MODEL-MAPPING.md +23 -35
  40. package/templates/agents/orc-executor-opus-4-7-high.md +1 -1
  41. package/templates/agents/orc-executor-opus-4-7-med.md +1 -1
  42. package/templates/agents/orc-executor-opus-4-8-high.md +1 -1
  43. package/templates/agents/orc-executor-opus-5-high.md +1 -1
  44. package/templates/agents/orc-executor-opus-5-low.md +1 -1
  45. package/templates/agents/orc-executor-opus-5-med.md +1 -1
  46. package/templates/agents/orc-retro-opus-5-med.md +73 -73
  47. package/templates/agents/orc-retro-sonnet-5-high.md +72 -72
  48. package/templates/agents/orc-trace-writer-haiku-4-5.md +107 -107
  49. package/templates/commands/orc-route.md +1 -1
  50. package/templates/commands/orc.md +1 -1
  51. package/templates/skills/_shared/README.md +7 -3
  52. package/templates/skills/_shared/config-precedence.md +198 -0
  53. package/templates/skills/_shared/drift-recovery.md +1 -1
  54. package/templates/skills/_shared/extra-dispatch.md +159 -7
  55. package/templates/skills/_shared/interview.md +1 -1
  56. package/templates/skills/_shared/opus5-only.md +9 -7
  57. package/templates/skills/_shared/phases/README.md +82 -0
  58. package/templates/skills/{orc/references → _shared/phases}/analyst-gates.md +15 -3
  59. package/templates/skills/_shared/phases/execution.md +143 -0
  60. package/templates/skills/{orc/references → _shared/phases}/house-rules.md +13 -1
  61. package/templates/skills/{orc/references → _shared/phases}/intake.md +15 -2
  62. package/templates/skills/_shared/phases/mock-example.md +56 -0
  63. package/templates/skills/{orc/references → _shared/phases}/plan-handoff.md +16 -3
  64. package/templates/skills/_shared/phases/planning.md +135 -0
  65. package/templates/skills/_shared/phases/preflight.md +76 -0
  66. package/templates/skills/_shared/phases/review.md +53 -0
  67. package/templates/skills/_shared/phases/scoring.md +65 -0
  68. package/templates/skills/{orc/references → _shared/phases}/security-checklist.md +12 -1
  69. package/templates/skills/_shared/phases/security.md +55 -0
  70. package/templates/skills/_shared/phases/ship.md +88 -0
  71. package/templates/skills/{orc/references/stop-and-resume.md → _shared/phases/stop-resume.md} +169 -160
  72. package/templates/skills/_shared/phases/summary.md +48 -0
  73. package/templates/skills/_shared/phases/testgen.md +51 -0
  74. package/templates/skills/{orc/references/trace-protocol.md → _shared/phases/trace.md} +49 -6
  75. package/templates/skills/_shared/phases/verify.md +70 -0
  76. package/templates/skills/{orc/references → _shared/phases}/wave-grouping.md +14 -2
  77. package/templates/skills/{orc/references → _shared/phases}/wiki-consult.md +13 -1
  78. package/templates/skills/_shared/read-ladder.md +48 -0
  79. package/templates/skills/context-combiner/SKILL.md +214 -187
  80. package/templates/skills/orc/README.md +148 -150
  81. package/templates/skills/orc/SKILL.md +70 -358
  82. package/templates/skills/orc/config.md +137 -389
  83. package/templates/skills/orc/examples/full-run-mock.md +1 -1
  84. package/templates/skills/orc/references/effort-and-mode.md +16 -18
  85. package/templates/skills/orc/references/phases/intake.md +47 -0
  86. package/templates/skills/orc/references/phases/integration.md +19 -0
  87. package/templates/skills/orc/references/preflight-report.md +4 -4
  88. package/templates/skills/orc/references/ultra-mode.md +117 -123
  89. package/templates/skills/orc/schemas/planning-output.md +279 -279
  90. package/templates/skills/orc/subskills/orc-planner/SKILL.md +260 -264
  91. package/templates/skills/orc/subskills/orc-pr/stack-gate.md +4 -1
  92. package/templates/skills/orc-aftermath/SKILL.md +153 -136
  93. package/templates/skills/orc-analyze/SKILL.md +247 -220
  94. package/templates/skills/orc-analyze/references/branching.md +51 -51
  95. package/templates/skills/orc-analyze/references/thin-input.md +1 -1
  96. package/templates/skills/orc-analyze-mini/SKILL.md +128 -112
  97. package/templates/skills/orc-boundary/SKILL.md +244 -208
  98. package/templates/skills/orc-brainstorm/SKILL.md +372 -339
  99. package/templates/skills/orc-budget/SKILL.md +243 -225
  100. package/templates/skills/orc-challenge/README.md +1 -1
  101. package/templates/skills/orc-challenge/SKILL.md +293 -255
  102. package/templates/skills/orc-challenge/examples/council-full-roster.md +1 -1
  103. package/templates/skills/orc-claude/SKILL.md +216 -199
  104. package/templates/skills/orc-diy/README.md +2 -1
  105. package/templates/skills/orc-diy/SKILL.md +129 -70
  106. package/templates/skills/orc-diy/references/blocks/analyze.md +1 -1
  107. package/templates/skills/orc-diy/references/compile.md +21 -7
  108. package/templates/skills/orc-diy/references/flow-schema.md +2 -2
  109. package/templates/skills/orc-doc/SKILL.md +44 -7
  110. package/templates/skills/orc-explain/SKILL.md +19 -0
  111. package/templates/skills/orc-export/SKILL.md +26 -5
  112. package/templates/skills/orc-fast/SKILL.md +215 -187
  113. package/templates/skills/orc-grill/SKILL.md +233 -207
  114. package/templates/skills/orc-handoff/SKILL.md +223 -204
  115. package/templates/skills/orc-learn/SKILL.md +176 -156
  116. package/templates/skills/orc-mini/SKILL.md +41 -23
  117. package/templates/skills/orc-pact/SKILL.md +250 -218
  118. package/templates/skills/orc-pattern/SKILL.md +149 -124
  119. package/templates/skills/orc-poly/SKILL.md +237 -216
  120. package/templates/skills/orc-poly/references/gather.md +1 -1
  121. package/templates/skills/orc-pr-driver/SKILL.md +196 -167
  122. package/templates/skills/orc-pr-driver/references/orc-run-split.md +1 -1
  123. package/templates/skills/orc-pr-setup/SKILL.md +212 -184
  124. package/templates/skills/orc-quick/README.md +2 -2
  125. package/templates/skills/orc-quick/SKILL.md +45 -12
  126. package/templates/skills/orc-quick/references/dispatch-gate.md +2 -3
  127. package/templates/skills/orc-retro/SKILL.md +244 -222
  128. package/templates/skills/orc-retro/examples/retro-mock.md +171 -171
  129. package/templates/skills/orc-route/SKILL.md +183 -165
  130. package/templates/skills/orc-verify/SKILL.md +100 -86
  131. package/templates/skills/orc-wiki/SKILL.md +55 -206
  132. package/templates/skills/orc-wiki/references/phases/phase-0.md +71 -0
  133. package/templates/skills/orc-wiki/references/phases/phase-1.md +35 -0
  134. package/templates/skills/orc-wiki/references/phases/phase-2.md +52 -0
  135. package/templates/skills/orc-wiki/references/phases/phase-3.md +57 -0
  136. package/templates/skills/orc-wiki/references/phases/phase-3c.md +36 -0
  137. package/templates/agents/orc-advisor-fable-5.md +0 -50
  138. package/templates/agents/orc-analyst-fable-5.md +0 -115
  139. package/templates/agents/orc-judge-fable-5.md +0 -79
  140. package/templates/agents/orc-planner-fable-5.md +0 -152
  141. package/templates/agents/orc-reviewer-fable-5.md +0 -57
  142. package/templates/skills/_shared/fable5-override.md +0 -56
  143. package/templates/skills/orc-diy/references/blocks/execution.md +0 -42
  144. package/templates/skills/orc-diy/references/blocks/mock-example.md +0 -22
  145. package/templates/skills/orc-diy/references/blocks/planning.md +0 -34
  146. package/templates/skills/orc-diy/references/blocks/review.md +0 -18
  147. package/templates/skills/orc-diy/references/blocks/scoring.md +0 -16
  148. package/templates/skills/orc-diy/references/blocks/security.md +0 -25
  149. package/templates/skills/orc-diy/references/blocks/ship.md +0 -25
  150. package/templates/skills/orc-diy/references/blocks/summary.md +0 -18
  151. package/templates/skills/orc-diy/references/blocks/testgen.md +0 -17
  152. package/templates/skills/orc-diy/references/blocks/trace.md +0 -28
  153. package/templates/skills/orc-diy/references/blocks/verify.md +0 -25
@@ -1,279 +1,279 @@
1
- # Schema — Planning Output (Phase 1)
2
-
3
- The single artifact planning produces. Everything downstream reads it: conflict
4
- graph, wave grouping, task scoring, checkpoint, dependency graph (forward =
5
- scheduling, reverse = stale-flagging), failure re-runs. Owned by the
6
- orchestrator; workers receive SLICES, never this whole object.
7
-
8
- YAML for readability; field names stable if serialized to JSON.
9
-
10
- ## Top level
11
-
12
- ```yaml
13
- run:
14
- id: string # "run-020726-1422"
15
- planner: enum # superpowers | openspec | orc
16
- effort: enum # low | medium | high (run-level → mode)
17
- execution_model: enum # sequential | parallel | parallel_worktrees (dispatch style; workers ALWAYS spawned)
18
- source_branch: string
19
- intent_spec: string # path: run/{run-slug}/intent-spec.md
20
- created_at: timestamp # DDMMYY HH:MM:SS.mmm
21
- plan_head: string # HEAD sha at plan time (mirror of the requirement-
22
- # spec's git_head). The plan-handoff entry contract
23
- # (references/plan-handoff.md) compares it to the
24
- # executing session's HEAD: a mismatch (or an absent
25
- # field, a pre-v0.31.0 plan) makes the Phase 1 exit
26
- # gate grounding spot-check COMPULSORY.
27
- plan_confidence: enum # high | medium | low (+ reason). Filled by the planner
28
- # (Part E). low → the orchestrator recommends
29
- # stepping back to orc-analyze before Phase 2.
30
-
31
- tasks: [ Task ]
32
- waves: [ Wave ] # planning may leave empty; orchestrator computes
33
- open_questions: [object] # [] or [{question, proposed_default, blocking: bool}]
34
- # — every ambiguity the planner met (Part E). The
35
- # orchestrator relays them in ONE batch after the
36
- # Phase 1 exit gate: blocking ones must be answered
37
- # before Phase 2; non-blocking show their default for
38
- # tacit approval.
39
- ```
40
-
41
- ## Task
42
-
43
- ```yaml
44
- - id: string # "T1" — referenced by depends_on and waves
45
- title: string
46
- description: string
47
- spec_ref: string|null # path to planner's prose spec ("openspec/x.md#section")
48
-
49
- owns_area: [string] # human-readable grouping (logs/summaries)
50
- declared_files: [string] # HARD GATE: actual files it will touch, incl. tests.
51
- # File-level globs. No declaration → no wave assignment.
52
- depends_on: [string] # forward = ordering; reverse = stale_review flagging
53
-
54
- # grounding attestation (filled by the PLANNER — one entry per declared path)
55
- grounding: [object] # {path, disposition: exists|new, evidence}
56
- # exists → the planner CONFIRMED the path this session
57
- # (evidence: "globbed" | "read" | the analyst spec's
58
- # file:line — copied through, never dropped)
59
- # new → a file to be created (evidence: the parent
60
- # dir confirmed to exist)
61
- # An ungrounded path is a MALFORMED plan — the
62
- # orchestrator spot-checks every `exists` path with
63
- # Glob at Phase 1 exit and bounces misses back (one
64
- # retry, then escalate). Plans from before v0.7.0
65
- # lack this field: resume them without the
66
- # spot-check, never bounce an old plan.
67
- acceptance: [string] # per-task acceptance criteria, sliced from the
68
- # intent-spec's definition-of-done. Each line CITES
69
- # its source ("R3" / "DoD#2") — a line with no
70
- # source is invented by definition and bounces.
71
- # Executors self-check against these before
72
- # returning; review/verify use them to localize
73
- # failures to a task instead of the whole diff.
74
-
75
- requirements: [string] # WHICH spec requirements this task implements —
76
- # R# ids (from-SA) or DoD line ids (direct intake).
77
- # [] allowed ONLY for pure-infra tasks WITH a stated
78
- # reason in description. Feeds the coverage gate:
79
- # every in-scope R#/DoD line must appear in ≥1
80
- # task's requirements[] — an orphan requirement is
81
- # a MALFORMED plan (bounced, one retry).
82
- spec_invariants: [string]# load-bearing lines copied VERBATIM from the spec's
83
- # Context & invariants (do not build) block into the
84
- # task(s) they guard. The orchestrator appends them
85
- # to the executor slice's constraints[] — hard rules
86
- # to respect, never tasks to build.
87
-
88
- # TDD anchor (v0.33.0 — filled by the PLANNER when the run's TDD policy is on:
89
- # full orc + ultra ALWAYS; orc-mini per its one intake question; orc-fast
90
- # never; orc-diy per its `tdd` flow key)
91
- #
92
- # v0.41.0 — TDD IS SCOPED TO WHAT CAN ACTUALLY FAIL. Every requirement used to
93
- # get a test unless it had "no runnable surface" (docs/config/markdown). A
94
- # translation map and a constant DO have a runnable surface, so the planner
95
- # correctly authored tests that only restated their own assignment: a
96
- # tautology that costs plan tokens, red-proof tokens and executor tokens and
97
- # asserts nothing. A pure file split was worse — it got brand-new tests when
98
- # the existing suite already proved the behavior was unchanged.
99
- tdd_spec: # per-requirement acceptance tests, authored AT PLAN
100
- # TIME — before any implementation
101
- - requirement: string # the R#/DoD line this test proves
102
- task: string # the implementation task id this entry belongs to
103
- # (v0.41.0) — TDD is materialized by a task PAIRED
104
- # with this one, so the entry must name its owner.
105
- disposition: enum # v0.41.0 — the CLOSED set below. Replaces the old
106
- # `exempt: string|null`, which had exactly one
107
- # escape and could not express the two cases that
108
- # actually matter. `kind` (v0.34.4) is retained as
109
- # the first two values, so no meaning is lost.
110
- #
111
- # TESTS ARE AUTHORED:
112
- # new-surface = the behavior does not exist
113
- # yet. MUST be red pre-implementation; passing is
114
- # a spec bug and blocks that requirement.
115
- # behavior-change = existing behavior intentionally
116
- # changes. Pairs a regression-guard (EXPECTED
117
- # green — its passing IS the assertion, blocks
118
- # nothing) with the new assertion (red first).
119
- #
120
- # NO TEST IS AUTHORED:
121
- # covered-by-existing = pure refactor/move/split.
122
- # The behavior is unchanged and an EXISTING test
123
- # already asserts it. REQUIRES `covered_by` — an
124
- # unverifiable claim here silently deletes
125
- # coverage, so the Phase-1 gate resolves the path
126
- # and bounces the plan if it does not exist.
127
- # no-behavior = declarative value only, where
128
- # a test could only restate the assignment:
129
- # constants, i18n/translation strings, docs,
130
- # config, markdown payloads. REQUIRES
131
- # facets.test_surface == none.
132
- # no-runner = the project has no test runner
133
- # at all → WHOLE-RUN exemption, stated once at
134
- # preflight (nothing silent); the smoke gate and
135
- # adversarial review carry verification.
136
- #
137
- # Absent (pre-v0.41.0 plan) → derive from `kind`;
138
- # absent `kind` too → new-surface.
139
- #
140
- # DEFAULT DERIVATION — the planner already produces
141
- # the facts this needs, so the disposition is
142
- # DERIVED, not judged, and a deviation is what needs
143
- # the reason:
144
- # test_surface: none + novelty: mechanical
145
- # -> no-behavior
146
- # test_surface: update-existing + novelty: mechanical
147
- # -> covered-by-existing
148
- # otherwise
149
- # -> new-surface | behavior-change
150
- #
151
- # SAFETY FLOOR (non-negotiable): a task whose
152
- # facets.risk[] is non-empty — auth, money,
153
- # migration, security, concurrency, data-integrity —
154
- # can NEVER be covered-by-existing or no-behavior.
155
- # A security invariant does not ride on another
156
- # test's coincidence.
157
- given_when_then: str # the scenario, given/when/then form. Required for
158
- # new-surface and behavior-change; omit otherwise.
159
- skeleton: string # runnable test skeleton in the PROJECT'S OWN test
160
- # framework (target file path + code) — the paired
161
- # TDD task materializes it into a real FAILING test.
162
- # Required for new-surface and behavior-change.
163
- covered_by: string # REQUIRED for covered-by-existing: `path:line` (or
164
- # `path::test name`) of the existing test that
165
- # already asserts this behavior. Must resolve — the
166
- # Phase-1 gate Globs it exactly as it does a
167
- # `disposition: exists` file.
168
- reason: string # REQUIRED for no-behavior and no-runner, and for any
169
- # disposition that DEVIATES from the derivation
170
- # table above. One line, plain language — it is
171
- # printed at preflight, so the user always sees what
172
- # was skipped and why.
173
-
174
- # scoring facets (filled by the PLANNER during grounding — the party that read
175
- # every declared file produces the FACTS; the orchestrator computes the score
176
- # arithmetically from them, so no number is judged from a task title. See
177
- # references/effort-and-mode.md for the fixed formula. The orchestrator
178
- # RECOMPUTES breadth + fan_in/fan_out from the plan and bounces a mismatch or
179
- # an uncited risk — same bounce mechanics as grounding.)
180
- facets: # object; absent ONLY on pre-v0.31.0 plans (resume
181
- # without the facet gate, score via the legacy path)
182
- breadth: int # = len(declared_files) — computed by the planner, not judged
183
- novelty: enum # mechanical | imitate | new-surface | novel-algorithm
184
- logic: enum # none | branching | stateful | algorithmic
185
- test_surface: enum # none | update-existing | new-tests
186
- risk: [object] # [] or [{class, cite}] — class ∈
187
- # auth|money|migration|security|concurrency|data-integrity;
188
- # cite = the file/requirement that makes it so (an
189
- # uncited risk entry is a MALFORMED plan → bounced).
190
- # risk ≠ [] forces the score floor of 70 (now DERIVED
191
- # from a cited facet, never remembered).
192
- uncertainty: enum # low | medium | high (+ one-line reason if not low)
193
- # fan_in / fan_out are NOT emitted here — the orchestrator computes them from
194
- # depends_on (forward = fan_in, reverse = fan_out) at Phase 2.
195
-
196
- # scoring (filled by orchestrator in Phase 2; ALWAYS — every task is scored)
197
- computed_score: int|null # 0–100 (facet formula, clamped)
198
- override_score: int|null # orchestrator override (requires reason)
199
- override_reason: string|null
200
- model: string|null # from the ladder — never null at dispatch time
201
- model_effort: string|null
202
-
203
- # runtime (filled by orchestrator during Phase 3)
204
- agent: string|null
205
- wave: int|null
206
- worktree: string|null # subagent_worktrees mode only
207
- status: enum # pending | running | done | failed | partial |
208
- # requeued | stale_review | needs_context
209
- failure_reason: string|null # the WHY — re-runs read this
210
- retry_count: int # hard cap 2
211
- context_requests: int # needs_context count — hard cap 2
212
- stale_cause: string|null # set when status=stale_review
213
- progress: object|null # {percent, files_written[], notes} — from
214
- # milestone pings; bounds mid-wave stop recovery
215
- actual_files: [string]|null # returned by worker; audited vs declared_files
216
- ```
217
-
218
- ## Wave
219
-
220
- ```yaml
221
- - number: int
222
- task_ids: [string] # zero declared_files overlap within a wave
223
- agents: int
224
- is_batch_pause: bool # recomputed from the Phase 2 pause schedule: true
225
- # when wave.number % N == 0 AND a later wave exists
226
- # (last wave is never a pause). A true here is a HARD
227
- # stop gate (stop-and-resume.md), not a hint.
228
- ```
229
-
230
- ## Status semantics
231
-
232
- - `requeued` ≠ `stale_review`. requeued = "I failed, run me again (reading my
233
- failure_reason)". stale_review = "my upstream changed; give me a cheap review
234
- pass — escalate to re-run only if actually broken."
235
- - `needs_context` = worker paused asking for a context re-slice; orchestrator
236
- adjudicates (in-scope for its area?), re-slices or treats as a planning
237
- correction (add the missing depends_on edge).
238
-
239
- ## Settled decisions (locked)
240
-
241
- 1. `declared_files` = file-level globs (symbol-level deferred).
242
- 2. `owns_area` kept for readability; `declared_files` does the conflict work.
243
- 3. Planner prose referenced via `spec_ref`, never inlined.
244
- 4. `grounding` is a per-file ATTESTATION, not prose: the planner states how each
245
- path was confirmed, and the orchestrator deterministically spot-checks it
246
- (instruction → contract → attestation → spot-check). `declared_files` stays a
247
- plain string list so the conflict graph and waves read it unchanged.
248
- 5. `requirements` + the coverage echo make plan COMPLETENESS checkable the same
249
- way `grounding` made paths checkable. The planner returns `coverage:
250
- {requirements: N, tasks: M, orphans: []}` (self-attested); the orchestrator
251
- independently recomputes it at Phase 1 exit — spec R# set vs the union of
252
- task `requirements[]` — and bounces orphans. Cycle detection + same-file
253
- collision re-run at the same gate (deterministic, trivial at ≤20 tasks)
254
- instead of being trusted to the planner's self-check.
255
- 6. `spec_invariants` paves the last mile of the analyst's do-not-build context:
256
- an invariant that reaches a task field demonstrably reaches the executor's
257
- `constraints[]`; one that lives only in the spec's prose may not.
258
- 7. `tdd_spec` (v0.33.0) anchors the definition-of-done in RUNNABLE tests before
259
- implementation. **A test that PASSES pre-implementation is a spec bug and
260
- blocks dispatch of that requirement** until resolved — for `new-surface`
261
- entries only; a `behavior-change` entry's regression-guard half is EXPECTED
262
- green. TDD tests are pipeline-internal, DO run, and live in the project's
263
- normal test tree (they ship with the code) — distinct from Phase 6.5's
264
- `test-generator/` deliverables, which are a separate opt-in that never runs.
265
- 8. **TDD is a PAIRED TASK, not a Wave 0 (v0.41.0).** The single synthesized
266
- Wave-0 task that materialized every skeleton at once is gone. For each
267
- implementation task carrying `new-surface` or `behavior-change` entries, the
268
- planner emits a SEPARATE task — `id`, `title` (`TDD: <what it proves>`),
269
- `declared_files` = just that task's test files, `owns_area` = the impl task's
270
- area — and the implementation task lists it in `depends_on`.
271
-
272
- These are ORDINARY tasks: they flow through the normal conflict graph and
273
- wave grouping, they are scored from their own facets, and `max_wave_tasks` /
274
- `is_batch_pause` / `pause_schedule` bind to them unchanged. So **independent
275
- TDD tasks share a wave and run in parallel**, while `depends_on` guarantees
276
- **a red proof never lands in the same wave as the code it proves**.
277
-
278
- **If no task needs TDD, no TDD task is emitted at all** — a plan of pure
279
- constants, translations and file moves runs with zero red-proof cost.
1
+ # Schema — Planning Output (Phase 1)
2
+
3
+ The single artifact planning produces. Everything downstream reads it: conflict
4
+ graph, wave grouping, task scoring, checkpoint, dependency graph (forward =
5
+ scheduling, reverse = stale-flagging), failure re-runs. Owned by the
6
+ orchestrator; workers receive SLICES, never this whole object.
7
+
8
+ YAML for readability; field names stable if serialized to JSON.
9
+
10
+ ## Top level
11
+
12
+ ```yaml
13
+ run:
14
+ id: string # "run-020726-1422"
15
+ planner: enum # superpowers | openspec | orc
16
+ effort: enum # low | medium | high (run-level → mode)
17
+ execution_model: enum # sequential | parallel | parallel_worktrees (dispatch style; workers ALWAYS spawned)
18
+ source_branch: string
19
+ intent_spec: string # path: run/{run-slug}/intent-spec.md
20
+ created_at: timestamp # DDMMYY HH:MM:SS.mmm
21
+ plan_head: string # HEAD sha at plan time (mirror of the requirement-
22
+ # spec's git_head). The plan-handoff entry contract
23
+ # (../../_shared/phases/plan-handoff.md) compares it to the
24
+ # executing session's HEAD: a mismatch (or an absent
25
+ # field, a pre-v0.31.0 plan) makes the Phase 1 exit
26
+ # gate grounding spot-check COMPULSORY.
27
+ plan_confidence: enum # high | medium | low (+ reason). Filled by the planner
28
+ # (Part E). low → the orchestrator recommends
29
+ # stepping back to orc-analyze before Phase 2.
30
+
31
+ tasks: [ Task ]
32
+ waves: [ Wave ] # planning may leave empty; orchestrator computes
33
+ open_questions: [object] # [] or [{question, proposed_default, blocking: bool}]
34
+ # — every ambiguity the planner met (Part E). The
35
+ # orchestrator relays them in ONE batch after the
36
+ # Phase 1 exit gate: blocking ones must be answered
37
+ # before Phase 2; non-blocking show their default for
38
+ # tacit approval.
39
+ ```
40
+
41
+ ## Task
42
+
43
+ ```yaml
44
+ - id: string # "T1" — referenced by depends_on and waves
45
+ title: string
46
+ description: string
47
+ spec_ref: string|null # path to planner's prose spec ("openspec/x.md#section")
48
+
49
+ owns_area: [string] # human-readable grouping (logs/summaries)
50
+ declared_files: [string] # HARD GATE: actual files it will touch, incl. tests.
51
+ # File-level globs. No declaration → no wave assignment.
52
+ depends_on: [string] # forward = ordering; reverse = stale_review flagging
53
+
54
+ # grounding attestation (filled by the PLANNER — one entry per declared path)
55
+ grounding: [object] # {path, disposition: exists|new, evidence}
56
+ # exists → the planner CONFIRMED the path this session
57
+ # (evidence: "globbed" | "read" | the analyst spec's
58
+ # file:line — copied through, never dropped)
59
+ # new → a file to be created (evidence: the parent
60
+ # dir confirmed to exist)
61
+ # An ungrounded path is a MALFORMED plan — the
62
+ # orchestrator spot-checks every `exists` path with
63
+ # Glob at Phase 1 exit and bounces misses back (one
64
+ # retry, then escalate). Plans from before v0.7.0
65
+ # lack this field: resume them without the
66
+ # spot-check, never bounce an old plan.
67
+ acceptance: [string] # per-task acceptance criteria, sliced from the
68
+ # intent-spec's definition-of-done. Each line CITES
69
+ # its source ("R3" / "DoD#2") — a line with no
70
+ # source is invented by definition and bounces.
71
+ # Executors self-check against these before
72
+ # returning; review/verify use them to localize
73
+ # failures to a task instead of the whole diff.
74
+
75
+ requirements: [string] # WHICH spec requirements this task implements —
76
+ # R# ids (from-SA) or DoD line ids (direct intake).
77
+ # [] allowed ONLY for pure-infra tasks WITH a stated
78
+ # reason in description. Feeds the coverage gate:
79
+ # every in-scope R#/DoD line must appear in ≥1
80
+ # task's requirements[] — an orphan requirement is
81
+ # a MALFORMED plan (bounced, one retry).
82
+ spec_invariants: [string]# load-bearing lines copied VERBATIM from the spec's
83
+ # Context & invariants (do not build) block into the
84
+ # task(s) they guard. The orchestrator appends them
85
+ # to the executor slice's constraints[] — hard rules
86
+ # to respect, never tasks to build.
87
+
88
+ # TDD anchor (v0.33.0 — filled by the PLANNER when the run's TDD policy is on:
89
+ # full orc + ultra ALWAYS; orc-mini per its one intake question; orc-fast
90
+ # never; orc-diy per its `tdd` flow key)
91
+ #
92
+ # v0.41.0 — TDD IS SCOPED TO WHAT CAN ACTUALLY FAIL. Every requirement used to
93
+ # get a test unless it had "no runnable surface" (docs/config/markdown). A
94
+ # translation map and a constant DO have a runnable surface, so the planner
95
+ # correctly authored tests that only restated their own assignment: a
96
+ # tautology that costs plan tokens, red-proof tokens and executor tokens and
97
+ # asserts nothing. A pure file split was worse — it got brand-new tests when
98
+ # the existing suite already proved the behavior was unchanged.
99
+ tdd_spec: # per-requirement acceptance tests, authored AT PLAN
100
+ # TIME — before any implementation
101
+ - requirement: string # the R#/DoD line this test proves
102
+ task: string # the implementation task id this entry belongs to
103
+ # (v0.41.0) — TDD is materialized by a task PAIRED
104
+ # with this one, so the entry must name its owner.
105
+ disposition: enum # v0.41.0 — the CLOSED set below. Replaces the old
106
+ # `exempt: string|null`, which had exactly one
107
+ # escape and could not express the two cases that
108
+ # actually matter. `kind` (v0.34.4) is retained as
109
+ # the first two values, so no meaning is lost.
110
+ #
111
+ # TESTS ARE AUTHORED:
112
+ # new-surface = the behavior does not exist
113
+ # yet. MUST be red pre-implementation; passing is
114
+ # a spec bug and blocks that requirement.
115
+ # behavior-change = existing behavior intentionally
116
+ # changes. Pairs a regression-guard (EXPECTED
117
+ # green — its passing IS the assertion, blocks
118
+ # nothing) with the new assertion (red first).
119
+ #
120
+ # NO TEST IS AUTHORED:
121
+ # covered-by-existing = pure refactor/move/split.
122
+ # The behavior is unchanged and an EXISTING test
123
+ # already asserts it. REQUIRES `covered_by` — an
124
+ # unverifiable claim here silently deletes
125
+ # coverage, so the Phase-1 gate resolves the path
126
+ # and bounces the plan if it does not exist.
127
+ # no-behavior = declarative value only, where
128
+ # a test could only restate the assignment:
129
+ # constants, i18n/translation strings, docs,
130
+ # config, markdown payloads. REQUIRES
131
+ # facets.test_surface == none.
132
+ # no-runner = the project has no test runner
133
+ # at all → WHOLE-RUN exemption, stated once at
134
+ # preflight (nothing silent); the smoke gate and
135
+ # adversarial review carry verification.
136
+ #
137
+ # Absent (pre-v0.41.0 plan) → derive from `kind`;
138
+ # absent `kind` too → new-surface.
139
+ #
140
+ # DEFAULT DERIVATION — the planner already produces
141
+ # the facts this needs, so the disposition is
142
+ # DERIVED, not judged, and a deviation is what needs
143
+ # the reason:
144
+ # test_surface: none + novelty: mechanical
145
+ # -> no-behavior
146
+ # test_surface: update-existing + novelty: mechanical
147
+ # -> covered-by-existing
148
+ # otherwise
149
+ # -> new-surface | behavior-change
150
+ #
151
+ # SAFETY FLOOR (non-negotiable): a task whose
152
+ # facets.risk[] is non-empty — auth, money,
153
+ # migration, security, concurrency, data-integrity —
154
+ # can NEVER be covered-by-existing or no-behavior.
155
+ # A security invariant does not ride on another
156
+ # test's coincidence.
157
+ given_when_then: str # the scenario, given/when/then form. Required for
158
+ # new-surface and behavior-change; omit otherwise.
159
+ skeleton: string # runnable test skeleton in the PROJECT'S OWN test
160
+ # framework (target file path + code) — the paired
161
+ # TDD task materializes it into a real FAILING test.
162
+ # Required for new-surface and behavior-change.
163
+ covered_by: string # REQUIRED for covered-by-existing: `path:line` (or
164
+ # `path::test name`) of the existing test that
165
+ # already asserts this behavior. Must resolve — the
166
+ # Phase-1 gate Globs it exactly as it does a
167
+ # `disposition: exists` file.
168
+ reason: string # REQUIRED for no-behavior and no-runner, and for any
169
+ # disposition that DEVIATES from the derivation
170
+ # table above. One line, plain language — it is
171
+ # printed at preflight, so the user always sees what
172
+ # was skipped and why.
173
+
174
+ # scoring facets (filled by the PLANNER during grounding — the party that read
175
+ # every declared file produces the FACTS; the orchestrator computes the score
176
+ # arithmetically from them, so no number is judged from a task title. See
177
+ # references/effort-and-mode.md for the fixed formula. The orchestrator
178
+ # RECOMPUTES breadth + fan_in/fan_out from the plan and bounces a mismatch or
179
+ # an uncited risk — same bounce mechanics as grounding.)
180
+ facets: # object; absent ONLY on pre-v0.31.0 plans (resume
181
+ # without the facet gate, score via the legacy path)
182
+ breadth: int # = len(declared_files) — computed by the planner, not judged
183
+ novelty: enum # mechanical | imitate | new-surface | novel-algorithm
184
+ logic: enum # none | branching | stateful | algorithmic
185
+ test_surface: enum # none | update-existing | new-tests
186
+ risk: [object] # [] or [{class, cite}] — class ∈
187
+ # auth|money|migration|security|concurrency|data-integrity;
188
+ # cite = the file/requirement that makes it so (an
189
+ # uncited risk entry is a MALFORMED plan → bounced).
190
+ # risk ≠ [] forces the score floor of 70 (now DERIVED
191
+ # from a cited facet, never remembered).
192
+ uncertainty: enum # low | medium | high (+ one-line reason if not low)
193
+ # fan_in / fan_out are NOT emitted here — the orchestrator computes them from
194
+ # depends_on (forward = fan_in, reverse = fan_out) at Phase 2.
195
+
196
+ # scoring (filled by orchestrator in Phase 2; ALWAYS — every task is scored)
197
+ computed_score: int|null # 0–100 (facet formula, clamped)
198
+ override_score: int|null # orchestrator override (requires reason)
199
+ override_reason: string|null
200
+ model: string|null # from the ladder — never null at dispatch time
201
+ model_effort: string|null
202
+
203
+ # runtime (filled by orchestrator during Phase 3)
204
+ agent: string|null
205
+ wave: int|null
206
+ worktree: string|null # subagent_worktrees mode only
207
+ status: enum # pending | running | done | failed | partial |
208
+ # requeued | stale_review | needs_context
209
+ failure_reason: string|null # the WHY — re-runs read this
210
+ retry_count: int # hard cap 2
211
+ context_requests: int # needs_context count — hard cap 2
212
+ stale_cause: string|null # set when status=stale_review
213
+ progress: object|null # {percent, files_written[], notes} — from
214
+ # milestone pings; bounds mid-wave stop recovery
215
+ actual_files: [string]|null # returned by worker; audited vs declared_files
216
+ ```
217
+
218
+ ## Wave
219
+
220
+ ```yaml
221
+ - number: int
222
+ task_ids: [string] # zero declared_files overlap within a wave
223
+ agents: int
224
+ is_batch_pause: bool # recomputed from the Phase 2 pause schedule: true
225
+ # when wave.number % N == 0 AND a later wave exists
226
+ # (last wave is never a pause). A true here is a HARD
227
+ # stop gate (stop-resume.md), not a hint.
228
+ ```
229
+
230
+ ## Status semantics
231
+
232
+ - `requeued` ≠ `stale_review`. requeued = "I failed, run me again (reading my
233
+ failure_reason)". stale_review = "my upstream changed; give me a cheap review
234
+ pass — escalate to re-run only if actually broken."
235
+ - `needs_context` = worker paused asking for a context re-slice; orchestrator
236
+ adjudicates (in-scope for its area?), re-slices or treats as a planning
237
+ correction (add the missing depends_on edge).
238
+
239
+ ## Settled decisions (locked)
240
+
241
+ 1. `declared_files` = file-level globs (symbol-level deferred).
242
+ 2. `owns_area` kept for readability; `declared_files` does the conflict work.
243
+ 3. Planner prose referenced via `spec_ref`, never inlined.
244
+ 4. `grounding` is a per-file ATTESTATION, not prose: the planner states how each
245
+ path was confirmed, and the orchestrator deterministically spot-checks it
246
+ (instruction → contract → attestation → spot-check). `declared_files` stays a
247
+ plain string list so the conflict graph and waves read it unchanged.
248
+ 5. `requirements` + the coverage echo make plan COMPLETENESS checkable the same
249
+ way `grounding` made paths checkable. The planner returns `coverage:
250
+ {requirements: N, tasks: M, orphans: []}` (self-attested); the orchestrator
251
+ independently recomputes it at Phase 1 exit — spec R# set vs the union of
252
+ task `requirements[]` — and bounces orphans. Cycle detection + same-file
253
+ collision re-run at the same gate (deterministic, trivial at ≤20 tasks)
254
+ instead of being trusted to the planner's self-check.
255
+ 6. `spec_invariants` paves the last mile of the analyst's do-not-build context:
256
+ an invariant that reaches a task field demonstrably reaches the executor's
257
+ `constraints[]`; one that lives only in the spec's prose may not.
258
+ 7. `tdd_spec` (v0.33.0) anchors the definition-of-done in RUNNABLE tests before
259
+ implementation. **A test that PASSES pre-implementation is a spec bug and
260
+ blocks dispatch of that requirement** until resolved — for `new-surface`
261
+ entries only; a `behavior-change` entry's regression-guard half is EXPECTED
262
+ green. TDD tests are pipeline-internal, DO run, and live in the project's
263
+ normal test tree (they ship with the code) — distinct from Phase 6.5's
264
+ `test-generator/` deliverables, which are a separate opt-in that never runs.
265
+ 8. **TDD is a PAIRED TASK, not a Wave 0 (v0.41.0).** The single synthesized
266
+ Wave-0 task that materialized every skeleton at once is gone. For each
267
+ implementation task carrying `new-surface` or `behavior-change` entries, the
268
+ planner emits a SEPARATE task — `id`, `title` (`TDD: <what it proves>`),
269
+ `declared_files` = just that task's test files, `owns_area` = the impl task's
270
+ area — and the implementation task lists it in `depends_on`.
271
+
272
+ These are ORDINARY tasks: they flow through the normal conflict graph and
273
+ wave grouping, they are scored from their own facets, and `max_wave_tasks` /
274
+ `is_batch_pause` / `pause_schedule` bind to them unchanged. So **independent
275
+ TDD tasks share a wave and run in parallel**, while `depends_on` guarantees
276
+ **a red proof never lands in the same wave as the code it proves**.
277
+
278
+ **If no task needs TDD, no TDD task is emitted at all** — a plan of pure
279
+ constants, translations and file moves runs with zero red-proof cost.