@pilotspace/add 2.1.0 → 2.3.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 +82 -0
- package/agents/add-advisor.md +10 -2
- package/agents/add-worker.md +2 -0
- package/bin/cli.js +2 -137
- package/package.json +1 -1
- package/skill/add/SKILL.md +7 -7
- package/skill/add/deltas.md +1 -1
- package/skill/add/design.md +1 -1
- package/skill/add/phases/build.md +23 -1
- package/skill/add/phases/direction.md +75 -17
- package/skill/add/phases/verify.md +25 -4
- package/tooling/add.py +407 -33
- package/tooling/add_engine/constants.py +10 -15
- package/tooling/add_engine/guidelines.py +86 -136
- package/tooling/templates/MILESTONE.md.tmpl +9 -0
- package/tooling/templates/PLAN.md.tmpl +12 -14
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,88 @@ All notable changes to the ADD method (`@pilotspace/add` on npm,
|
|
|
4
4
|
`pilotspace-add` on PyPI) are documented here. The format follows
|
|
5
5
|
[Keep a Changelog](https://keepachangelog.com/); versions follow semver.
|
|
6
6
|
|
|
7
|
+
## [2.3.0] — 2026-07-24
|
|
8
|
+
|
|
9
|
+
Minor: three waves — a **signal graph** view over the task DAG, the **§2
|
|
10
|
+
Scenarios fold** into §4, and a **call-lean pass** that kills the two measured
|
|
11
|
+
WM1 freeze/scope call sinks. Engine changes are additive; templates migrate
|
|
12
|
+
in place (no manual task-file edits).
|
|
13
|
+
|
|
14
|
+
### Signal graph — one addressable node for every note/todo/delta
|
|
15
|
+
- **unified signal model** — note, todo, and spec-delta collapse into ONE
|
|
16
|
+
addressable `signal` node (status + edges), projected as a VIEW, not a new
|
|
17
|
+
store; `_signals` reader.
|
|
18
|
+
- **`graph --signals`** — opt-in overlay renders signals on the task DAG;
|
|
19
|
+
**exit-criteria** render as `ec_` *delivered-by* nodes (a milestone's own
|
|
20
|
+
criteria appear as ✓/○ nodes wired to the tasks that meet them).
|
|
21
|
+
- **`graph --html`** — emits a self-rendering HTML page to tmp (Mermaid inline,
|
|
22
|
+
no external host).
|
|
23
|
+
- **atomicity signal** — the freeze SEEDS a persistent atomicity signal into the
|
|
24
|
+
task's todos instead of an ephemeral print, so the nudge survives the session.
|
|
25
|
+
|
|
26
|
+
### §2 Scenarios folded into §4 — one place for cases
|
|
27
|
+
- the standalone **§2 SCENARIOS** section is **retired in place**: pass/fail cases
|
|
28
|
+
now live with the tests in **§4 · TESTS & SCENARIOS** (primary-case rigor). The
|
|
29
|
+
§3–§7 numbers are unchanged so the freeze parser and every §-reference keep
|
|
30
|
+
working — the §1→§3 jump is intentional.
|
|
31
|
+
- **PROJECT.md** gains a managed `ADD:SPECS` pointer block (init/migrate inject it
|
|
32
|
+
from the 5-DD spec set); foundation references reconciled to the `.add/specs/`
|
|
33
|
+
model; the generated **CLAUDE.md** block finalized in the generator.
|
|
34
|
+
- the Step-2 Scenarios book chapter folds into Step-4; `add-flow.png` retired.
|
|
35
|
+
|
|
36
|
+
### Call-lean pass — the WM1 freeze/scope sinks die at the source
|
|
37
|
+
- **freeze-flag slot** — `PLAN.md.tmpl` §3 carries a drafted-blank *Least-sure
|
|
38
|
+
flag* slot; the first freeze no longer fails `unflagged_freeze` (0/6 reps in the
|
|
39
|
+
re-measure, was 3/3). The unfilled part-menu placeholder still never satisfies
|
|
40
|
+
the gate — the floor holds.
|
|
41
|
+
- **scope-first freeze** — a §3 Scope that resolves to zero cover is now refused
|
|
42
|
+
`scope_unresolved` AT the freeze with a paste-ready fix, instead of surfacing
|
|
43
|
+
later as `scope_violation` → re-cross → re-gate. UNDECLARED stays grandfathered;
|
|
44
|
+
greenfield `[MISSING]` tokens still freeze; a `.add/tasks/` token gets a
|
|
45
|
+
task-dir teach note.
|
|
46
|
+
- **scope-walk prunes** — `.venv` · `venv` · `.tox` · `.mypy_cache` · `.ruff_cache`
|
|
47
|
+
· `.eggs` and any `*.egg-info` dir are pruned from the scope walk, so an
|
|
48
|
+
in-workspace virtualenv or `pip install -e .` metadata is never read as an
|
|
49
|
+
out-of-scope write. `dist`/`build` stay watched (can be a real write-set). The
|
|
50
|
+
untouched-Scope-default warning now self-explains (a note, not a blocker; clears
|
|
51
|
+
only by editing the Scope line — re-cross does not clear it).
|
|
52
|
+
- **honest fidelity meter** — the artifact-blind LLM `spec_fidelity` metric is
|
|
53
|
+
replaced by a deterministic `requirement_coverage` (frozen per-WM checklists +
|
|
54
|
+
probes, no LLM in the metric path); `oracle_pass_rate` promoted to the headline;
|
|
55
|
+
the judge demoted to an advisory `code_quality_annotation`.
|
|
56
|
+
- **§3 Build-strategy relabel** — *Scope (may touch)* is the HARD scope-lock; the
|
|
57
|
+
rest (Strategy · Regression floor · Persona) is SOFT/optional. `MILESTONE.md`
|
|
58
|
+
gains a drafted-blank `## Strategy` slot.
|
|
59
|
+
|
|
60
|
+
Retired (no CLI/install surface change): the standalone **§2 SCENARIOS** section
|
|
61
|
+
(folded into §4) · the **ccsk / rule-file** mode · `add-flow.png`.
|
|
62
|
+
|
|
63
|
+
Pinned by `test_release_2_3_0.py`. `ENGINE_MD5` re-aimed to `60eef504…`
|
|
64
|
+
(scope refusal + walk prunes); the four tooling twins stay byte-identical;
|
|
65
|
+
full tooling suite green (2277 tests).
|
|
66
|
+
|
|
67
|
+
## [2.2.0] — 2026-07-22
|
|
68
|
+
|
|
69
|
+
Minor: the Direction beat gains a **fable reasoning discipline** — a prompt-only
|
|
70
|
+
pass that makes the agent derive from the task in front of it instead of a fluent
|
|
71
|
+
template, distilled from the fable-thinking protocol. No engine change.
|
|
72
|
+
|
|
73
|
+
- **fable reasoning discipline** — `phases/direction.md` opens with the lens for
|
|
74
|
+
the whole bundle: **Fluent ≠ true** (a draft's polish tracks its token count,
|
|
75
|
+
not its evidence), the **Five Moves** (FRAME · GROUND · REASON · ATTACK ·
|
|
76
|
+
DELIVER) each mapped to the beat that already applies it, and two pre-answer
|
|
77
|
+
checks the fluent draft skips — the **Floor** (restate the Goal in the human's
|
|
78
|
+
world, then sweep the Leftovers: every supplied invariant and the BARE runtime)
|
|
79
|
+
and the **constraint loop** (expand → verify mechanically → repair the §3 tag
|
|
80
|
+
census · §5 scope tokens · §4 `covers:` keys · REDS refs before the freeze).
|
|
81
|
+
- **claim grammar** — `add-advisor`'s §6 Return tags every factual assertion by
|
|
82
|
+
how it's known: `[OBSERVED]` (checked live this session) · `[DERIVED]` ·
|
|
83
|
+
`[PRIOR]` (memory, may be stale) · `[ASSUMED]`; a bare claim reads as OBSERVED,
|
|
84
|
+
so a guess never rides in unmarked. **GROUND** makes the same rule structural:
|
|
85
|
+
a recalled file/flag/symbol is `[PRIOR]` until re-confirmed against the live tree.
|
|
86
|
+
- Prompt-only, propagated byte-identical across the three synced skill trees;
|
|
87
|
+
`add.py` == ENGINE_MD5 unchanged. Pinned by `test_fable_floor.py`.
|
|
88
|
+
|
|
7
89
|
## [2.1.0] — 2026-07-22
|
|
8
90
|
|
|
9
91
|
Minor: the two-agent roster matures and the persona author learns from real
|
package/agents/add-advisor.md
CHANGED
|
@@ -19,8 +19,10 @@ beat keeps moving. Personas carry the expertise; you carry independent, first-pr
|
|
|
19
19
|
options and RETURN A DECISION with its rationale. This is delegated judgement — binding for
|
|
20
20
|
the beat — not one more opinion to hold open.
|
|
21
21
|
- **refute** — an adversarial read of a drafted artifact (bundle · earned-green · verdict):
|
|
22
|
-
try to BREAK it.
|
|
23
|
-
|
|
22
|
+
try to BREAK it. Your PRIMARY output is the concrete input/state/interleaving that makes it wrong —
|
|
23
|
+
values, file, line; not a category, not a bare verdict. A "looks fine" with no attempted repro is
|
|
24
|
+
not a refute; if a real attempt finds none, concede it holds and say so. Default to "not yet proven"
|
|
25
|
+
when uncertain — catch the plausible-but-wrong before the human or the gate does.
|
|
24
26
|
|
|
25
27
|
Every mode serves EVERY beat — the spawn names the beat + mode, and you calibrate to it:
|
|
26
28
|
**direction** (propose the bundle plan · refute the draft so the human freezes the stronger
|
|
@@ -71,6 +73,12 @@ worker cannot be about its own work.
|
|
|
71
73
|
`{ mode, persona, kind, recommendation, decision|verdict, tradeoffs: [weighed],
|
|
72
74
|
weakest_dimension, risks: [🔴|🟡|💭 …], assumptions, confidence: {per-dimension 0–1},
|
|
73
75
|
escalate: {security_hard_stop|change_request|residue}? }`
|
|
76
|
+
**Claim grammar** — tag each factual assertion in `recommendation`/`decision`/`risks` by its
|
|
77
|
+
evidence basis, so the worker can tell a checked fact from a recalled one: `[OBSERVED]` you
|
|
78
|
+
verified it against the live tree this session · `[DERIVED]` it follows from an observation ·
|
|
79
|
+
`[PRIOR]` training or memory, may be stale · `[ASSUMED]` unverified but required. A bare claim
|
|
80
|
+
reads as OBSERVED — so never leave a guess untagged. **Fluent ≠ true**: your confidence rises
|
|
81
|
+
with token count, not evidence; the tag is what keeps the two apart.
|
|
74
82
|
You PROPOSE and DECIDE the delegable; you never RUN the engine or write shared state.
|
|
75
83
|
|
|
76
84
|
Method depth: the AIDD book — read only when a decision is genuinely unclear.
|
package/agents/add-worker.md
CHANGED
|
@@ -29,6 +29,8 @@ Read YOUR mode's guide from the project's skill tree (`.claude/skills/add/phases
|
|
|
29
29
|
spawn — the orchestrator reads only SKILL.md and does not pre-read it for you.
|
|
30
30
|
|
|
31
31
|
## 2 · Become the persona (FIRST — before any task-specific instruction)
|
|
32
|
+
The §3 Boundary below is the floor this persona cannot lower — it binds BEFORE the persona's voice
|
|
33
|
+
can soften it; a persona is advisory, the boundary is not. Now become the persona:
|
|
32
34
|
Select from `.add/personas/` by frontmatter alone (name · vibe · flow · task-kinds ·
|
|
33
35
|
use-when · not-when): prefer a persona whose `flow:` names your mode's surface
|
|
34
36
|
(direction→design · build→build · verify→verify) AND whose `task-kinds:` covers the
|
package/bin/cli.js
CHANGED
|
@@ -39,7 +39,7 @@ function parseArgs(argv) {
|
|
|
39
39
|
// hint only echoes flags the user actually chose (shortest true command).
|
|
40
40
|
const args = { _: [], force: false, check: false, noSkill: false, stage: null, name: null,
|
|
41
41
|
yes: false, nonInteractive: false, global: false, globalData: false,
|
|
42
|
-
fromGlobalData: false,
|
|
42
|
+
fromGlobalData: false, lockTimeout: null };
|
|
43
43
|
for (let i = 0; i < argv.length; i++) {
|
|
44
44
|
const a = argv[i];
|
|
45
45
|
if (a === "--force") args.force = true;
|
|
@@ -61,9 +61,6 @@ function parseArgs(argv) {
|
|
|
61
61
|
// already provides the `add` skill, so a plugin bootstrap uses this to materialize
|
|
62
62
|
// .add/tooling/ into the project without a duplicate .claude/skills/add.
|
|
63
63
|
else if (a === "--no-skill") args.noSkill = true;
|
|
64
|
-
// --rule-file: write the ADD block to .claude/rules/add-workflows.md + reference it from
|
|
65
|
-
// CLAUDE.md instead of inlining (auto-on for ccsk projects with a .ccsk/ dir).
|
|
66
|
-
else if (a === "--rule-file") args.ruleFile = true;
|
|
67
64
|
else if (a === "--stage" || a === "--name") {
|
|
68
65
|
const v = argv[++i];
|
|
69
66
|
// fail loudly on a trailing/abutting flag — never silently drop a value
|
|
@@ -263,126 +260,6 @@ function writeAgentPointer(target, profile) {
|
|
|
263
260
|
}
|
|
264
261
|
}
|
|
265
262
|
|
|
266
|
-
// --- rule-file mode: ccsk-style relocation of the CLAUDE.md block ---------------------
|
|
267
|
-
// Mirror of add.py / _installer.py rule-file logic (twins by duplication). For ccsk projects
|
|
268
|
-
// (.ccsk/ dir) or an explicit --rule-file, the ADD pointer goes to .claude/rules/add-workflows.md
|
|
269
|
-
// and CLAUDE.md keeps only a reference bullet. CLAUDE-only — AGENTS.md/.clinerules stay inline.
|
|
270
|
-
const RULES_FILE_REL = path.join(".claude", "rules", "add-workflows.md");
|
|
271
|
-
const WORKFLOW_HEADINGS = ["Rules & Workflows", "Workflows", "Rules"];
|
|
272
|
-
const RULE_REF_LINE = "- ADD (AI-Driven Development) Workflows rules: ./.claude/rules/add-workflows.md";
|
|
273
|
-
|
|
274
|
-
// True when the ADD block belongs in .claude/rules/add-workflows.md instead of inline.
|
|
275
|
-
// Re-derived from disk: explicit flag, a ccsk project (.ccsk/), or a rule file already present.
|
|
276
|
-
function ruleFileMode(root, flag) {
|
|
277
|
-
if (flag) return true;
|
|
278
|
-
try {
|
|
279
|
-
if (fs.existsSync(path.join(root, ".ccsk")) &&
|
|
280
|
-
fs.statSync(path.join(root, ".ccsk")).isDirectory()) return true;
|
|
281
|
-
if (fs.existsSync(path.join(root, RULES_FILE_REL))) return true;
|
|
282
|
-
} catch (_e) { /* fail-soft */ }
|
|
283
|
-
return false;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Remove an inline ADD:BEGIN..END region (migration), collapsing the gap. An unterminated
|
|
287
|
-
// BEGIN is left as-is rather than eating the rest of the file.
|
|
288
|
-
function stripInlineBlock(text) {
|
|
289
|
-
const begin = text.indexOf(GUIDE_BEGIN);
|
|
290
|
-
if (begin === -1) return text;
|
|
291
|
-
let end = text.indexOf(GUIDE_END, begin);
|
|
292
|
-
if (end === -1) return text;
|
|
293
|
-
end += GUIDE_END.length;
|
|
294
|
-
const head = text.slice(0, begin).replace(/\n+$/, "");
|
|
295
|
-
const tail = text.slice(end).replace(/^\n+/, "");
|
|
296
|
-
if (head && tail) return head + "\n\n" + tail;
|
|
297
|
-
return head || tail;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Insert the ADD rule-file bullet under an existing Workflows/Rules heading, or append a fresh
|
|
301
|
-
// '## Workflows' section. Caller guarantees the bullet is absent.
|
|
302
|
-
function insertRuleReference(text) {
|
|
303
|
-
const lines = text.split("\n");
|
|
304
|
-
let headingIdx = -1;
|
|
305
|
-
for (let i = 0; i < lines.length; i++) {
|
|
306
|
-
const m = lines[i].match(/^(#{1,6})\s+(.*?)\s*$/);
|
|
307
|
-
if (m && WORKFLOW_HEADINGS.some((h) => m[2].trim().toLowerCase() === h.toLowerCase())) {
|
|
308
|
-
headingIdx = i;
|
|
309
|
-
break;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (headingIdx === -1) {
|
|
313
|
-
const body = text.replace(/\n+$/, "");
|
|
314
|
-
const sep = body ? "\n\n" : "";
|
|
315
|
-
return body + sep + "## Workflows\n\n" + RULE_REF_LINE + "\n";
|
|
316
|
-
}
|
|
317
|
-
const level = lines[headingIdx].match(/^(#{1,6})/)[1].length;
|
|
318
|
-
let end = lines.length;
|
|
319
|
-
for (let j = headingIdx + 1; j < lines.length; j++) {
|
|
320
|
-
const m = lines[j].match(/^(#{1,6})\s+/);
|
|
321
|
-
if (m && m[1].length <= level) { end = j; break; }
|
|
322
|
-
}
|
|
323
|
-
let insertAt = headingIdx + 1;
|
|
324
|
-
for (let j = headingIdx + 1; j < end; j++) {
|
|
325
|
-
if (lines[j].trim()) insertAt = j + 1;
|
|
326
|
-
}
|
|
327
|
-
lines.splice(insertAt, 0, RULE_REF_LINE);
|
|
328
|
-
return lines.join("\n");
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Make CLAUDE.md reference the ADD rule file under a Workflows/Rules heading, migrating any prior
|
|
332
|
-
// inline ADD block out. created|updated|unchanged|skipped; .bak on change; fail-soft.
|
|
333
|
-
function ensureClaudeReference(claudeMd) {
|
|
334
|
-
try {
|
|
335
|
-
const existed = fs.existsSync(claudeMd);
|
|
336
|
-
const current = existed ? fs.readFileSync(claudeMd, "utf8") : "";
|
|
337
|
-
let next = stripInlineBlock(current);
|
|
338
|
-
if (next.indexOf("add-workflows.md") === -1) next = insertRuleReference(next);
|
|
339
|
-
if (!next.endsWith("\n")) next += "\n";
|
|
340
|
-
if (next === current) return "unchanged";
|
|
341
|
-
if (existed) fs.writeFileSync(claudeMd + ".bak", current);
|
|
342
|
-
fs.writeFileSync(claudeMd, next);
|
|
343
|
-
return existed ? "updated" : "created";
|
|
344
|
-
} catch (e) {
|
|
345
|
-
warn("could not write CLAUDE.md — " + (e && e.message ? e.message : e) + "; skipped");
|
|
346
|
-
return "skipped";
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// Rule-file variant of writeAgentPointer for the Claude profile: write the ADD pointer block to
|
|
351
|
-
// .claude/rules/add-workflows.md and leave a reference in CLAUDE.md. Fail-soft.
|
|
352
|
-
function writeRuleFilePointer(target, profile) {
|
|
353
|
-
const rulesPath = path.join(target, RULES_FILE_REL);
|
|
354
|
-
const block = agentPointerBlock(profile);
|
|
355
|
-
try {
|
|
356
|
-
if (fs.existsSync(rulesPath)) {
|
|
357
|
-
const current = fs.readFileSync(rulesPath, "utf8");
|
|
358
|
-
const begin = current.indexOf(GUIDE_BEGIN);
|
|
359
|
-
let next;
|
|
360
|
-
if (begin !== -1) {
|
|
361
|
-
const endIdx = current.indexOf(GUIDE_END, begin);
|
|
362
|
-
if (endIdx !== -1) {
|
|
363
|
-
next = current.slice(0, begin) + block + current.slice(endIdx + GUIDE_END.length);
|
|
364
|
-
} else {
|
|
365
|
-
next = current.replace(/\n+$/, "") + "\n\n" + block + "\n";
|
|
366
|
-
}
|
|
367
|
-
} else {
|
|
368
|
-
next = current.replace(/\n+$/, "") + "\n\n" + block + "\n";
|
|
369
|
-
}
|
|
370
|
-
if (next !== current) {
|
|
371
|
-
fs.writeFileSync(rulesPath + ".bak", current);
|
|
372
|
-
fs.writeFileSync(rulesPath, next);
|
|
373
|
-
}
|
|
374
|
-
} else {
|
|
375
|
-
fs.mkdirSync(path.dirname(rulesPath), { recursive: true });
|
|
376
|
-
fs.writeFileSync(rulesPath, block + "\n");
|
|
377
|
-
}
|
|
378
|
-
} catch (e) {
|
|
379
|
-
warn("could not write " + RULES_FILE_REL + " — " + (e && e.message ? e.message : e) + "; skipped");
|
|
380
|
-
return "skipped";
|
|
381
|
-
}
|
|
382
|
-
ensureClaudeReference(path.join(target, "CLAUDE.md"));
|
|
383
|
-
return "ok";
|
|
384
|
-
}
|
|
385
|
-
|
|
386
263
|
// --- interactive layer (clack on a real TTY; plain text everywhere else) -----
|
|
387
264
|
// Designed-for-failure: any doubt (non-TTY, CI, --yes, a failed import, an
|
|
388
265
|
// un-promptable stream) degrades to the EXACT plain-text path below. The clack
|
|
@@ -650,16 +527,7 @@ function dropFiles(args, target, profile, intent) {
|
|
|
650
527
|
// Agent detection: write THE detected agent's integration file (a marker-delimited
|
|
651
528
|
// pointer init's sync-guidelines later supersedes) + tailor the closing next-step.
|
|
652
529
|
// Best-effort + fail-soft — never aborts the successful drop above.
|
|
653
|
-
|
|
654
|
-
// .claude/rules/add-workflows.md + a reference — CLAUDE-only; other agents stay inline.
|
|
655
|
-
if (profile.integration_file === "CLAUDE.md" && ruleFileMode(target, args.ruleFile)) {
|
|
656
|
-
if (fs.existsSync(path.join(target, ".ccsk"))) {
|
|
657
|
-
log(" ccsk detected — ADD rules go to .claude/rules/add-workflows.md");
|
|
658
|
-
}
|
|
659
|
-
writeRuleFilePointer(target, profile);
|
|
660
|
-
} else {
|
|
661
|
-
writeAgentPointer(target, profile);
|
|
662
|
-
}
|
|
530
|
+
writeAgentPointer(target, profile);
|
|
663
531
|
|
|
664
532
|
// Gemini CLI auto-loads GEMINI.md, not AGENTS.md — so for the gemini profile we ALSO merge
|
|
665
533
|
// .gemini/settings.json (context.fileName) to load the AGENTS.md pointer. Fail-soft + idempotent.
|
|
@@ -1985,7 +1853,4 @@ module.exports = {
|
|
|
1985
1853
|
scopeOptions: scopeOptions,
|
|
1986
1854
|
writeIntentNote: writeIntentNote,
|
|
1987
1855
|
writeGeminiSettings: writeGeminiSettings,
|
|
1988
|
-
ruleFileMode: ruleFileMode,
|
|
1989
|
-
ensureClaudeReference: ensureClaudeReference,
|
|
1990
|
-
writeRuleFilePointer: writeRuleFilePointer,
|
|
1991
1856
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pilotspace/add",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "ADD (AI-Driven Development) 2.0. The agent is the hands; ADD is the memory, judgment, and conscience — a minimal, state-tracked skill: one freeze per feature, trust from passing tests, state on disk so context rot never survives a new session.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"add": "bin/cli.js"
|
package/skill/add/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: add
|
|
|
3
3
|
description: >-
|
|
4
4
|
ADD (AI-Driven Development) — a minimal, state-tracked workflow: the AI writes
|
|
5
5
|
the code, the human owns direction and verification. Drives every feature through
|
|
6
|
-
one lean PLAN.md: Specify →
|
|
6
|
+
one lean PLAN.md: Specify → Plan → Tests & Scenarios → Build → Verify → Observe,
|
|
7
7
|
red/green TDD built in. Use whenever a repo has `.add/`, or the user says "add",
|
|
8
8
|
"start a task", "next phase", "specify this feature", "ADD method", "AI-driven
|
|
9
9
|
development", or wants spec/tests-first discipline over vague-prompt coding. Also
|
|
@@ -15,7 +15,7 @@ argument-hint: "status | init | continue | --todo <text> | [describe new short g
|
|
|
15
15
|
license: MIT
|
|
16
16
|
metadata:
|
|
17
17
|
author: add
|
|
18
|
-
version: "2.
|
|
18
|
+
version: "2.3.0"
|
|
19
19
|
---
|
|
20
20
|
|
|
21
21
|
# ADD — memory · judgment · conscience (the agent is the hands)
|
|
@@ -69,10 +69,10 @@ confirms. Unsharp intent? **Interview before you size** (`intake.md`). A milesto
|
|
|
69
69
|
|
|
70
70
|
Every task is three beats (seven steps, folded), three engine calls, ONE human decision:
|
|
71
71
|
|
|
72
|
-
1. **DIRECTION** — load the domain-fit persona (seed via add-worker persona-mode if none), then
|
|
73
|
-
the whole bundle
|
|
74
|
-
§
|
|
75
|
-
(
|
|
72
|
+
1. **DIRECTION** — load the domain-fit persona (seed via add-worker persona-mode if none), then compose
|
|
73
|
+
the whole bundle in ONE silent draft — §1·§3 + §5-scope, no per-section narration; §4 then runs red — in PLAN.md: §1 rules + ranked ⚠ flag (co-specify) ·
|
|
74
|
+
§3 PLAN (grounding → frozen contract shape → build-strategy + Scope + Target) ·
|
|
75
|
+
§4 TESTS & SCENARIOS — the red suite (cases live here; optional inline gherkin when a human needs it): one test per Must & per Reject (a Must/Reject encoded in no §4 test = §1 not understood — stop); minor behaviors are prose build-guidance, not gated; run red for the RIGHT reason; fill each `covers:` key. Then the ONE approval,
|
|
76
76
|
presented lowest-confidence-first: `add.py freeze` (a setup session's baseline `lock` IS this approval).
|
|
77
77
|
2. **BUILD** — code in `src/` until every red is green; change no test, no frozen contract; stay
|
|
78
78
|
inside the §3 Scope. A test OUTSIDE your suite failing? `add.py locate` names the owning node, the
|
|
@@ -118,7 +118,7 @@ confirmable delta the human confirms rewrites `SOUL.md` (the human is the only w
|
|
|
118
118
|
|
|
119
119
|
## Command cookbook — copy a line; `-h` only off-menu
|
|
120
120
|
|
|
121
|
-
`add.py` = `python3 .add/tooling/add.py`; lines 2–4 = the 3
|
|
121
|
+
`add.py` = `python3 .add/tooling/add.py`; lines 2–4 = the 3 calls — default is ONE composed draft then bare `advance`/`freeze`; `advance --fill <draft>` = step-wise, only for a large/uncertain task.
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
add.py status --brief # resume · status --section <n|phase> = §body · --foundation · --json
|
package/skill/add/deltas.md
CHANGED
|
@@ -43,7 +43,7 @@ If a learning touches two, ask "which competency, once updated, would have PREVE
|
|
|
43
43
|
|
|
44
44
|
```
|
|
45
45
|
emit (OBSERVE) human review
|
|
46
|
-
open ───────────▶ folded (merged into
|
|
46
|
+
open ───────────▶ folded (merged into its `.add/specs/<dd>` spec; version bumps)
|
|
47
47
|
└──────────▶ rejected (deliberately NOT consolidated — trail kept)
|
|
48
48
|
```
|
|
49
49
|
|
package/skill/add/design.md
CHANGED
|
@@ -42,7 +42,7 @@ Record **before** review-domain: project **defaults** in DESIGN.md's `## Design
|
|
|
42
42
|
|
|
43
43
|
### 1 · review-domain
|
|
44
44
|
Start from the **domain**, not a blank canvas. Read the domain model — entities, flows, the
|
|
45
|
-
ubiquitous language in
|
|
45
|
+
ubiquitous language in `.add/specs/domain.md` / `GLOSSARY.md` — and derive **which screens** the feature needs
|
|
46
46
|
+ each screen's **regions**. Map each entity to a *presentational* component (owns no domain
|
|
47
47
|
decision). Output: the screen list + regions.
|
|
48
48
|
|
|
@@ -5,6 +5,28 @@ acceptance check — passes, without changing any test or the contract. This is
|
|
|
5
5
|
AI leads; §1–§4 removed all ambiguity. Write code into `.add/tasks/<slug>/src/` (a non-coding
|
|
6
6
|
task writes its artifact to the path its §5 Scope declares).
|
|
7
7
|
|
|
8
|
+
## The reasoning discipline — build's slice of the arc (definitions: `phases/direction.md`)
|
|
9
|
+
|
|
10
|
+
**Fluent ≠ true** holds in code: a diff feels done in proportion to how much you wrote, not how
|
|
11
|
+
much you verified — a green you haven't refuted is a claim, not evidence. Run the arc per batch:
|
|
12
|
+
|
|
13
|
+
- **FRAME** — restate the batch's tests and the frozen §3 clause they cover before writing a line.
|
|
14
|
+
- **GROUND** — open every anchor before editing it; a recalled file/symbol/flag is `[PRIOR]`
|
|
15
|
+
until re-confirmed against the live tree THIS session; a live read outranks memory.
|
|
16
|
+
- **REASON** — name the mechanism ("because…"), simulate one concrete input through the change
|
|
17
|
+
before committing it; when a red survives a fix, hold a second hypothesis instead of patching harder.
|
|
18
|
+
- **ATTACK** — before presenting green: re-run the suite fresh, then reviewer-read your own diff
|
|
19
|
+
hunting the cheap falsifying input (file · line · values). An earned green is one you tried to
|
|
20
|
+
kill. Security findings stay HARD-STOP.
|
|
21
|
+
- **DELIVER** — the green report leads with the outcome and tags its claims: a pass you ran THIS
|
|
22
|
+
session is `[OBSERVED]`; a remembered pass is `[PRIOR]` — never present it bare.
|
|
23
|
+
- **Constraint loop on the §5 Scope allowlist** — don't eyeball it: list the files actually
|
|
24
|
+
touched (`git status` / diff) and check each against the declared Scope tokens mechanically
|
|
25
|
+
before the gate; a miss is `scope_violation` — caught by you, not by the engine.
|
|
26
|
+
- **Follow-through (the Floor's second check)** — green tests ≠ the goal reached; simulate the
|
|
27
|
+
human's end state once — run the artifact under the BARE declared runtime — before calling
|
|
28
|
+
the batch done.
|
|
29
|
+
|
|
8
30
|
## Work in small batches
|
|
9
31
|
|
|
10
32
|
Pick ONE task-sized slice, restate its tests, implement, iterate to green —
|
|
@@ -76,4 +98,4 @@ verify residue → a SPEC delta.
|
|
|
76
98
|
Routing: `ddd`→domain · `sdd`→system · `udd`→experience · `tdd`→quality · `add`→method — each
|
|
77
99
|
lands in-flight in its living spec via `add.py delta-append <dd>` (grammar: `deltas.md`). A
|
|
78
100
|
HOW-an-agent-behaves lesson → a persona, not the shared pile. Deltas prepend newest-first;
|
|
79
|
-
the spec diff is the receipt. Self-score before emitting (the confidence six dimensions;
|
|
101
|
+
the spec diff is the receipt. Self-score before emitting (the confidence six dimensions; name the weakest, refine).
|
|
@@ -1,9 +1,39 @@
|
|
|
1
1
|
# Direction — the whole specification bundle (setup · rules · plan · red suite) to the ONE freeze
|
|
2
2
|
|
|
3
|
-
Every task
|
|
4
|
-
|
|
3
|
+
Every task COMPOSES §1–§3 + §5-scope in ONE silent draft — a single write, no "moving on to §N"
|
|
4
|
+
narration — then §4 runs red and ONE human approval crosses it into build:
|
|
5
|
+
`add.py freeze --by <name> --cross`. The only mandatory breaks in the draft are running the §4 red
|
|
6
|
+
suite (a tool action, not prose) and the freeze. This file is the reference depth for that span —
|
|
5
7
|
SKILL.md carries the loop; read the section you're stuck in, not the file.
|
|
6
8
|
|
|
9
|
+
## The reasoning discipline (the lens for the sections below)
|
|
10
|
+
|
|
11
|
+
**Fluent ≠ true.** A draft's polish tracks its token count, not its evidence; every check in this
|
|
12
|
+
file forces a fresh derivation from THIS task over a plausible template. It is Rule 2 (trust
|
|
13
|
+
evidence, not inspection) turned inward — on your own reasoning, not just the build. Distilled from
|
|
14
|
+
the fable-thinking protocol; each move maps to where the loop already applies it.
|
|
15
|
+
|
|
16
|
+
**Five moves, one arc per beat:**
|
|
17
|
+
- **FRAME** — restate the real question + the load-bearing facts. → §1 co-specify.
|
|
18
|
+
- **GROUND** — verify by observation, not memory; a recalled file/flag/symbol/lesson is `[PRIOR]`
|
|
19
|
+
until re-confirmed against the live tree THIS session; a live read outranks memory. → §3 Grounding.
|
|
20
|
+
- **REASON** — hold more than one hypothesis; demand a mechanism ("because…"), not a correlation;
|
|
21
|
+
simulate with concrete values before committing. → the persona plan · the advisor's propose-plan.
|
|
22
|
+
- **ATTACK** — switch to reviewer, run the cheap kill-test; its output is a concrete falsifying input
|
|
23
|
+
(file · line · values), not a verdict. → advisor `refute` · verify earned-green (security = HARD-STOP).
|
|
24
|
+
- **DELIVER** — lead with the outcome, expose the weakness, recommend don't survey. → the gate report, lowest-confidence-first.
|
|
25
|
+
|
|
26
|
+
**Two pre-answer checks the fluent draft skips** (applied at the freeze — checklist below): the
|
|
27
|
+
**Floor** — restate the **Goal** in the human's world (not the wording), then sweep the
|
|
28
|
+
**Leftovers** (every supplied invariant / the BARE runtime encoded or waived) — and the
|
|
29
|
+
**constraint loop** for mechanically-checkable output shape (§3 tag census · §5 scope tokens · §4
|
|
30
|
+
`covers:` keys · REDS): expand → verify mechanically (grep/count, not a re-read) → repair → then freeze.
|
|
31
|
+
|
|
32
|
+
**Claim grammar** — tag each factual assertion by how you know it: `[OBSERVED]` (checked live this
|
|
33
|
+
session) · `[DERIVED]` (follows from an observation) · `[PRIOR]` (memory, may be stale) · `[ASSUMED]`
|
|
34
|
+
(unverified but required). A bare claim reads as OBSERVED — never leave a guess untagged; it is the
|
|
35
|
+
advisor's §6 Return discipline.
|
|
36
|
+
|
|
7
37
|
---
|
|
8
38
|
|
|
9
39
|
## Setup — first session only (autonomous draft → one baseline lock)
|
|
@@ -123,7 +153,7 @@ Rejects: `not_classified` · `dangling_criterion` · `no_milestone` · `duplicat
|
|
|
123
153
|
|
|
124
154
|
---
|
|
125
155
|
|
|
126
|
-
## Rules (§1)
|
|
156
|
+
## Rules (§1) — co-specification
|
|
127
157
|
|
|
128
158
|
State what the feature MUST do and MUST REJECT — zero ambiguity left to guessing. Co-specify in three moves: **Diverge** (surface the 2–3 genuine framings +
|
|
129
159
|
open questions; let the user react), **Converge** (draft §1 by PROJECTING from the milestone
|
|
@@ -141,7 +171,10 @@ the design-definition loop (`design.md`).
|
|
|
141
171
|
`⚠ <assumption> — lowest confidence because <why>; if wrong: <cost>`.
|
|
142
172
|
</output_format>
|
|
143
173
|
|
|
144
|
-
|
|
174
|
+
Every Must and Reject must be checkable — canonically as a §4 test (its `covers:` tag). Cases live
|
|
175
|
+
in §4 · TESTS & SCENARIOS (the old standalone §2 SCENARIOS section is retired). A Given/When/Then
|
|
176
|
+
line is an OPTIONAL readable projection, added inline in §4 only when a human needs prose cases at
|
|
177
|
+
the freeze, never as ceremony:
|
|
145
178
|
|
|
146
179
|
```gherkin
|
|
147
180
|
Scenario: <short name>
|
|
@@ -151,16 +184,17 @@ Scenario: <short name>
|
|
|
151
184
|
And <what must remain unchanged> # REQUIRED for every rejection
|
|
152
185
|
```
|
|
153
186
|
|
|
154
|
-
Then sweep the edge cases — boundary · duplicate · partial failure · concurrency · malformed input
|
|
155
|
-
|
|
187
|
+
Then sweep the edge cases — boundary · duplicate · partial failure · concurrency · malformed input.
|
|
188
|
+
Gate the PRIMARY cases + primary edge cases with a red test each; minor/secondary behaviors are
|
|
189
|
+
DESCRIBED in prose as build-guidance, not a red test. Every Then is specific and observable, never
|
|
156
190
|
"then it works". Your §1 ranking feeds the bundle-level flag the human reads at the freeze.
|
|
157
191
|
|
|
158
192
|
<exit_gate>
|
|
159
193
|
- [ ] Framings weighed noted; every required behavior stated; every rejection has a named error code.
|
|
160
194
|
- [ ] Assumptions ordered lowest-confidence first; the 1–2 `⚠` flags carry why + cost — or an honest
|
|
161
195
|
"none material" that still names the single biggest risk (never a blank "none").
|
|
162
|
-
- [ ]
|
|
163
|
-
cases covered or ruled out on purpose.
|
|
196
|
+
- [ ] Every Must and Reject is encoded as a §4 test (`covers:` tag); every rejection asserts what
|
|
197
|
+
stays unchanged; primary edge cases covered or ruled out on purpose (minor ones may be prose).
|
|
164
198
|
</exit_gate>
|
|
165
199
|
|
|
166
200
|
---
|
|
@@ -173,7 +207,10 @@ above it the Contract does not move.
|
|
|
173
207
|
### Grounding — reason it in-context (don't write an essay — `PLAN.md.tmpl`: persist the interface, not prose)
|
|
174
208
|
Project from the milestone `## Ground`, then deepen only where THIS task lands. Never invent a
|
|
175
209
|
file/symbol you have not opened; cite the **symbol**, not a bare line number (`l.NNN` rots; symbols
|
|
176
|
-
survive), via code-navigation tools, not memory.
|
|
210
|
+
survive), via code-navigation tools, not memory. A recalled fact — a file, a flag, a symbol, or a
|
|
211
|
+
prior lesson (even one carried in from memory) — is **PRIOR until re-confirmed** against the live
|
|
212
|
+
tree THIS session; a live read outranks memory, and a safety-grep counts only once you have
|
|
213
|
+
confirmed it actually matched (a `for x in $VAR` that ran vacuous proves nothing). **Persist only what the contract needs**: the
|
|
177
214
|
**Anchors** it may cite (the specific symbols §3 names — it may cite ONLY these) and, optionally, a
|
|
178
215
|
**Ground SHA** (the commit grounded against — the engine stamps it when the line is present).
|
|
179
216
|
Everything else — what it **Touches**, the **Honors**/seams consulted, the **Issues/Risks**, the
|
|
@@ -212,12 +249,27 @@ line the freeze records it (audit-only — `route_unrecorded` is measured, never
|
|
|
212
249
|
|
|
213
250
|
## The freeze review checklist
|
|
214
251
|
|
|
215
|
-
The human's one minute, aimed.
|
|
216
|
-
|
|
252
|
+
The human's one minute, aimed. **Fluent ≠ true** — a bundle's polish tracks its token count, not its
|
|
253
|
+
evidence, so these checks force a fresh read of THIS task over a plausible template. Run the **Floor**
|
|
254
|
+
first, then walk the rest before saying yes:
|
|
255
|
+
|
|
256
|
+
- **Floor (before you read the shape)** — the pre-answer check the fluent draft skips. (1) Restate the
|
|
257
|
+
**Goal**: the end-state the human actually wants, in their world, not the ticket's wording — a bundle
|
|
258
|
+
that satisfies the words but misses the goal is the most expensive miss. (2) Check the **Leftovers**:
|
|
259
|
+
every supplied constraint — each PROJECT.md `invariant:`, the BARE declared runtime, every ⚠ the
|
|
260
|
+
interview surfaced — is either encoded in §1–§4 or explicitly waived. An unused constraint is a trap,
|
|
261
|
+
not noise: the artifact must hold under the BARE runtime, so a leftover invariant is a defect already
|
|
262
|
+
waiting at verify.
|
|
217
263
|
- **⚠ flags first** — read the lowest-confidence flags; accept each knowing its cost if wrong. The engine refuses an unflagged freeze before build (`unflagged_freeze`).
|
|
218
264
|
- **Intent** — does §1 say what you actually want built?
|
|
219
|
-
- **Cases** — does every Must and Reject have an observable §
|
|
265
|
+
- **Cases** — does every Must and Reject have an observable §4 test/scenario (`covers:` tag)?
|
|
220
266
|
- **Shape** — glossary names, error codes, additive vs breaking: is THIS the shape to freeze?
|
|
267
|
+
- **Shape self-verify (the constraint loop)** — for the mechanically-checkable output-shape rules — the
|
|
268
|
+
frozen §3 tag census (the closed XML vocabulary), the §5 Scope path tokens, each §4 `covers:` key, any
|
|
269
|
+
REDS / dangling refs — don't eyeball them: expand the rule, self-verify the draft **mechanically**
|
|
270
|
+
(grep/count in reasoning space, not a re-read), repair, THEN freeze. This is where the freeze-parser
|
|
271
|
+
self-breaks get caught before the engine does — a bare `<word>` colliding with the tag census, a
|
|
272
|
+
`./src/` scope token tripping `scope_violation`.
|
|
221
273
|
- **Grounded** — does the Contract cite anchors that exist in the Grounding map? `status`/`check` surface this.
|
|
222
274
|
- **Risk** — high-risk or method-defining? Require `risk: high · autonomy: conservative` in the PLAN.md header.
|
|
223
275
|
- **Tests** — will §4 go red for the right reason, asserting behavior rather than internals?
|
|
@@ -231,8 +283,8 @@ Reject any line → the bundle goes back to draft; the freeze stays the only gat
|
|
|
231
283
|
Run the suite now, with no implementation — **red for the right reason** (missing implementation,
|
|
232
284
|
not a broken harness). A test green before code exists is testing nothing. **A test is any
|
|
233
285
|
machine-checkable assertion**, not only xUnit code — a metric threshold (ML/data), a reconciliation
|
|
234
|
-
query, a plan-diff (infra), a rendered-screen diff (UI). Produce: one executable test per
|
|
235
|
-
scenario asserting **behavior, not internals** · contract-conformance tests (shapes + error
|
|
286
|
+
query, a plan-diff (infra), a rendered-screen diff (UI). Produce: one executable test per PRIMARY
|
|
287
|
+
case/scenario asserting **behavior, not internals** · contract-conformance tests (shapes + error
|
|
236
288
|
responses) · side-effect assertions on rejection paths (`assert balance unchanged`) · a recorded
|
|
237
289
|
coverage target.
|
|
238
290
|
|
|
@@ -247,6 +299,8 @@ mode on any task). Coding kinds keep the executable red suite above.
|
|
|
247
299
|
|
|
248
300
|
§4's `Tests live in:` line is machine-read — declare paths as backticked tokens on that line: with
|
|
249
301
|
no local `tests/`, `add.py report` counts test functions at the declared paths (FIRST such line only).
|
|
302
|
+
REPLACE the template's `./tests/` placeholder in place — never append a SECOND `Tests live in:` line:
|
|
303
|
+
the report reads the FIRST, so a stale default left above your real path silently wins.
|
|
250
304
|
`./…` → this task dir · a token with `/` → the project root · a bare name → a
|
|
251
305
|
sibling of the previous token's dir. A directory counts its `*.py` files
|
|
252
306
|
(non-recursive); a `.py` file counts itself. Resolved files dedupe; declared counts
|
|
@@ -278,9 +332,13 @@ it 0–1 on six dimensions: **Completeness** (every rule/scenario/rejection cove
|
|
|
278
332
|
(understood without you in the room?) · **Practicality** (implementable against the real code?) ·
|
|
279
333
|
**Optimization** (correctness/simplicity/cost balanced — no gold-plating, no corner cut?) ·
|
|
280
334
|
**Edge cases** (failure modes, concurrency, empty/oversized inputs named?) · **Self-evaluation**
|
|
281
|
-
(does it carry its own refine step?).
|
|
282
|
-
|
|
283
|
-
|
|
335
|
+
(does it carry its own refine step?). Rank the six worst→best (a model ranks far more reliably than
|
|
336
|
+
it calibrates an absolute), then NAME the one concrete deficiency in your weakest dimension — a
|
|
337
|
+
missing scenario, an unhandled input, not a number — and fix THAT before presenting; re-rank after.
|
|
338
|
+
The lowest dimension is what you surface ⚠-first at the freeze; persistently low on risky scope →
|
|
339
|
+
*recommend* lowering autonomy (the level stays the human's call). The self-score is a **weak signal**:
|
|
340
|
+
the load-bearing correctness check is the adversarial refute-read (`phases/verify.md`) — the
|
|
341
|
+
plausible-but-wrong a self-score waves through is exactly what the refute exists to catch.
|
|
284
342
|
The hard rule: **advisory, never a gate** — it never auto-passes a verify, never substitutes for evidence or the
|
|
285
343
|
human decision, and a self-asserted score is never recorded as something the human "agreed to".
|
|
286
344
|
|
|
@@ -9,13 +9,34 @@ sufficient. Fill **§6** in PLAN.md including the GATE RECORD.
|
|
|
9
9
|
> **security is always a HARD-STOP and is never auto-passed**. Under `conservative`, or whenever
|
|
10
10
|
> residue is found, this phase is **human-led** (auto-PASS conditions: `run.md`).
|
|
11
11
|
|
|
12
|
+
## The reasoning discipline — verify's slice of the arc (definitions: `phases/direction.md`)
|
|
13
|
+
|
|
14
|
+
**Fluent ≠ true** holds for verdicts: a verdict's confidence tracks how much evidence prose you
|
|
15
|
+
wrote, not what you checked — a checkbox ticked from memory is a guess wearing a PASS. The arc
|
|
16
|
+
at the gate:
|
|
17
|
+
|
|
18
|
+
- **GROUND** — every Part-one checkbox is a factual claim: tick it only `[OBSERVED]` — you ran
|
|
19
|
+
the suite / read the evidence THIS session; a remembered pass is `[PRIOR]` — re-run it, never
|
|
20
|
+
recall it. A safety-grep counts only once you confirmed it actually matched.
|
|
21
|
+
- **ATTACK** — verify IS the arc's attack beat: the earned-green refute-read (Part four) whose
|
|
22
|
+
primary output is a concrete falsifying input, and the three lenses of Part two. Security
|
|
23
|
+
stays HARD-STOP.
|
|
24
|
+
- **DELIVER** — the gate card leads with the outcome, exposes the residue yourself
|
|
25
|
+
lowest-confidence-first, and tags its claims by evidence basis — never a bare "all green".
|
|
26
|
+
- **Floor Goal check** — before recording PASS, restate the goal in the human's world: a suite
|
|
27
|
+
that satisfies the §4 words but misses what they actually wanted is the most expensive miss,
|
|
28
|
+
and this gate is the last place to catch it.
|
|
29
|
+
- **Constraint loop on the §6 record** — the record blocks (3-lens verdict · Deep checks ·
|
|
30
|
+
Refute-read verdict · `Reported:`) are mechanically checkable: sweep them as a census before
|
|
31
|
+
the gate — an unfilled block is an unrecorded verdict, caught by you, not by the spot-audit.
|
|
32
|
+
|
|
12
33
|
## Part one — confirm the evidence
|
|
13
34
|
|
|
14
35
|
- [ ] All tests pass — or, for a non-coding task, every §4 acceptance check is green (the evidence it names is real).
|
|
15
36
|
- [ ] Coverage did not decrease.
|
|
16
37
|
- [ ] No test or contract was altered during build.
|
|
17
38
|
- [ ] The §3 Target (measurable) is hit — including any declared outcome tests can't show, confirmed by real evidence.
|
|
18
|
-
- [ ] §1 rules trace to §
|
|
39
|
+
- [ ] §1 rules trace to a §4 test (`covers:` tag) — an untraced rule is a coverage gap (`add.py check` warns on it).
|
|
19
40
|
- [ ] every §3-cited symbol still resolves in the CURRENT tree.
|
|
20
41
|
|
|
21
42
|
If any is false, stop and return to Build.
|
|
@@ -36,7 +57,7 @@ Record in the §6 **Deep checks** block — an unfilled one is a **shallow verif
|
|
|
36
57
|
|
|
37
58
|
## Part four — was the green earned?
|
|
38
59
|
|
|
39
|
-
A green suite proves tests pass — not that the build EARNED them. Three judgment cheats pass the unchanged suite: src overfit to the test fixtures (special-cased to literal inputs), vacuous asserts (green against an empty implementation), and real logic stubbed away — all invisible to the mechanical tamper tripwire. Score them with an adversarial refute-read: an independent reviewer — the engine never spawns one — prompted to argue the green was NOT earned. A confirmed earned-green failure is HARD-STOP-class: never auto-passed, never RISK-ACCEPTED — a first cheat enters the bounded self-heal loop (run.md). Under `auto`, **record the verdict** in §6's `### Refute-read verdict` block — an unrecorded verdict leaves the auto-PASS untraceable (the human spot-audit is the backstop).
|
|
60
|
+
A green suite proves tests pass — not that the build EARNED them. Three judgment cheats pass the unchanged suite: src overfit to the test fixtures (special-cased to literal inputs), vacuous asserts (green against an empty implementation), and real logic stubbed away — all invisible to the mechanical tamper tripwire. Score them with an adversarial refute-read: an independent reviewer — the engine never spawns one — prompted to argue the green was NOT earned. Its PRIMARY output is a concrete falsifying input — the fixture value, interleaving, or caller that makes the green wrong (file · line · values), not a verdict; a "looks fine" with no attempted repro is not a refute, and if a real attempt finds none it concedes the green holds and says so. A confirmed earned-green failure is HARD-STOP-class: never auto-passed, never RISK-ACCEPTED — a first cheat enters the bounded self-heal loop (run.md). Under `auto`, **record the verdict** in §6's `### Refute-read verdict` block — an unrecorded verdict leaves the auto-PASS untraceable (the human spot-audit is the backstop).
|
|
40
61
|
|
|
41
62
|
## Record exactly one outcome (no silent pass)
|
|
42
63
|
|
|
@@ -44,7 +65,7 @@ Render this gate from the card: banner → ARC → SUMMARY → FLAGS → EVIDENC
|
|
|
44
65
|
(`gate-udd.md` = the full template + examples, read at most once per session), and reconcile FLAGS
|
|
45
66
|
with `add.py report --decide`'s open-item count. Right-size the render to the risk: `sensitivity: mechanical`
|
|
46
67
|
tasks use the compact form — banner → SUMMARY → EVIDENCE → APPROVE; `security` / `data` /
|
|
47
|
-
`architecture` always get the full card. **Human-led: render before `gate` and record `Reported: yes` in §6, never self-stamp.**
|
|
68
|
+
`architecture` always get the full card. Audience by mode: under `conservative` the card renders to the human before the gate; under `autonomy: auto` (no reachable human) you WRITE it to the §6/trace record as the accountable artifact and proceed — you render, you don't wait. **Human-led: render before `gate` and record `Reported: yes` in §6, never self-stamp.**
|
|
48
69
|
|
|
49
70
|
| Outcome | When |
|
|
50
71
|
|---------|------|
|
|
@@ -73,7 +94,7 @@ python3 .add/tooling/add.py gate PASS # marks the task done
|
|
|
73
94
|
Verify owns the loop's tail since the six-phase merge. After the gate, fill §7:
|
|
74
95
|
|
|
75
96
|
1. **Release behind a scope-of-impact limit** — a flag and/or gradual rollout.
|
|
76
|
-
2. **Reuse scenarios as monitors** — the §
|
|
97
|
+
2. **Reuse scenarios as monitors** — the §4 scenarios/tests that defined "correct" define
|
|
77
98
|
what you alert on: overall error rate, each rejection's rate, latency of the risky op.
|
|
78
99
|
3. **Draft the next spec delta** — every defect, surprise, or new need becomes a change
|
|
79
100
|
that re-enters the flow at Specify (a new task). Emit lessons tagged by the
|