@pilotspace/add 1.8.0 → 1.10.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.
- package/CHANGELOG.md +109 -0
- package/bin/cli.js +137 -2
- package/docs/16-releasing.md +2 -2
- package/docs/17-components.md +125 -0
- package/docs/appendix-c-glossary.md +8 -0
- package/package.json +2 -2
- package/skill/add/SKILL.md +90 -116
- package/skill/add/adopt.md +13 -34
- package/skill/add/advisor.md +9 -10
- package/skill/add/compact-foundation.md +21 -34
- package/skill/add/components.md +54 -0
- package/skill/add/confidence.md +9 -25
- package/skill/add/deltas.md +12 -28
- package/skill/add/design.md +26 -32
- package/skill/add/fold.md +26 -51
- package/skill/add/graduate.md +18 -54
- package/skill/add/intake.md +30 -34
- package/skill/add/loop.md +30 -34
- package/skill/add/phases/0-ground.md +6 -14
- package/skill/add/phases/0-setup.md +30 -81
- package/skill/add/phases/1-specify.md +7 -22
- package/skill/add/phases/2-scenarios.md +1 -3
- package/skill/add/phases/3-contract.md +8 -22
- package/skill/add/phases/4-tests.md +3 -6
- package/skill/add/phases/5-build.md +8 -22
- package/skill/add/phases/6-verify.md +14 -49
- package/skill/add/phases/7-observe.md +1 -3
- package/skill/add/phases/fast-lane.md +31 -0
- package/skill/add/release.md +36 -90
- package/skill/add/report-template.md +41 -126
- package/skill/add/run.md +89 -159
- package/skill/add/scope.md +40 -89
- package/skill/add/setup-review.md +10 -27
- package/skill/add/soul.md +17 -36
- package/skill/add/streams.md +90 -149
- package/tooling/add.py +804 -14
- package/tooling/templates/TASK.fast.md.tmpl +72 -0
- package/tooling/templates/TASK.md.tmpl +1 -1
package/skill/add/soul.md
CHANGED
|
@@ -1,37 +1,26 @@
|
|
|
1
1
|
# Self-improving the voice — how SOUL.md converges to the human
|
|
2
2
|
|
|
3
|
-
`SOUL.md` is the AI's voice (
|
|
4
|
-
and is **human-owned**; this doc is how it stops being write-once and starts converging to *this*
|
|
5
|
-
human. It mirrors `deltas.md` (emit) + `fold.md` (confirm → rewrite), but a confirmed voice delta is
|
|
6
|
-
consolidated into **SOUL.md**, not the foundation — because voice is not one of the five competencies.
|
|
3
|
+
`SOUL.md` is the AI's voice (Tone · Communication style · Trust). It ships as a **proposed starter** and is **human-owned**; this doc is how it starts converging to *this* human. It mirrors `deltas.md` (emit) + `fold.md` (confirm → rewrite), but a confirmed voice delta consolidates into **SOUL.md**, not the foundation — voice is not one of the five competencies.
|
|
7
4
|
|
|
8
|
-
You
|
|
9
|
-
delta rewrites SOUL.md. **The human's confirm is the only writer** — you never self-approve a voice
|
|
10
|
-
rewrite (rewriting someone's voice is theirs to approve, like a foundation consolidation).
|
|
5
|
+
You **emit** voice deltas as `open`. Only the **human** confirms one; **the human's confirm is the only writer** — you never self-approve a voice rewrite.
|
|
11
6
|
|
|
12
7
|
## What a voice delta is drawn from
|
|
13
8
|
|
|
14
|
-
A voice delta is grounded in how the human
|
|
15
|
-
- their **wordings** — the words they reach for, and the words they correct you on
|
|
16
|
-
|
|
17
|
-
- their **flow** — what they skip, what they double-check, where they want the summary before the detail.
|
|
9
|
+
A voice delta is grounded in how the human shows up **in session**:
|
|
10
|
+
- their **wordings** — the words they reach for, and the words they correct you on;
|
|
11
|
+
- their **flow** — what they skip, what they double-check, where they want summary before detail.
|
|
18
12
|
|
|
19
|
-
NOT from their private **memory** files or anything outside the working session — SOUL learns from what
|
|
20
|
-
you observed together, never from reading a personal store.
|
|
13
|
+
NOT from their private **memory** files or anything outside the working session — SOUL learns only from what you observed together.
|
|
21
14
|
|
|
22
15
|
## The grammar (mirrors deltas.md)
|
|
23
16
|
|
|
24
|
-
Each voice delta begins on its own tag line; the observation may wrap, and a required `(evidence: …)`
|
|
25
|
-
clause closes it:
|
|
26
|
-
|
|
27
17
|
```
|
|
28
18
|
- [VOICE · <status>] <observation about the voice> (evidence: <in-session pointer>)
|
|
29
19
|
```
|
|
30
20
|
|
|
31
|
-
- `<status>` — `open` | `confirmed` | `declined`. A newly emitted delta is **`open`**.
|
|
32
21
|
- `<observation>` — what the voice should become ("lead with the decision, not the preamble").
|
|
33
|
-
-
|
|
34
|
-
|
|
22
|
+
- `<status>` — `open` | `confirmed` | `declined`. A newly emitted delta is **`open`**.
|
|
23
|
+
- `(evidence: …)` — **required**, non-empty: a moment in the session (a correction, a re-ask, a visible preference). No evidence → drop it.
|
|
35
24
|
|
|
36
25
|
```
|
|
37
26
|
- [VOICE · open] the human strips hedging from my drafts — cut "I think / it seems" and state it plainly
|
|
@@ -40,12 +29,9 @@ clause closes it:
|
|
|
40
29
|
|
|
41
30
|
## The loop — observe → confirm → rewrite
|
|
42
31
|
|
|
43
|
-
1. **Emit** (OBSERVE) —
|
|
44
|
-
from the session's wordings + flow. Surface them in the report; show-before-ask.
|
|
32
|
+
1. **Emit** (OBSERVE) — propose 0–N voice deltas as `open` from wordings + flow. Surface in the report; show-before-ask.
|
|
45
33
|
2. **Confirm** — the human accepts or declines each. **No SOUL.md write happens without this.**
|
|
46
|
-
3. **Rewrite** — on a confirmed delta, edit the routed SOUL.md section,
|
|
47
|
-
(status `confirmed`) at the **top** of the "Voice deltas" ledger (**newest-first**, append-only — a
|
|
48
|
-
declined delta flips to `declined` and stays in place, so "considered, chose not to" is auditable).
|
|
34
|
+
3. **Rewrite** — on a confirmed delta, edit the routed SOUL.md section, record the delta line (`confirmed`) at the **top** of "Voice deltas" (**newest-first**, append-only — declined stays in place).
|
|
49
35
|
|
|
50
36
|
## Routing — every voice delta has a SOUL.md home
|
|
51
37
|
|
|
@@ -55,23 +41,18 @@ clause closes it:
|
|
|
55
41
|
| how I *structure* what I say (summary-first, show-before-ask, length) | **## Communication style** |
|
|
56
42
|
| what keeps the human's *trust* (gates, honesty, what I never do) | **## Trust** |
|
|
57
43
|
|
|
58
|
-
The rewrite is surgical: refine or append the bullet the delta names; never silently rewrite the rest
|
|
59
|
-
of the voice. Every confirmed delta also gets its line in **## Voice deltas** (newest-first).
|
|
44
|
+
The rewrite is surgical: refine or append the bullet the delta names; never silently rewrite the rest of the voice. Every confirmed delta also gets its line in **## Voice deltas** (newest-first).
|
|
60
45
|
|
|
61
|
-
## Reject codes
|
|
46
|
+
## Reject codes
|
|
62
47
|
|
|
63
48
|
<reject_codes>
|
|
64
|
-
- `unconfirmed_voice_rewrite` — a SOUL.md write was attempted without a recorded human confirm. The AI
|
|
65
|
-
proposes; it never self-approves. Stop and get the confirm. (The identity-owned floor.)
|
|
49
|
+
- `unconfirmed_voice_rewrite` — a SOUL.md write was attempted without a recorded human confirm. The AI proposes; it never self-approves. Stop and get the confirm.
|
|
66
50
|
- `no_open_voice_deltas` — nothing is `open`. The loop is a no-op; do not touch SOUL.md.
|
|
67
|
-
- `unroutable_voice_delta` — the observation maps to no SOUL.md section (not tone/style/trust). Fix the
|
|
68
|
-
delta or widen the routing before writing.
|
|
51
|
+
- `unroutable_voice_delta` — the observation maps to no SOUL.md section (not tone/style/trust). Fix the delta or widen the routing before writing.
|
|
69
52
|
</reject_codes>
|
|
70
53
|
|
|
71
54
|
## Where it plugs in
|
|
72
55
|
|
|
73
|
-
- **Emit**: `phases/7-observe.md` proposes voice deltas beside
|
|
74
|
-
- **Target**: `SOUL.md`
|
|
75
|
-
- **Kin**: `deltas.md`
|
|
76
|
-
discipline). This is the voice's version of that discipline; the engine stays judgment-free (no
|
|
77
|
-
`add.py` command writes the voice).
|
|
56
|
+
- **Emit**: `phases/7-observe.md` proposes voice deltas beside competency/spec deltas.
|
|
57
|
+
- **Target**: `SOUL.md` — "## Voice deltas" ledger holds confirmed history.
|
|
58
|
+
- **Kin**: `deltas.md` + `fold.md` (same propose→confirm→write discipline). No `add.py` command writes the voice.
|
package/skill/add/streams.md
CHANGED
|
@@ -3,48 +3,41 @@
|
|
|
3
3
|
Load this when a milestone has more than one task and you want to run them concurrently.
|
|
4
4
|
**Default:** when a project confirms `parallel + auto` as its run mode at setup
|
|
5
5
|
(`phases/0-setup.md` "Run mode"), parallel streaming is the project default — an **opt-out**, not
|
|
6
|
-
the opt-in it once was; downgrade in one step (`add.py autonomy set conservative --project`, or
|
|
7
|
-
run tasks one at a time). A project that kept the conservative run mode still treats this
|
|
8
|
-
the opt-in escape hatch.
|
|
6
|
+
the opt-in it once was; downgrade in one step (`add.py autonomy set conservative --project`, or
|
|
7
|
+
just run tasks one at a time). A project that kept the conservative run mode still treats this
|
|
8
|
+
rubric as the opt-in escape hatch.
|
|
9
9
|
|
|
10
|
-
It changes **no `add.py` code and no phase semantics**. It is a way *you, the
|
|
11
|
-
|
|
12
|
-
|
|
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
13
|
|
|
14
14
|
## The honest frame — this is pipelining, not N× speed
|
|
15
15
|
|
|
16
|
-
With **one human reviewer** you cannot beat `review_time × N_tasks` (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
task A's frozen bundle, the builds for B·C·D run behind *their* frozen contracts. You hide
|
|
20
|
-
build latency under human latency. Do not promise more than that.
|
|
16
|
+
With **one human reviewer** you cannot beat `review_time × N_tasks` (decision points are serial).
|
|
17
|
+
The win is that the reviewer is **never blocked waiting on a build**: builds for B·C·D run behind
|
|
18
|
+
*their* frozen contracts while the human reviews A. You hide build latency under human latency.
|
|
21
19
|
|
|
22
20
|
## The two queues
|
|
23
21
|
|
|
24
22
|
Compute both from one `python3 .add/tooling/add.py status` — no new state:
|
|
25
23
|
|
|
26
|
-
- **READY-QUEUE** — tasks
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- **REVIEW-QUEUE** — the irreducibly serial part: the **bundle approval** (contract
|
|
31
|
-
freeze) and any **Verify escalation**. One human, one queue. Present these one at a
|
|
32
|
-
time, never in a batch the human will approve without reading.
|
|
24
|
+
- **READY-QUEUE** — tasks where `phase ≠ done` **and** every `deps=` task shows `gate=PASS`.
|
|
25
|
+
A task with unmet deps stays queued; a task finishing PASS unblocks its dependents.
|
|
26
|
+
- **REVIEW-QUEUE** — the irreducibly serial part: the **bundle approval** (contract freeze) and
|
|
27
|
+
any **Verify escalation**. One human, one queue. Present these one at a time, never in a batch.
|
|
33
28
|
|
|
34
29
|
```
|
|
35
30
|
add.py status ─► READY-QUEUE ──spawn workers──► builds run ──► REVIEW-QUEUE ──► done
|
|
36
|
-
(deps=PASS?) (machine span) (concurrent) (decision points,
|
|
37
|
-
▲
|
|
38
|
-
|
|
31
|
+
(deps=PASS?) (machine span) (concurrent) (decision points, serial)
|
|
32
|
+
▲
|
|
33
|
+
└──────── a task gating PASS unblocks its dependents ──────────────────────────┘
|
|
39
34
|
```
|
|
40
35
|
|
|
41
36
|
## The DAG strategy — let the engine schedule the waves (`add.py waves`)
|
|
42
37
|
|
|
43
|
-
Do **not** eyeball the READY-QUEUE by hand once a milestone has more than a couple of
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
tasks into **topological waves**, names the **critical path**, and emits an advisory
|
|
47
|
-
**tier hint** — exactly the inputs you need to fan out effectively:
|
|
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**:
|
|
48
41
|
|
|
49
42
|
```
|
|
50
43
|
$ add.py waves
|
|
@@ -55,94 +48,67 @@ critical path: dag-scheduler → setup-run-mode (2 tasks)
|
|
|
55
48
|
tier hint: top → dag-scheduler, setup-run-mode; mid → the rest
|
|
56
49
|
```
|
|
57
50
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
applied to the graph. It is **advisory** — graph position is a proxy for scope difficulty, not a
|
|
69
|
-
gate; override it when you know a task is harder than its position suggests.
|
|
70
|
-
- **`--json`** (`{ milestone, waves, critical_path, critical_path_len, tiers, blocked }`) feeds a
|
|
71
|
-
runner that spawns the wave programmatically. `blocked` lists any task whose dep can never be
|
|
72
|
-
satisfied within this milestone (a cross-milestone dep) — surfaced, never silently dropped; a
|
|
73
|
-
`dependency_cycle` is refused with the offending members named (no schedule exists).
|
|
74
|
-
|
|
75
|
-
What `waves` does **not** change: the irreducible floor below still holds — one human approval
|
|
76
|
-
per contract, builds overlap but the review queue stays serial. `waves` decides *order and model*,
|
|
77
|
-
never *whether the human gate fires*.
|
|
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 (`isolation="worktree"`). Finish a wave, gate tasks PASS, then
|
|
53
|
+
`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
|
+
- **`--json`** (`{ milestone, waves, critical_path, critical_path_len, tiers, blocked }`) feeds
|
|
59
|
+
a runner that spawns programmatically. `blocked` lists tasks whose dep cannot be satisfied
|
|
60
|
+
within this milestone; a `dependency_cycle` is refused with the offending members named.
|
|
78
61
|
|
|
79
|
-
|
|
62
|
+
The irreducible floor holds — `waves` decides *order and model*, never *whether the human gate fires*.
|
|
80
63
|
|
|
81
|
-
|
|
82
|
-
(`run.md`), not by this rubric:
|
|
64
|
+
## The autonomy level is the throttle (not a new flag)
|
|
83
65
|
|
|
84
66
|
| `autonomy` (TASK.md) | What serializes on the human | Concurrency |
|
|
85
67
|
|----------------------|------------------------------|-------------|
|
|
86
|
-
| `conservative` / `manual` | bundle approval **+** every Verify | pure pipelining — builds overlap, both gates queue
|
|
68
|
+
| `conservative` / `manual` | bundle approval **+** every Verify | pure pipelining — builds overlap, both gates queue |
|
|
87
69
|
| `auto` (default) | bundle approval **only**; Verify auto-PASSes on evidence | real concurrency — only the decision point + residue escalations queue |
|
|
88
|
-
| `auto` but **high-risk** | refused → must lower
|
|
70
|
+
| `auto` but **high-risk** | refused → must lower (`unguarded_high_risk_auto`) | back to pipelining, by design |
|
|
89
71
|
|
|
90
|
-
The irreducible floor is **one human approval per task at the contract decision point** —
|
|
91
|
-
never drops to zero (`run.md:22`).
|
|
72
|
+
The irreducible floor is **one human approval per task at the contract decision point** — that
|
|
73
|
+
floor never drops to zero (`run.md:22`). Do not engineer around it.
|
|
92
74
|
|
|
93
75
|
## Who writes what — the hard boundary
|
|
94
76
|
|
|
95
77
|
<constraints>
|
|
96
|
-
- **You (orchestrator)** own all shared writes: `MILESTONE.md`, and every
|
|
97
|
-
`add.py
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
cannot collide. The worktree is discarded on failure; the task resets to its last-good
|
|
106
|
-
phase.
|
|
78
|
+
- **You (orchestrator)** own all shared writes: `MILESTONE.md`, and every `add.py advance <slug>` /
|
|
79
|
+
`add.py gate <outcome> <slug>` call. Always pass the explicit `<slug>` — **name the task every time** —
|
|
80
|
+
omitting it falls back to the single `active_task`, which races once more than one stream is live.
|
|
81
|
+
Workers never run these.
|
|
82
|
+
- **A worker** owns only its own `.add/tasks/<slug>/` — it builds `src/`, drives tests green,
|
|
83
|
+
gathers evidence, and writes `SUMMARY.md` + OBSERVE deltas. It touches **no sibling stream and
|
|
84
|
+
no shared file** — never write shared state (state.json, MILESTONE.md, a sibling's files).
|
|
85
|
+
- **Isolation**: spawn each worker with `isolation="worktree"` so concurrent builds cannot
|
|
86
|
+
collide. The worktree is discarded on failure; the task resets to its last-good phase.
|
|
107
87
|
</constraints>
|
|
108
88
|
|
|
109
89
|
## Design for failure (required)
|
|
110
90
|
|
|
111
91
|
- **Fresh worktree base (verify base == HEAD)** — create each worker's worktree from current
|
|
112
|
-
`HEAD` **after**
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
`
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
pending echo (`unverified_fork_base`) and an off-template ledger (`wave_ledger_malformed`, fail-closed);
|
|
125
|
-
`add.py check` is the standing monitor (red at `status: merging`, `fork_base_pending` WARN at `live`).
|
|
126
|
-
- **Lease + timeout** — record which worker holds which task (in the wave ledger, below);
|
|
127
|
-
if a worker dies, release the claim back to READY (re-spawn, do not assume partial work is sound).
|
|
128
|
-
- **Failure isolates** — a worker that hits a STOP-and-escalate (below) blocks only its
|
|
129
|
-
own task. Siblings keep running; the escalation joins the REVIEW-QUEUE.
|
|
92
|
+
`HEAD` **after** committing the task's frozen specification bundle. Confirm `git -C <worktree>
|
|
93
|
+
rev-parse HEAD` equals the orchestrator's `HEAD`; if drifted, `git merge` the base first.
|
|
94
|
+
On a pool-based runner (e.g. Claude Code) the pre-spawn check **shifts** to the worker's
|
|
95
|
+
**step-0**: sync to base and re-echo `rev-parse HEAD`, which the orchestrator verifies at
|
|
96
|
+
**merge-time**. The engine executes this gate (`engine-merge-base-enforcement`): run
|
|
97
|
+
`python3 .add/tooling/add.py wave-verify` before the first merge-back — it refuses a
|
|
98
|
+
mismatched or pending echo (`unverified_fork_base`) and an off-template ledger
|
|
99
|
+
(`wave_ledger_malformed`, fail-closed); `add.py check` is the standing monitor.
|
|
100
|
+
- **Lease + timeout** — record which worker holds which task (in the wave ledger); if a worker
|
|
101
|
+
dies, release the claim back to READY.
|
|
102
|
+
- **Failure isolates** — a worker that hits a STOP-and-escalate blocks only its own task;
|
|
103
|
+
siblings keep running and the escalation joins the REVIEW-QUEUE.
|
|
130
104
|
- **Circuit-breaker** — if N workers fail in a wave, stop fanning out and fall back to
|
|
131
105
|
sequential. Repeated failure means the scope was wrong, not the parallelism.
|
|
132
106
|
|
|
133
107
|
## Wave ledger — the wave's resume point
|
|
134
108
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
(the base check existed in prose and never ran). The ledger fixes both: it is the file you
|
|
139
|
-
re-orient from, and its evidence cells cannot be filled without executing the checks.
|
|
140
|
-
|
|
141
|
-
**The file** — `.add/milestones/<m>/WAVE.md`, orchestrator-owned like `MILESTONE.md` and
|
|
142
|
-
`state.json`. ONE live wave per milestone at a time; opening a second while one is live is
|
|
143
|
-
refused (`wave_already_live`). **Workers never read WAVE.md** — the orchestrator copies the
|
|
144
|
-
relevant mid-wave decisions into each worker's PROMPT.md at spawn/respawn, so the worker
|
|
145
|
-
contract below stays unchanged and no worker widens into sibling state.
|
|
109
|
+
**The file** — `.add/milestones/<m>/WAVE.md`, orchestrator-owned. ONE live wave per milestone;
|
|
110
|
+
opening a second while one is live is refused (`wave_already_live`). **Workers never read
|
|
111
|
+
WAVE.md** — the orchestrator copies relevant decisions into each worker's PROMPT.md at spawn.
|
|
146
112
|
|
|
147
113
|
```markdown
|
|
148
114
|
# WAVE.md — transient wave ledger (orchestrator-owned · one live wave per milestone)
|
|
@@ -162,48 +128,34 @@ base: <orchestrator HEAD at spawn — the sha every fork must equal>
|
|
|
162
128
|
```
|
|
163
129
|
|
|
164
130
|
**Evidence cells, not ticks.** The fork-base cell holds the PASTED output of
|
|
165
|
-
`git -C <worktree> rev-parse HEAD
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
`## Wave log` block (this is the integration-Verify *record*, previously homeless), and only
|
|
178
|
-
then remove the file. Removing WAVE.md before the digest is absorbed is refused
|
|
179
|
-
(`digest_not_absorbed`) — the proof the checks ran must outlive the file.
|
|
180
|
-
|
|
181
|
-
**Resume rule.** On session start, a live WAVE.md is the wave's resume point: re-orient from
|
|
182
|
-
the file — roster, bases, decisions, merge order — never from conversational memory.
|
|
131
|
+
`git -C <worktree> rev-parse HEAD` and must equal `base:`. Filling the row requires running the
|
|
132
|
+
command — words-exist ≠ method-works. Spawning a worker whose roster row lacks that evidence is
|
|
133
|
+
refused (`unverified_fork_base`). On a pool runner the cell holds the worker's **step-0**
|
|
134
|
+
post-sync echo (still `== base:`) and the refusal **shifts to merge-time**.
|
|
135
|
+
|
|
136
|
+
**Lifecycle — open → consume → digest → delete.** Open when the first worker spawns. At wave
|
|
137
|
+
close, absorb the evidence digest — base · roster fork-base · merge order · integration-Verify
|
|
138
|
+
outcome — into `MILESTONE.md` as an append-only `## Wave log` block, then remove the file.
|
|
139
|
+
Removing WAVE.md before the digest is absorbed is refused (`digest_not_absorbed`).
|
|
140
|
+
|
|
141
|
+
**Resume rule.** On session start, a live WAVE.md is the wave's resume point: re-orient from the
|
|
142
|
+
file — roster, bases, decisions, merge order — never from conversational memory.
|
|
183
143
|
|
|
184
144
|
## Merge is serial — integration Verify
|
|
185
145
|
|
|
186
|
-
Parallel build, **serial integration**. After workers return,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
still conflict when merged; this step is where that surfaces. Never auto-pass it.
|
|
146
|
+
Parallel build, **serial integration**. After workers return, merge worktrees one at a time and
|
|
147
|
+
run the **integration** Verify — the concurrency / architecture / layering checks automation
|
|
148
|
+
cannot judge. Two green tasks in isolation can still conflict when merged. Never auto-pass it.
|
|
190
149
|
|
|
191
150
|
Each worktree carries a full copy of `.add/`. Merge back **only** `src/`, `tests/`, and the
|
|
192
151
|
worker's own `.add/tasks/<slug>/` (TASK.md · SUMMARY.md) — `.add/state.json`, `MILESTONE.md`,
|
|
193
|
-
and the live `WAVE.md` stay orchestrator-owned
|
|
152
|
+
and the live `WAVE.md` stay orchestrator-owned.
|
|
194
153
|
|
|
195
154
|
## The worker contract — portable across coding agents
|
|
196
155
|
|
|
197
|
-
A worker **is** the dynamic run (`run.md`) for one task.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
no model, no spawn API. It is a durable ADD artifact, like the spec and the tests.
|
|
201
|
-
- **The adapter** (next sections) — the thin, swappable mapping that tells *one* runner
|
|
202
|
-
(Claude Code · Codex · opencode · pi-mono · any CLI agent) how to launch the contract.
|
|
203
|
-
|
|
204
|
-
This split is the whole point: the same frozen contract runs on any agent; only the adapter
|
|
205
|
-
changes. Fill every `{{...}}` per stream. The ADD-specific value is `<touch_boundary>` + the
|
|
206
|
-
"return a verdict, never write shared state" rule — they are identical on every runner.
|
|
156
|
+
A worker **is** the dynamic run (`run.md`) for one task. The contract below is **agent-agnostic**:
|
|
157
|
+
no vendor tool, no model, no spawn API — a durable ADD artifact. The adapter (next sections) is
|
|
158
|
+
the thin, swappable mapping for one runner. Fill every `{{...}}` per stream.
|
|
207
159
|
|
|
208
160
|
```xml
|
|
209
161
|
<!-- PROMPT.md — dropped into the worker's worktree, or passed inline. No runner-specific tokens. -->
|
|
@@ -227,7 +179,7 @@ Score confidence (0-1) on Completeness · Clarity · Practicality · Optimizatio
|
|
|
227
179
|
Self-Eval; if any < 0.9, refine before returning.
|
|
228
180
|
</persona>
|
|
229
181
|
|
|
230
|
-
<touch_boundary> <!-- from run.md
|
|
182
|
+
<touch_boundary> <!-- from run.md; the worker's contract, identical on every runner -->
|
|
231
183
|
MAY: rewrite code in src/ · drive tests green WITHOUT weakening them · gather verify evidence.
|
|
232
184
|
MUST NOT: edit the frozen CONTRACT or locked scope · weaken/delete/skip any test ·
|
|
233
185
|
touch §1–§3 bundle artifacts · write MILESTONE.md / state.json / any sibling stream.
|
|
@@ -235,7 +187,7 @@ STOP-and-escalate (return your findings; do not decide):
|
|
|
235
187
|
• a discovered scope/contract gap → backward-correction, reopen Specify (principle 4)
|
|
236
188
|
• any SECURITY finding → HARD-STOP, always
|
|
237
189
|
• a concurrency/timing OR architecture/layering risk the tests cannot exercise
|
|
238
|
-
• [include this bullet when autonomy is conservative OR manual
|
|
190
|
+
• [include this bullet when autonomy is conservative OR manual] the verify gate itself — STOP for the human
|
|
239
191
|
Auto-PASS only if autonomy=auto AND: all tests green · coverage not decreased · no test weakened ·
|
|
240
192
|
no contract edited · loops dry · completeness-critic clean · no residue above. Log it as
|
|
241
193
|
auto-resolved, naming this run as owner — never forge a human signature.
|
|
@@ -247,9 +199,8 @@ Auto-PASS only if autonomy=auto AND: all tests green · coverage not decreased
|
|
|
247
199
|
</context_files>
|
|
248
200
|
|
|
249
201
|
<expertise>
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
If it does not, the persona IS your expertise.
|
|
202
|
+
If your runner supports specialist injection (a Claude Code skill, a system-prompt preamble, an
|
|
203
|
+
agent profile), load the one matching {{DOMAIN}}. Otherwise the persona above IS your expertise.
|
|
253
204
|
</expertise>
|
|
254
205
|
|
|
255
206
|
<tools>
|
|
@@ -259,8 +210,8 @@ ripgrep otherwise. Design every IO path for failure — timeouts, retries, rollb
|
|
|
259
210
|
|
|
260
211
|
<return> <!-- the worker PROPOSES; the orchestrator RECORDS. A worker never runs add.py. -->
|
|
261
212
|
End with a structured verdict AND write the same into SUMMARY.md in the task dir, then
|
|
262
|
-
**commit SUMMARY.md + deltas.md** in the worktree (uncommitted
|
|
263
|
-
|
|
213
|
+
**commit SUMMARY.md + deltas.md** in the worktree (uncommitted files survive only by harness
|
|
214
|
+
courtesy — commit them so the serial-integration merge-back carries your report):
|
|
264
215
|
{ task, outcome: PASS|RISK-ACCEPTED|HARD-STOP|ESCALATE, evidence: <tests+coverage>,
|
|
265
216
|
residue: [security|concurrency|architecture findings], deltas: [open lessons learned] }.
|
|
266
217
|
Do NOT touch add.py or any shared file — the orchestrator gates on your verdict.
|
|
@@ -270,23 +221,20 @@ Do NOT touch add.py or any shared file — the orchestrator gates on your verdic
|
|
|
270
221
|
## Choosing the model — vendor-neutral tiers
|
|
271
222
|
|
|
272
223
|
ADD picks a **tier** from the scope's nature; the adapter maps the tier to the runner's model id.
|
|
273
|
-
The contract is identical whichever model runs it (the model is disposable, like the code):
|
|
274
224
|
|
|
275
225
|
| Tier | When | Claude Code | Any other runner |
|
|
276
226
|
|------|------|-------------|------------------|
|
|
277
227
|
| **mid** | ordinary, well-tested scope; clear contract | `sonnet` | the runner's balanced model |
|
|
278
228
|
| **top** | complex / ambiguous / cross-cutting / broad scope of impact | `opus` | the runner's strongest reasoning model |
|
|
279
229
|
|
|
280
|
-
Two rules sit **above** model choice
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
- **Security residue always escalates** — no tier and no model auto-passes it.
|
|
230
|
+
Two rules sit **above** model choice: **high-risk ⇒ a lowered rung (`conservative` or `manual`),
|
|
231
|
+
regardless of model** — a stronger model does not buy back the human gate. And **security residue
|
|
232
|
+
always escalates** — no tier auto-passes it.
|
|
284
233
|
|
|
285
234
|
## The spawn adapter — one thin mapping per runner
|
|
286
235
|
|
|
287
236
|
ADD needs six capabilities from any runner. **Isolation is the one ADD owns itself** (a git
|
|
288
|
-
worktree), so streams stay portable even on a runner with no native sandbox
|
|
289
|
-
worktree, then points the agent at that directory.
|
|
237
|
+
worktree), so streams stay portable even on a runner with no native sandbox.
|
|
290
238
|
|
|
291
239
|
| ADD needs | Abstract | Claude Code (verified reference) | Any CLI agent — Codex · opencode · pi-mono · … |
|
|
292
240
|
|-----------|----------|----------------------------------|-----------------------------------------------|
|
|
@@ -297,16 +245,9 @@ worktree, then points the agent at that directory.
|
|
|
297
245
|
| domain expertise | skill / preamble | a Claude skill in `<expertise>` | a system-prompt / profile preamble |
|
|
298
246
|
| return a verdict | structured | final message (optionally a schema) | stdout JSON the orchestrator parses |
|
|
299
247
|
|
|
300
|
-
The **hint of `Task` spawn** is the Claude Code column — the worked reference. For any other
|
|
301
|
-
agent the recipe is the same shape: `git worktree add` → point the agent CLI at that dir with
|
|
302
|
-
the chosen model → it reads `PROMPT.md` → you parse its verdict.
|
|
303
|
-
|
|
304
248
|
> **Honesty:** only the Claude Code column is verified. The CLI forms for Codex/opencode/pi-mono
|
|
305
|
-
> are *illustrative shapes
|
|
306
|
-
> confirm with the `find-docs` skill. The portable, durable parts are the **contract** and the
|
|
307
|
-
> **six-capability mapping**, never any one runner's flags.
|
|
249
|
+
> are *illustrative shapes* — confirm exact syntax with the `find-docs` skill.
|
|
308
250
|
|
|
309
251
|
When workers return, **you** record each outcome with the explicit slug — `add.py advance <slug>`
|
|
310
252
|
as evidence lands, `add.py gate PASS|RISK-ACCEPTED|HARD-STOP <slug>` at verify — then re-read
|
|
311
|
-
`status` to refill the READY-QUEUE. The worker proposes
|
|
312
|
-
That split is exactly what lets a non-Claude worker take part without ever touching shared state.
|
|
253
|
+
`status` to refill the READY-QUEUE. The worker proposes; the orchestrator records.
|