@pilotspace/add 1.17.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/GETTING-STARTED.md +20 -64
  3. package/README.md +138 -158
  4. package/agents/add-advisor.md +66 -21
  5. package/agents/add-worker.md +102 -0
  6. package/bin/cli.js +88 -21
  7. package/package.json +2 -3
  8. package/personas-teacher/VENDOR.md +6 -0
  9. package/skill/add/SKILL.md +100 -144
  10. package/skill/add/adopt.md +28 -0
  11. package/skill/add/beyond.md +37 -0
  12. package/skill/add/deltas.md +25 -2
  13. package/skill/add/design.md +56 -74
  14. package/skill/add/{report-template.md → gate-udd.md} +28 -38
  15. package/skill/add/intake.md +56 -25
  16. package/skill/add/loop.md +32 -19
  17. package/skill/add/persona-author/SKILL.md +116 -0
  18. package/skill/add/persona-author/assets/example-design-persona.md +55 -0
  19. package/skill/add/persona-author/assets/example-persona.md +57 -0
  20. package/skill/add/persona-author/references/contract.md +69 -0
  21. package/skill/add/persona-author/references/patterns.md +122 -0
  22. package/skill/add/persona-author/references/seeding.md +79 -0
  23. package/skill/add/phases/build.md +79 -0
  24. package/skill/add/phases/direction.md +287 -0
  25. package/skill/add/phases/verify.md +161 -0
  26. package/skill/add/run.md +16 -18
  27. package/skill/add/terms.md +18 -0
  28. package/tooling/add.py +2421 -3258
  29. package/tooling/add_engine/autonomy.py +2 -37
  30. package/tooling/add_engine/components.py +4 -87
  31. package/tooling/add_engine/constants.py +148 -93
  32. package/tooling/add_engine/guidelines.py +10 -11
  33. package/tooling/add_engine/io_state.py +72 -5
  34. package/tooling/add_engine/predicates.py +90 -2
  35. package/tooling/add_engine/search.py +6 -6
  36. package/tooling/add_engine/taskdoc.py +15 -10
  37. package/tooling/templates/CONVENTIONS.md.tmpl +1 -1
  38. package/tooling/templates/GLOSSARY.md.tmpl +10 -4
  39. package/tooling/templates/MILESTONE.md.tmpl +20 -16
  40. package/tooling/templates/PLAN.md.tmpl +129 -0
  41. package/tooling/templates/PROJECT.md.tmpl +6 -1
  42. package/tooling/templates/PROMPT.persona.md.tmpl +17 -21
  43. package/tooling/templates/personas/build-engineer.md.tmpl +45 -0
  44. package/tooling/templates/personas/data-steward.md.tmpl +45 -0
  45. package/tooling/templates/personas/evidence-verifier.md.tmpl +45 -0
  46. package/tooling/templates/personas/platform-engineer.md.tmpl +45 -0
  47. package/tooling/templates/personas/product-lead.md.tmpl +51 -0
  48. package/tooling/templates/personas/quality-auditor.md.tmpl +47 -0
  49. package/tooling/templates/personas/release-manager.md.tmpl +52 -0
  50. package/tooling/templates/personas/security-gatekeeper.md.tmpl +45 -0
  51. package/tooling/templates/personas/software-architect.md.tmpl +45 -0
  52. package/tooling/templates/personas/stream-orchestrator.md.tmpl +44 -0
  53. package/tooling/templates/personas/technical-writer.md.tmpl +49 -0
  54. package/tooling/templates/personas/ux-experience-lead.md.tmpl +48 -0
  55. package/tooling/templates/specs/SPEC.md.tmpl +18 -0
  56. package/tooling/templates/udd-wireframe.md +1 -1
  57. package/agents/add-build.md +0 -29
  58. package/agents/add-design.md +0 -32
  59. package/agents/add-persona.md +0 -33
  60. package/agents/add-verify.md +0 -36
  61. package/docs/00-introduction.md +0 -46
  62. package/docs/01-principles.md +0 -71
  63. package/docs/02-the-flow.md +0 -113
  64. package/docs/03-step-1-specify.md +0 -123
  65. package/docs/04-step-2-scenarios.md +0 -90
  66. package/docs/05-step-3-contract.md +0 -80
  67. package/docs/06-step-4-tests.md +0 -85
  68. package/docs/07-step-5-build.md +0 -82
  69. package/docs/08-step-6-verify.md +0 -105
  70. package/docs/09-the-loop.md +0 -75
  71. package/docs/10-setup-and-stages.md +0 -118
  72. package/docs/11-governance.md +0 -91
  73. package/docs/12-roles.md +0 -99
  74. package/docs/13-adoption.md +0 -67
  75. package/docs/14-foundation.md +0 -142
  76. package/docs/15-foundations-and-lineage.md +0 -106
  77. package/docs/16-releasing.md +0 -182
  78. package/docs/17-components.md +0 -143
  79. package/docs/18-personas.md +0 -80
  80. package/docs/README.md +0 -77
  81. package/docs/add-competencies.png +0 -0
  82. package/docs/add-flow.png +0 -0
  83. package/docs/add-foundation.png +0 -0
  84. package/docs/add-hierarchy.png +0 -0
  85. package/docs/add-milestone-task-lifecycle.png +0 -0
  86. package/docs/add-task-growth-wheel.png +0 -0
  87. package/docs/appendix-a-templates.md +0 -88
  88. package/docs/appendix-b-prompts.md +0 -154
  89. package/docs/appendix-c-glossary.md +0 -176
  90. package/docs/appendix-d-worked-example.md +0 -231
  91. package/docs/appendix-e-checklists.md +0 -92
  92. package/docs/appendix-f-requirements-matrix.md +0 -171
  93. package/docs/appendix-g-references.md +0 -106
  94. package/skill/add/advisor.md +0 -81
  95. package/skill/add/compact-foundation.md +0 -40
  96. package/skill/add/components.md +0 -52
  97. package/skill/add/confidence.md +0 -32
  98. package/skill/add/fold.md +0 -63
  99. package/skill/add/graduate.md +0 -39
  100. package/skill/add/phases/0-ground.md +0 -64
  101. package/skill/add/phases/0-setup.md +0 -103
  102. package/skill/add/phases/1-specify.md +0 -61
  103. package/skill/add/phases/2-scenarios.md +0 -48
  104. package/skill/add/phases/3-contract.md +0 -60
  105. package/skill/add/phases/4-tests.md +0 -61
  106. package/skill/add/phases/5-build.md +0 -62
  107. package/skill/add/phases/6-verify.md +0 -69
  108. package/skill/add/phases/7-observe.md +0 -45
  109. package/skill/add/phases/fast-lane.md +0 -34
  110. package/skill/add/release.md +0 -61
  111. package/skill/add/scope.md +0 -72
  112. package/skill/add/self-improve.md +0 -20
  113. package/skill/add/sensitivity.md +0 -51
  114. package/skill/add/setup-review.md +0 -48
  115. package/skill/add/soul.md +0 -58
  116. package/skill/add/streams.md +0 -269
  117. package/tooling/add_engine/release.py +0 -86
  118. package/tooling/templates/TASK.fast.md.tmpl +0 -78
  119. package/tooling/templates/TASK.md.tmpl +0 -181
  120. package/tooling/templates/personas/_template.md.tmpl +0 -82
@@ -1,269 +0,0 @@
1
- # Parallel streams — pipelining independent tasks
2
-
3
- Load this when a milestone has more than one task and you want to run them concurrently.
4
- **Default:** `sequential + auto` is the project default at setup (`phases/0-setup.md` "Run
5
- mode") — one task at a time, but Verify still auto-PASSes on evidence. Parallel streaming is an
6
- **opt-in** for a milestone with genuinely independent tasks: `add.py streams set parallel
7
- --project`, then read on. A project that raised its gate to `conservative`/`manual` still treats
8
- this rubric as the same opt-in escape hatch.
9
-
10
- It changes **no `add.py` code and no phase semantics**. It is a way *you, the orchestrator*,
11
- drive several tasks at once by reading the dependency DAG `add.py status` already prints and
12
- spawning one worker per ready task.
13
-
14
- ## The honest frame — this is pipelining, not N× speed
15
-
16
- With **one human reviewer** you cannot beat `review_time × N_tasks` (decision points are serial).
17
- The win: the reviewer is **never blocked waiting on a build** — builds for B·C·D run behind *their*
18
- frozen contracts while the human reviews A. Build latency hides under human latency.
19
-
20
- ## The two queues
21
-
22
- Both from one `add.py status` — no new state:
23
-
24
- - **READY-QUEUE** — tasks where `phase ≠ done` **and** every `deps=` task shows `gate=PASS`.
25
- Unmet deps stay queued; a PASS unblocks dependents.
26
- - **REVIEW-QUEUE** — the serial part: **bundle approval** (contract freeze) + any **Verify
27
- escalation**. One human, one queue; present one at a time, never batched.
28
-
29
- ```
30
- add.py status ─► READY-QUEUE ──spawn workers──► builds run ──► REVIEW-QUEUE ──► done
31
- (deps=PASS?) (machine span) (concurrent) (decision points, serial)
32
-
33
- └──────── a task gating PASS unblocks its dependents ──────────────────────────┘
34
- ```
35
-
36
- ## The DAG strategy — let the engine schedule the waves (`add.py waves`)
37
-
38
- Do **not** eyeball the READY-QUEUE by hand once a milestone has more than a couple of tasks.
39
- `add.py waves` (read-only) groups not-done tasks into **topological waves**, names the **critical
40
- path**, and emits an advisory **tier hint**:
41
-
42
- ```
43
- $ add.py waves
44
- milestone: v13-onboarding-polish
45
- wave 1: dag-scheduler, setup-suggest-milestone, setup-domain-deepdive, soul-artifact
46
- wave 2: setup-run-mode (deps: dag-scheduler), soul-self-improve (deps: soul-artifact)
47
- critical path: dag-scheduler → setup-run-mode (2 tasks)
48
- tier hint: top → dag-scheduler, setup-run-mode; mid → the rest
49
- ```
50
-
51
- - **Wave = a fan-out batch.** Every task in a wave has all in-milestone deps PASS, so the whole
52
- wave is spawnable at once — worktree isolation is the default for any spawn, not just a wave.
53
- Finish a wave, gate tasks PASS, then `add.py waves` again — the next wave is unblocked.
54
- - **Run the widest wave first** to hide the most build latency under human review latency.
55
- - **Spend your strongest model on the critical path.** Critical-path tasks gate the most
56
- downstream work; off-path tasks take **mid**. The tier hint is advisory — override when you
57
- know a task is harder than its position suggests.
58
- - **Prefer the named roster per worker** — `add-build` for a tests/build-phase worker, `add-design`
59
- for design-phase, `add-verify` for verify-phase (full roster + when-to-spawn in advisor.md) — over
60
- a generic ad-hoc spawn.
61
- - **`--json`** (`{ milestone, waves, critical_path, critical_path_len, tiers, blocked }`) feeds
62
- a runner that spawns programmatically. `blocked` lists tasks whose dep cannot be satisfied
63
- within this milestone; a `dependency_cycle` is refused with the offending members named.
64
-
65
- The irreducible floor holds — `waves` decides *order and model*, never *whether the human gate fires*.
66
-
67
- ## The autonomy level is the throttle (not a new flag)
68
-
69
- | `autonomy` (TASK.md) | What serializes on the human | Concurrency |
70
- |----------------------|------------------------------|-------------|
71
- | `conservative` / `manual` | bundle approval **+** every Verify | pure pipelining — builds overlap, both gates queue |
72
- | `auto` (default) | bundle approval **only**; Verify auto-PASSes on evidence | real concurrency — only the decision point + residue escalations queue |
73
- | `auto` but **high-risk** | refused → must lower (`unguarded_high_risk_auto`) | back to pipelining, by design |
74
-
75
- The irreducible floor is **one human approval per task at the contract decision point** — that
76
- floor never drops to zero (`run.md:22`). Do not engineer around it.
77
-
78
- ## Who writes what — the hard boundary
79
-
80
- <constraints>
81
- - **You (orchestrator)** own all shared writes: `MILESTONE.md`, and every `add.py advance <slug>` /
82
- `add.py gate <outcome> <slug>` call. Always pass the explicit `<slug>` — **name the task every time** —
83
- omitting it falls back to the single `active_task`, which races once more than one stream is live.
84
- Workers never run these.
85
- - **A worker** owns only its own `.add/tasks/<slug>/` — it builds `src/`, drives tests green,
86
- gathers evidence, and writes `SUMMARY.md` + OBSERVE deltas. It touches **no sibling stream and
87
- no shared file** — never write shared state (state.json, MILESTONE.md, a sibling's files).
88
- - **Isolation**: `isolation="worktree"` is the default for any agent-spawned step, not only a
89
- wave — a shared-tree spawn needs a stated reason. The worktree is discarded on failure; the task
90
- resets to its last-good phase.
91
- </constraints>
92
-
93
- ## Design for failure (required)
94
-
95
- - **Fresh worktree base (verify base == HEAD)** — cut each worktree from current `HEAD` **after**
96
- committing the frozen bundle; confirm `git -C <worktree> rev-parse HEAD` equals the orchestrator's
97
- `HEAD` (drifted → `git merge` first). On a pool runner (e.g. Claude Code) the check **shifts** to
98
- the worker's **step-0** (sync + re-echo `rev-parse HEAD`), verified at **merge-time**. The engine
99
- gates this (`engine-merge-base-enforcement`): `add.py wave-verify` before the first merge-back
100
- refuses a mismatched/pending echo (`unverified_fork_base`) or off-template ledger
101
- (`wave_ledger_malformed`); `add.py check` is the standing monitor.
102
- - **Materialize gitignored engine content** — `git worktree add` checks out TRACKED files only;
103
- `.add/tooling` (engine) and `.add/docs` (book) are gitignored and will be ABSENT even when the
104
- worktree's HEAD matches. `add.py worktree-prep <slug>` mechanizes the recipe: cuts the
105
- worktree, copies both trees in, and echoes the fork base for the ledger — one step.
106
- - **Lease + timeout** — record which worker holds which task (wave ledger); a dead worker releases
107
- its claim back to READY.
108
- - **Failure isolates** — a worker's STOP-and-escalate blocks only its own task; siblings run on, the
109
- escalation joins the REVIEW-QUEUE.
110
- - **Circuit-breaker** — if N workers fail in a wave, stop fanning out and fall back to sequential.
111
- Repeated failure means the scope was wrong, not the parallelism.
112
-
113
- ## Wave ledger — the wave's resume point
114
-
115
- **The file** — `.add/milestones/<m>/WAVE.md`, orchestrator-owned. ONE live wave per milestone;
116
- opening a second while one is live is refused (`wave_already_live`). **Workers never read
117
- WAVE.md** — the orchestrator copies relevant decisions into each worker's PROMPT.md at spawn.
118
-
119
- ```markdown
120
- # WAVE.md — transient wave ledger (orchestrator-owned · one live wave per milestone)
121
- wave: <n> · opened: <date> · status: live|merging
122
- base: <orchestrator HEAD at spawn — the sha every fork must equal>
123
-
124
- ### Roster (lease ledger)
125
- | task | lease (worker) | fork-base (pasted) | autonomy | spawned | timeout |
126
- |--------|----------------|---------------------------------------------|----------|---------|---------|
127
- | <slug> | wt-a | <paste `git -C <wt> rev-parse HEAD` output> | auto | <time> | <dur> |
128
-
129
- ### Mid-wave decisions
130
- - <date> <decision a later or respawned worker must honor — copy it into that worker's PROMPT.md>
131
-
132
- ### Merge order (serial; integration Verify per merge)
133
- 1. <slug> → 2. <slug>
134
- ```
135
-
136
- **Evidence cells, not ticks.** The fork-base cell holds the PASTED output of
137
- `git -C <worktree> rev-parse HEAD` and must equal `base:`. Filling the row requires running the
138
- command — words-exist ≠ method-works. Spawning a worker whose roster row lacks that evidence is
139
- refused (`unverified_fork_base`). On a pool runner the cell holds the worker's **step-0**
140
- post-sync echo (still `== base:`) and the refusal **shifts to merge-time**.
141
-
142
- **Lifecycle — open → consume → digest → delete.** Open when the first worker spawns. At wave
143
- close, absorb the evidence digest — base · roster fork-base · merge order · integration-Verify
144
- outcome — into `MILESTONE.md` as an append-only `## Wave log` block, then remove the file.
145
- Removing WAVE.md before the digest is absorbed is refused (`digest_not_absorbed`).
146
-
147
- **Resume rule.** On session start, a live WAVE.md is the wave's resume point: re-orient from the
148
- file — roster, bases, decisions, merge order — never from conversational memory.
149
-
150
- ## Merge is serial — integration Verify
151
-
152
- Parallel build, **serial integration**. After workers return, merge worktrees one at a time and
153
- run the **integration** Verify — the concurrency / architecture / layering checks automation
154
- cannot judge. Two green tasks in isolation can still conflict when merged. Never auto-pass it.
155
-
156
- Each worktree carries a full copy of `.add/`. Merge back **only** `src/`, `tests/`, and the
157
- worker's own `.add/tasks/<slug>/` (TASK.md · SUMMARY.md) — `.add/state.json`, `MILESTONE.md`,
158
- and the live `WAVE.md` stay orchestrator-owned.
159
-
160
- ## The worker contract — portable across coding agents
161
-
162
- A worker **is** the dynamic run (`run.md`) for one task. The contract below is **agent-agnostic**:
163
- no vendor tool, no model, no spawn API — a durable ADD artifact. The adapter (next sections) is
164
- the thin, swappable mapping for one runner. Fill every `{{...}}` per stream.
165
-
166
- ```xml
167
- <!-- PROMPT.md — dropped into the worker's worktree, or passed inline. No runner-specific tokens. -->
168
- <objective>
169
- Execute the LOCKED dynamic run for task '{{TASK_SLUG}}' in milestone {{MILESTONE}}:
170
- drive §4 TESTS red→green against the FROZEN contract {{CONTRACT_VERSION}}, converge, and
171
- resolve verify per autonomy={{AUTONOMY}}. You own ONLY the machine-led span — the two human
172
- decision points (bundle approval · escalated Verify) are NOT yours.
173
- </objective>
174
-
175
- <persona>
176
- Load `.add/personas/{{PERSONA_SLUG}}.md` (Identity→you · Critical Rules→constraints · Success
177
- Metrics→done-bar); no match → the generic default below. Portable body + per-runner spawn stubs:
178
- `templates/PROMPT.persona.md.tmpl` (one canonical body; Claude Code verified, the rest illustrative).
179
- You are a {{DOMAIN}} engineer with 15 years building {{DOMAIN_DETAIL}}.
180
- A wrong-but-plausible result here is expensive; correctness over speed.
181
- Work step by step:
182
- 1. Load the context files. Confirm the start gate: §3 CONTRACT FROZEN @ {{CONTRACT_VERSION}}
183
- AND §4 TESTS RED for the right reason. If not → STOP and escalate (forward-skip forbidden).
184
- 2. Build in small batches in src/ until the red tests pass — never weaken or skip a test.
185
- 3. Converge: loop-until-dry · adversarial-verify every 'done' claim · completeness-critic.
186
- 4. Resolve verify per the boundary. Write SUMMARY.md + OBSERVE deltas (deltas.md grammar).
187
- Score confidence (0-1) on Completeness · Clarity · Practicality · Optimization · EdgeCases ·
188
- Self-Eval; if any < 0.9, refine before returning.
189
- </persona>
190
-
191
- <strategy>
192
- The task's §5 plan — the Strategy (ordered batches) order and the Known-problem fixes — is
193
- your PREFERRED starting path, not a hard rule. Improve on it when a better strategy emerges
194
- as you build; on done, report the strategy you ACTUALLY used so the orchestrator can update
195
- §5 for the audit trail.
196
- </strategy>
197
-
198
- <touch_boundary> <!-- from run.md; the worker's contract, identical on every runner -->
199
- MAY: rewrite code in src/ · drive tests green WITHOUT weakening them · gather verify evidence.
200
- MUST NOT: edit the frozen CONTRACT or locked scope · weaken/delete/skip any test ·
201
- touch §1–§3 bundle artifacts · write MILESTONE.md / state.json / any sibling stream.
202
- STOP-and-escalate (return your findings; do not decide):
203
- • a discovered scope/contract gap → backward-correction, reopen Specify (principle 4)
204
- • any SECURITY finding → HARD-STOP, always
205
- • a concurrency/timing OR architecture/layering risk the tests cannot exercise
206
- • [include this bullet when autonomy is conservative OR manual] the verify gate itself — STOP for the human
207
- Auto-PASS only if autonomy=auto AND: all tests green · coverage not decreased · no test weakened ·
208
- no contract edited · loops dry · completeness-critic clean · no residue above. Log it as
209
- auto-resolved, naming this run as owner — never forge a human signature.
210
- </touch_boundary>
211
-
212
- <context_files> <!-- paths relative to the worktree root -->
213
- .add/PROJECT.md · .add/milestones/{{MILESTONE}}/MILESTONE.md (READ-ONLY) ·
214
- .add/tasks/{{TASK_SLUG}}/TASK.md · .claude/skills/add/run.md · .claude/skills/add/deltas.md
215
- </context_files>
216
-
217
- <expertise>
218
- If your runner supports specialist injection (a Claude Code skill, a system-prompt preamble, an
219
- agent profile), load the one matching {{DOMAIN}}. Otherwise the persona above IS your expertise.
220
- </expertise>
221
-
222
- <tools>
223
- Navigate with your runner's code-intelligence: mcp__serena under Claude Code; LSP / ctags /
224
- ripgrep otherwise. Design every IO path for failure — timeouts, retries, rollback.
225
- </tools>
226
-
227
- <return> <!-- the worker PROPOSES; the orchestrator RECORDS. A worker never runs add.py. -->
228
- End with a structured verdict AND write the same into SUMMARY.md in the task dir, then
229
- **commit SUMMARY.md + deltas.md** in the worktree (uncommitted files survive only by harness
230
- courtesy — commit them so the serial-integration merge-back carries your report):
231
- { task, outcome: PASS|RISK-ACCEPTED|HARD-STOP|ESCALATE, evidence: <tests+coverage>,
232
- residue: [security|concurrency|architecture findings], deltas: [open lessons learned] }.
233
- Do NOT touch add.py or any shared file — the orchestrator gates on your verdict.
234
- </return>
235
- ```
236
-
237
- ## Choosing the model — vendor-neutral tiers
238
-
239
- ADD picks a **tier** from the scope's nature; the adapter maps the tier to the runner's model id.
240
-
241
- | Tier | When | Claude Code | Any other runner |
242
- |------|------|-------------|------------------|
243
- | **mid** | ordinary, well-tested scope; clear contract | `sonnet` | the runner's balanced model |
244
- | **top** | complex / ambiguous / cross-cutting / broad scope of impact | `opus` | the runner's strongest reasoning model |
245
-
246
- Two rules sit **above** model choice: **high-risk ⇒ a lowered rung (`conservative` or `manual`),
247
- regardless of model** — a stronger model does not buy back the human gate. And **security residue
248
- always escalates** — no tier auto-passes it.
249
-
250
- ## The spawn adapter — one thin mapping per runner
251
-
252
- ADD needs six capabilities from any runner. **Isolation ADD owns itself** (a git worktree,
253
- default for any spawn), so streams stay portable even without a native sandbox.
254
-
255
- | ADD needs | Abstract | Claude Code (verified reference) | Any CLI agent — Codex · opencode · pi-mono · … |
256
- |-----------|----------|----------------------------------|-----------------------------------------------|
257
- | spawn a worker | prompt + label | `Task(description=…, prompt=…)` | `cd $WT && <agent> run --prompt-file PROMPT.md` |
258
- | pick the model | tier → id | `model="opus"\|"sonnet"` | a `--model <id>` flag |
259
- | isolate | worktree | `isolation="worktree"` | `git worktree add $WT HEAD` (after committing the bundle; verify base == HEAD), then run inside it |
260
- | load context | files / cwd | `<context_files>` + repo cwd | run inside `$WT`; paths are relative |
261
- | domain expertise | skill / preamble | a Claude skill in `<expertise>` | a system-prompt / profile preamble |
262
- | return a verdict | structured | final message (optionally a schema) | stdout JSON the orchestrator parses |
263
-
264
- > **Honesty:** only the Claude Code column is verified. The CLI forms for Codex/opencode/pi-mono
265
- > are *illustrative shapes* — confirm exact syntax with the `find-docs` skill.
266
-
267
- When workers return, **you** record each outcome with the explicit slug — `add.py advance <slug>`
268
- as evidence lands, `add.py gate PASS|RISK-ACCEPTED|HARD-STOP <slug>` at verify — then re-read
269
- `status` to refill the READY-QUEUE. The worker proposes; the orchestrator records.
@@ -1,86 +0,0 @@
1
- """add_engine.release — the RELEASE-pillar render helpers (engine-modularization 14/N).
2
-
3
- Render the CHANGELOG block and the append-only RELEASES.md attribution row, locate the
4
- ledger, find closed milestones / key decisions for a cut, and summarise the in-flight build.
5
- A closed, unpatched cluster (transitive-closure AST = zero outbound). Deps: constants + stdlib.
6
- """
7
- from __future__ import annotations
8
-
9
- import re
10
- from pathlib import Path
11
-
12
- from add_engine.constants import RELEASES_FILE
13
-
14
-
15
- def _releases_path(root: Path) -> Path:
16
- """The append-only release ledger — at the PROJECT ROOT (root IS the .add dir, so its
17
- parent), a sibling of CHANGELOG.md. NOT inside .add/."""
18
- return root.parent / RELEASES_FILE
19
-
20
- def _closed_milestones(state: dict) -> list[dict]:
21
- """Every CLOSED milestone (its milestone-done gate passed): LIVE done milestones
22
- (status == 'done', still in state) + ARCHIVED milestones (all were PASS-done before
23
- archive — see _archived_task_slugs). Each: {slug, title, tier}."""
24
- out: list[dict] = []
25
- for slug, m in (state.get("milestones") or {}).items():
26
- if m.get("status") == "done":
27
- out.append({"slug": slug, "title": m.get("title", slug), "tier": "live"})
28
- for rec in state.get("archived") or []:
29
- if rec.get("slug"):
30
- out.append({"slug": rec["slug"], "title": rec.get("title", rec["slug"]),
31
- "tier": "archived"})
32
- return out
33
-
34
- def _key_decisions_for(root: Path, slug: str) -> list[str]:
35
- """Best-effort §Key-Decisions rows from PROJECT.md that NAME this milestone slug — the
36
- consolidated decisions the changelog can cite. Fail-open: a missing section / unreadable
37
- foundation / no slug match -> [] (a gather never raises). READ-ONLY."""
38
- try:
39
- text = (root / "PROJECT.md").read_text(encoding="utf-8")
40
- except OSError:
41
- return []
42
- m = re.search(r"^#{1,6}[^\n]*key decision[^\n]*$(.*?)(?=^#{1,6}\s|\Z)", text, re.S | re.M | re.I)
43
- if not m:
44
- return []
45
- return [st.lstrip("-* ").strip() for st in (ln.strip() for ln in m.group(1).splitlines())
46
- if st.startswith(("-", "*")) and slug in st]
47
-
48
- def _build_in_flight(state: dict) -> bool:
49
- """release_build_in_flight proxy (PURE): is any ACTIVE task mid-build without a recorded green
50
- gate — phase ∈ {build, verify} AND gate == 'none'? The tool-agnostic engine never runs the
51
- suite, so an entered-but-ungated build is the recorded-evidence stand-in for 'the suite is red'."""
52
- return any(t.get("phase") in ("build", "verify") and t.get("gate") == "none"
53
- for t in (state.get("tasks") or {}).values())
54
-
55
- def _render_changelog_block(version: str, day: str, bundle: list[dict],
56
- changed_by_slug: dict) -> str:
57
- """A CHANGELOG block: `## <version> — <date>` + one bullet per bundled milestone (title +
58
- carried-delta / key-decision counts from release_data['changed'])."""
59
- lines = [f"## {version} — {day}", ""]
60
- if bundle:
61
- for m in bundle:
62
- c = changed_by_slug.get(m["slug"], {})
63
- lines.append(f"- {m['title']} — {c.get('carried_deltas', 0)} carried · "
64
- f"{len(c.get('key_decisions', []))} key decision(s)")
65
- else:
66
- lines.append("- (no milestone bundled)")
67
- return "\n".join(lines) + "\n\n"
68
-
69
- def _render_releases_row(version: str, day: str, bundle: list[dict],
70
- waiver_slugs: list[str], evidence: str | None,
71
- actor: str | None = None, loose: list[dict] | None = None) -> str:
72
- """One append-only RELEASES.md row — the attribution source (`milestones:` membership +,
73
- additively, `loose tasks:` membership for done milestone-free standalones). The `actor:`
74
- line records WHO cut the release (structured-actor stamping); absent on a legacy row
75
- (back-compat) when no actor is supplied. `loose` defaults to None so existing callers keep
76
- working; the `loose tasks:` line always renders (`none` when empty), the other lines unchanged."""
77
- ms = ", ".join(m["slug"] for m in bundle) if bundle else "none"
78
- lt = ", ".join(t["slug"] for t in loose) if loose else "none"
79
- wv = ", ".join(waiver_slugs) if waiver_slugs else "none"
80
- actor_line = f"actor: {actor}\n" if actor else ""
81
- return (f"## {version} — {day}\n"
82
- f"milestones: {ms}\n"
83
- f"loose tasks: {lt}\n"
84
- f"waivers: {wv}\n"
85
- f"{actor_line}"
86
- f"evidence: {evidence or 'recorded by add.py release'}\n\n")
@@ -1,78 +0,0 @@
1
- # TASK: {{title}}
2
-
3
- slug: {{slug}} · created: {{date}} · stage: {{stage}}
4
- milestone: {{milestone}}
5
- autonomy: {{autonomy}} <!-- Multi-component repo? add a `component: <name>` line (declared in .add/components.toml) to bind this fast task to a component — its root joins §5 Scope and its green-bar/verify surface at the gate. Omit for single-component projects. -->
6
- phase: ground <!-- fast lane: ground -> specify -> contract -> tests -> build -> verify -> observe -> done -->
7
- fast: true <!-- the fast lane: a small task, collapsed flow + minimal template. Omit --fast for full rigor. -->
8
-
9
- > Fast lane — one small task, minimal sections, filled top-to-bottom. The trust floor still
10
- > holds: a FROZEN §3 contract · ≥1 red test before build · a recorded §6 gate (security = HARD-STOP).
11
- > The acceptance scenario collapses into §1 `Accept:`; OBSERVE is one optional line at the gate.
12
-
13
- ---
14
-
15
- ## 0 · GROUND — the real codebase
16
-
17
- Touches (files · symbols): <path:symbol — what it is / how it is keyed>
18
- Context (working folder): <docs · config · data the task touches — task-delta only>
19
- Honors (patterns / conventions): <PROJECT.md / CONVENTIONS.md anchors — task-delta>
20
- Anchors the contract cites: <the symbols §3 will name>
21
- Ground SHA: <`git rev-parse --short HEAD` at ground time — any line ref reads "as of" it>
22
-
23
- ---
24
-
25
- ## 1 · SPECIFY — the rules
26
-
27
- Feature: <name>
28
- Must:
29
- - <required behavior>
30
- Reject:
31
- - <bad input / situation> -> "<error_code>"
32
- Accept: <the one acceptance scenario, Given/When/Then condensed to one line — it drives the §4 test>
33
- Assumptions: ⚠ <the one most likely wrong> — why; if wrong: <cost> (or "none material — biggest risk: X")
34
-
35
- ---
36
-
37
- ## 3 · CONTRACT — freeze the shape
38
-
39
- ```
40
- <the shape that freezes: signature / fields · success + each rejection's response>
41
- ```
42
-
43
- `Least-sure flag surfaced at freeze:` <[spec|contract|test] the point most likely wrong — why; if wrong: cost>
44
- Status: DRAFT
45
- <!-- The freeze IS the one approval. Approved -> Status: FROZEN @ vN — approved by <name>.
46
- Changing a frozen contract = change request back to SPECIFY. -->
47
-
48
- ---
49
-
50
- ## 4 · TESTS — failing-first (red)
51
-
52
- Plan: test_<accept> — assert the §1 Accept line's Then (behavior, not internals).
53
- Tests live in: `./tests/` · MUST run red (missing implementation) before Build.
54
-
55
- ---
56
-
57
- ## 5 · BUILD — AI writes code
58
-
59
- Scope (may touch): `./src/` <every file the build may write — declared before the §3 freeze>
60
- Strategy & known-problem fixes: <ordered build steps · the trap each known problem must dodge · let the active persona's domain stance (or "generic") shape the approach, not just patterns>
61
- Strategy actually used: <fill at verify — what you ACTUALLY did, or "as planned"; harvested into §7 Decisions>
62
- Code lives in: `./src/` · Constraints: change no test, no contract; allow-list packages only.
63
-
64
- ---
65
-
66
- ## 6 · VERIFY — evidence + gate
67
-
68
- - [ ] all tests pass · coverage held · no test or contract altered during build
69
- - [ ] green was EARNED — no overfit / vacuous asserts / stubbed-away logic
70
- - [ ] no exposed secrets, injection openings, or unexpected dependencies (security = HARD-STOP)
71
-
72
- Build expectations (from §1 Accept + §3 CONTRACT): <the observable outcome a correct build must produce — confirmed by <how / where>>
73
-
74
- ### GATE RECORD
75
- Outcome: <PASS | RISK-ACCEPTED | HARD-STOP>
76
- Reviewed by: <name> · date: <date>
77
- <!-- A security finding is ALWAYS HARD-STOP. Record exactly one outcome — no silent pass.
78
- OBSERVE (optional): one `[SPEC · open]` or competency-delta line here if the loop taught the foundation something. -->
@@ -1,181 +0,0 @@
1
- # TASK: {{title}}
2
-
3
- slug: {{slug}} · created: {{date}} · stage: {{stage}}
4
- milestone: {{milestone}}
5
- autonomy: {{autonomy}} <!-- level: manual < conservative < auto — lower for a high-risk task (`add.py autonomy set`). Multi-component repo? add a `component: <name>` line (.add/components.toml) to join that root to §5 Scope. -->
6
- phase: ground <!-- ground -> specify -> scenarios -> contract -> tests -> build -> verify -> observe -> done -->
7
- <!-- high-risk/method-defining? declare `risk: high` on the slug line + a lowered autonomy — the engine refuses an unguarded completion (`unguarded_high_risk_auto`). A comment is never a declaration. -->
8
-
9
- > One file = one task — fill top-to-bottom; the phase marker above is the single source of truth (`add.py phase`); unclear phase → its book chapter.
10
-
11
- ---
12
-
13
- ## 0 · GROUND — the real codebase ▸ docs/02-the-flow.md
14
-
15
- Touches (files · symbols · signatures): <path:symbol — what it is / how it is keyed>
16
- Context (working folder): <docs · todos · config · data the task touches — task-delta only>
17
- Honors (patterns / conventions): <PROJECT.md / CONVENTIONS.md anchors — task-delta only, never a re-scan>
18
- Seams consulted: <SEAMS.md entry cited instead of re-deriving, e.g. .add/SEAMS.md#scope-token-grammar — optional, omit if none apply>
19
- Anchors the contract cites: <the symbols §3 will name>
20
- Issues/Risks (→ feed §1): <problems · traps · untestable risks found in the real code — task-delta; §1 builds on these>
21
- Related intent: <PROJECT.md § · GLOSSARY term(s) · originating request/milestone rationale — the WHY; task-delta>
22
- Ground SHA: <`git rev-parse --short HEAD` at ground time — cite symbols, not bare line numbers; any line ref is "as of" this commit>
23
-
24
- ---
25
-
26
- ## 1 · SPECIFY — the rules ▸ docs/03-step-1-specify.md
27
-
28
- Feature: <name>
29
- Framings weighed: <chosen> (chosen) · <alternative> · <alternative>
30
- Must:
31
- <must>
32
- - <required behavior>
33
- </must>
34
- Reject:
35
- <reject>
36
- - <bad input / situation> -> "<error_code>"
37
- </reject>
38
- After:
39
- <after>
40
- - <state that is true once it succeeds>
41
- </after>
42
- Assumptions — lowest-confidence first:
43
- <assumptions>
44
- ⚠ <the one assumption most likely to be wrong> — lowest confidence because <why>; if wrong: <cost>
45
- - [ ] <next assumption, ranked> — confirm or deny; never carry an open one forward
46
- </assumptions>
47
-
48
- <!-- EXIT: every rule + rejection stated; assumptions ranked lowest-confidence first, top 1–2 ⚠-flagged with why + cost (or an honest "none material" naming the biggest risk). -->
49
-
50
- ---
51
-
52
- ## 2 · SCENARIOS — pass/fail cases ▸ docs/04-step-2-scenarios.md
53
-
54
- <scenarios>
55
-
56
- ```gherkin
57
- Scenario: <short name> # <Must/Reject item this covers, e.g. M1 or R1>
58
- Given <starting situation>
59
- When <action>
60
- Then <expected result>
61
- And <what must remain unchanged> # required for every rejection
62
- ```
63
-
64
- </scenarios>
65
-
66
- <!-- EXIT: one scenario per Must AND per Reject; each result is observable. -->
67
-
68
- ---
69
-
70
- ## 3 · CONTRACT — freeze the shape ▸ docs/05-step-3-contract.md
71
-
72
- ```
73
- <METHOD> <path> body: { <fields> }
74
- 200 -> { <success fields> }
75
- 4xx -> { error: "<code>" | "<code>" }
76
- Schema: <tables/fields touched, and access pattern>
77
- ```
78
-
79
- Glossary deltas: <new domain term(s) this task introduces, `Term: definition` — or "none">
80
- Status: DRAFT
81
- Reported: <yes — the freeze report (banner/ARC/SHAPE) rendered before this froze | no>
82
- <!-- The freeze IS the one approval — lead it with the bundle's lowest-confidence flag (§1 ⚠ feeds it; a flag may point at any part — run.md). Approved -> Status: FROZEN @ vN — approved by <name>; changing a frozen contract = change request back to SPECIFY. EXIT: frozen · every §1 rejection has a contracted response · names match GLOSSARY (new terms = Glossary delta) · flag surfaced. -->
83
-
84
- ---
85
-
86
- ## 4 · TESTS — failing-first suite (red) ▸ docs/06-step-4-tests.md
87
-
88
- Coverage target: <e.g. 90%>
89
- Plan (one test per scenario, asserting behavior not internals):
90
- <test_plan>
91
- - test_<scenario>: arrange <Given> / act <When> / assert <Then> + assert <unchanged> · covers: <M#, R:code — optional>
92
- </test_plan>
93
-
94
- Tests live in: `./tests/` · MUST run red (missing implementation) before Build.
95
- <!-- declare paths as backticked tokens on this line: `./…` = this task dir · a token with "/" = the project root · a bare name = a sibling of the previous token's dir · a directory counts its *.py files (non-recursive) · declared counts marked † · outside the project root counts 0 -->
96
-
97
- <!-- EXIT: one test per scenario; suite red for the RIGHT reason; target recorded. -->
98
-
99
- ---
100
-
101
- ## 5 · BUILD — AI writes code ▸ docs/07-step-5-build.md
102
-
103
- Scope (may touch): `./src/` <fill before the §3 freeze — every file the build may write>
104
- Strategy (ordered batches): <1. … 2. … — the planned build order; guidance, not enforced; preferred architecture/pattern strategies; advise solution/method to resolve issues/implement features; let the named Persona's domain stance (below) shape the approach, not just architecture patterns>
105
-
106
- Persona (required): <name the persona file under `.add/personas/` this build embodies as a domain stance atop SOUL.md — advisory, never lowers a gate; name "generic" if no project persona fits yet>
107
- Spawn isolation (default): <prefer isolation: "worktree" for any subagent build/verify spawn, not only explicit parallel mode; shared-tree needs a stated reason — see worktree-isolated-spawn-default>
108
- Known-problem fixes: <trap → planned fix — the failure modes this build must dodge; guidance, not enforced>
109
- Strategy actually used: <fill at VERIFY — the strategy you ACTUALLY used (or "as planned"); harvested into the §7 Decisions (ADR) block as the [AI] build decision>
110
- Safety rule (feature-specific): <e.g. debit+credit in one atomic transaction>
111
- Code lives in: `./src/`
112
- Constraints: do NOT change any test or the contract; allow-list packages only; ask if unclear.
113
-
114
- <!-- Scope tokens, backticked, FIRST declaring line: `./…` = this task dir · a token with "/" = project root · a bare name = sibling of the previous token's dir · a DIRECTORY token covers its whole subtree (diverges from §4's non-recursive counting) · outside-root resolutions drop fail-closed · absent line = UNDECLARED (grandfathered, never retro-red) · enforcement live: a completing verify gate refuses an out-of-scope build (scope_violation → self-heal); check surfaces it. EXIT: all green; coverage held; no test/contract touched; no unlisted dependency. -->
115
-
116
- ---
117
-
118
- ## 6 · VERIFY — evidence + non-functional review ▸ docs/08-step-6-verify.md
119
-
120
- - [ ] all tests pass
121
- - [ ] coverage did not decrease
122
- - [ ] no test or contract was altered during build
123
- - [ ] the green was EARNED, not gamed — no overfit to fixtures, vacuous asserts, or stubbed-away logic (score with an adversarial refute-read — a subagent recommended under `autonomy: auto`; a confirmed cheat is HARD-STOP)
124
- - [ ] concurrency / timing of the risky operation is safe
125
- - [ ] no exposed secrets, injection openings, or unexpected dependencies
126
- - [ ] layering & dependencies follow CONVENTIONS.md
127
- - [ ] a person reviewed and approved the change
128
-
129
- ### Build expectations — what "correct" looks like (fill BEFORE build; confirm each at the gate)
130
- > OBSERVABLE outcomes a correct build must produce, derived from the §2 scenarios + §3 contract — evidence you can SEE, not test names.
131
- - [ ] <observable outcome a correct build must produce> — confirmed by <how / where>
132
- - [ ] <another observable outcome> — confirmed by <evidence seen>
133
-
134
- ### Deep checks — do not skim (fill the path that applies; the resolver judges which)
135
- - [ ] WIRING (code) — every new symbol is referenced; record where / how confirmed
136
- - [ ] DEAD-CODE (code) — no new unused or orphaned symbol introduced
137
- - [ ] SEMANTIC (prose / non-code) — read in full, not skimmed: <what read · what confirmed>
138
-
139
- ### Live-verify evidence — confirm the §0 GROUND anchors still resolve (fill at the gate)
140
- > Re-resolve every symbol §3 cites against the CURRENT tree (code moved since Ground SHA) — catch a stale anchor here, not later.
141
- - [ ] every symbol §3 CONTRACT cites still resolves in the current tree — confirmed by <how / where>
142
- - [ ] any anchor that moved/renamed since Ground SHA is named here, not left silent
143
-
144
- ### Refute-read verdict — the earned-green check (record it; required for an auto-PASS)
145
- > Under auto, record the earned-green refute-read (the engine never spawns it — you do; NOT-EARNED -> `add.py heal`). Audit-measured (`refute_unrecorded`), never blocked; a human spot-audit is the backstop.
146
- Verdict: <EARNED | NOT-EARNED>
147
- By: <self | agent-id> · adversarially checked: <what was probed>
148
-
149
- ### Advisor 3-lens verdict — sequential (security → concurrency → architecture)
150
- > Lenses run in order; a Security HARD-STOP ends the checklist (leave the rest blank). Binding for sensitivity: mechanical (advisor-gate-relax); advisory otherwise. Audit-measured (`advisor_verdict_unrecorded`), never blocked.
151
- Advisor: <agent-id | self>
152
- 1. Security: <CLEAR | HARD-STOP: finding>
153
- 2. Concurrency: <CLEAR | RESIDUE: finding>
154
- 3. Architecture: <CLEAR | RESIDUE: finding>
155
- Verdict: <PASS | HARD-STOP>
156
- Residue: <none | summary>
157
- Binding: <yes — mechanical | advisory — <sensitivity>>
158
-
159
- ### GATE RECORD
160
- Reported: <yes — the gate report (banner/ARC) rendered before this outcome recorded | no>
161
- Outcome: <PASS | RISK-ACCEPTED | HARD-STOP>
162
- If RISK-ACCEPTED -> owner: <name> · ticket: <link> · expires: <date> (never for a security gap)
163
- Reviewed by: <name> · date: <date>
164
-
165
- <!-- Security is ALWAYS HARD-STOP; record exactly one outcome — no silent pass. The Advisor 3-lens and Refute-read verdicts are audit-measured (`advisor_verdict_unrecorded` · `refute_unrecorded`), never engine-blocked; a human spot-audit backstops anything unrecorded. -->
166
-
167
- ---
168
-
169
- ## 7 · OBSERVE — feed the next loop ▸ docs/09-the-loop.md
170
-
171
- Watch (reuse scenarios as monitors): <error rate / per-rejection rate / latency>
172
-
173
- ### Decisions (ADR)
174
- <harvested at done from §1/§3/§5/§6 — do not hand-edit; one actor-tagged line per decision, refilled only while this placeholder stands>
175
-
176
- ### Spec delta
177
- One line per forward change, tagged `[SPEC · open|seeded|dropped]` + evidence — each re-enters at Specify (`deltas.md`).
178
-
179
- ### Competency deltas
180
- One lesson per line: `[DDD|SDD|UDD|TDD|ADD · open] the learning (evidence: …)` — see `deltas.md`.
181
- <!-- e.g. - [DDD · open] the model missed multi-tenancy (evidence: scenario_x failed) -->