@pilotspace/add 1.12.0 → 1.14.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.
@@ -16,11 +16,11 @@
16
16
 
17
17
  **Co-specification** — how a spec is made in ADD: the AI and the human **brainstorm the shape together** (diverge), the AI **drafts** it, and the human **validates with the AI's advice** (validate). The AI's decisive advice is the *lowest-confidence flag*. It replaces dictation-by-one-side — the human owns the decision, the AI owns surfacing what it does not yet know. See [03 Specify](./03-step-1-specify.md).
18
18
 
19
- **Component** — a declared part of a multi-part codebase that owns a source `root` and its own `green-bar` (suite + checks), named in `.add/components.toml` under `[component.<name>]`. A task binds to one with a `component:` header line, which adds that root to its §5 Scope and holds it to that component's green bar at verify. Declared, never inferred; a project with no components is byte-identical to a single-codebase project. See [17 Components](./17-components.md).
19
+ **Component** — a declared part of a multi-part codebase that owns a source `root` and its own `green-bar` (suite + checks), named in `.add/components.toml` under `[component.<name>]`. A task binds to one with a `component:` header line, which adds that root to its §5 Scope and holds it to that component's green bar at verify. At the gate the engine also **surfaces** the component's `verify` command (the literal suite to run, e.g. `pytest -q`) and records it — NO-EXEC, the operator runs it; the fast lane carries the same `component:` affordance. Declared, never inferred; a project with no components is byte-identical to a single-codebase project. See [17 Components](./17-components.md).
20
20
 
21
- **Cross-component contract** — the frozen, machine-checkable interface between a producer component and its consumers, declared under `[contract.<id>]` (producer + consumers). A task names its role with a `produces: <id>` or `consumes: <id>` header. On the producer's freeze the engine writes an immutable snapshot at `.add/contracts/<id>.json`; a consumer pins its hash and is flagged `contract_consumer_stale` if the producer later re-freezes a changed shape. Inside one milestone a `consumes:` task is HELD from writing its §3 until the producer's snapshot exists — the intra-milestone BE→FE ordering. See [17 Components](./17-components.md).
21
+ **Cross-component contract** — the frozen, machine-checkable interface between a producer component and its consumers, declared under `[contract.<id>]` (producer + consumers). A task names its role with a `produces: <id>` or `consumes: <id>` header. On the producer's freeze the engine writes an immutable snapshot at `.add/contracts/<id>.json`; a consumer pins its hash and is flagged `contract_consumer_stale` if the producer later re-freezes a changed shape. Inside one milestone a `consumes:` task is HELD from writing its §3 until the producer's snapshot exists — the intra-milestone BE→FE ordering. Freeze-recency: the consumer is also held `producer_contract_stale` if a *live* producer task has re-opened or drifted its §3 (the snapshot no longer matches a frozen producer); `add.py check` surfaces the softer `contract_producer_stale` and `contract_snapshot_hashless` (a snapshot with no hash to verify) as never-red warnings. See [17 Components](./17-components.md).
22
22
 
23
- **Federation (multi-repo)** — the transport that carries a frozen cross-component contract between separate repositories. A consumer repo declares `[federation.<id>]` with a `source` (and optional `pin`); `add.py federate pull <id>` validates the producer repo's published snapshot and lands a byte-for-byte copy locally, where it behaves exactly as in a monorepo. Fail-loud: an unknown id, unreadable source, invalid snapshot, or version mismatch HARD-STOPS and lands nothing. Each repo keeps its own git-native `state.json`; only the immutable snapshot crosses. See [17 Components](./17-components.md).
23
+ **Federation (multi-repo)** — the transport that carries a frozen cross-component contract between separate repositories. A consumer repo declares `[federation.<id>]` with a `source` (and optional `pin`); `add.py federate pull <id>` validates the producer repo's published snapshot and lands a byte-for-byte copy locally, where it behaves exactly as in a monorepo. Fail-loud: an unknown id, unreadable source, a `source` that escapes the repo's allowlist (`federation_source_escapes` — the path is confined to a sibling of the repo root), invalid snapshot, or version mismatch HARD-STOPS and lands nothing. Each repo keeps its own git-native `state.json`; only the immutable snapshot crosses. See [17 Components](./17-components.md).
24
24
 
25
25
  **Disposable code** — the view that code is one regenerable implementation of the artifacts, not a durable asset to be preserved.
26
26
 
@@ -46,6 +46,8 @@
46
46
 
47
47
  **Onboarding** (formerly "on-ramp") — the path a new user walks from install to their first milestone: install → `/add` → describe the goal → the agent runs intake (sizing the request into a milestone the human confirms) → the specification bundle → the self-driving run. The AI-first entry to the method; the human talks to the agent rather than hand-typing `add.py`.
48
48
 
49
+ **Decisions (ADR)** — the engine-harvested record in a task's §7 OBSERVE: one actor-tagged line per key decision, gathered at the gate from the stamps already in the task — §1 framing `[AI]` (the choice + the rejected alternatives), §3 freeze `[human]`, §5 strategy-actually-used `[AI]`, §6 gate `[human|AI]`. *Harvested, never authored* — the engine invents no decision content, only mirrors what the task recorded — and scoped to the §7 OBSERVE placeholder alone. The durable who-decided-what trail that separates human direction from AI building; `add.py audit` flags a done task whose block never harvested (`adr_record_missing`).
50
+
49
51
  **Decision point** (formerly "seam") — a place where the flow stops for human judgment: the contract-freeze approval (the one approval), an escalated verify gate, intake confirmation, milestone close. The machine layer keeps the legacy name: the `--json` owner enum `seam`, the decide-digest key `seam`, and the `seam-audit` CI job.
50
52
 
51
53
  **The decision arc** — the three engine-sourced lines a gate report opens with at every **decision point**: `goal:` the milestone goal the work serves · `done:` the achievement, the proven progress toward it (the gate reports render this line as `done`) · `plan:` what comes next. What `done` reports adapts per gate (verify: tests + evidence · milestone close: exit-criteria met · intake: the request sized) while the three-part shape stays constant. Rendered first, above the report's summary, so the human confirms with sight of the whole trajectory, not a local snapshot. Engine-sourced like all evidence — goal · done · plan are pulled from `add.py` output, never re-typed. Presentation only: it never adds a gate or changes a `PASS` / `RISK-ACCEPTED` / `HARD-STOP` / freeze outcome. The report it opens is the chat report a person reads at a decision point — distinct from the three Test/Quality/Risk reports a verify gate produces ([11 Governance](./11-governance.md)). See the `add` skill's `report-template.md`.
@@ -100,7 +102,7 @@
100
102
 
101
103
  **Release steps** — the AI-defined, per-milestone ordered hints to ship a closed milestone, of which `merge` is one small step (a pull request, an exported hand-off document, a tag or a publish are others). Defined at close and **fed** into the release scope (see **Release**), never a second flow.
102
104
 
103
- **Readiness floor** — the engine-enforced pre-cut gate `add.py release` applies before it records anything: a green suite, zero open security `HARD-STOP`, a closed-and-unreleased milestone to bundle, and every riding `RISK-ACCEPTED` waiver disclosed in the notes. Its four rejects are `release_security_open` (un-forceable) · `release_tests_red` · `release_no_closed_milestone` · `release_undisclosed_waiver`; `--force` may override every reject except the security stop.
105
+ **Readiness floor** — the engine-enforced pre-cut gate `add.py release` applies before it records anything: a green suite, zero open security `HARD-STOP`, a closed-and-unreleased milestone to bundle, and every riding `RISK-ACCEPTED` waiver disclosed in the notes. Its four rejects are `release_security_open` (un-forceable) · `release_build_in_flight` · `release_no_closed_milestone` · `release_undisclosed_waiver`; `--force` may override every reject except the security stop.
104
106
 
105
107
  **RELEASES.md ledger** — the append-only, newest-first trail of release rows at the project root (date · version · milestones · waivers shipped · evidence). Like the §Key Decisions log it is never rewritten; a superseded or yanked version is recorded as a new row. The ledger is the attribution source — a milestone is "released" because a row says so — which is why the `→ releasable` cue never has to read a milestone file.
106
108
 
@@ -150,3 +150,82 @@ A week later, telemetry shows an unexpectedly high `forbidden` rate. The `6_obse
150
150
  ---
151
151
 
152
152
  This is the whole method in one feature: four artifacts written in order, an AI build bounded by them, a verification grounded in evidence plus the one check tests miss, and a loop that turns production reality into the next specification.
153
+
154
+ ---
155
+
156
+ ## Multi-component, end to end
157
+
158
+ The example above is a single codebase with one green bar. Real slices often cross components — a backend endpoint and the frontend that calls it. ADD ships that slice *inside one milestone* using the component pillar (chapter 17). Here is the same flow, now spanning two components: a `gateway` backend that **produces** an `orders` contract, and a `web` frontend that **consumes** it.
159
+
160
+ ### Declare the components
161
+
162
+ The two parts and the boundary between them are declared in `.add/components.toml` — never inferred:
163
+
164
+ ```toml
165
+ [component.gateway]
166
+ root = "apps/gateway"
167
+ green_bar = "pytest + pyright"
168
+ verify = "pytest -q apps/gateway"
169
+
170
+ [component.web]
171
+ root = "apps/web"
172
+ green_bar = "vitest + a11y"
173
+ verify = "pnpm -C apps/web test"
174
+
175
+ [contract.orders]
176
+ producer = "gateway"
177
+ consumers = ["web"]
178
+ ```
179
+
180
+ One milestone, **list-orders slice**, holds two tasks: `orders-api` (the BE, `produces: orders`) and `orders-list` (the FE, `consumes: orders`).
181
+
182
+ ### The backend freezes first → an immutable snapshot
183
+
184
+ `orders-api` carries a `component: gateway` and a `produces: orders` header. It runs the normal flow — specify, scenarios, contract — and the human freezes its §3:
185
+
186
+ ```
187
+ GET /orders?status= -> 200 { orders: [{ id, status, total, placedAt }], nextCursor }
188
+ 400 { error: "bad_status" }
189
+ Status: FROZEN @ v1 — approved by the tech lead
190
+ ```
191
+
192
+ The moment that contract freezes and the task crosses contract→tests, the engine writes an immutable snapshot — `.add/contracts/orders.json` — recording the id, producer, version, frozen date, and a hash over the frozen §3 shape. That file *is* the published interface.
193
+
194
+ ### The frontend is held until the backend freezes
195
+
196
+ `orders-list` (`component: web`, `consumes: orders`) was started in the same milestone, but it must not commit to a shape the backend has not frozen. When it tries to advance scenarios→contract before the snapshot exists, the engine refuses:
197
+
198
+ ```
199
+ $ python3 .add/tooling/add.py advance
200
+ add: error: producer_contract_unfrozen: orders-list consumes 'orders' but no frozen producer snapshot exists yet — the FE is held until gateway freezes
201
+ ```
202
+
203
+ Once `orders.json` exists, the same `advance` succeeds: the FE writes its §3 against the frozen shape and **pins that snapshot's hash**. The slice is ordered by the contract, not by splitting BE and FE across two milestones.
204
+
205
+ If the backend later *re-opens* its §3 to change the shape, the engine holds the consumer `producer_contract_stale` rather than letting it pin a shape that is mid-change — and `add.py check` separately surfaces `contract_producer_stale` / `contract_snapshot_hashless` as never-red warnings. Freeze-recency, not just existence.
206
+
207
+ ### Each task verifies against its own green bar
208
+
209
+ At the gate, the engine holds each task to *its* component. `orders-api` must cite `pytest + pyright` in its §6 evidence; `orders-list` must cite `vitest + a11y` — cite the wrong bar (or none) and the gate refuses `component_green_bar_uncited`. The engine never runs either suite; it **surfaces** the component's `verify` command so the operator sees exactly what to run:
210
+
211
+ ```
212
+ $ python3 .add/tooling/add.py gate PASS
213
+ task 'orders-api' gate -> PASS
214
+ component: gateway · expected green-bar: pytest + pyright · verify: pytest -q apps/gateway # run this suite — the engine does not (NO-EXEC)
215
+ ```
216
+
217
+ Two tasks, one milestone, two green bars — each held to its own, each suite run by you.
218
+
219
+ ### Across repositories — federation
220
+
221
+ When `gateway` and `web` live in *separate* repos, only the snapshot transport changes. The `web` repo declares where the producer publishes:
222
+
223
+ ```toml
224
+ [federation.orders]
225
+ source = "../gateway/.add/contracts/orders.json"
226
+ pin = "v1"
227
+ ```
228
+
229
+ `add.py federate pull orders` validates the producer repo's published snapshot (valid JSON, matching id, a hash, matching version) and lands a byte-for-byte copy locally — from there the FE holds and pins exactly as in a monorepo. The pull is fail-loud: an unknown id, an unreadable source, a `source` that escapes the repo's allowlist (`federation_source_escapes`), an invalid snapshot, or a version mismatch each HARD-STOPS and lands nothing. Federation never builds the FE against a guessed, out-of-tree, or stale endpoint.
230
+
231
+ That is the component pillar in one slice: declare the parts, freeze the boundary, hold the consumer behind the producer, verify each part on its own bar, and carry the frozen contract across repos — all within the same six-step flow and its single contract-freeze approval.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pilotspace/add",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "ADD (AI-Driven Development). One skill. Eight steps. Five disciplines. Every feature ships through the loop — a minimal, state-tracked Claude Code skill that ships the AIDD book as its trust layer.",
5
5
  "bin": {
6
6
  "add": "bin/cli.js"
@@ -15,7 +15,7 @@ user-invocable: true
15
15
  when_to_use: "Invoke in any repo with a `.add/` directory, or when the user wants spec/tests-first feature work, resumes ADD work, or asks to start/advance a task."
16
16
  category: workflows
17
17
  keywords: [add, aidd, ai-driven-development, spec-first, tdd, contract, scenarios, verify, milestone, task-orchestration]
18
- argument-hint: "status | init | continue | [describe new short goals or expectation]"
18
+ argument-hint: "status | init | continue | --todo <text> | [describe new short goals or expectation]"
19
19
  license: MIT
20
20
  metadata:
21
21
  author: add
@@ -32,6 +32,10 @@ result through passing evidence rather than a plausible-looking diff.
32
32
  preamble plus seven step sections, filled top to bottom. The Python tool tracks where you
33
33
  are so context never rots across sessions.
34
34
 
35
+ **The `--todo` fast-path.** When the skill ARGUMENTS begin with `--todo`, skip orienting: route to
36
+ `add.py todo` and print its output — `--todo <text>` captures · `--todo` lists open todos ·
37
+ `--todo --done <id>` closes (engine errors surfaced verbatim) — then STOP.
38
+
35
39
  ## Always start here (orient — do not skip)
36
40
 
37
41
  Engine: `.add/tooling/add.py` · book: `.add/docs/`. Ensure the engine is in the project first:
@@ -24,7 +24,7 @@ independent enough to earn it. When in doubt, do it in-context.
24
24
 
25
25
  Give the subagent the *piece of your plan it owns* and a fixed return shape. This reuses
26
26
  `streams.md`'s worker-contract tags for a single advisory subagent — the contract is identical
27
- on any runner; only the spawn adapter (see `streams.md`) changes.
27
+ on any runner; only the spawn adapter (see `streams.md`) changes. The `<strategy>` block mirrors the task's §5 (Strategy + Known-problem fixes) as the subagent's PREFERRED path — it self-improves on that plan and reports the strategy it actually used.
28
28
 
29
29
  ```xml
30
30
  <objective>
@@ -40,6 +40,13 @@ Work step by step, following the plan:
40
40
  3. Self-score your result with confidence.md; if any dimension < 0.9, refine before returning.
41
41
  </persona>
42
42
 
43
+ <strategy>
44
+ The task's §5 plan — the Strategy (ordered batches) order and the Known-problem fixes — is
45
+ your PREFERRED starting path, not a hard rule. Improve on it when a better strategy emerges
46
+ as you build; on done, report the strategy you ACTUALLY used so the orchestrator can update
47
+ §5 for the audit trail.
48
+ </strategy>
49
+
43
50
  <context_files>
44
51
  the plan / task files the piece needs (read-only unless the piece says otherwise)
45
52
  </context_files>
@@ -1,10 +1,8 @@
1
1
  # Components — monorepo and multi-repo slices
2
2
 
3
- Opt-in pillar for a milestone that spans **more than one green bar** — a backend
4
- and its frontend, a shared lib and two apps, services across repos. A project
5
- that declares no components is byte-identical to a single-codebase project. Reach
6
- for this only when one milestone genuinely crosses components. Full narrative:
7
- book chapter `17-components.md`.
3
+ Opt-in pillar for a milestone spanning **more than one green bar** — a BE + its
4
+ FE, a shared lib + two apps, services across repos. No components declared =
5
+ byte-identical to a single-codebase project. Full narrative: `17-components.md`.
8
6
 
9
7
  ## Declare (never inferred)
10
8
 
@@ -13,21 +11,21 @@ book chapter `17-components.md`.
13
11
  ```toml
14
12
  [component.gateway]
15
13
  root = "apps/gateway"
16
- green-bar = "pytest + pyright"
14
+ green_bar = "pytest + pyright"
17
15
  [component.dashboard]
18
16
  root = "apps/web"
19
- green-bar = "vitest + a11y"
17
+ green_bar = "vitest + a11y"
20
18
  ```
21
19
 
22
- A task binds with a `component: <name>` header line → that root joins its §5
23
- Scope, and verify holds it to that component's green-bar.
20
+ A task binds with a `component: <name>` header → that root joins its §5 Scope,
21
+ and verify holds it to that component's green-bar.
24
22
 
25
23
  ## The loop
26
24
 
27
- 1. **Per-component verify.** A bound task must CITE its component's green-bar in
28
- the §6 Build-expectations evidence, or the gate refuses
29
- `component_green_bar_uncited`. The engine never runs the suite you run the
30
- right one; the gate checks the right bar was cited.
25
+ 1. **Per-component verify.** A bound task must CITE its green-bar in §6 evidence
26
+ or the gate refuses `component_green_bar_uncited`. The engine never runs the
27
+ suite it **surfaces** the component's `verify` command (and records it in §6);
28
+ you run it (NO-EXEC). The fast lane carries the same `component:` affordance.
31
29
  2. **Freeze a cross-component contract.** Declare `[contract.<id>]`
32
30
  (producer + consumers). A task names its role `produces: <id>` / `consumes: <id>`.
33
31
  The producer's freeze (contract→tests) writes the immutable snapshot
@@ -35,20 +33,20 @@ Scope, and verify holds it to that component's green-bar.
35
33
  flags consumers `contract_consumer_stale`; a missing/malformed snapshot
36
34
  HARD-STOPS — never build against an unfrozen shape.
37
35
  3. **One milestone, full slice.** A `consumes:` task is HELD from advancing
38
- scenarios→contract (`producer_contract_unfrozen`) until the producer's
39
- snapshot exists. The FE stays downstream of the frozen BE endpoint, in one
40
- milestone.
36
+ scenarios→contract (`producer_contract_unfrozen`) until the producer's snapshot
37
+ exists and `producer_contract_stale` if a live producer re-opened/drifted its
38
+ §3 (freeze-recency). The FE stays downstream of the frozen BE, in one milestone.
41
39
  4. **Across repos — federate.** A consumer repo declares `[federation.<id>]`
42
40
  (`source` + optional `pin`); `add.py federate pull <id>` validates and lands a
43
- byte-for-byte copy of the producer repo's published snapshot locally, where it
44
- behaves as in a monorepo. Fail-loud: unknown id / unreadable source / invalid
41
+ byte-for-byte copy of the producer's snapshot locally. Fail-loud:
42
+ unknown id / unreadable source / a `source` escaping the repo's allowlist
43
+ (`federation_source_escapes`, confined to a repo-root sibling) / invalid
45
44
  snapshot / version mismatch each HARD-STOPS and lands nothing.
46
45
 
47
46
  ## Hold the line
48
47
 
49
48
  - **Declared, not inferred** — no scanning `apps/*`.
50
- - **No central server / no shared mutable state** — federation copies an
51
- immutable snapshot; each repo keeps its own git-native `state.json`.
52
- - **No new approval** — these are engine-enforced gates on the existing six-step
53
- flow, not extra human checkpoints. Ownership/autonomy per component is the
54
- identity story (`streams.md`, governance), layered on this graph.
49
+ - **No central server / no shared mutable state** — federation copies an immutable
50
+ snapshot; each repo keeps its own `state.json`.
51
+ - **No new approval** — engine-enforced gates on the six-step flow, not extra human
52
+ checkpoints. Per-component ownership/autonomy is the identity story (`streams.md`).
@@ -16,7 +16,7 @@ tests, iterate to green. Keep each batch small enough to review in full.
16
16
  - **Scope (may touch)** — the allowlist of every file the build may write (backticked tokens). Needing a file outside the declared Scope is a **STOP → change request** back to Specify, never improvisation.
17
17
  - **Strategy (ordered batches)** — the planned build order. Guidance, not enforced.
18
18
 
19
- Deferral, named: the engine gate (touched declared) lands in the `scope-gate-enforce` task until it ships this section is prose discipline.
19
+ Enforced: a completing verify gate refuses an out-of-scope build (`scope_violation` self-heal); `add.py check` surfaces it.
20
20
 
21
21
  ## The cardinal rule
22
22
 
@@ -3,16 +3,15 @@
3
3
  Goal: establish trust and record an outcome. Passing tests are necessary, not
4
4
  sufficient. Fill **§6** in TASK.md including the GATE RECORD.
5
5
 
6
- > **Who resolves this gate depends on the `autonomy:` header (see `run.md`).**
7
- > Under `autonomy: auto` (the default) a run auto-PASSes once evidence is complete
8
- > every test green, convergence loops dry, and **no residue** (security · concurrency · architecture) —
9
- > recorded as *auto-resolved* with the named run as accountable owner. **Security is
10
- > always a HARD-STOP and is never auto-passed.** Under `autonomy: conservative`, or
11
- > whenever residue is found, this phase is **human-led**.
6
+ > **Who resolves this gate depends on the `autonomy:` header.** Under `autonomy: auto` (the default)
7
+ > a run auto-PASSes on complete evidence with **no residue** (security · concurrency · architecture),
8
+ > recorded *auto-resolved* with the named run as owner;
9
+ > **security is always a HARD-STOP and is never auto-passed**. Under `conservative`, or whenever
10
+ > residue is found, this phase is **human-led** (auto-PASS conditions: `run.md`).
12
11
 
13
12
  ## Before you build — declare the build expectations
14
13
 
15
- Fill the §6 **Build expectations** block BEFORE Build: OBSERVABLE outcomes derived from §2 SCENARIOS + §3 CONTRACT. At this gate, confirm each against real evidence (the `confirmed by` column). An expectation with no evidence is not yet verified.
14
+ Fill the §6 **Build expectations** block BEFORE Build: OBSERVABLE outcomes derived from §2 + §3. At this gate, confirm each against real evidence (the `confirmed by` column) one with no evidence is not yet verified.
16
15
 
17
16
  ## Part one — confirm the evidence
18
17
 
@@ -26,22 +25,22 @@ If any is false, stop and return to Build.
26
25
  ## Part two — check what tests miss
27
26
 
28
27
  - **Concurrency/timing** — correct when two run at once? (Tests run serially and miss races.)
29
- - **Security** — exposed secrets, injection openings, unexpected dependencies. A security finding is always `HARD-STOP`, never a waiver. ANY note here escalates to the human — start it with `NOTE` or `⚠` so `add.py audit` can see it (`unescalated_security_note`).
28
+ - **Security** — exposed secrets, injection openings, unexpected dependencies. A security finding is always `HARD-STOP`, never a waiver. ANY note here escalates to the human — start it with `NOTE` or `⚠` so `add.py audit` can see it (`unescalated_security_note`). **But that check sees only what you wrote down:** it fires on a *marked* note that slipped through as an auto-gate PASS — a finding you never marked is **invisible** to the engine, escalated to no one. Honest disclosure, not false cover: under `auto`, a human **spot-audit** (reading the diff) is the only backstop for a *missed* security finding.
30
29
  - **Architecture** — respects layering/dependency rules in CONVENTIONS.md?
31
30
 
32
31
  ## Part three — the deep check (do not skim)
33
32
 
34
- Deep check — do not skim. If the task produced code, record that every new symbol is referenced (wiring) and that no new dead/unused code was introduced. If it produced prose or non-code, record a semantic read — what you read in full and what it confirmed. Which path applies is the resolver's judgement; the engine never classifies.
33
+ If the task produced code, record that every new symbol is referenced (wiring) and that no new dead/unused code was introduced. If it produced prose or non-code, record a semantic read — what you read in full and what it confirmed. The resolver judges which path; the engine never classifies.
35
34
 
36
- Record it in the §6 **Deep checks** block. An unfilled Deep checks block is a **shallow verify**, not a PASS.
35
+ Record it in the §6 **Deep checks** block an unfilled one is a **shallow verify**, not a PASS.
37
36
 
38
37
  ## Part four — was the green earned?
39
38
 
40
- A green suite proves tests pass — not that the build EARNED them. Three judgment cheats pass the unchanged suite: src overfit to the test fixtures (special-cased to literal inputs), vacuous asserts (tautological — green against an empty implementation), and real logic stubbed away. These are invisible to the mechanical tamper tripwire. Score them with an adversarial refute-read: an independent reviewer — the engine never spawns one — prompted to argue the green was NOT earned. A confirmed earned-green failure is HARD-STOP-class: never auto-passed, never RISK-ACCEPTED — a first cheat enters the bounded self-heal loop (run.md).
39
+ A green suite proves tests pass — not that the build EARNED them. Three judgment cheats pass the unchanged suite: src overfit to the test fixtures (special-cased to literal inputs), vacuous asserts (green against an empty implementation), and real logic stubbed away all invisible to the mechanical tamper tripwire. Score them with an adversarial refute-read: an independent reviewer — the engine never spawns one — prompted to argue the green was NOT earned. A confirmed earned-green failure is HARD-STOP-class: never auto-passed, never RISK-ACCEPTED — a first cheat enters the bounded self-heal loop (run.md). Under `auto`, **record the verdict** in §6's `### Refute-read verdict` block — `add.py audit` flags an unrecorded `refute_unrecorded`, one of three measure-not-block shape lints it surfaces (also `shallow_deep_check` + `risk_unset`).
41
40
 
42
41
  ## Record exactly one outcome (no silent pass)
43
42
 
44
- When you present this gate, open with the ARC per `report-template.md`, render the DECISION as a guided choice, and reconcile FLAGS with `add.py report --decide`'s open-item count before the ask.
43
+ Present this gate via `report-template.md`'s ARC, render DECISION as a guided choice, and reconcile FLAGS with `add.py report --decide`'s open-item count first.
45
44
 
46
45
  | Outcome | When |
47
46
  |---------|------|
@@ -53,10 +52,10 @@ When you present this gate, open with the ARC per `report-template.md`, render t
53
52
 
54
53
  <exit_gate>
55
54
  - [ ] Evidence confirmed, non-functional risks checked, outcome recorded — a person approved, or
56
- (under `autonomy: auto` with no residue) the run auto-resolved as the accountable owner.
55
+ (under `autonomy: auto`, no residue) the run auto-resolved as accountable owner.
57
56
  </exit_gate>
58
57
 
59
- > **Advisor · Confidence** — the earned-green refute-read is the canonical adversarial spawn (advisor.md); score the verdict before you record the gate (confidence.md).
58
+ > **Advisor · Confidence** — the earned-green refute-read is the canonical adversarial spawn (advisor.md); score it before recording the gate (confidence.md).
60
59
 
61
60
  ```bash
62
61
  python3 .add/tooling/add.py gate PASS # marks the task done
@@ -1,20 +1,21 @@
1
1
  # Phase 7 — Observe (feed the next loop)
2
2
 
3
- Goal: release deliberately, watch reality, and turn what you learn into the next spec. Fill **§7** in TASK.md.
3
+ Goal: release deliberately, watch reality, turn what you learn into the next spec. Fill **§7** in TASK.md.
4
4
 
5
5
  ## Do
6
6
 
7
- 1. **Release behind a scope-of-impact limit** — feature flag and/or gradual rollout.
7
+ 1. **Release behind a scope-of-impact limit** — a flag and/or gradual rollout.
8
8
  2. **Reuse scenarios as monitors** — the §2 scenarios that defined "correct" now
9
- define what you alert on: overall error rate, each rejection's rate (a spike in
10
- one is a signal), latency of the risky operation under load.
9
+ define what you alert on: overall error rate, each rejection's rate (a spike is a
10
+ signal), latency of the risky op under load.
11
11
  3. **Draft the next spec delta** — every defect, surprise, or new need becomes a
12
- concrete change that re-enters the flow at Specify (a new task).
13
- 4. **Propose a voice delta** — you just worked a whole task alongside the human, so
14
- notice where your voice diverged from theirs (their wordings + flow) and propose a
15
- confirmable **voice delta** that tunes `SOUL.md`. Emit it `open`; the human confirms;
16
- only then do you rewrite the routed SOUL.md section. Read `soul.md` for the grammar,
17
- the routing, and the human-is-only-writer rule.
12
+ change that re-enters the flow at Specify (a new task).
13
+ 4. **Propose a voice delta** — note where your voice diverged from the human's (wordings +
14
+ flow); propose a confirmable **voice delta** tuning `SOUL.md`, emitted `open`. The human
15
+ confirms, then you rewrite the routed section. Read `soul.md` (grammar, routing,
16
+ human-is-only-writer).
17
+
18
+ > **Decisions (ADR)** — at the gate the engine harvests §7's ADR block (§1/§3/§5/§6); `add.py audit` flags one never harvested.
18
19
 
19
20
  ## AI prompt
20
21
 
@@ -35,7 +35,7 @@ One arc, seven steps: **cue → gather → draft notes → readiness floor → h
35
35
 
36
36
  <reject_codes>
37
37
  - `release_security_open` — open security HARD-STOP exists. Never shipped. `--force` does NOT override this.
38
- - `release_tests_red` — suite not green.
38
+ - `release_build_in_flight` — a build is in flight, ungated.
39
39
  - `release_no_closed_milestone` — nothing new since last release.
40
40
  - `release_undisclosed_waiver` — a RISK-ACCEPTED waiver rides into the release but is absent from the notes.
41
41
  </reject_codes>
package/skill/add/run.md CHANGED
@@ -1,11 +1,9 @@
1
1
  # The dynamic run — executing a locked scope
2
2
 
3
- Once a task's CONTRACT is frozen (phase 3), the scope is *locked*. That lock is ADD's autonomy
4
- decision point — below it code is disposable; above it nothing breaks. This rubric covers the
5
- **build->verify half, executed as a dynamic, self-improving run**. The human-led **specification
6
- bundle** (Specify · Scenarios · Contract) still owns *direction*, but v7 compresses it to a
7
- **single human approval at the decision point** — the AI drafts the whole bundle, a human approves
8
- it once. The engine stays judgment-free: this is a rubric, not `add.py`.
3
+ Once a task's CONTRACT is frozen (phase 3), the scope is *locked* ADD's autonomy decision point:
4
+ below it code is disposable; above it nothing breaks. This rubric covers the **build->verify half,
5
+ executed as a dynamic, self-improving run**. The human-led **specification bundle** (Specify ·
6
+ Scenarios · Contract) still owns *direction*. The engine stays judgment-free: this is a rubric, not `add.py`.
9
7
 
10
8
  ## The specification bundle (v7)
11
9
 
@@ -14,19 +12,18 @@ bundle in one pass** — Spec, Scenarios, Contract, and failing Tests — and pr
14
12
  The human gives **one approval, at the frozen contract** (the decision point).
15
13
 
16
14
  Why one and not zero: the decision point **stays human**. The AI *drafts* the contract but never
17
- *freezes its own* — a person approves the frozen shape before any auto-run touches code. What the
18
- human approves: that the Spec captures real intent, the Scenarios cover the cases that matter, and
19
- the Contract shape is the one to freeze. Reject any part and the bundle goes back to draft
20
- backward-correction (principle 4), not failure. The decision-point guide (`phases/3-contract.md`) carries the **freeze review checklist** —
21
- seven lines that walk the human through exactly this, ⚠-first.
15
+ *freezes its own* — a person approves the frozen shape before any auto-run touches code: that the
16
+ Spec captures real intent, the Scenarios cover the cases that matter, and the Contract shape is the
17
+ one to freeze. Reject any part back to draft (backward-correction, principle 4, not failure). The
18
+ decision-point guide (`phases/3-contract.md`) carries the **freeze review checklist** — seven lines,
19
+ ⚠-first.
22
20
 
23
21
  **The lowest-confidence flag.** The AI presents the bundle **lowest-confidence first**: the
24
22
  **1–2 points most likely to be wrong**, tagged by part
25
- (`⚠ [spec|scenario|contract|test] … — because …; if wrong: …`). The `because` names the §1
26
- assumption that makes it uncertain; the `if wrong` names what it costs if that assumption is off.
27
- If nothing is materially uncertain, the AI still names the single biggest risk — never a blank "none".
28
- Raising this flag is honor-system: the lint cannot force the AI to engage with it — closing that
29
- gap is a CI checker's job, not prose.
23
+ (`⚠ [spec|scenario|contract|test] … — because …; if wrong: …`) `because` names the §1
24
+ assumption behind the doubt, `if wrong` its cost. If nothing is materially uncertain, the AI still
25
+ names the single biggest risk — never a blank "none". This flag is honor-system: the lint cannot
26
+ force engagement closing that gap is a CI checker's job, not prose.
30
27
 
31
28
  ## When the run begins — the scope-lock trigger
32
29
 
@@ -71,6 +68,7 @@ recorded pass is an explicit pass, not a skip).
71
68
  - **Auto-PASS requires ALL of:** every test green; coverage not decreased; no test weakened and no
72
69
  contract edited; loops dry; completeness-critic clean; and the deep check below.
73
70
  - **The deep check (every gate, do not skim).** If the task produced code, record that every new symbol is referenced (wiring) and that no new dead/unused code was introduced. If it produced prose or non-code, record a semantic read. An unfilled deep check is a **shallow verify**, not an auto-PASS.
71
+ - **The recorded refute-read (under `auto`).** The earned-green refute-read (`6-verify.md`) is not just run — its **verdict is recorded** in §6 (`EARNED | NOT-EARNED`); `add.py audit` surfaces an unrecorded one as `refute_unrecorded` — one of three shape lints it lists (with `shallow_deep_check` + `risk_unset`) — and a human spot-audit is the backstop. NOT-EARNED routes to `add.py heal`, never an auto-PASS.
74
72
  - **Always escalates to a human (never auto-passed):** any **security** finding (HARD-STOP, always);
75
73
  a **concurrency**/timing risk the tests cannot exercise; an **architecture**/layering violation;
76
74
  any failing test.
@@ -118,7 +116,9 @@ autonomy: manual | conservative | auto
118
116
  ```
119
117
 
120
118
  - **auto (the default)** — the run may auto-PASS when evidence + residue checks are satisfied.
121
- Security still always escalates.
119
+ Security still always escalates — but only a finding the AI *surfaces*: a security issue the
120
+ reviewer misses is **invisible** to the engine, so under `auto` a human **spot-audit** is the
121
+ only backstop for a missed finding.
122
122
  - **conservative** — the deliberate *lowering*: the run converges but STOPS at the verify gate.
123
123
  - **manual** — the strict floor: the human owns the verify gate; the engine never auto-resolves.
124
124
 
@@ -138,7 +138,7 @@ in its header is not blocked by the v14 mechanical guard.
138
138
 
139
139
  **Autonomy is earned by goal-clarity — the auto-ready goal.** A milestone goal is auto-ready
140
140
  when **every exit criterion cites a verifier** — `(verify: <test | command | metric>)`.
141
- `add.py check` raises a `goal_not_auto_ready` WARN while criteria are uncited, and `status`
142
- prints a `goal-ready:` line every session. It **measures, never blocks**. The lint cannot prove
143
- the citation is honest — `(verify: it works)` passes the check — that judgment stays the human's.
141
+ `add.py check` raises `goal_not_auto_ready` while criteria are uncited; `status` prints a
142
+ `goal-ready:` line. It **measures, never blocks** the lint cannot prove the citation honest
143
+ (`(verify: it works)` passes); that judgment stays the human's.
144
144
  </constraints>
@@ -11,7 +11,7 @@
11
11
  | `change-request` | route to SPECIFY/CONTRACT of the affected task | 0 milestones |
12
12
  | `split_required` | draft ALL N items as a batch in ONE pass | N milestones/tasks |
13
13
 
14
- **Confirm before create is the invariant.** "One pass" means one drafting pass, NOT auto-creation — nothing is written until the human confirms.
14
+ **Confirm before create is the convention.** "One pass" means one drafting pass, NOT auto-creation — nothing is written until the human confirms; enforced only by the opt-in `--await-confirm` (below).
15
15
 
16
16
  **Confirm the milestone before detailing tasks.** `new-milestone <slug> --await-confirm` seeds it *unconfirmed* — `new-task` is HELD (`milestone_unconfirmed`) until you show the filled `MILESTONE.md`, get the human's go, and run `milestone-confirm <slug>`. Keeps you from digging into task §0–§5 before the parent is agreed. (Omit the flag: no gate.)
17
17
 
@@ -179,6 +179,13 @@ Score confidence (0-1) on Completeness · Clarity · Practicality · Optimizatio
179
179
  Self-Eval; if any < 0.9, refine before returning.
180
180
  </persona>
181
181
 
182
+ <strategy>
183
+ The task's §5 plan — the Strategy (ordered batches) order and the Known-problem fixes — is
184
+ your PREFERRED starting path, not a hard rule. Improve on it when a better strategy emerges
185
+ as you build; on done, report the strategy you ACTUALLY used so the orchestrator can update
186
+ §5 for the audit trail.
187
+ </strategy>
188
+
182
189
  <touch_boundary> <!-- from run.md; the worker's contract, identical on every runner -->
183
190
  MAY: rewrite code in src/ · drive tests green WITHOUT weakening them · gather verify evidence.
184
191
  MUST NOT: edit the frozen CONTRACT or locked scope · weaken/delete/skip any test ·