@pilotspace/add 1.10.0 → 1.12.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 +102 -0
- package/bin/cli.js +55 -0
- package/docs/02-the-flow.md +10 -0
- package/docs/09-the-loop.md +1 -1
- package/docs/11-governance.md +1 -1
- package/docs/14-foundation.md +7 -5
- package/docs/16-releasing.md +2 -2
- package/docs/appendix-c-glossary.md +10 -4
- package/package.json +4 -1
- package/skill/add/SKILL.md +9 -3
- package/skill/add/design.md +19 -2
- package/skill/add/intake.md +16 -0
- package/skill/add/phases/0-ground.md +9 -3
- package/skill/add/phases/0-setup.md +2 -2
- package/skill/add/scope.md +1 -1
- package/tooling/add.py +614 -1598
- package/tooling/add_engine/__init__.py +5 -0
- package/tooling/add_engine/accessors.py +61 -0
- package/tooling/add_engine/autonomy.py +58 -0
- package/tooling/add_engine/components.py +117 -0
- package/tooling/add_engine/constants.py +221 -0
- package/tooling/add_engine/guidelines.py +252 -0
- package/tooling/add_engine/identity.py +107 -0
- package/tooling/add_engine/io_state.py +201 -0
- package/tooling/add_engine/milestones.py +108 -0
- package/tooling/add_engine/predicates.py +75 -0
- package/tooling/add_engine/release.py +86 -0
- package/tooling/add_engine/render.py +90 -0
- package/tooling/add_engine/taskdoc.py +217 -0
- package/tooling/add_engine/version.py +45 -0
- package/tooling/templates/DESIGN.md.tmpl +11 -0
- package/tooling/templates/TASK.fast.md.tmpl +2 -0
- package/tooling/templates/gitignore.tmpl +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,108 @@ All notable changes to the ADD method (`@pilotspace/add` on npm,
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.12.0] — 2026-06-26
|
|
10
|
+
|
|
11
|
+
Multi-milestone polish release — the intake/roadmap front grows a real **queue**,
|
|
12
|
+
the parallel-front residuals close, and the UDD loop gains a design-intake beat.
|
|
13
|
+
Backward-compatible throughout; a single-active project sees no behavior change.
|
|
14
|
+
|
|
15
|
+
### Added (multi-milestone-intake — a request that is several milestones)
|
|
16
|
+
- **`queued` milestone status.** The milestone status enum becomes
|
|
17
|
+
**active · queued · done** (was active · done). A milestone can now exist
|
|
18
|
+
non-active, awaiting promotion — created with `new-milestone --queued` and made
|
|
19
|
+
active with an explicit `activate`. Migration-safe: an old state with no `queued`
|
|
20
|
+
milestones reads byte-identically.
|
|
21
|
+
- **Roadmap intake.** `intake.md` now guides decomposing a request that is *several*
|
|
22
|
+
milestones into a roadmap that creates **all N — 1 active + N−1 queued** — instead
|
|
23
|
+
of only the first. Promotion stays human-gated; the whole set is never auto-activated.
|
|
24
|
+
- **Queued-backlog resume cue.** `status` surfaces the queued backlog (active
|
|
25
|
+
milestone + what's queued next), so a multi-milestone session resumes cleanly. The
|
|
26
|
+
cue is present-only — byte-identical output when nothing is queued.
|
|
27
|
+
|
|
28
|
+
### Added (multi-active-polish — close the parallel-front residuals)
|
|
29
|
+
- **`waves --merge`** folds the active SET into one cross-milestone DAG and critical
|
|
30
|
+
path (today's `waves` is per-milestone only).
|
|
31
|
+
- **`mine --all`** widens the ownership lens past the active milestones — every
|
|
32
|
+
not-done task you own or are assigned, across all milestones plus loose, with an
|
|
33
|
+
email-OR-name match. Plain `mine` (active-only) stays byte-identical.
|
|
34
|
+
- **`doctor` value-domain checks.** `doctor` now flags a bad `gate` enum
|
|
35
|
+
(∉ {PASS, RISK-ACCEPTED, HARD-STOP}), a bad `phase`, archived inconsistency, or a
|
|
36
|
+
malformed owner/assignee — beyond the existing referential pointers. It **adds
|
|
37
|
+
findings only**; it never auto-fails or retro-reds grandfathered history.
|
|
38
|
+
- **`new-milestone` add-and-focus.** Creating a milestone while one is active now
|
|
39
|
+
**preserves the active SET** (adds the new one and focuses it) instead of replacing
|
|
40
|
+
the set and evicting the others. `--queued` and single-active stay byte-identical.
|
|
41
|
+
|
|
42
|
+
### Added (udd-design-intake)
|
|
43
|
+
- **`design-intake` beat.** The UDD design loop opens with a new front beat that
|
|
44
|
+
interviews the human on four axes — **FIDELITY · CONCEPT · LAYOUT · VISUAL DESIGN**
|
|
45
|
+
— recorded in `DESIGN.md` before review-capture-confirm. Convention-only (the engine
|
|
46
|
+
never renders); identity values (brand color/type) stay human-owned — surfaced to
|
|
47
|
+
decide, never auto-picked.
|
|
48
|
+
|
|
49
|
+
### Added / Changed (loose tasks since 1.11.0)
|
|
50
|
+
- **Descriptive-slug nudge (`new-milestone`).** A milestone slug that is a bare
|
|
51
|
+
version number (`v2`, `v1-1`, `1.2` — matched by `^v?\d+([._-]\d+)*$`) prints an
|
|
52
|
+
advisory `note:` suggesting a short **descriptive** name (e.g. `payment-retries`) and
|
|
53
|
+
**still creates the milestone** — never blocks.
|
|
54
|
+
- **Full-ISO `created:` stamp.** MILESTONE.md's `created:` line is the full UTC ISO
|
|
55
|
+
timestamp (`2026-06-26T03:47:28+00:00`); a single `_now()` instant feeds both the
|
|
56
|
+
rendered file and the `state.json` record.
|
|
57
|
+
- **`add.py freeze`** — an engine-stamped human-approval write at the §3 contract
|
|
58
|
+
freeze (DRAFT → FROZEN @ vN with a structured actor line). A security finding remains
|
|
59
|
+
an un-forceable HARD-STOP.
|
|
60
|
+
- **Queued + await-confirm reminder.** A milestone that is both `queued` and
|
|
61
|
+
`--await-confirm` now surfaces its `milestone-confirm` reminder at resume.
|
|
62
|
+
- **Flow docs.** Book ch.02 gains a subsection explaining the milestone-scale
|
|
63
|
+
composition rule — tasks are **listed breadth-first up front** (the DAG), then each
|
|
64
|
+
**specified just-in-time**.
|
|
65
|
+
|
|
66
|
+
This release bundles **3 closed milestones** (`udd-design-intake`,
|
|
67
|
+
`multi-milestone-intake`, `multi-active-polish`) and the loose tasks above since
|
|
68
|
+
1.11.0. Every milestone was built end-to-end through ADD's own
|
|
69
|
+
spec→tests→build→verify flow.
|
|
70
|
+
|
|
71
|
+
## [1.11.0] — 2026-06-26
|
|
72
|
+
|
|
73
|
+
Engine-modularization + audit-hardening release — the 7k-line monolith becomes a
|
|
74
|
+
navigable package, the verify/atomicity/coverage gates get five fixes, and the
|
|
75
|
+
standalone (milestone-free) lane becomes first-class. **No behavior change** to the
|
|
76
|
+
CLI, the flow, or any output: this is an internal architecture + hardening release.
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
- **The engine is now a focused package.** `add-method/tooling/add.py` (7049 → 5640
|
|
80
|
+
lines, −20%) split into **13 `add_engine/*.py` modules** — `constants`, `io_state`,
|
|
81
|
+
`accessors`, `predicates`, `identity`, `guidelines`, `render`, `milestones`,
|
|
82
|
+
`components`, `version`, `release`, `taskdoc`, `autonomy` — behind a stable
|
|
83
|
+
re-export surface (`import add; add.<name>` still resolves, public AND `_`-prefixed,
|
|
84
|
+
so every existing test is untouched). `add.py` stays the runnable **orchestrator
|
|
85
|
+
entry** (the `load_state`/`save_state`/`report_data`/`cmd_*`/`main` spine). Each of
|
|
86
|
+
the 16 extractions was its own CI-green PR, proven verbatim by an AST source-segment
|
|
87
|
+
diff and gated by the full suite (1815 → 1959 green throughout, no test weakened).
|
|
88
|
+
- **Two-pin integrity model.** Alongside `ENGINE_MD5` (md5 of `add.py`),
|
|
89
|
+
`ENGINE_PKG_MD5` is a manifest digest over every `add_engine/*.py`; both are literal
|
|
90
|
+
pins (never self-hashed) and are checked byte-identical across the 3-tree mirror
|
|
91
|
+
(canonical · `.add` · `_bundled`). `prepare_bundle` + both installers + the `.add`
|
|
92
|
+
mirror now ship the whole `add_engine/` package.
|
|
93
|
+
|
|
94
|
+
### Fixed (audit-hardening)
|
|
95
|
+
- Five gate/atomicity/coverage fixes: a phase-build guard, hardened save-state
|
|
96
|
+
atomicity, force-preserve self-healing, setup-tests-before-build ordering, and a
|
|
97
|
+
consumer-stale gate. A security finding remains an un-forceable HARD-STOP.
|
|
98
|
+
|
|
99
|
+
### Added (the standalone / lightweight lane)
|
|
100
|
+
- **`add.py todo`** — capture a milestone-free backlog item without scaffolding a task.
|
|
101
|
+
- **`loose tasks:` release attribution** — a release now attributes *any* done,
|
|
102
|
+
milestone-free task on its `RELEASES.md` row (not only milestone membership), with a
|
|
103
|
+
separate status cue for releasable loose work.
|
|
104
|
+
- **`fast` (task) + `auto` (mode) flag modes** — the standalone lane is first-class:
|
|
105
|
+
a minimal `TASK.fast.md`, freeze-gated under any milestone, with a flag-mode quick
|
|
106
|
+
reference.
|
|
107
|
+
|
|
108
|
+
This release bundles **2 closed milestones** (`audit-hardening`,
|
|
109
|
+
`engine-modularization`) and **27 loose tasks** since 1.10.0.
|
|
110
|
+
|
|
9
111
|
## [1.10.0] — 2026-06-25
|
|
10
112
|
|
|
11
113
|
Component-aware major — ADD now models every codebase as a **graph of components**,
|
package/bin/cli.js
CHANGED
|
@@ -562,6 +562,57 @@ function writeGeminiSettings(target) {
|
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
564
|
|
|
565
|
+
// Seed .add/SOUL.md from the bundled template if it does not yet exist. Mirror of
|
|
566
|
+
// _installer.py:_seed_soul_md (npm <-> pip parity): skip-if-exists (SOUL.md is
|
|
567
|
+
// user-owned — never clobber); fail-soft (warn + return, never abort install/update).
|
|
568
|
+
function seedSoulMd(target) {
|
|
569
|
+
const dest = path.join(target, ".add", "SOUL.md");
|
|
570
|
+
if (fs.existsSync(dest)) return; // skip-if-exists (never clobber)
|
|
571
|
+
const source = path.join(PKG_ROOT, "tooling", "templates", "SOUL.md.tmpl");
|
|
572
|
+
if (!fs.existsSync(source)) {
|
|
573
|
+
warn("soul_seed_skipped: SOUL.md.tmpl not found in bundled tooling/templates/");
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
try {
|
|
577
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
578
|
+
fs.writeFileSync(dest, fs.readFileSync(source, "utf8"));
|
|
579
|
+
} catch (e) {
|
|
580
|
+
warn("soul_seed_skipped: could not write .add/SOUL.md — " + (e && e.message ? e.message : e));
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// Ensure .add/.gitignore lists the engine's transient artifacts. Seed it from the bundled
|
|
585
|
+
// tooling/templates/gitignore.tmpl if absent; else APPEND-IF-ABSENT each pattern line the
|
|
586
|
+
// template carries that the file lacks — additive only, never reorders/removes user lines,
|
|
587
|
+
// idempotent; comment/blank lines are not appended to an existing file. Fail-soft. Twin of
|
|
588
|
+
// _installer.py:_seed_gitignore.
|
|
589
|
+
function seedGitignore(target) {
|
|
590
|
+
const source = path.join(PKG_ROOT, "tooling", "templates", "gitignore.tmpl");
|
|
591
|
+
if (!fs.existsSync(source)) {
|
|
592
|
+
warn("gitignore_seed_skipped: gitignore.tmpl not found in bundled tooling/templates/");
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const dest = path.join(target, ".add", ".gitignore");
|
|
596
|
+
try {
|
|
597
|
+
const body = fs.readFileSync(source, "utf8");
|
|
598
|
+
if (!fs.existsSync(dest)) {
|
|
599
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
600
|
+
fs.writeFileSync(dest, body); // seed-if-missing
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const current = fs.readFileSync(dest, "utf8");
|
|
604
|
+
const have = new Set(current.split("\n").map((l) => l.trim()));
|
|
605
|
+
const missing = body.split("\n").filter(
|
|
606
|
+
(l) => l.trim() && !l.trim().startsWith("#") && !have.has(l.trim())
|
|
607
|
+
);
|
|
608
|
+
if (missing.length === 0) return; // idempotent — nothing to add
|
|
609
|
+
const suffix = current === "" || current.endsWith("\n") ? "" : "\n";
|
|
610
|
+
fs.writeFileSync(dest, current + suffix + missing.join("\n") + "\n");
|
|
611
|
+
} catch (e) {
|
|
612
|
+
warn("gitignore_seed_skipped: could not update .add/.gitignore — " + (e && e.message ? e.message : e));
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
565
616
|
// The drop — now a RECONCILE: restore missing managed trees + refresh present ones
|
|
566
617
|
// (sweep orphans) + report per-tree status. Byte-compatible handoff with the prior
|
|
567
618
|
// installer. The interactive path resolves a target then calls straight into this.
|
|
@@ -569,6 +620,8 @@ function dropFiles(args, target, profile, intent) {
|
|
|
569
620
|
profile = profile || detectAgent(process.env);
|
|
570
621
|
log("Installing ADD into " + target);
|
|
571
622
|
reconcile(args, target);
|
|
623
|
+
seedSoulMd(target); // pip parity: re-seed a missing user-owned SOUL.md (never clobber)
|
|
624
|
+
seedGitignore(target); // pip parity: seed/append-if-absent the engine-transient ignore lines
|
|
572
625
|
|
|
573
626
|
// Agent detection: write THE detected agent's integration file (a marker-delimited
|
|
574
627
|
// pointer init's sync-guidelines later supersedes) + tailor the closing next-step.
|
|
@@ -932,6 +985,8 @@ function cmdUpdate(args) {
|
|
|
932
985
|
fs.copyFileSync(stateFile, path.join(addDir, "pre-update-state.bak.json"));
|
|
933
986
|
}
|
|
934
987
|
reconcile(args, target);
|
|
988
|
+
seedSoulMd(target); // pip parity: re-seed a missing user-owned SOUL.md (never clobber)
|
|
989
|
+
seedGitignore(target); // pip parity: seed/append-if-absent the engine-transient ignore lines
|
|
935
990
|
writeStamp(addDir, version);
|
|
936
991
|
log("ADD updated " + (cur || "(unstamped)") + " -> " + version +
|
|
937
992
|
" · managed layer reconciled · your project state untouched.");
|
package/docs/02-the-flow.md
CHANGED
|
@@ -52,6 +52,16 @@ The shape is deliberate: the human-led steps establish direction, a frozen contr
|
|
|
52
52
|
|
|
53
53
|
> **What changed in v7 (the diagrams above show the structural flow, which is unchanged).** The *steps* and their order are exactly as drawn — only **who resolves them** moved. The AI now drafts the whole specification bundle (steps 1–4) and a person approves it **once**, at the contract freeze (not a sign-off at each step); and **Verify is auto-gated on evidence** under `autonomy: auto` (the default), escalating security — always a `HARD-STOP` — and other residue to a person. Lower the autonomy level to `conservative` to keep a human at the Verify gate. See [11 Governance](./11-governance.md).
|
|
54
54
|
|
|
55
|
+
## Many features, one at a time — listed up front, specified just-in-time
|
|
56
|
+
|
|
57
|
+
The flow above runs *one* feature. A milestone holds many, and they compose by one rule: **list every task up front, specify each just-in-time.**
|
|
58
|
+
|
|
59
|
+
- **Listed up front (breadth-first).** When a milestone is created it is decomposed **breadth-first** into a task *list* — `slug · depends-on · one line` each. That is the whole plan and its dependency DAG (`add.py waves` views the order and the critical path). The milestone living-doc (`MILESTONE.md`) holds this list plus the shared decisions and the exit criteria, and it stays **thin** — no per-task detail lives there.
|
|
60
|
+
- **Specified just-in-time.** Each listed task runs the full seven-step flow (0 Ground … 6 Verify) only when work reaches it. Its specification bundle — §1–§4 — is written then, **not** bundled for every task before any build begins.
|
|
61
|
+
- **Why just-in-time.** A later task's spec absorbs what earlier tasks' Observe step taught (a sharper contract, a convention that emerged, a delta fed back), and a bundle written too early rots before you arrive at it. This is the same backward-correction principle — Observe → Specify — applied at milestone scale rather than within one feature. So: list all the tasks, then specify each in turn.
|
|
62
|
+
|
|
63
|
+
The sequence is therefore **decompose the milestone → schedule the task DAG → run each task's seven-step flow just-in-time → close the milestone** — breadth planned once, depth earned one task at a time.
|
|
64
|
+
|
|
55
65
|
## Why the order is the order
|
|
56
66
|
|
|
57
67
|
Each step produces exactly one artifact, and each artifact is the input to the next step. The order is not a preference; it is a dependency chain.
|
package/docs/09-the-loop.md
CHANGED
|
@@ -51,7 +51,7 @@ Each delta is one tagged entry — `- [COMPETENCY · status] the learning (evide
|
|
|
51
51
|
|
|
52
52
|
**The consolidation.** At milestone close (or on demand, when open deltas pile up), a person runs the retrospective consolidation: **gather** every `open` delta across the milestone's tasks, **group** them by competency, **propose** the exact foundation edit for each, **confirm** with the human one by one, then **write** — append-only, newest-first (the newest record prepended at the top) — flipping each delta to `folded` (merged) or `rejected` (considered and deliberately not merged, left in place so the trail survives), and bumping the `foundation-version:` marker. `DDD`/`SDD`/`UDD` deltas consolidate into the matching section of `PROJECT.md`; `TDD`/`ADD` consolidate into `CONVENTIONS.md` (they sharpen the engine, not the product); and **every** consolidation also prepends one row at the top of `PROJECT.md` §Key Decisions — the universal, auditable record of what the foundation learned.
|
|
53
53
|
|
|
54
|
-
**Tooling.** `add.py deltas` lists every open delta across the project (so nothing waiting to be consolidated is invisible); `add.py check` lints each delta's well-formedness — known competency tag, valid status, non-empty evidence.
|
|
54
|
+
**Tooling.** `add.py deltas` lists every open delta across the project (so nothing waiting to be consolidated is invisible); `add.py check` lints each delta's well-formedness — known competency tag, valid status, non-empty evidence. `add.py fold [--task <slug>] [--comp <TAG>]` mechanizes the consolidation — flip + transcribe + route + bump, validate-all-then-write so a reject leaves the tree byte-unchanged; running it **is** the human's confirmation, and the engine never self-approves *which* lessons to keep.
|
|
55
55
|
|
|
56
56
|
**Foundation compaction.** The consolidation *prepends* new learnings; **foundation compaction** is the separate, later step that *shrinks* the result. At milestone close (or on demand, once a foundation spec grows past one screen), the AI proposes collapsing the stable, shipped, zero-residue tail of each foundation spec into ONE per-spec **rolled-up settled line** at the bottom — and the human confirms, one line at a time, exactly as with the consolidation. It never deletes: a settled line summarizes the prose and keeps a `see git` pointer, so the record is lossy on wording but lossless on traceability, and any OPEN residue always stays live. Each spec collapses in its own **per-spec shape** — `PROJECT.md` §Spec version bullets, §Key-Decisions rows, `CONVENTIONS.md` learnings, the `GLOSSARY.md` definition, the `MODEL_REGISTRY.md` rows — under one shared eligibility rule. Because every append-only sequence is **newest-first** (newest record on top), compaction collapses *upward from the bottom*: the settled line anchors at the tail (the oldest end). Like the consolidation it is convention-guided — there is deliberately no `add.py` command for it (read `compact-foundation.md`) — and it is distinct from the engine's `add.py compact <slug>`, which archives a finished milestone's files rather than shrinking a living spec.
|
|
57
57
|
|
package/docs/11-governance.md
CHANGED
|
@@ -31,7 +31,7 @@ Every checkpoint produces three short reports — **Test** (does it pass?), **Qu
|
|
|
31
31
|
|
|
32
32
|
- **`PASS`** — criteria met; proceed.
|
|
33
33
|
- **`RISK-ACCEPTED`** — proceed with a signed waiver carrying a named owner, a linked ticket, and an expiry. Allowed for non-security gaps only.
|
|
34
|
-
- **`HARD-STOP`** — cannot proceed. Triggered by any failing test or any security finding
|
|
34
|
+
- **`HARD-STOP`** — cannot proceed. Triggered by any failing test or any security finding. A non-security limitation may proceed only with a signed `RISK-ACCEPTED` record carrying an owner and an expiry; security is never waved through.
|
|
35
35
|
|
|
36
36
|
The rule behind the protocol is *no silent skips.* A report nobody is accountable for approving is just a document; an outcome with an owner is governance.
|
|
37
37
|
|
package/docs/14-foundation.md
CHANGED
|
@@ -49,14 +49,16 @@ the method already names, made explicit as three concerns.
|
|
|
49
49
|
|
|
50
50
|
When a milestone has screens, UDD is not only a static `DESIGN.md` — it runs a
|
|
51
51
|
**design-definition loop** that turns the domain into a screen the human has *seen
|
|
52
|
-
and confirmed before build*. Its
|
|
53
|
-
→ wireframe → render-capture-confirm`:
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
and confirmed before build*. Its five beats are `design-intake → review-domain →
|
|
53
|
+
research-components → wireframe → render-capture-confirm`: interview the human on the
|
|
54
|
+
four design axes (fidelity · concept · layout · visual design) so the look is directed
|
|
55
|
+
not guessed, read the domain into screens and regions, research and reuse components
|
|
56
|
+
before inventing them, wireframe the structure low-fi, then render a real screen and
|
|
57
|
+
**capture** it. That capture is the **design-confirm**
|
|
56
58
|
evidence — a real image the person approves *before* implementation, so the build
|
|
57
59
|
matches the layout instead of discovering it. The book keeps the *why*; the
|
|
58
60
|
operational recipe (the wireframe format, the token-bound mock, the capture engines)
|
|
59
|
-
lives in the `add` skill's `design.md` and `udd-wireframe.md
|
|
61
|
+
lives in the `add` skill's `design.md` and the `udd-wireframe.md` template (`tooling/templates/`).
|
|
60
62
|
|
|
61
63
|
These three foundation competencies, together with the **TDD ⇄ ADD** engine of
|
|
62
64
|
[Part II](./02-the-flow.md), are ADD's five. The first four feed context to the
|
package/docs/16-releasing.md
CHANGED
|
@@ -11,8 +11,8 @@ them *ship*. This chapter names the act every project eventually performs and th
|
|
|
11
11
|
now, never formalized: bundling closed milestones into a versioned, user-facing release whose notes
|
|
12
12
|
are evidence-backed, whose risk is disclosed, and whose behaviour is then watched.
|
|
13
13
|
|
|
14
|
-
Releasing is the **fifth scope level** — after
|
|
15
|
-
|
|
14
|
+
Releasing is the **fifth scope level** — after setup, intake, the milestone loop, and stage graduation.
|
|
15
|
+
Like every scope level it runs the same shape: **gather → propose → the human
|
|
16
16
|
confirms → the engine records and enforces a floor.** And like graduation, it ends with an outward
|
|
17
17
|
act the human owns. The operational recipe lives in the `release.md` skill guide; this chapter is the
|
|
18
18
|
*why* behind it.
|
|
@@ -84,7 +84,11 @@
|
|
|
84
84
|
|
|
85
85
|
**Baseline approval** (formerly "the lock-down") — the single human gate ending autonomous setup: an explicit yes that freezes the foundation, first scope, and first contract together; runs as `add.py lock --by <name>`.
|
|
86
86
|
|
|
87
|
-
**
|
|
87
|
+
**Queued milestone** — a milestone created non-active: its status is `queued` (the milestone status enum is **active · queued · done**). It is recorded with its `MILESTONE.md` on disk but does not hold the active focus; `add.py new-milestone --queued <slug>` creates it, and `add.py activate <slug>` promotes it queued→active one at a time. A queued milestone is not `done`, so it does not satisfy the graduation gate.
|
|
88
|
+
|
|
89
|
+
**Roadmap** — the multi-milestone intake artifact: when a request decomposes into N>1 milestones of the same line, the AI proposes the ordered roadmap and, on human confirm, creates all N — the first active, the rest **queued** — then promotes each with `activate` as it is started. Distinct from `split_required` (which spans different buckets). Lives in the `add` skill's `intake.md`.
|
|
90
|
+
|
|
91
|
+
**Scope level** (formerly "altitude") — the granularity a decision lives at, as one ordered ladder of five: **setup/foundation** · **intake** (request → versioned scope) · **the milestone loop** (the task is its inner unit) · **stage graduation** (changes rigor, not version; see **Stage graduation**) · **release** (≥1 closed milestone → a versioned, watched cut; see **Release scope level**). One ⚠-assumption notation is shared across every scope level.
|
|
88
92
|
|
|
89
93
|
**Autonomy level** (formerly "autonomy dial") — the explicit per-task setting (`autonomy: manual | conservative | auto`, an ordered ladder manual < conservative < auto) choosing who resolves Verify: `auto` auto-PASSes on complete evidence, `conservative` keeps a human at the gate, `manual` is the strict floor (the human owns the gate; nothing auto-resolves). A high-risk scope refuses an unguarded `auto` — it must be lowered to `manual` or `conservative`. New tasks seed a visible, overridable `autonomy: auto`; a live task with no level warns (`implicit_autonomy`), a token outside the set is rejected (`unknown_autonomy_level`).
|
|
90
94
|
|
|
@@ -134,13 +138,15 @@
|
|
|
134
138
|
|
|
135
139
|
**Newest-first append-only** — every append-only foundation sequence prepends the newest record at the top; the rolled-up settled line anchors at the bottom (the oldest end), so compaction collapses upward.
|
|
136
140
|
|
|
137
|
-
**
|
|
141
|
+
**Design intake** — beat 0 of the UDD **design-definition loop**: the agent interviews the human on four design **axes** *before* reading the domain, so the look is directed not guessed. **Fidelity** (lo-fi wireframe · hi-fi mockup · production — how far the design renders), **Concept** (idea · mood · direction), **Layout** (structure · grid · hierarchy), and **Visual design** (color · type · spacing · imagery — surfaced for the human, never auto-picked). Recorded as project defaults in `DESIGN.md`'s `## Design intake` and per-screen overrides in the prototype note. Fidelity is recorded intent, not an engine gate.
|
|
142
|
+
|
|
143
|
+
**Wireframe** — the Stage-A low-fidelity, *structural* map of one screen: its regions and the component **slots** inside them, derived from `prototypes/<name>.json` *before* any color, type, or spacing — it answers "what goes where", not "what it looks like". Beat 3 of the UDD **design-definition loop**; the low-fi half of the two-stage fidelity that ends in a confirmed capture. See the `udd-wireframe.md` template (`tooling/templates/`, Stage A).
|
|
138
144
|
|
|
139
|
-
**Design mock** — the Stage-B high-fidelity, **self-contained** HTML render of a screen: the `catalog.json` components as a reusable token-bound kit, bound to `tokens.json` and populated with mock data, openable offline and screenshot-able. The human-facing *visible* evidence the human confirms (the frozen `prototypes/<name>.json` tree is its machine-checkable twin). Beat 4's hi-fi artifact; the recipe lives in the `
|
|
145
|
+
**Design mock** — the Stage-B high-fidelity, **self-contained** HTML render of a screen: the `catalog.json` components as a reusable token-bound kit, bound to `tokens.json` and populated with mock data, openable offline and screenshot-able. The human-facing *visible* evidence the human confirms (the frozen `prototypes/<name>.json` tree is its machine-checkable twin). Beat 4's hi-fi artifact; the recipe lives in the `udd-wireframe.md` template (`tooling/templates/`, Stage B).
|
|
140
146
|
|
|
141
147
|
**Capture** — the real rendered image (PNG/SVG) of a design mock: the **design-confirm evidence** artifact. Captures live at `.add/design/captures/<name>.<ext>` (one per prototype) and are attached or mentioned in the feature's `TASK.md`; `@json-render/image` (Satori → PNG/SVG, no browser) is the named default capture engine, otherwise the self-contained mock is screenshot headless. The engine never renders — it only MEASURES presence: `add.py check` raises a never-red `missing_capture` WARN for a prototype with no capture.
|
|
142
148
|
|
|
143
|
-
**Design-confirm** — the human touchpoint closing the UDD **design-definition loop** (`review-domain → research-components → wireframe → render-capture-confirm`, beat
|
|
149
|
+
**Design-confirm** — the human touchpoint closing the UDD **design-definition loop** (`design-intake → review-domain → research-components → wireframe → render-capture-confirm`, the final beat of the `add` skill's `design.md`): approving the captured screen image **before build**, show-before-ask, so the implementation matches the layout the human has already seen instead of discovering it.
|
|
144
150
|
|
|
145
151
|
---
|
|
146
152
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pilotspace/add",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.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"
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"bin/",
|
|
20
20
|
"skill/",
|
|
21
21
|
"tooling/add.py",
|
|
22
|
+
"tooling/add_engine/",
|
|
23
|
+
"!tooling/add_engine/__pycache__",
|
|
24
|
+
"!**/*.pyc",
|
|
22
25
|
"tooling/templates/",
|
|
23
26
|
"docs/",
|
|
24
27
|
"README.md",
|
package/skill/add/SKILL.md
CHANGED
|
@@ -62,7 +62,13 @@ self-improving via the `soul-self-improve` path). Then branch on state:
|
|
|
62
62
|
- **No active task** → first SIZE the request (Intake below), then `add.py new-task <slug> --title "..."`.
|
|
63
63
|
|
|
64
64
|
**Quick ref** — `status` resume · `init` bootstrap · `advance` continue · `gate PASS` at verify.
|
|
65
|
-
**
|
|
65
|
+
**Flag mode** — two human-owned settings (never auto-picked): **fast** (task) · **auto** (mode).
|
|
66
|
+
- **fast** — `new-task --fast`: minimal template, freeze-gated; a milestone-free `--fast` task is a
|
|
67
|
+
blessed standalone low-ceremony lane. Jot ideas first with `add.py todo "<text>"` (then `todo` to
|
|
68
|
+
list · `todo --done <id>`).
|
|
69
|
+
- **auto** — `autonomy: auto` (default) auto-gates verify on evidence; lower the autonomy level with
|
|
70
|
+
`add.py autonomy set conservative|manual` for a human gate · `new-milestone --await-confirm`
|
|
71
|
+
confirm-gates a milestone's tasks.
|
|
66
72
|
|
|
67
73
|
## Intake — size a request before creating scope
|
|
68
74
|
|
|
@@ -117,8 +123,8 @@ once the human confirms, rewrites `SOUL.md` (the human is the only writer) — `
|
|
|
117
123
|
- **Small, low-risk task**, less ceremony → the **fast lane**: `new-task --fast` scaffolds the minimal
|
|
118
124
|
`TASK.fast.md`, bundle approved in one freeze — `phases/fast-lane.md`. Floor held (frozen contract ·
|
|
119
125
|
red test · verify gate; `--fast` is freeze-gated under any milestone). Collapse, never skip; opt-in.
|
|
120
|
-
- **UI feature** at specify → the **design-definition loop** (UDD):
|
|
121
|
-
reuse components → wireframe → a
|
|
126
|
+
- **UI feature** at specify → the **design-definition loop** (UDD): intake the design axes → review the
|
|
127
|
+
domain → research and reuse components → wireframe → a captured screen the human confirms **before** build — `design.md`.
|
|
122
128
|
Tool-agnostic; the engine never renders.
|
|
123
129
|
- Tasks all done but the milestone **goal** unmet → `milestone-done` holds it open; the loop turns open
|
|
124
130
|
deltas + extras into the next tasks (you propose, the human confirms) until the goal is met — `loop.md`.
|
package/skill/add/design.md
CHANGED
|
@@ -10,14 +10,29 @@ draws from already exists — `tokens.json` (the compact-DTCG dialect, `udd-toke
|
|
|
10
10
|
`catalog.json` + `prototypes/<name>.json` (`udd-catalog.md`). This loop fills that foundation
|
|
11
11
|
for a feature and earns the human's sign-off on the look before build.
|
|
12
12
|
|
|
13
|
-
## The loop —
|
|
13
|
+
## The loop — five beats
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
review-domain → research-components → wireframe → render-capture-confirm
|
|
16
|
+
design-intake → review-domain → research-components → wireframe → render-capture-confirm
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Run the beats in order. Each feeds the next; the last ends at a human design-confirm.
|
|
20
20
|
|
|
21
|
+
### 0 · design-intake
|
|
22
|
+
Before you read the domain, interview the human on **four design axes** — so the look is
|
|
23
|
+
*directed*, not guessed. Ask each, show the options, record the pick:
|
|
24
|
+
|
|
25
|
+
- **FIDELITY** — how far this design goes: *lo-fi wireframe* · *hi-fi mockup* · *production*.
|
|
26
|
+
Recorded **intent** that **informs** how far the later beats render (it is not an engine gate).
|
|
27
|
+
- **CONCEPT** — the design *idea / mood / direction* in a line.
|
|
28
|
+
- **LAYOUT** — the *structure / grid / hierarchy* the screens lean on.
|
|
29
|
+
- **VISUAL DESIGN** — *color · type · spacing · imagery*. **Surface** identity values for the
|
|
30
|
+
human to choose — never auto-pick a brand value (identity stays **human-owned**, `udd-tokens.md`).
|
|
31
|
+
|
|
32
|
+
Record the answers **before** review-domain, at both levels: project **defaults** in DESIGN.md's
|
|
33
|
+
`## Design intake` section; per-screen **overrides** (only the deltas) in the per-feature design
|
|
34
|
+
note (the `prototypes/<name>.json` companion). Show-before-ask — confirm the picks, never assume.
|
|
35
|
+
|
|
21
36
|
### 1 · review-domain
|
|
22
37
|
Start from the **domain**, not a blank canvas. Read the domain model — entities, flows, the
|
|
23
38
|
ubiquitous language in `PROJECT.md` / `GLOSSARY.md` — and derive **which screens** the feature
|
|
@@ -70,6 +85,8 @@ human to decide, never auto-pick a brand value (`udd-tokens.md`).
|
|
|
70
85
|
## The hard rules
|
|
71
86
|
|
|
72
87
|
<constraints>
|
|
88
|
+
- **Intake before domain.** The four axes (FIDELITY · CONCEPT · LAYOUT · VISUAL DESIGN) are
|
|
89
|
+
interviewed and recorded — DESIGN.md defaults + per-screen overrides — before beat 1.
|
|
73
90
|
- **Domain first.** A screen is derived from the domain (beat 1), never sketched blind.
|
|
74
91
|
- **Reuse before invent.** Beat 2 checks the catalog first; a new component is a justified,
|
|
75
92
|
cited exception — never the reflex.
|
package/skill/add/intake.md
CHANGED
|
@@ -56,6 +56,22 @@ request, emit ONE of:
|
|
|
56
56
|
When confirmed, record the `rationale` in the artifact you create or affect — the new MILESTONE.md
|
|
57
57
|
goal/body, the new TASK.md, or a note in the affected TASK.md — never in state.json.
|
|
58
58
|
|
|
59
|
+
## Roadmap — a request that is several milestones
|
|
60
|
+
|
|
61
|
+
Some requests decompose into **N>1 milestones of the same line** — a roadmap, not one milestone.
|
|
62
|
+
Don't create only the first and lose the rest. Instead:
|
|
63
|
+
|
|
64
|
+
1. **Propose** the roadmap — the ordered milestone list, each with a one-line goal. (AI proposes.)
|
|
65
|
+
2. **Confirm** — the human confirms the roadmap before anything is created. Never auto-create N
|
|
66
|
+
milestones unprompted — the intake floor (`ask_human`) still holds.
|
|
67
|
+
3. **Create** all N on confirm — the first with `add.py new-milestone <slug>` (active), the rest
|
|
68
|
+
with `add.py new-milestone --queued <slug>` (status `queued`, not focused).
|
|
69
|
+
4. **Promote** one at a time — as each is started, `add.py activate <slug>` flips it queued→active.
|
|
70
|
+
You work one active milestone at a time; the queue is the agreed backlog, surfaced at resume.
|
|
71
|
+
|
|
72
|
+
This is NOT `split_required`: that code is for a request spanning **different buckets** (propose the
|
|
73
|
+
smallest correctly-sized set). A roadmap is several milestones of the **same line**, created queued.
|
|
74
|
+
|
|
59
75
|
## Worked examples (from this project's own history)
|
|
60
76
|
|
|
61
77
|
| request | bucket | rationale |
|
|
@@ -47,11 +47,17 @@ Never: invent a file, symbol, or signature you have not opened.
|
|
|
47
47
|
## Exit gate
|
|
48
48
|
|
|
49
49
|
<exit_gate>
|
|
50
|
-
- [ ]
|
|
51
|
-
- [ ]
|
|
52
|
-
- [ ]
|
|
50
|
+
- [ ] **Touches** — the real files/symbols the task touches are named (from the code, not assumed).
|
|
51
|
+
- [ ] **Context** (working folder) — the non-code artifacts the task touches (docs · todos · config · data) are named, task-delta only.
|
|
52
|
+
- [ ] **Honors** — the patterns/conventions to honor are cited (task-delta only; no architecture re-scan).
|
|
53
|
+
- [ ] **Anchors** — the anchors §3 will cite are listed — §3 names only anchors that exist here.
|
|
53
54
|
</exit_gate>
|
|
54
55
|
|
|
56
|
+
**Grounding is complete when** all four fields are filled from real assets: a STRONG grounding cites
|
|
57
|
+
actual files/symbols/docs/conventions you opened; a WEAK one leaves a `<…>` placeholder or names what you
|
|
58
|
+
assume. All four are non-optional — skipping **Context** (the working folder beyond code) is the usual
|
|
59
|
+
silent gap. §3 may cite only anchors that appear here.
|
|
60
|
+
|
|
55
61
|
> **Advisor · Confidence** — a broad sweep is the canonical spawn case (advisor.md); self-score your grounding before you specify against it (confidence.md).
|
|
56
62
|
|
|
57
63
|
## Next
|
|
@@ -57,7 +57,7 @@ Capture each surfaced decision as an **ADR** into `PROJECT.md` **Key Decisions**
|
|
|
57
57
|
```bash
|
|
58
58
|
python3 .add/tooling/add.py new-task <slug> --title "<first feature>"
|
|
59
59
|
```
|
|
60
|
-
Draft
|
|
60
|
+
Draft the full bundle **§1–§4** — incl. the **§4 red suite** (`phases/4-tests.md`); the lock approves it whole. **Leave §3 `Status: DRAFT`** — the lock is its approval. You MAY `advance` pre-lock, but the engine **refuses crossing into build** until you `lock` (`setup_unlocked`). Sequence: **bundle (§1–§4, tests RED) → lock → build** — the red suite must FAIL **before build** (never start Build until §1–§4 exist and tests are red).
|
|
61
61
|
4. **Write `.add/SETUP-REVIEW.md`** per `setup-review.md`: every drafted decision, **lowest-confidence-first**, tagged `guessed` | `evidence-grounded`.
|
|
62
62
|
|
|
63
63
|
## Run mode — how the build will be driven (propose parallel + auto; confirm to keep)
|
|
@@ -93,7 +93,7 @@ Typing it themselves stays the **escape hatch** — the decision is always the h
|
|
|
93
93
|
<exit_gate>
|
|
94
94
|
- [ ] `.add/state.json` exists; setup was seeded unlocked (`--await-lock`) then locked.
|
|
95
95
|
- [ ] Living docs filled (brownfield: from code, tagged evidence-grounded; greenfield: from the interview).
|
|
96
|
-
- [ ] First task created;
|
|
96
|
+
- [ ] First task created; **§1–§4 drafted — the red suite (per `phases/4-tests.md`) runs RED before build opens**; `.add/SETUP-REVIEW.md` written lowest-confidence-first.
|
|
97
97
|
- [ ] Human confirmed the baseline approval and `add.py lock --by` ran with their name; first task §3 `FROZEN @ v1`; build open.
|
|
98
98
|
</exit_gate>
|
|
99
99
|
|
package/skill/add/scope.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
Before drafting the goal sentence, position the request in what already exists — distinct from intake's classification, not redundant with it.
|
|
21
21
|
|
|
22
|
-
1. **Ground in current assets.** Read the goal against `
|
|
22
|
+
1. **Ground in current assets.** Read the goal against what exists — the goal must reflect what the project already is. Ground as rigorously as a task's §0 (`phases/0-ground.md`), using the **same four fields** at milestone scope: **Touches** (the subsystems/files the milestone spans) · **Context** (the docs · todos · config · data it works against) · **Honors** (the `PROJECT.md` / `CONVENTIONS.md` invariants it must respect) · **Anchors** (the existing contracts/symbols its tasks will cite). Grounding is complete when each is named from real assets, not assumed.
|
|
23
23
|
2. **Relate to the milestone map.** Read every existing goal — `.add/milestones/*/MILESTONE.md` and `.add/archive/*` — and name THIS request's relationship: *extends* X · *depends-on* Y · *overlaps* Z. Record in the `rationale` line.
|
|
24
24
|
3. **If the goal is already delivered** by an existing milestone, reject `duplicate_goal` and route as `task` or `change-request`.
|
|
25
25
|
|