@pilotspace/add 1.1.0 → 1.2.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 +40 -0
- package/GETTING-STARTED.md +165 -139
- package/README.md +13 -7
- package/bin/cli.js +13 -4
- package/docs/01-principles.md +3 -3
- package/docs/02-the-flow.md +15 -11
- package/docs/03-step-1-specify.md +13 -13
- package/docs/04-step-2-scenarios.md +2 -2
- package/docs/05-step-3-contract.md +3 -3
- package/docs/06-step-4-tests.md +2 -2
- package/docs/07-step-5-build.md +1 -1
- package/docs/08-step-6-verify.md +14 -5
- package/docs/09-the-loop.md +12 -6
- package/docs/10-setup-and-stages.md +27 -13
- package/docs/11-governance.md +2 -2
- package/docs/12-roles.md +3 -3
- package/docs/13-adoption.md +1 -1
- package/docs/14-foundation.md +15 -15
- package/docs/15-foundations-and-lineage.md +106 -0
- package/docs/README.md +4 -0
- package/docs/appendix-a-templates.md +3 -3
- package/docs/appendix-b-prompts.md +40 -5
- package/docs/appendix-c-glossary.md +42 -12
- package/docs/appendix-d-worked-example.md +2 -2
- package/docs/appendix-e-checklists.md +2 -2
- package/docs/appendix-f-requirements-matrix.md +8 -8
- package/docs/appendix-g-references.md +106 -0
- package/package.json +1 -1
- package/skill/add/SKILL.md +39 -37
- package/skill/add/adopt.md +13 -11
- package/skill/add/deltas.md +8 -6
- package/skill/add/fold.md +19 -17
- package/skill/add/graduate.md +74 -0
- package/skill/add/intake.md +22 -7
- package/skill/add/loop.md +59 -0
- package/skill/add/phases/0-setup.md +29 -24
- package/skill/add/phases/1-specify.md +23 -13
- package/skill/add/phases/2-scenarios.md +14 -4
- package/skill/add/phases/3-contract.md +24 -11
- package/skill/add/phases/4-tests.md +15 -5
- package/skill/add/phases/5-build.md +11 -4
- package/skill/add/phases/6-verify.md +24 -2
- package/skill/add/phases/7-observe.md +13 -5
- package/skill/add/report-template.md +65 -7
- package/skill/add/run.md +45 -34
- package/skill/add/scope.md +10 -6
- package/skill/add/setup-review.md +13 -10
- package/skill/add/streams.md +69 -19
- package/tooling/add.py +476 -34
- package/tooling/templates/CONVENTIONS.md.tmpl +1 -1
- package/tooling/templates/GLOSSARY.md.tmpl +23 -0
- package/tooling/templates/MILESTONE.md.tmpl +1 -0
- package/tooling/templates/PROJECT.md.tmpl +4 -3
- package/tooling/templates/TASK.md.tmpl +33 -12
package/skill/add/SKILL.md
CHANGED
|
@@ -34,7 +34,7 @@ python3 .add/tooling/add.py status
|
|
|
34
34
|
- **No `.add/state.json` yet** (a fresh install drops tooling + docs but does *not* init — so `status` says
|
|
35
35
|
`no .add/ project found`) → enter **autonomous setup**: YOU run init yourself —
|
|
36
36
|
`add.py init --name "<inferred>" --stage <picked> --await-lock` (don't tell the human to) — then read
|
|
37
|
-
`phases/0-setup.md` and draft the foundation + first scope + first contract through to the human
|
|
37
|
+
`phases/0-setup.md` and draft the foundation + first scope + first contract through to the human baseline approval.
|
|
38
38
|
- **A task is active** → open `.add/tasks/<active>/TASK.md`, look at its `phase:`
|
|
39
39
|
marker, and read the matching `phases/<n>-<phase>.md`. Work *only* that phase.
|
|
40
40
|
- **No active task** → first SIZE the request (see Intake below), then create the
|
|
@@ -45,8 +45,9 @@ python3 .add/tooling/add.py status
|
|
|
45
45
|
When the user brings a raw request, classify it BEFORE making a milestone or task:
|
|
46
46
|
read `intake.md` and place it in exactly one bucket — `new-major` · `sub-milestone`
|
|
47
47
|
· `task` · `change-request` — then propose `{ bucket, rationale, command }` and let
|
|
48
|
-
the human confirm. This is the intake
|
|
49
|
-
`intake.md` for the rubric, the tie-break order, and worked examples.
|
|
48
|
+
the human confirm. This is the intake level (request → versioned scope); see
|
|
49
|
+
`intake.md` for the rubric, the tie-break order, and worked examples. A question or
|
|
50
|
+
unsharp intent? **Interview before you size** — explore and suggest first (`intake.md`).
|
|
50
51
|
|
|
51
52
|
Once a request is classified `new-major`/`sub-milestone`, drafting the actual
|
|
52
53
|
`MILESTONE.md` (goal · scope · exit criteria · breadth-first tasks) is the second
|
|
@@ -59,57 +60,55 @@ Load the phase guide **only for the phase you are in** (progressive disclosure):
|
|
|
59
60
|
|
|
60
61
|
| Phase | Guide | Produces (TASK.md section) | Who leads |
|
|
61
62
|
|-------|-------|----------------------------|-----------|
|
|
62
|
-
| setup | `phases/0-setup.md` | `.add/` +
|
|
63
|
-
| specify | `phases/1-specify.md` | §1 rules + ranked
|
|
63
|
+
| setup | `phases/0-setup.md` | `.add/` + living docs + first §1–§3 + `SETUP-REVIEW.md` | AI drafts → **human locks** (the baseline approval) |
|
|
64
|
+
| specify | `phases/1-specify.md` | §1 rules + ranked lowest-confidence flag | AI drafts (co-specify)† |
|
|
64
65
|
| scenarios | `phases/2-scenarios.md` | §2 Given/When/Then | AI drafts† |
|
|
65
|
-
| contract | `phases/3-contract.md` | §3 frozen shape | AI drafts → **human approves once** (the
|
|
66
|
+
| contract | `phases/3-contract.md` | §3 frozen shape | AI drafts → **human approves once** (the decision point)† |
|
|
66
67
|
| tests | `phases/4-tests.md` | §4 + red suite in `tests/` | AI drafts† |
|
|
67
68
|
| build | `phases/5-build.md` | code in `src/`, tests green | **AI** |
|
|
68
69
|
| verify | `phases/6-verify.md` | §6 checks + gate record | **AI auto-gates on evidence**; human on residue/security‡ |
|
|
69
70
|
| observe | `phases/7-observe.md` | §7 spec delta | human + AI |
|
|
70
71
|
|
|
71
|
-
† **
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
architecture residue and `conservative` autonomy. See `run.md`.
|
|
72
|
+
† **The specification bundle (v7).** §1–§4 are one bundle; the human gives **one approval at the
|
|
73
|
+
contract freeze** (the decision point), presented lowest-confidence-first. See `run.md`.
|
|
74
|
+
‡ **Verify auto-gate (v6–v7).** Under `autonomy: auto` (the default) a run may auto-PASS on
|
|
75
|
+
complete evidence — recorded as *auto-resolved*, an explicit PASS, not a skip. **Security always
|
|
76
|
+
escalates** (HARD-STOP); so do concurrency / architecture residue and `conservative` autonomy.
|
|
77
|
+
See `run.md`.
|
|
78
78
|
|
|
79
|
-
Whenever you present a
|
|
80
|
-
milestone close), follow `report-template.md` —
|
|
81
|
-
EVIDENCE → NEXT,
|
|
79
|
+
Whenever you present a decision point to the human in chat (intake · bundle approval · gate ·
|
|
80
|
+
milestone close), follow `report-template.md` — open with the ARC (goal · done · plan,
|
|
81
|
+
engine-sourced), then SUMMARY → DECISION → ⚠ FLAGS → EVIDENCE → NEXT, show-before-ask, never
|
|
82
|
+
pre-stamp a decision point — and the question is a summary, never the artifact.
|
|
82
83
|
|
|
83
|
-
In **observe**, also emit **
|
|
84
|
+
In **observe**, also emit **lessons learned** — learnings tagged by which of the five
|
|
84
85
|
(`DDD · SDD · UDD · TDD · ADD`) they improve — so the foundation self-improves across loops.
|
|
85
|
-
You write them as `open`; the human
|
|
86
|
-
grammar and the status lifecycle. At milestone close (or on demand), run the
|
|
86
|
+
You write them as `open`; the human consolidates them into `PROJECT.md`. Read `deltas.md` for the
|
|
87
|
+
grammar and the status lifecycle. At milestone close (or on demand), run the retrospective consolidation that
|
|
87
88
|
gathers confirmed deltas into a versioned foundation — read `fold.md`.
|
|
88
89
|
|
|
89
|
-
##
|
|
90
|
+
## Beyond the bundle — load on demand
|
|
90
91
|
|
|
91
|
-
Once **§3 CONTRACT is FROZEN**, the build→verify half
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
the evidence auto-gate, and the autonomy dial. The human-led front still owns *direction*, but v7
|
|
95
|
-
compresses it to a **single approval at the contract seam**; the run never edits a frozen contract
|
|
96
|
-
and never auto-passes a security finding.
|
|
92
|
+
Once **§3 CONTRACT is FROZEN**, the build→verify half is a dynamic, auto-gated run
|
|
93
|
+
(`autonomy: auto` default, lowered to `conservative` for a human gate) — read `run.md`. To
|
|
94
|
+
pipeline several ready tasks behind their own frozen contracts, read `streams.md`.
|
|
97
95
|
|
|
98
|
-
|
|
96
|
+
When a milestone's tasks are all done but its **goal** (the `MILESTONE.md` exit criteria) is not
|
|
97
|
+
yet met, `milestone-done` holds the milestone open — read `loop.md` for the dynamic loop that turns
|
|
98
|
+
open deltas + extras into the next tasks, proposed by you and confirmed by the human, until the goal is met.
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
REVIEW-QUEUE. The honest gain is pipelining (the reviewer never waits on a build), not
|
|
106
|
-
N× speed; the autonomy dial sets how much actually overlaps.
|
|
100
|
+
When `add.py status` prints **`MVP covered → propose graduation`** (every milestone done AND the
|
|
101
|
+
stage-goal-criteria all `[x]`), the project is ready to graduate its stage — read `graduate.md` for the
|
|
102
|
+
orchestration: gather `graduation-report` analytics → co-specify interview → draft ≥1 production
|
|
103
|
+
milestone → human confirm → then (and only then) `stage production`. The flip is guarded
|
|
104
|
+
(`stage_no_roadmap`) and is the FINAL step — never a bare label change.
|
|
107
105
|
|
|
108
106
|
## Non-negotiable rules (from the method)
|
|
109
107
|
|
|
108
|
+
<constraints>
|
|
110
109
|
1. **Direction before speed.** Never start Build until §1–§4 exist and tests are red.
|
|
111
110
|
2. **Trust evidence, not inspection.** A feature is trusted because its tests pass
|
|
112
|
-
and the
|
|
111
|
+
and the non-functional risks (concurrency, security, architecture) were checked — not
|
|
113
112
|
because the code reads plausibly.
|
|
114
113
|
3. **Never weaken a test or edit a frozen contract to make the build pass.** That
|
|
115
114
|
inverts the method. A real change is a *change request* back to Specify.
|
|
@@ -117,6 +116,7 @@ N× speed; the autonomy dial sets how much actually overlaps.
|
|
|
117
116
|
`PASS`, `RISK-ACCEPTED` (signed, non-security only), or `HARD-STOP`. A security
|
|
118
117
|
finding is always `HARD-STOP`.
|
|
119
118
|
5. **Ask, don't guess.** If a requirement is unclear, stop and ask the user.
|
|
119
|
+
</constraints>
|
|
120
120
|
|
|
121
121
|
## Advancing
|
|
122
122
|
|
|
@@ -136,9 +136,11 @@ The steps never change; their depth does. Read the stage from `add.py status`:
|
|
|
136
136
|
- **prototype** — run light; code is throwaway; design/experience is the point.
|
|
137
137
|
- **poc** — run contract/tests/build deeply on the single riskiest slice only.
|
|
138
138
|
- **mvp** — full flow, narrow scope, light observation.
|
|
139
|
-
- **production** — every step at full rigor + the observe loop.
|
|
139
|
+
- **production** — every step at full rigor + the observe loop. Reach it via the graduation
|
|
140
|
+
orchestration (`graduate.md`) when status shows `MVP covered → propose graduation`, never a bare
|
|
141
|
+
`stage production` flip — the transition is guarded behind a human-confirmed roadmap.
|
|
140
142
|
|
|
141
|
-
## The
|
|
143
|
+
## The method rationale
|
|
142
144
|
|
|
143
145
|
The full method (the *why* behind every rule) is the AIDD book in `.add/docs/`.
|
|
144
146
|
When a phase decision is genuinely unclear, read the linked chapter — each phase
|
package/skill/add/adopt.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
When ADD is pointed at a repo that already has code, onboarding is **silent**: the code
|
|
4
4
|
answers the questions a greenfield interview would ask, so you read it rather than ask.
|
|
5
5
|
This is the **brownfield path** of setup (the greenfield path keeps the 4-lens interview —
|
|
6
|
-
see `phases/0-setup.md`). You fill the
|
|
7
|
-
human gate: the **
|
|
6
|
+
see `phases/0-setup.md`). You fill the living-documentation files from evidence, then stop at the one
|
|
7
|
+
human gate: the **baseline approval** (`add.py lock`).
|
|
8
8
|
|
|
9
9
|
## The signal — and arming the gate
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ Enter a brownfield repo with `--await-lock`:
|
|
|
14
14
|
python3 .add/tooling/add.py init --await-lock
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
`--await-lock` does two things. It seeds an **unlocked** setup, which *arms the
|
|
17
|
+
`--await-lock` does two things. It seeds an **unlocked** setup, which *arms the baseline-approval gate*
|
|
18
18
|
— the engine then refuses a second task, crossing into build, and recording a gate until you
|
|
19
19
|
`lock`. And init, being brownfield-aware, prints a line that begins:
|
|
20
20
|
|
|
@@ -29,9 +29,9 @@ code (a mechanical fact); it never reads or fills it — interpreting it is your
|
|
|
29
29
|
|
|
30
30
|
## The silent mapping
|
|
31
31
|
|
|
32
|
-
Fill each
|
|
32
|
+
Fill each living-doc file in `.add/` from what the code actually shows — **ask nothing**:
|
|
33
33
|
|
|
34
|
-
|
|
|
34
|
+
| Living doc | Read it from |
|
|
35
35
|
|----------|--------------|
|
|
36
36
|
| `PROJECT.md` (foundation) | the domain nouns, entry points, the README, the first milestone the code implies |
|
|
37
37
|
| `CONVENTIONS.md` | the languages, folder layout, naming, lint config, error style already in the tree |
|
|
@@ -41,19 +41,21 @@ Fill each survivor file in `.add/` from what the code actually shows — **ask n
|
|
|
41
41
|
|
|
42
42
|
Two rules that never bend:
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
<constraints>
|
|
45
|
+
1. **Never clobber a living doc.** `init` already skips any living-doc file that exists; if a human
|
|
45
46
|
already wrote `PROJECT.md`, you READ it, you do not overwrite it. Add, never replace.
|
|
46
47
|
2. **Tag every drafted decision `evidence-grounded` vs `guessed`.** A line you read from the
|
|
47
48
|
code is *evidence-grounded* (cite the file). A line you inferred because the code was silent
|
|
48
|
-
is *guessed*. The human's single
|
|
49
|
+
is *guessed*. The human's single baseline approval is only honest if they can see which is which —
|
|
49
50
|
the guesses are what they actually need to check. (The tags feed `SETUP-REVIEW.md`.)
|
|
51
|
+
</constraints>
|
|
50
52
|
|
|
51
|
-
## Where it ends — the
|
|
53
|
+
## Where it ends — the baseline approval
|
|
52
54
|
|
|
53
55
|
Brownfield onboarding draws no per-step approvals. You map the foundation, then draft the
|
|
54
|
-
first milestone's scope and the first task's candidate
|
|
55
|
-
present it all at **one** human gate. The human reviews the decisions (
|
|
56
|
-
first) and
|
|
56
|
+
first milestone's scope and the first task's candidate specification bundle exactly as greenfield does, and
|
|
57
|
+
present it all at **one** human gate. The human reviews the decisions (lowest-confidence / `guessed`
|
|
58
|
+
first) and confirms in conversation; you run the lock with their name:
|
|
57
59
|
|
|
58
60
|
```bash
|
|
59
61
|
python3 .add/tooling/add.py lock --by "<name>"
|
package/skill/add/deltas.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Lessons learned — how each loop sharpens the foundation
|
|
2
2
|
|
|
3
|
-
A **
|
|
3
|
+
A **lesson learned** is a single learning a task produces, tagged by which of ADD's five
|
|
4
4
|
competencies it improves. You write deltas in a task's **OBSERVE** phase; later, the
|
|
5
|
-
`foundation-update-loop` gathers the confirmed ones and
|
|
5
|
+
`foundation-update-loop` gathers the confirmed ones and consolidates them into a versioned `PROJECT.md`.
|
|
6
6
|
This is how `DDD · SDD · UDD · TDD · ADD` stop being write-once and start converging.
|
|
7
7
|
|
|
8
8
|
You (the AI) **emit** deltas as `open`. Only the **human** moves a delta to `folded` or `rejected`
|
|
9
|
-
(
|
|
9
|
+
(consolidating into the foundation is judgment — see the verify/observe decision point). You never self-approve a consolidation.
|
|
10
10
|
|
|
11
11
|
## The grammar (frozen)
|
|
12
12
|
|
|
@@ -50,7 +50,7 @@ That is its home. Split genuinely separate learnings into separate deltas; never
|
|
|
50
50
|
```
|
|
51
51
|
emit (OBSERVE) human review (foundation-update-loop)
|
|
52
52
|
open ───────────▶ folded (the learning is merged into PROJECT.md; version bumps)
|
|
53
|
-
└──────────▶ rejected (considered and deliberately NOT
|
|
53
|
+
└──────────▶ rejected (considered and deliberately NOT consolidated — the trail is kept)
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
An `open` delta is a pending signal. `folded` and `rejected` are both human decisions; a `rejected`
|
|
@@ -60,9 +60,11 @@ delta is left in place (not deleted) so "we saw this and chose not to act" stays
|
|
|
60
60
|
|
|
61
61
|
There is no engine validator yet, so before you record a delta, self-check it:
|
|
62
62
|
|
|
63
|
+
<reject_codes>
|
|
63
64
|
- `unknown_competency` — the tag is missing or not one of `DDD · SDD · UDD · TDD · ADD`. Fix the tag.
|
|
64
65
|
- `no_evidence` — the `(evidence: …)` pointer is missing or empty. Add the proof, or drop the line.
|
|
65
66
|
- `unknown_status` — the status is not `open | folded | rejected`. A fresh delta is `open`.
|
|
67
|
+
</reject_codes>
|
|
66
68
|
|
|
67
69
|
## Worked example
|
|
68
70
|
|
|
@@ -75,5 +77,5 @@ A task that built a tenancy feature finished its OBSERVE phase with:
|
|
|
75
77
|
```
|
|
76
78
|
|
|
77
79
|
Three learnings, three competencies, each with a pointer. At the next foundation update the human
|
|
78
|
-
|
|
80
|
+
consolidated the DDD and TDD deltas into `PROJECT.md` (→ `folded`) and rejected the ADD one as a one-off
|
|
79
81
|
(→ `rejected`). The foundation got sharper; nothing was silently lost.
|
package/skill/add/fold.md
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Consolidating deltas — how the foundation self-improves
|
|
2
2
|
|
|
3
|
-
This **closes the loop**. `deltas.md` lets a task EMIT learnings (`open`
|
|
4
|
-
OBSERVE phase);
|
|
3
|
+
This **closes the loop**. `deltas.md` lets a task EMIT learnings (`open` lessons learned in its
|
|
4
|
+
OBSERVE phase); the retrospective consolidation gathers the confirmed ones and writes them into a **versioned foundation**,
|
|
5
5
|
so `DDD · SDD · UDD · TDD · ADD` sharpen across milestones instead of drifting.
|
|
6
6
|
|
|
7
|
-
You (the AI) **gather and propose**; the **human confirms**; you then write the **append-only**
|
|
8
|
-
You never self-
|
|
7
|
+
You (the AI) **gather and propose**; the **human confirms**; you then write the **append-only** consolidation.
|
|
8
|
+
You never self-approve a consolidation — consolidating is judgment (see the verify/observe decision point).
|
|
9
9
|
|
|
10
|
-
## When to
|
|
10
|
+
## When to consolidate
|
|
11
11
|
|
|
12
12
|
At **milestone close** (the natural "version bump to the foundation"), or **on demand** when open
|
|
13
|
-
deltas have piled up. This is a convention, not a command — there is no `add.py fold`; the
|
|
13
|
+
deltas have piled up. This is a convention, not a command — there is no `add.py fold`; the consolidation
|
|
14
14
|
lives here so the engine stays judgment-free.
|
|
15
15
|
|
|
16
16
|
## The ritual
|
|
17
17
|
|
|
18
|
-
1. **Gather** — scan every task's OBSERVE
|
|
18
|
+
1. **Gather** — scan every task's §7 OBSERVE block for lesson-learned lines still `open` (`add.py deltas` reads them by the machine heading).
|
|
19
19
|
2. **Group** — bucket them by competency (`DDD · SDD · UDD · TDD · ADD`).
|
|
20
20
|
3. **Propose** — for each, draft the exact foundation edit (see routing) and show the human.
|
|
21
21
|
4. **Confirm** — the human accepts or declines each delta. No write happens without this.
|
|
22
22
|
5. **Write** — append the accepted edits, flip each delta's status, and bump the version.
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## Consolidation routing (every competency has a home)
|
|
25
25
|
|
|
26
|
-
| competency |
|
|
26
|
+
| competency | consolidates into | how |
|
|
27
27
|
|------------|-----------|-----|
|
|
28
28
|
| `DDD` | `PROJECT.md` §Domain (DDD) | refine/append a model bullet |
|
|
29
29
|
| `SDD` | `PROJECT.md` §Spec / Living Document (SDD) | refine/append a settled-vs-open line |
|
|
@@ -31,7 +31,7 @@ lives here so the engine stays judgment-free.
|
|
|
31
31
|
| `TDD` | `CONVENTIONS.md` | append a testing convention (no PROJECT.md section — it is the engine) |
|
|
32
32
|
| `ADD` | `CONVENTIONS.md` | append a build/harness convention (likewise the engine) |
|
|
33
33
|
|
|
34
|
-
**Every**
|
|
34
|
+
**Every** consolidation — whatever the competency — ALSO appends one row to `PROJECT.md` **§Key Decisions**
|
|
35
35
|
(date · decision · why · outcome): the universal, auditable trail of what the foundation learned.
|
|
36
36
|
|
|
37
37
|
## Status transitions & version
|
|
@@ -39,16 +39,18 @@ lives here so the engine stays judgment-free.
|
|
|
39
39
|
- on **confirm**: the delta moves `open` → `folded` (and its edit is appended to the routed target).
|
|
40
40
|
- on **decline**: the delta moves `open` → `rejected` and is **left in place** — never deleted —
|
|
41
41
|
so "we considered this and chose not to act" stays auditable.
|
|
42
|
-
- a
|
|
43
|
-
- each
|
|
42
|
+
- a consolidation is **append-only**: it adds bullets/rows; it never silently rewrites existing foundation text.
|
|
43
|
+
- each consolidation session **bumps** the `foundation-version:` marker in `PROJECT.md` by one (monotonic int).
|
|
44
44
|
|
|
45
45
|
## Reject codes (the AI is first check, the human the backstop)
|
|
46
46
|
|
|
47
|
+
<reject_codes>
|
|
47
48
|
- `no_open_deltas` — nothing is `open` anywhere. The ritual is a no-op; do **not** bump the version.
|
|
48
49
|
- `unconfirmed_fold` — a write was attempted without recorded human confirmation. The AI proposes;
|
|
49
|
-
it never self-
|
|
50
|
-
- `unroutable_delta` — a delta's competency is not one of the five, so it has no
|
|
51
|
-
delta (it is malformed per `deltas.md`) before
|
|
50
|
+
it never self-approves one. Stop and get confirmation.
|
|
51
|
+
- `unroutable_delta` — a delta's competency is not one of the five, so it has no consolidation target. Fix the
|
|
52
|
+
delta (it is malformed per `deltas.md`) before consolidating.
|
|
53
|
+
</reject_codes>
|
|
52
54
|
|
|
53
55
|
## Worked example (from this repo's own history)
|
|
54
56
|
|
|
@@ -60,7 +62,7 @@ which have no PROJECT.md section:
|
|
|
60
62
|
- [TDD · open] structural tests guard canonical artifacts but not their dogfood twins (evidence: scope-loop note + this build)
|
|
61
63
|
```
|
|
62
64
|
|
|
63
|
-
At the next
|
|
65
|
+
At the next consolidation the human confirms both. Routing sends each to `CONVENTIONS.md` (a "sync the dogfood
|
|
64
66
|
tree + assert md5 parity" convention), appends a §Key Decisions row for each, flips them to `folded`,
|
|
65
67
|
and bumps `foundation-version` 1 → 2. The two competencies the foundation never tracked before now
|
|
66
68
|
have a home — which is exactly why v5 routes TDD/ADD to `CONVENTIONS.md`.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Stage graduation — propose the move to production as a roadmap, never a flip
|
|
2
|
+
|
|
3
|
+
A project does not become "production" because someone typed a new label. It graduates when
|
|
4
|
+
the MVP is genuinely covered AND a human-confirmed roadmap of production work exists. This guide
|
|
5
|
+
is the **4th scope level** — after setup (`phases/0-setup.md`), intake (`intake.md` / `scope.md`),
|
|
6
|
+
and the milestone loop (`loop.md`). It turns the bare `add.py stage` flip into the **final step** of
|
|
7
|
+
an analytics-driven, interview-led orchestration.
|
|
8
|
+
|
|
9
|
+
You (the AI) **gather and propose**; the **human confirms and judges**; the engine only counts
|
|
10
|
+
tallies and enforces the floor. The engine never decides that the project is "ready" — that is
|
|
11
|
+
judgment, and it belongs to the interview.
|
|
12
|
+
|
|
13
|
+
## The cue (what starts this)
|
|
14
|
+
|
|
15
|
+
When every milestone is `done` AND the human's stage-goal-criteria in `PROJECT.md` are all `[x]`,
|
|
16
|
+
`add.py status` prints:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
→ MVP covered → propose graduation
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
That line is the trigger. Before both tallies complete, status is silent and nothing here applies
|
|
23
|
+
(a project with no stage-goal-criteria block behaves exactly as today — grandfathered, zero change).
|
|
24
|
+
|
|
25
|
+
## The flow
|
|
26
|
+
|
|
27
|
+
1. **Gather the analytics** — run `add.py graduation-report` (add `--json` to branch on it). It
|
|
28
|
+
clusters the whole MVP loop's evidence into five labeled record-sets: open deltas by competency ·
|
|
29
|
+
open RISK-ACCEPTED waivers by expiry · RETRO records · verify residue · observe-loop coverage gaps.
|
|
30
|
+
It **gathers, never judges** — there is no readiness verdict to read; the records are what you
|
|
31
|
+
reason from.
|
|
32
|
+
2. **Co-specify interview** — synthesize *"what production means HERE"* WITH the human, using the
|
|
33
|
+
gathered records as the agenda (the residue to harden, the coverage gaps to monitor, the open
|
|
34
|
+
deltas to consolidate). This synthesis is the judgment the engine refuses to make. Interview to real confidence —
|
|
35
|
+
do not guess what "production-ready" means for this project.
|
|
36
|
+
3. **Draft the roadmap** — for each production outcome the interview surfaces, draft a production
|
|
37
|
+
milestone with the EXISTING command and goal-gate criteria:
|
|
38
|
+
`add.py new-milestone <slug> --stage production --goal "…"`, then write its exit criteria. The
|
|
39
|
+
roadmap is **≥1** milestone — the hardening work itself (SLOs, rollback tests, incident runbooks)
|
|
40
|
+
is what these milestones *contain*; this guide proposes them, it does not do them.
|
|
41
|
+
4. **Human confirms** — present the roadmap via `report-template.md`, opening with the ARC
|
|
42
|
+
(goal · done · plan): the stage-graduation goal, the MVP coverage that earns the move, and the
|
|
43
|
+
plan the production milestones lay out. The human accepts, edits, or declines each drafted
|
|
44
|
+
milestone. No milestone is created without this; nothing advances on a draft the human has not confirmed.
|
|
45
|
+
5. **Flip — the final step** — only now run `add.py stage production`. Because ≥1 production milestone
|
|
46
|
+
now exists, the guard passes and the transition is recorded. This is the orchestration's last act.
|
|
47
|
+
|
|
48
|
+
## The floor (what the engine enforces)
|
|
49
|
+
|
|
50
|
+
`add.py stage production` is **guarded**: it refuses with `stage_no_roadmap` (non-zero exit, state
|
|
51
|
+
byte-unchanged) when zero milestones have `stage: production`. The check is a **tally** — "does a
|
|
52
|
+
production-roadmap record exist?" — never a readiness judgment (gather-not-judge at stage level;
|
|
53
|
+
it mirrors the milestone goal-gate's `milestone_goal_unmet`). `--force` overrides it, preserving human
|
|
54
|
+
authority for grandfathered/edge cases; use it deliberately, not as the normal path.
|
|
55
|
+
|
|
56
|
+
Scope: the guard is on the `→production` **transition** only. Flips to prototype/poc/mvp are the
|
|
57
|
+
existing bare flip, unchanged. `add.py init --stage production` is an explicit at-creation declaration
|
|
58
|
+
(the same authority as `--force`), not a transition — it is out of scope of the guard by design.
|
|
59
|
+
|
|
60
|
+
## Invariants (never break these)
|
|
61
|
+
|
|
62
|
+
- **The flip is the final step**, never called outside this confirmed-roadmap path. A bare flip with
|
|
63
|
+
no roadmap is the symptom this scope level removes.
|
|
64
|
+
- **The engine never auto-flips.** Every step here is human-confirmed; the engine gathers, counts, and
|
|
65
|
+
enforces the floor — it does not advance the stage on its own.
|
|
66
|
+
- **The flow is continuous, not cue-reentrant.** The moment you draft the first production milestone,
|
|
67
|
+
`status` stops printing the cue (the "every milestone done" tally breaks). That is expected — do NOT
|
|
68
|
+
re-await the cue after drafting; carry the flow straight through to confirm and flip.
|
|
69
|
+
|
|
70
|
+
## Depth and reuse
|
|
71
|
+
|
|
72
|
+
The same orchestration serves prototype→poc and poc→mvp; **mvp→production** is the rigorous proof
|
|
73
|
+
case (every step at full depth + the observe loop). At lower stages, run it light — the shape is the
|
|
74
|
+
same, the depth is less.
|
package/skill/add/intake.md
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
# Intake — size a request into versioned scope
|
|
2
2
|
|
|
3
3
|
Before a task exists, ADD turns a raw request into correctly-sized, versioned scope.
|
|
4
|
-
This is the **intake
|
|
4
|
+
This is the **intake level**: the per-task flow is phases 0–7; intake is the step
|
|
5
5
|
*before* a task — request → milestone or task. You (the AI) **propose**; the human
|
|
6
6
|
**confirms**. Never create scope without a confirmed proposal.
|
|
7
7
|
|
|
8
|
+
## Interview before you size
|
|
9
|
+
|
|
10
|
+
When the request arrives as a question, or its intent is not yet sharp enough to
|
|
11
|
+
place in one bucket: explore it WITH the user before classifying. Reflect the
|
|
12
|
+
intent you heard, name what seems in and out of scope, and offer 2–3 sized options
|
|
13
|
+
with your own recommendation. Only then emit `{ bucket, rationale, command }`.
|
|
14
|
+
`ask_human` stays the floor: when interviewing cannot sharpen the request,
|
|
15
|
+
reject — never guess a bucket.
|
|
16
|
+
|
|
8
17
|
## The four buckets
|
|
9
18
|
|
|
10
19
|
Classify every request into exactly ONE bucket:
|
|
@@ -24,17 +33,23 @@ First ask "does this change already-frozen scope?" → if yes, it is a `change-r
|
|
|
24
33
|
|
|
25
34
|
## What you emit (the proposal)
|
|
26
35
|
|
|
36
|
+
Present the proposal to the human via `report-template.md` — open with the ARC (goal · done ·
|
|
37
|
+
plan): the goal this request serves, what is already covered, and the plan the chosen bucket sets up.
|
|
38
|
+
|
|
27
39
|
For every request, emit ONE of:
|
|
28
40
|
|
|
29
41
|
- **a classification** — `{ bucket, rationale, command }` — where `rationale` names WHY
|
|
30
42
|
(the theme, the slice, the fit, or the frozen scope touched) and `command` is the exact
|
|
31
43
|
`add.py …` from the table. The human confirms or overrides before you run it.
|
|
32
|
-
- **a rejection** — `{ reject, rationale }` — and you create nothing:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
- **a rejection** — `{ reject, rationale }` — and you create nothing, emitting one of the closed set:
|
|
45
|
+
|
|
46
|
+
<reject_codes>
|
|
47
|
+
- `ask_human` — too ambiguous/underspecified to size. Ask the human; never guess a bucket.
|
|
48
|
+
- `frozen_scope` — it changes frozen scope; route it as a `change-request` back to
|
|
49
|
+
SPECIFY/CONTRACT of the affected task — never spawn a parallel milestone that forks the truth.
|
|
50
|
+
- `split_required` — it spans more than one bucket; propose the SMALLEST set of correctly-sized
|
|
51
|
+
items, each with its own rationale; never force it into one milestone.
|
|
52
|
+
</reject_codes>
|
|
38
53
|
|
|
39
54
|
When confirmed, record the `rationale` in the artifact you create or affect — the new
|
|
40
55
|
MILESTONE.md goal/body, the new TASK.md, or a note in the affected TASK.md — never in state.json.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# The dynamic loop — open deltas and extras become the next tasks
|
|
2
|
+
|
|
3
|
+
A milestone is not done when its tasks are done — it is done when its **GOAL** is met.
|
|
4
|
+
This guide is the loop that drives a milestone toward that goal: turn what each task
|
|
5
|
+
leaves behind (open lessons, and work discovered but out of scope) into the next tasks,
|
|
6
|
+
and keep going until the exit criteria are all met.
|
|
7
|
+
|
|
8
|
+
You (the AI) **gather and propose**; the **human confirms**; the existing `add.py new-task`
|
|
9
|
+
creates each one. The engine never decides what the next task is — that is judgment.
|
|
10
|
+
|
|
11
|
+
## The goal-gate (what holds the loop open)
|
|
12
|
+
|
|
13
|
+
`add.py milestone-done <slug>` REFUSES to close a milestone while its exit criteria are not
|
|
14
|
+
all met — it stops with `milestone_goal_unmet` and the milestone stays active. The exit-criteria
|
|
15
|
+
checkboxes in `MILESTONE.md` ARE the human's goal-met affirmation: the engine reads the
|
|
16
|
+
`- [x]`/`- [ ]` tally, it never judges whether the goal is met (the same trust model as reading a
|
|
17
|
+
recorded `PASS`). Checking the last box is the deliberate act that releases the gate.
|
|
18
|
+
|
|
19
|
+
The gate fires only when criteria exist. A milestone with no exit-criteria checkboxes closes as
|
|
20
|
+
before — write criteria into `MILESTONE.md` if you want the goal-gate to hold the milestone open.
|
|
21
|
+
|
|
22
|
+
`milestone-done` is the only way a milestone reaches `done`; `archive-milestone` and `compact`
|
|
23
|
+
both refuse a milestone that is not done. So the one gate is enough — there is no quiet way around it.
|
|
24
|
+
|
|
25
|
+
## The loop
|
|
26
|
+
|
|
27
|
+
When every task is done but the goal is not, `add.py status` shows
|
|
28
|
+
`goal not met (m/n exit criteria)` where it would otherwise prompt to archive. That is the cue:
|
|
29
|
+
|
|
30
|
+
1. **Gather** the carried inventory:
|
|
31
|
+
- open lessons — `add.py deltas` (the §7 OBSERVE deltas still `open`);
|
|
32
|
+
- the planned-but-unscaffolded tasks — the plan-vs-state line in `add.py status`;
|
|
33
|
+
- any reopened task — one a deepened verify returned to the flow (see below).
|
|
34
|
+
2. **Propose** the next tasks: for each carried item worth doing now, draft a one-line task
|
|
35
|
+
(slug + title + why) and show the human. Group the trivial ones; do not propose noise.
|
|
36
|
+
3. **Confirm** — the human accepts, edits, or declines each. No task is created without this.
|
|
37
|
+
4. **Create** each accepted task — `add.py new-task <slug> --title "..."` — and run it through
|
|
38
|
+
the normal flow (specify → … → verify).
|
|
39
|
+
5. **Repeat** until the work the goal needs is done.
|
|
40
|
+
6. **Close** — when the goal is genuinely met, check the exit-criteria boxes in `MILESTONE.md`,
|
|
41
|
+
then `add.py milestone-done <slug>` succeeds (then consolidate the open deltas and archive).
|
|
42
|
+
Present the close via `report-template.md` — open with the ARC (goal · done · plan): the
|
|
43
|
+
milestone goal, the exit-criteria met that prove it, and the plan beyond the close.
|
|
44
|
+
|
|
45
|
+
## Reopen is the verb; this loop is the trigger
|
|
46
|
+
|
|
47
|
+
When a deepened verify (the no-skim wiring / dead-code / semantic check) finds a criterion unmet
|
|
48
|
+
on a task already marked done, `add.py reopen <task> --to <phase> --reason "..."` returns it to the
|
|
49
|
+
flow with a recorded reason and a reset gate. `reopen` is the recorded action; deciding WHEN to
|
|
50
|
+
fire it — because a goal criterion is unmet — is this loop's job.
|
|
51
|
+
|
|
52
|
+
## The reactivation residual (deferred)
|
|
53
|
+
|
|
54
|
+
A reopen fired inside the loop happens while the milestone is still **active** — the goal-gate held
|
|
55
|
+
it open, so it never reached done, and no reactivation is needed. The one residual — reopening a
|
|
56
|
+
task inside a milestone that was already closed — is surfaced by `add.py check` (a done milestone
|
|
57
|
+
with a live task reads as incoherent). Re-activating a closed milestone is **deferred**: resolve it
|
|
58
|
+
by hand for now (the loop's own design keeps in-flight milestones open), until a later task makes
|
|
59
|
+
milestone reactivation first-class.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# Phase 0 — Setup (autonomous draft → one human
|
|
1
|
+
# Phase 0 — Setup (autonomous draft → one human baseline approval)
|
|
2
2
|
|
|
3
3
|
Goal: point ADD at a repo and **you** draft the whole foundation — domain, first-milestone scope,
|
|
4
|
-
and the first task's contract — then hand the human exactly one decision: the **
|
|
4
|
+
and the first task's contract — then hand the human exactly one decision: the **baseline approval**. Brownfield
|
|
5
5
|
is silent (the code answers the questions); greenfield keeps a short interview. Either way, the human's
|
|
6
|
-
only gate is `add.py lock`. This is the setup-
|
|
6
|
+
only gate is `add.py lock`. This is the setup-level analog of a task's one-approval contract freeze.
|
|
7
7
|
|
|
8
8
|
## 1 · Zero-touch entry — you run init yourself
|
|
9
9
|
|
|
10
10
|
When there is no `.add/state.json`, do **not** tell the human to initialise — run it yourself. Infer the
|
|
11
|
-
project name and stage from the repo, and **arm the
|
|
11
|
+
project name and stage from the repo, and **arm the baseline-approval gate** with `--await-lock`:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
python3 .add/tooling/add.py init --name "<inferred from repo/dir>" --stage <prototype|poc|mvp|production> --await-lock
|
|
@@ -27,16 +27,16 @@ python3 .add/tooling/add.py init --name "<inferred from repo/dir>" --stage <prot
|
|
|
27
27
|
|
|
28
28
|
## 2a · Brownfield — map it silently
|
|
29
29
|
|
|
30
|
-
The code answers the questions a greenfield interview would ask, so **read it
|
|
31
|
-
`adopt.md` and follow it: fill each
|
|
30
|
+
The code answers the questions a greenfield interview would ask, so **read it instead of asking**. Open
|
|
31
|
+
`adopt.md` and follow it: fill each living-doc file from the code, never clobber an existing one, and tag
|
|
32
32
|
every decision `evidence-grounded` (cite the file) or `guessed`. Ask the human **nothing** at this step.
|
|
33
33
|
|
|
34
|
-
## 2b · Greenfield — the 4-lens interview (kept): co-specify at foundation
|
|
34
|
+
## 2b · Greenfield — the 4-lens interview (kept): co-specify at foundation level
|
|
35
35
|
|
|
36
36
|
An empty repo has no code to read, so run the short interview. This is the **co-specify at foundation
|
|
37
|
-
|
|
37
|
+
level** move — the same diverge → converge → validate brainstorm a task's §1 uses (`phases/1-specify.md`),
|
|
38
38
|
lifted to the foundation. Ask the one load-bearing question per lens (diverge), draft the foundation
|
|
39
|
-
(converge), then rank
|
|
39
|
+
(converge), then rank where your confidence is lowest and show the top flag first (validate):
|
|
40
40
|
|
|
41
41
|
| Lens | The one question that unblocks the section |
|
|
42
42
|
|------|--------------------------------------------|
|
|
@@ -45,52 +45,57 @@ lifted to the foundation. Ask the one load-bearing question per lens (diverge),
|
|
|
45
45
|
| Users (UDD) | The primary user and the one job they hire this for? (or "no UI — surface is X") |
|
|
46
46
|
| Decisions | What's already decided that you'd regret re-litigating? (first Key Decision row) |
|
|
47
47
|
|
|
48
|
-
Ask only the live ones; skip what the request already answers. Rank your drafts
|
|
49
|
-
one notation every
|
|
48
|
+
Ask only the live ones; skip what the request already answers. Rank your drafts lowest-confidence-first using the
|
|
49
|
+
one notation every scope level shares — `⚠ <assumption> — lowest confidence because <why>; if wrong: <cost>` — and
|
|
50
50
|
tag thin or inferred answers `guessed`.
|
|
51
51
|
|
|
52
52
|
## 3 · Draft to the lock (both paths)
|
|
53
53
|
|
|
54
|
-
1. **Fill the
|
|
54
|
+
1. **Fill the living documentation** (it outlives all code): `.add/PROJECT.md` (the foundation — Domain · Spec/active
|
|
55
55
|
milestone · UI/UX · Key Decisions, one screen), `CONVENTIONS.md`, `GLOSSARY.md`, `MODEL_REGISTRY.md`,
|
|
56
56
|
`dependencies.allowlist`. Brownfield: from the code. Greenfield: from the interview, gaps flagged `guessed`.
|
|
57
57
|
2. **Size the first milestone** (read `scope.md`) and draft its `MILESTONE.md` — goal · scope · exit criteria
|
|
58
58
|
· breadth-first tasks.
|
|
59
|
-
3. **Create the first task and draft its candidate
|
|
59
|
+
3. **Create the first task and draft its candidate specification bundle.** `new-task` is allowed pre-lock:
|
|
60
60
|
```bash
|
|
61
61
|
python3 .add/tooling/add.py new-task <slug> --title "<first feature>"
|
|
62
62
|
```
|
|
63
63
|
Draft §1 (specify) · §2 (scenarios) · §3 (contract). **Leave §3 `Status: DRAFT`** — the lock is its
|
|
64
64
|
approval (see §5). You MAY `advance` through specify → scenarios → contract → tests pre-lock, but the
|
|
65
|
-
engine **refuses crossing into build** until you `lock` (`setup_unlocked`). Sequence:
|
|
65
|
+
engine **refuses crossing into build** until you `lock` (`setup_unlocked`). Sequence: bundle → lock → build.
|
|
66
66
|
4. **Write `.add/SETUP-REVIEW.md`** per `setup-review.md`: every decision you drafted (foundation, scope,
|
|
67
|
-
first contract), **
|
|
67
|
+
first contract), **lowest-confidence-first**, each tagged `guessed` | `evidence-grounded`.
|
|
68
68
|
|
|
69
|
-
## 4 · The one human gate — the
|
|
69
|
+
## 4 · The one human gate — the baseline approval
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
Open the report with the ARC (goal · done · plan) per `report-template.md`, then present
|
|
72
|
+
`SETUP-REVIEW.md` lowest-confidence-first (the `guessed` rows are what the human must actually check). They
|
|
73
|
+
confirm **once** — an explicit yes to the baseline approval itself, in conversation; ambient agreement mid-stream is
|
|
74
|
+
not a confirmation. On that recorded confirmation, you run the lock with their name:
|
|
73
75
|
|
|
74
76
|
```bash
|
|
75
77
|
python3 .add/tooling/add.py lock --by "<name>"
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
Typing the command themselves stays the **escape hatch** — the decision is always the human's; you just
|
|
81
|
+
execute it. `lock` records the lock layers (foundation · scope · contract) in one atomic write and opens the
|
|
82
|
+
build. It is judgment-free — it does **not** parse `SETUP-REVIEW.md`; the human *reading* it is the review.
|
|
80
83
|
|
|
81
84
|
## 5 · After the lock
|
|
82
85
|
|
|
83
|
-
- The lock **is** the first task's contract approval — the v7
|
|
86
|
+
- The lock **is** the first task's contract approval — the v7 specification-bundle approval and the baseline approval collapse
|
|
84
87
|
into this single signature. Do **not** ask for a separate contract-freeze sign-off (that double-gates).
|
|
85
88
|
- Stamp the first task's §3 `Status: FROZEN @ v1` (lock-authorized), then read `phases/5-build.md` — build is
|
|
86
89
|
now open. Everything before this signature, you drafted.
|
|
87
90
|
|
|
88
91
|
## Exit gate
|
|
89
92
|
|
|
93
|
+
<exit_gate>
|
|
90
94
|
- [ ] `.add/state.json` exists; setup was seeded unlocked (`--await-lock`) then locked.
|
|
91
|
-
- [ ]
|
|
92
|
-
- [ ] First task created; §1–§3 drafted; `.add/SETUP-REVIEW.md` written
|
|
93
|
-
- [ ] Human
|
|
95
|
+
- [ ] Living docs filled (brownfield: from code, tagged evidence-grounded; greenfield: from the interview).
|
|
96
|
+
- [ ] First task created; §1–§3 drafted; `.add/SETUP-REVIEW.md` written lowest-confidence-first.
|
|
97
|
+
- [ ] Human confirmed the baseline approval and `add.py lock --by` ran with their name; first task §3 `FROZEN @ v1`; build open.
|
|
98
|
+
</exit_gate>
|
|
94
99
|
|
|
95
100
|
## Next
|
|
96
101
|
|