@pilotspace/add 1.16.1 → 1.17.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 +83 -0
- package/agents/add-advisor.md +1 -1
- package/agents/add-build.md +1 -1
- package/agents/add-design.md +1 -1
- package/agents/add-persona.md +6 -4
- package/agents/add-verify.md +3 -1
- package/bin/cli.js +143 -8
- package/docs/10-setup-and-stages.md +1 -1
- package/docs/18-personas.md +2 -2
- package/package.json +1 -1
- package/skill/add/advisor.md +2 -1
- package/skill/add/deltas.md +1 -1
- package/skill/add/design.md +2 -2
- package/skill/add/fold.md +7 -7
- package/skill/add/intake.md +17 -12
- package/skill/add/loop.md +6 -7
- package/skill/add/phases/0-setup.md +3 -3
- package/skill/add/phases/4-tests.md +19 -17
- package/skill/add/phases/7-observe.md +8 -10
- package/skill/add/phases/fast-lane.md +3 -0
- package/skill/add/report-template.md +7 -6
- package/skill/add/run.md +7 -17
- package/skill/add/scope.md +1 -1
- package/skill/add/self-improve.md +20 -0
- package/skill/add/streams.md +14 -13
- package/tooling/add.py +502 -37
- package/tooling/add_engine/constants.py +12 -0
- package/tooling/add_engine/io_state.py +13 -0
- package/tooling/templates/TASK.fast.md.tmpl +2 -1
- package/tooling/templates/TASK.md.tmpl +16 -51
- package/tooling/templates/personas/_template.md.tmpl +2 -0
|
@@ -25,6 +25,7 @@ __all__ = [
|
|
|
25
25
|
"PERSONA_FRONTMATTER_KEYS",
|
|
26
26
|
"PERSONA_REQUIRED_SECTIONS",
|
|
27
27
|
"PERSONA_HINT",
|
|
28
|
+
"PERSONA_FIT_HINT_TEMPLATE",
|
|
28
29
|
"GUIDELINE_FILES",
|
|
29
30
|
"RULES_FILE_REL",
|
|
30
31
|
"WORKFLOW_HEADINGS",
|
|
@@ -108,6 +109,16 @@ PERSONA_HINT = ("no project-fit persona seeded yet under .add/personas/ — spaw
|
|
|
108
109
|
"agent (or read docs/18-personas.md) to seed the project's persona(s) from "
|
|
109
110
|
"PROJECT.md's domain")
|
|
110
111
|
|
|
112
|
+
# persona-fit-nudge: the OPPOSITE-branch, mutually-exclusive sibling of PERSONA_HINT — fires only
|
|
113
|
+
# when ≥1 real persona ALREADY exists, so a brand-new milestone doesn't silently assume one of
|
|
114
|
+
# them fits its domain. Existence-only (names the persona slugs already seeded); the AI still
|
|
115
|
+
# owns the actual fit judgment via add-persona — the engine never scores content similarity.
|
|
116
|
+
# {slugs} is filled at call time from `.add/personas/*.md` (excluding `_template`).
|
|
117
|
+
PERSONA_FIT_HINT_TEMPLATE = (
|
|
118
|
+
"existing persona(s) seeded — {slugs} — confirm one fits this milestone's domain, or spawn "
|
|
119
|
+
"the add-persona agent (or read docs/18-personas.md) to draft a better-fit one"
|
|
120
|
+
)
|
|
121
|
+
|
|
111
122
|
# Scaffolded into .add/.gitignore at init so the engine's transient LOCAL artifacts
|
|
112
123
|
# never reach git. Bare-filename patterns match at any depth under .add/ (tasks/,
|
|
113
124
|
# milestones/, archive/). These are working state, not records: scope-snapshot.json
|
|
@@ -208,6 +219,7 @@ fast: true
|
|
|
208
219
|
## 0 · GROUND
|
|
209
220
|
Touches (files · symbols):
|
|
210
221
|
Anchors the contract cites:
|
|
222
|
+
Ground SHA:
|
|
211
223
|
|
|
212
224
|
## 1 · SPECIFY
|
|
213
225
|
Feature:
|
|
@@ -213,3 +213,16 @@ def _personas_unseeded(root: Path) -> bool:
|
|
|
213
213
|
return not any(p.stem != "_template" for p in d.glob("*.md"))
|
|
214
214
|
except OSError:
|
|
215
215
|
return True
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _real_persona_slugs(root: Path) -> list[str]:
|
|
219
|
+
"""Sorted slugs of REAL (non-template) personas under `.add/personas/` — the existence-only
|
|
220
|
+
listing persona-fit-nudge names in its hint. Fail-soft: an unreadable/absent dir is empty,
|
|
221
|
+
mirroring `_personas_unseeded`'s own fail-soft convention."""
|
|
222
|
+
d = root / "personas"
|
|
223
|
+
if not d.is_dir():
|
|
224
|
+
return []
|
|
225
|
+
try:
|
|
226
|
+
return sorted(p.stem for p in d.glob("*.md") if p.stem != "_template")
|
|
227
|
+
except OSError:
|
|
228
|
+
return []
|
|
@@ -18,6 +18,7 @@ Touches (files · symbols): <path:symbol — what it is / how it is keyed>
|
|
|
18
18
|
Context (working folder): <docs · config · data the task touches — task-delta only>
|
|
19
19
|
Honors (patterns / conventions): <PROJECT.md / CONVENTIONS.md anchors — task-delta>
|
|
20
20
|
Anchors the contract cites: <the symbols §3 will name>
|
|
21
|
+
Ground SHA: <`git rev-parse --short HEAD` at ground time — any line ref reads "as of" it>
|
|
21
22
|
|
|
22
23
|
---
|
|
23
24
|
|
|
@@ -56,7 +57,7 @@ Tests live in: `./tests/` · MUST run red (missing implementation) before Build.
|
|
|
56
57
|
## 5 · BUILD — AI writes code
|
|
57
58
|
|
|
58
59
|
Scope (may touch): `./src/` <every file the build may write — declared before the §3 freeze>
|
|
59
|
-
Strategy & known-problem fixes: <ordered build steps · the trap each known problem must dodge>
|
|
60
|
+
Strategy & known-problem fixes: <ordered build steps · the trap each known problem must dodge · let the active persona's domain stance (or "generic") shape the approach, not just patterns>
|
|
60
61
|
Strategy actually used: <fill at verify — what you ACTUALLY did, or "as planned"; harvested into §7 Decisions>
|
|
61
62
|
Code lives in: `./src/` · Constraints: change no test, no contract; allow-list packages only.
|
|
62
63
|
|
|
@@ -2,15 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
slug: {{slug}} · created: {{date}} · stage: {{stage}}
|
|
4
4
|
milestone: {{milestone}}
|
|
5
|
-
autonomy: {{autonomy}} <!--
|
|
5
|
+
autonomy: {{autonomy}} <!-- level: manual < conservative < auto — lower for a high-risk task (`add.py autonomy set`). Multi-component repo? add a `component: <name>` line (.add/components.toml) to join that root to §5 Scope. -->
|
|
6
6
|
phase: ground <!-- ground -> specify -> scenarios -> contract -> tests -> build -> verify -> observe -> done -->
|
|
7
|
-
<!-- high-risk/method-defining
|
|
8
|
-
autonomy level to `manual` or `conservative` — the engine refuses an unguarded completion
|
|
9
|
-
(`unguarded_high_risk_auto`, run.md guard). A comment is never a declaration. -->
|
|
7
|
+
<!-- high-risk/method-defining? declare `risk: high` on the slug line + a lowered autonomy — the engine refuses an unguarded completion (`unguarded_high_risk_auto`). A comment is never a declaration. -->
|
|
10
8
|
|
|
11
|
-
> One file = one task
|
|
12
|
-
> When a phase is unclear, read its book chapter in `.add/docs/` (linked per section).
|
|
13
|
-
> The phase marker above is the single source of truth — keep it in sync via `add.py phase`.
|
|
9
|
+
> One file = one task — fill top-to-bottom; the phase marker above is the single source of truth (`add.py phase`); unclear phase → its book chapter.
|
|
14
10
|
|
|
15
11
|
---
|
|
16
12
|
|
|
@@ -49,7 +45,7 @@ Assumptions — lowest-confidence first:
|
|
|
49
45
|
- [ ] <next assumption, ranked> — confirm or deny; never carry an open one forward
|
|
50
46
|
</assumptions>
|
|
51
47
|
|
|
52
|
-
<!-- EXIT: every rule
|
|
48
|
+
<!-- EXIT: every rule + rejection stated; assumptions ranked lowest-confidence first, top 1–2 ⚠-flagged with why + cost (or an honest "none material" naming the biggest risk). -->
|
|
53
49
|
|
|
54
50
|
---
|
|
55
51
|
|
|
@@ -83,14 +79,7 @@ Schema: <tables/fields touched, and access pattern>
|
|
|
83
79
|
Glossary deltas: <new domain term(s) this task introduces, `Term: definition` — or "none">
|
|
84
80
|
Status: DRAFT
|
|
85
81
|
Reported: <yes — the freeze report (banner/ARC/SHAPE) rendered before this froze | no>
|
|
86
|
-
<!-- The freeze IS the one approval — lead it with the bundle's lowest-confidence flag:
|
|
87
|
-
points most likely wrong across the whole bundle, tagged [spec|scenario|contract|test], each
|
|
88
|
-
with why + cost (the §1 ⚠ assumptions feed it; a flag may point at a scenario or the contract
|
|
89
|
-
too — see run.md). Approved -> Status: FROZEN @ vN — approved by <name>. Changing a frozen
|
|
90
|
-
contract = change request back to SPECIFY.
|
|
91
|
-
EXIT: frozen + every spec rejection has a contracted response + names match GLOSSARY (new
|
|
92
|
-
terms declared as a Glossary delta) + the bundle's lowest-confidence flag was surfaced at
|
|
93
|
-
the freeze (or an honest "none material"). -->
|
|
82
|
+
<!-- The freeze IS the one approval — lead it with the bundle's lowest-confidence flag (§1 ⚠ feeds it; a flag may point at any part — run.md). Approved -> Status: FROZEN @ vN — approved by <name>; changing a frozen contract = change request back to SPECIFY. EXIT: frozen · every §1 rejection has a contracted response · names match GLOSSARY (new terms = Glossary delta) · flag surfaced. -->
|
|
94
83
|
|
|
95
84
|
---
|
|
96
85
|
|
|
@@ -103,10 +92,7 @@ Plan (one test per scenario, asserting behavior not internals):
|
|
|
103
92
|
</test_plan>
|
|
104
93
|
|
|
105
94
|
Tests live in: `./tests/` · MUST run red (missing implementation) before Build.
|
|
106
|
-
<!-- declare paths as backticked tokens on this line: `./…` = this task dir ·
|
|
107
|
-
a token with "/" = project root · a bare name = sibling of the previous
|
|
108
|
-
token's dir · a directory counts its *.py files (non-recursive); reports
|
|
109
|
-
mark declared counts with † · anything resolving outside the project root counts 0 -->
|
|
95
|
+
<!-- declare paths as backticked tokens on this line: `./…` = this task dir · a token with "/" = the project root · a bare name = a sibling of the previous token's dir · a directory counts its *.py files (non-recursive) · declared counts marked † · outside the project root counts 0 -->
|
|
110
96
|
|
|
111
97
|
<!-- EXIT: one test per scenario; suite red for the RIGHT reason; target recorded. -->
|
|
112
98
|
|
|
@@ -115,9 +101,9 @@ Tests live in: `./tests/` · MUST run red (missing implementation) before Build.
|
|
|
115
101
|
## 5 · BUILD — AI writes code ▸ docs/07-step-5-build.md
|
|
116
102
|
|
|
117
103
|
Scope (may touch): `./src/` <fill before the §3 freeze — every file the build may write>
|
|
118
|
-
Strategy (ordered batches): <1. … 2. … — the planned build order; guidance, not enforced; preferred architecture/pattern strategies; advise solution/method to resolve issues/implement features>
|
|
104
|
+
Strategy (ordered batches): <1. … 2. … — the planned build order; guidance, not enforced; preferred architecture/pattern strategies; advise solution/method to resolve issues/implement features; let the named Persona's domain stance (below) shape the approach, not just architecture patterns>
|
|
119
105
|
|
|
120
|
-
Persona (
|
|
106
|
+
Persona (required): <name the persona file under `.add/personas/` this build embodies as a domain stance atop SOUL.md — advisory, never lowers a gate; name "generic" if no project persona fits yet>
|
|
121
107
|
Spawn isolation (default): <prefer isolation: "worktree" for any subagent build/verify spawn, not only explicit parallel mode; shared-tree needs a stated reason — see worktree-isolated-spawn-default>
|
|
122
108
|
Known-problem fixes: <trap → planned fix — the failure modes this build must dodge; guidance, not enforced>
|
|
123
109
|
Strategy actually used: <fill at VERIFY — the strategy you ACTUALLY used (or "as planned"); harvested into the §7 Decisions (ADR) block as the [AI] build decision>
|
|
@@ -125,14 +111,7 @@ Safety rule (feature-specific): <e.g. debit+credit in one atomic transaction>
|
|
|
125
111
|
Code lives in: `./src/`
|
|
126
112
|
Constraints: do NOT change any test or the contract; allow-list packages only; ask if unclear.
|
|
127
113
|
|
|
128
|
-
<!-- Scope tokens, backticked, FIRST declaring line: `./…` = this task dir · a token
|
|
129
|
-
with "/" = project root · a bare name = sibling of the previous token's dir ·
|
|
130
|
-
outside-root resolutions are dropped fail-closed · a DIRECTORY token covers its
|
|
131
|
-
whole subtree (containment — diverges from §4's non-recursive counting) ·
|
|
132
|
-
absent line = UNDECLARED (pre-existing tasks grandfathered, never retro-red) ·
|
|
133
|
-
engine enforcement (touched ⊆ declared) is live: a completing verify gate refuses an
|
|
134
|
-
out-of-scope build (scope_violation → self-heal) and add.py check surfaces it.
|
|
135
|
-
EXIT: all green; coverage held; no test/contract touched; no unlisted dependency. -->
|
|
114
|
+
<!-- Scope tokens, backticked, FIRST declaring line: `./…` = this task dir · a token with "/" = project root · a bare name = sibling of the previous token's dir · a DIRECTORY token covers its whole subtree (diverges from §4's non-recursive counting) · outside-root resolutions drop fail-closed · absent line = UNDECLARED (grandfathered, never retro-red) · enforcement live: a completing verify gate refuses an out-of-scope build (scope_violation → self-heal); check surfaces it. EXIT: all green; coverage held; no test/contract touched; no unlisted dependency. -->
|
|
136
115
|
|
|
137
116
|
---
|
|
138
117
|
|
|
@@ -148,9 +127,7 @@ Constraints: do NOT change any test or the contract; allow-list packages only; a
|
|
|
148
127
|
- [ ] a person reviewed and approved the change
|
|
149
128
|
|
|
150
129
|
### Build expectations — what "correct" looks like (fill BEFORE build; confirm each at the gate)
|
|
151
|
-
>
|
|
152
|
-
> + §3 CONTRACT — so this gate checks the build is RIGHT, not merely that tests are green. Each
|
|
153
|
-
> row is evidence you can SEE, not a restatement of a test name.
|
|
130
|
+
> OBSERVABLE outcomes a correct build must produce, derived from the §2 scenarios + §3 contract — evidence you can SEE, not test names.
|
|
154
131
|
- [ ] <observable outcome a correct build must produce> — confirmed by <how / where>
|
|
155
132
|
- [ ] <another observable outcome> — confirmed by <evidence seen>
|
|
156
133
|
|
|
@@ -160,26 +137,17 @@ Constraints: do NOT change any test or the contract; allow-list packages only; a
|
|
|
160
137
|
- [ ] SEMANTIC (prose / non-code) — read in full, not skimmed: <what read · what confirmed>
|
|
161
138
|
|
|
162
139
|
### Live-verify evidence — confirm the §0 GROUND anchors still resolve (fill at the gate)
|
|
163
|
-
> §
|
|
164
|
-
> build. Before the gate, re-resolve every symbol §3 CONTRACT cites against the CURRENT tree
|
|
165
|
-
> (not the Ground SHA) so a stale anchor is caught here, not by a future reader chasing a moved
|
|
166
|
-
> line.
|
|
140
|
+
> Re-resolve every symbol §3 cites against the CURRENT tree (code moved since Ground SHA) — catch a stale anchor here, not later.
|
|
167
141
|
- [ ] every symbol §3 CONTRACT cites still resolves in the current tree — confirmed by <how / where>
|
|
168
142
|
- [ ] any anchor that moved/renamed since Ground SHA is named here, not left silent
|
|
169
143
|
|
|
170
144
|
### Refute-read verdict — the earned-green check (record it; required for an auto-PASS)
|
|
171
|
-
> Under
|
|
172
|
-
> recorded here (the engine never spawns it — you do; NOT-EARNED -> `add.py heal`). The engine
|
|
173
|
-
> MEASURES it is filled (`audit: refute_unrecorded`); it never auto-blocks — a human spot-audit
|
|
174
|
-
> is the backstop. A human-gated (conservative/manual) task may leave it for the human's judgment.
|
|
145
|
+
> Under auto, record the earned-green refute-read (the engine never spawns it — you do; NOT-EARNED -> `add.py heal`). Audit-measured (`refute_unrecorded`), never blocked; a human spot-audit is the backstop.
|
|
175
146
|
Verdict: <EARNED | NOT-EARNED>
|
|
176
147
|
By: <self | agent-id> · adversarially checked: <what was probed>
|
|
177
148
|
|
|
178
149
|
### Advisor 3-lens verdict — sequential (security → concurrency → architecture)
|
|
179
|
-
>
|
|
180
|
-
> order; a Security HARD-STOP ends the checklist (leave remaining lenses blank). Binding for
|
|
181
|
-
> sensitivity: mechanical (advisor-gate-relax reads it); advisory for all other sensitivities.
|
|
182
|
-
> The engine MEASURES this block is filled (audit: advisor_verdict_unrecorded); it never blocks.
|
|
150
|
+
> Lenses run in order; a Security HARD-STOP ends the checklist (leave the rest blank). Binding for sensitivity: mechanical (advisor-gate-relax); advisory otherwise. Audit-measured (`advisor_verdict_unrecorded`), never blocked.
|
|
183
151
|
Advisor: <agent-id | self>
|
|
184
152
|
1. Security: <CLEAR | HARD-STOP: finding>
|
|
185
153
|
2. Concurrency: <CLEAR | RESIDUE: finding>
|
|
@@ -194,7 +162,7 @@ Outcome: <PASS | RISK-ACCEPTED | HARD-STOP>
|
|
|
194
162
|
If RISK-ACCEPTED -> owner: <name> · ticket: <link> · expires: <date> (never for a security gap)
|
|
195
163
|
Reviewed by: <name> · date: <date>
|
|
196
164
|
|
|
197
|
-
<!--
|
|
165
|
+
<!-- Security is ALWAYS HARD-STOP; record exactly one outcome — no silent pass. The Advisor 3-lens and Refute-read verdicts are audit-measured (`advisor_verdict_unrecorded` · `refute_unrecorded`), never engine-blocked; a human spot-audit backstops anything unrecorded. -->
|
|
198
166
|
|
|
199
167
|
---
|
|
200
168
|
|
|
@@ -206,11 +174,8 @@ Watch (reuse scenarios as monitors): <error rate / per-rejection rate / latency>
|
|
|
206
174
|
<harvested at done from §1/§3/§5/§6 — do not hand-edit; one actor-tagged line per decision, refilled only while this placeholder stands>
|
|
207
175
|
|
|
208
176
|
### Spec delta
|
|
209
|
-
|
|
210
|
-
each, tagged `[SPEC · open|seeded|dropped]`, with evidence (e.g. `[SPEC · open] rate-limit
|
|
211
|
-
the retry path (evidence: prod herd spikes)`). See the `add` skill's `deltas.md`.
|
|
177
|
+
One line per forward change, tagged `[SPEC · open|seeded|dropped]` + evidence — each re-enters at Specify (`deltas.md`).
|
|
212
178
|
|
|
213
179
|
### Competency deltas
|
|
214
|
-
|
|
215
|
-
(`DDD · SDD · UDD · TDD · ADD`), status `open`, with evidence. See the `add` skill's `deltas.md`.
|
|
180
|
+
One lesson per line: `[DDD|SDD|UDD|TDD|ADD · open] the learning (evidence: …)` — see `deltas.md`.
|
|
216
181
|
<!-- e.g. - [DDD · open] the model missed multi-tenancy (evidence: scenario_x failed) -->
|
|
@@ -46,6 +46,8 @@ source: <OPTIONAL — the teacher file(s) this was distilled from, e.g. `.add/pe
|
|
|
46
46
|
Critical Rules (always-enforced constraints) and Playbook (optional step-by-step scaffolding).
|
|
47
47
|
State each as something the agent can perform right now, anchored to a real file/tool/command
|
|
48
48
|
where possible — not an aspiration.>
|
|
49
|
+
- <ORIENT first (convention): lead with the 1–3 commands the agent RUNS on load before acting —
|
|
50
|
+
e.g. `add.py status` · the domain's suite · the diff to judge — acting beats re-deriving>
|
|
49
51
|
- <a concrete capability — e.g. "can diff two response fixtures byte-for-byte to prove passthrough">
|
|
50
52
|
- <another concrete capability>
|
|
51
53
|
|