@pilotspace/add 1.17.0 → 2.1.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.
Files changed (120) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/GETTING-STARTED.md +20 -64
  3. package/README.md +138 -158
  4. package/agents/add-advisor.md +66 -21
  5. package/agents/add-worker.md +102 -0
  6. package/bin/cli.js +88 -21
  7. package/package.json +2 -3
  8. package/personas-teacher/VENDOR.md +6 -0
  9. package/skill/add/SKILL.md +100 -144
  10. package/skill/add/adopt.md +28 -0
  11. package/skill/add/beyond.md +37 -0
  12. package/skill/add/deltas.md +25 -2
  13. package/skill/add/design.md +56 -74
  14. package/skill/add/{report-template.md → gate-udd.md} +28 -38
  15. package/skill/add/intake.md +56 -25
  16. package/skill/add/loop.md +32 -19
  17. package/skill/add/persona-author/SKILL.md +116 -0
  18. package/skill/add/persona-author/assets/example-design-persona.md +55 -0
  19. package/skill/add/persona-author/assets/example-persona.md +57 -0
  20. package/skill/add/persona-author/references/contract.md +69 -0
  21. package/skill/add/persona-author/references/patterns.md +122 -0
  22. package/skill/add/persona-author/references/seeding.md +79 -0
  23. package/skill/add/phases/build.md +79 -0
  24. package/skill/add/phases/direction.md +287 -0
  25. package/skill/add/phases/verify.md +161 -0
  26. package/skill/add/run.md +16 -18
  27. package/skill/add/terms.md +18 -0
  28. package/tooling/add.py +2421 -3258
  29. package/tooling/add_engine/autonomy.py +2 -37
  30. package/tooling/add_engine/components.py +4 -87
  31. package/tooling/add_engine/constants.py +148 -93
  32. package/tooling/add_engine/guidelines.py +10 -11
  33. package/tooling/add_engine/io_state.py +72 -5
  34. package/tooling/add_engine/predicates.py +90 -2
  35. package/tooling/add_engine/search.py +6 -6
  36. package/tooling/add_engine/taskdoc.py +15 -10
  37. package/tooling/templates/CONVENTIONS.md.tmpl +1 -1
  38. package/tooling/templates/GLOSSARY.md.tmpl +10 -4
  39. package/tooling/templates/MILESTONE.md.tmpl +20 -16
  40. package/tooling/templates/PLAN.md.tmpl +129 -0
  41. package/tooling/templates/PROJECT.md.tmpl +6 -1
  42. package/tooling/templates/PROMPT.persona.md.tmpl +17 -21
  43. package/tooling/templates/personas/build-engineer.md.tmpl +45 -0
  44. package/tooling/templates/personas/data-steward.md.tmpl +45 -0
  45. package/tooling/templates/personas/evidence-verifier.md.tmpl +45 -0
  46. package/tooling/templates/personas/platform-engineer.md.tmpl +45 -0
  47. package/tooling/templates/personas/product-lead.md.tmpl +51 -0
  48. package/tooling/templates/personas/quality-auditor.md.tmpl +47 -0
  49. package/tooling/templates/personas/release-manager.md.tmpl +52 -0
  50. package/tooling/templates/personas/security-gatekeeper.md.tmpl +45 -0
  51. package/tooling/templates/personas/software-architect.md.tmpl +45 -0
  52. package/tooling/templates/personas/stream-orchestrator.md.tmpl +44 -0
  53. package/tooling/templates/personas/technical-writer.md.tmpl +49 -0
  54. package/tooling/templates/personas/ux-experience-lead.md.tmpl +48 -0
  55. package/tooling/templates/specs/SPEC.md.tmpl +18 -0
  56. package/tooling/templates/udd-wireframe.md +1 -1
  57. package/agents/add-build.md +0 -29
  58. package/agents/add-design.md +0 -32
  59. package/agents/add-persona.md +0 -33
  60. package/agents/add-verify.md +0 -36
  61. package/docs/00-introduction.md +0 -46
  62. package/docs/01-principles.md +0 -71
  63. package/docs/02-the-flow.md +0 -113
  64. package/docs/03-step-1-specify.md +0 -123
  65. package/docs/04-step-2-scenarios.md +0 -90
  66. package/docs/05-step-3-contract.md +0 -80
  67. package/docs/06-step-4-tests.md +0 -85
  68. package/docs/07-step-5-build.md +0 -82
  69. package/docs/08-step-6-verify.md +0 -105
  70. package/docs/09-the-loop.md +0 -75
  71. package/docs/10-setup-and-stages.md +0 -118
  72. package/docs/11-governance.md +0 -91
  73. package/docs/12-roles.md +0 -99
  74. package/docs/13-adoption.md +0 -67
  75. package/docs/14-foundation.md +0 -142
  76. package/docs/15-foundations-and-lineage.md +0 -106
  77. package/docs/16-releasing.md +0 -182
  78. package/docs/17-components.md +0 -143
  79. package/docs/18-personas.md +0 -80
  80. package/docs/README.md +0 -77
  81. package/docs/add-competencies.png +0 -0
  82. package/docs/add-flow.png +0 -0
  83. package/docs/add-foundation.png +0 -0
  84. package/docs/add-hierarchy.png +0 -0
  85. package/docs/add-milestone-task-lifecycle.png +0 -0
  86. package/docs/add-task-growth-wheel.png +0 -0
  87. package/docs/appendix-a-templates.md +0 -88
  88. package/docs/appendix-b-prompts.md +0 -154
  89. package/docs/appendix-c-glossary.md +0 -176
  90. package/docs/appendix-d-worked-example.md +0 -231
  91. package/docs/appendix-e-checklists.md +0 -92
  92. package/docs/appendix-f-requirements-matrix.md +0 -171
  93. package/docs/appendix-g-references.md +0 -106
  94. package/skill/add/advisor.md +0 -81
  95. package/skill/add/compact-foundation.md +0 -40
  96. package/skill/add/components.md +0 -52
  97. package/skill/add/confidence.md +0 -32
  98. package/skill/add/fold.md +0 -63
  99. package/skill/add/graduate.md +0 -39
  100. package/skill/add/phases/0-ground.md +0 -64
  101. package/skill/add/phases/0-setup.md +0 -103
  102. package/skill/add/phases/1-specify.md +0 -61
  103. package/skill/add/phases/2-scenarios.md +0 -48
  104. package/skill/add/phases/3-contract.md +0 -60
  105. package/skill/add/phases/4-tests.md +0 -61
  106. package/skill/add/phases/5-build.md +0 -62
  107. package/skill/add/phases/6-verify.md +0 -69
  108. package/skill/add/phases/7-observe.md +0 -45
  109. package/skill/add/phases/fast-lane.md +0 -34
  110. package/skill/add/release.md +0 -61
  111. package/skill/add/scope.md +0 -72
  112. package/skill/add/self-improve.md +0 -20
  113. package/skill/add/sensitivity.md +0 -51
  114. package/skill/add/setup-review.md +0 -48
  115. package/skill/add/soul.md +0 -58
  116. package/skill/add/streams.md +0 -269
  117. package/tooling/add_engine/release.py +0 -86
  118. package/tooling/templates/TASK.fast.md.tmpl +0 -78
  119. package/tooling/templates/TASK.md.tmpl +0 -181
  120. package/tooling/templates/personas/_template.md.tmpl +0 -82
package/bin/cli.js CHANGED
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * npx @pilotspace/add init [targetDir] [--force] [--stage <stage>] [--name <name>] [--yes|--non-interactive]
8
8
  *
9
- * Installs the ADD skill + tooling + book into a target project:
9
+ * Installs the ADD skill + tooling into a target project:
10
10
  * <target>/.claude/skills/add/ (the skill Claude loads)
11
11
  * <target>/.add/tooling/ (add.py scaffolder + state tracker)
12
- * <target>/.add/docs/ (the AIDD book — the trust layer)
13
12
  * It DROPS FILES ONLY — it does NOT run `add.py init`. Initialisation is deferred to
14
13
  * the AI (via `/add`, which runs `init --await-lock` to arm the v12 lock-down gate) or
15
14
  * to a CLI user. A pre-run plain init would grandfather-lock the gate before `/add` runs
@@ -58,9 +57,9 @@ function parseArgs(argv) {
58
57
  // non-interactive selector the interactive() gate honors (CI/pipes do this too).
59
58
  else if (a === "--yes" || a === "-y") args.yes = true;
60
59
  else if (a === "--non-interactive") args.nonInteractive = true;
61
- // --no-skill: drop the engine + book ONLY, not the skill. The Claude Code plugin
60
+ // --no-skill: drop the engine ONLY, not the skill. The Claude Code plugin
62
61
  // already provides the `add` skill, so a plugin bootstrap uses this to materialize
63
- // .add/tooling/ + .add/docs/ into the project without a duplicate .claude/skills/add.
62
+ // .add/tooling/ into the project without a duplicate .claude/skills/add.
64
63
  else if (a === "--no-skill") args.noSkill = true;
65
64
  // --rule-file: write the ADD block to .claude/rules/add-workflows.md + reference it from
66
65
  // CLAUDE.md instead of inlining (auto-on for ccsk projects with a .ccsk/ dir).
@@ -217,7 +216,7 @@ function agentPointerBlock(profile) {
217
216
  GUIDE_BEGIN + "\n" +
218
217
  "## ADD — how to work in this repo\n" +
219
218
  "\n" +
220
- "This project uses **ADD (AI-Driven Development)**. The engine + book are installed.\n" +
219
+ "This project uses **ADD (AI-Driven Development)**. The engine is installed.\n" +
221
220
  "To begin: run `python3 .add/tooling/add.py status` (the resume point), read\n" +
222
221
  "`.add/PROJECT.md`, then `python3 .add/tooling/add.py guide` for the current phase.\n" +
223
222
  "\n" +
@@ -410,10 +409,11 @@ async function loadClack() {
410
409
  // --- brand + feature showcase (interactive path only; fail-soft) -------------
411
410
  // Wordmark + value line + the 7-step Specify->Observe loop, rendered BEFORE the first
412
411
  // prompt on the interactive path only — so the non-interactive byte stream is unchanged.
413
- // The 7 labels are the real ADD phases (grounded in the method, never invented). Fail-soft:
414
- // any draw error is swallowed so a banner can never abort the install. No color is emitted
415
- // (default accent: none); the glyphs / tagline / accent are a SWAPPABLE content slot.
416
- const BRAND_LOOP = ["Specify", "Scenarios", "Contract", "Tests", "Build", "Verify", "Observe"];
412
+ // The 7 labels are the real ADD phases (grounded in the method, never invented; grounding
413
+ // itself is folded into step 3, Plan, not a separate phase). Fail-soft: any draw error is
414
+ // swallowed so a banner can never abort the install. No color is emitted (default accent:
415
+ // none); the glyphs / tagline / accent are a SWAPPABLE content slot.
416
+ const BRAND_LOOP = ["Specify", "Plan", "Tests", "Build", "Verify"];
417
417
 
418
418
  function terminalCaps(env, stream) {
419
419
  const width = Number(env.COLUMNS) || (stream && stream.columns) || 80;
@@ -481,7 +481,7 @@ async function runClackPreamble(clack, target, detected, askScope) {
481
481
  initialValue: target, defaultValue: target,
482
482
  });
483
483
  if (clack.isCancel(chosen)) return { cancelled: true, target: target };
484
- const ok = await clack.confirm({ message: "Write the ADD skill + tooling + book here?" });
484
+ const ok = await clack.confirm({ message: "Write the ADD skill + tooling here?" });
485
485
  if (clack.isCancel(ok) || !ok) return { cancelled: true, target: target };
486
486
  // global-first SCOPE step (after the target confirm, before agent-detect) — recommended
487
487
  // global home, explicit pick; skipped when --global already chose. global stays ADDITIVE.
@@ -671,7 +671,7 @@ function dropFiles(args, target, profile, intent) {
671
671
  // NO step 4: the installer DROPS FILES ONLY. Initialisation is deferred to the AI
672
672
  // (via `/add`) or a CLI user — a pre-run plain `add.py init` would grandfather-lock
673
673
  // the v12 lock-down gate before `/add` runs (see file header). So no Python is run here.
674
- log("\nDone. " + (args.noSkill ? "The engine + book are" : "The `add` skill + tooling are") +
674
+ log("\nDone. " + (args.noSkill ? "The engine is" : "The `add` skill + tooling are") +
675
675
  " installed (no project state yet — that's intentional).");
676
676
  if (profile.id === "generic") {
677
677
  // the generic onramp line — kept literal so the conversational-only handoff is stable
@@ -753,7 +753,6 @@ const MANAGED = [
753
753
  ["skill/add", [".claude", "skills", "add"], false],
754
754
  ["agents", [".claude", "agents"], false],
755
755
  ["tooling", [".add", "tooling"], true],
756
- ["docs", [".add", "docs"], false],
757
756
  ["personas-teacher", [".add", "personas-teacher"], false],
758
757
  ];
759
758
  // Optional managed trees: an ENHANCEMENT the persona phase reads, not core runtime. The real
@@ -762,6 +761,20 @@ const MANAGED = [
762
761
  // _installer.py:OPTIONAL. Design-for-failure. `agents` joins here (roster-install-drift): the
763
762
  // phase-agent roster is a spawn-acceleration enhancement, not core runtime.
764
763
  const OPTIONAL = new Set(["personas-teacher", "agents"]);
764
+ // SHARED-namespace managed trees (installer-shared-namespace-guard): destinations OTHER
765
+ // TOOLS also write — `.claude/agents` holds the user's own Claude Code subagents. A
766
+ // whole-dir clean-replace there sweeps the user's files as "orphans" (the reported
767
+ // data-loss bug), so these trees route to sharedFileReplace: per-file atomic landings of
768
+ // the shipped files + removal of ONLY the explicit tombstones below. Twin of
769
+ // _installer.py:_SHARED / _RETIRED_AGENTS.
770
+ const SHARED = new Set(["agents"]);
771
+ // Roster names retired upstream — the ONLY names the shared lander may remove (never a
772
+ // pattern/prefix heuristic: a USER file named add-anything.md must survive).
773
+ // roster-distill (ADD 2.0 M1): the 5-agent roster collapsed into the ONE `add` agent.
774
+ // advisor-split: that ONE `add` agent split into `add-worker` + `add-advisor`, so `add.md`
775
+ // retires here and `add-advisor.md` leaves the list (it ships again; landing precedes removal).
776
+ const RETIRED_AGENTS = ["add-design.md", "add-build.md", "add-verify.md",
777
+ "add-persona.md", "add.md"];
765
778
  const STAMP_FILE = ".add-version";
766
779
  const LOCK_FILE = ".update.lock"; // the `update --global` home lock (never user-data)
767
780
  const LOCK_STALE_DEFAULT = 600; // seconds (10 min); ADD_LOCK_STALE_SECONDS env-overridable
@@ -948,7 +961,7 @@ function cleanReplaceTree(src, dest, stripTests) {
948
961
  return { restored: restored, refreshed: refreshed };
949
962
  }
950
963
 
951
- const TREE_LABEL = { "skill/add": "skill", "agents": "agents", "tooling": "tooling", "docs": "docs", "personas-teacher": "personas" };
964
+ const TREE_LABEL = { "skill/add": "skill", "agents": "agents", "tooling": "tooling", "personas-teacher": "personas" };
952
965
 
953
966
  // Per managed tree: "missing" (dest absent OR empty) or "present".
954
967
  function managedStatus(target) {
@@ -961,6 +974,36 @@ function managedStatus(target) {
961
974
  return status;
962
975
  }
963
976
 
977
+ // installer-shared-namespace-guard: land a SHARED-namespace managed tree per FILE.
978
+ // `.claude/agents` belongs to the user as much as to ADD — only the shipped files are
979
+ // written (temp-sibling + atomic rename each, so a crash never leaves a torn file) and
980
+ // only the explicit RETIRED_AGENTS tombstones are removed; every other destination file
981
+ // is never opened. Returns the same { restored, refreshed } roll-up shape as
982
+ // cleanReplaceTree so the reconcile reporting is agnostic. Mirror of
983
+ // _installer.py:_shared_file_replace.
984
+ function sharedFileReplace(src, dest) {
985
+ fs.mkdirSync(dest, { recursive: true });
986
+ let restored = 0, refreshed = 0;
987
+ const entries = fs.readdirSync(src).filter((n) => fs.statSync(path.join(src, n)).isFile()).sort();
988
+ for (const name of entries) {
989
+ const target = path.join(dest, name);
990
+ const existed = fs.existsSync(target);
991
+ const tmp = path.join(dest, name + ".add-tmp-" + Math.random().toString(36).slice(2, 10));
992
+ try {
993
+ fs.copyFileSync(path.join(src, name), tmp);
994
+ fs.renameSync(tmp, target); // atomic overwrite (same directory)
995
+ } catch (e) {
996
+ fs.rmSync(tmp, { force: true }); // dest entry untouched or already whole
997
+ throw e;
998
+ }
999
+ if (existed) refreshed++; else restored++;
1000
+ }
1001
+ for (const name of RETIRED_AGENTS) {
1002
+ fs.rmSync(path.join(dest, name), { force: true }); // absent tombstone — never fatal
1003
+ }
1004
+ return { restored: restored, refreshed: refreshed };
1005
+ }
1006
+
964
1007
  // reconcile: restore-missing + refresh-present (sweep orphans) across the managed trees,
965
1008
  // reporting per-tree status. Honors --no-skill (the plugin provides the skill). Touches
966
1009
  // ONLY managed trees — never user data. Prechecks ALL sources first (design-for-failure:
@@ -978,7 +1021,9 @@ function reconcile(args, target, srcRoot) {
978
1021
  const status = managedStatus(target);
979
1022
  let restored = 0, refreshed = 0;
980
1023
  for (const [sub, destParts, stripTests] of trees) {
981
- const roll = cleanReplaceTree(path.join(srcRoot, sub), path.join(target, ...destParts), stripTests);
1024
+ const roll = SHARED.has(sub)
1025
+ ? sharedFileReplace(path.join(srcRoot, sub), path.join(target, ...destParts))
1026
+ : cleanReplaceTree(path.join(srcRoot, sub), path.join(target, ...destParts), stripTests);
982
1027
  restored += roll.restored;
983
1028
  refreshed += roll.refreshed;
984
1029
  const dest = destParts.join("/");
@@ -992,7 +1037,7 @@ function reconcile(args, target, srcRoot) {
992
1037
  return { restored: restored, refreshed: refreshed, trees: status };
993
1038
  }
994
1039
 
995
- // --- global home: an OPT-IN shared install (engine+book+skill) updated for all projects ----
1040
+ // --- global home: an OPT-IN shared install (engine+skill) updated for all projects ----
996
1041
  // Resolution is PURE + total (never throws); the home MIRRORS the bundled managed layer so
997
1042
  // `update --global` propagation reuses reconcile() unchanged. Mirror of _installer.py.
998
1043
  function resolveGlobalHome(env) {
@@ -1034,12 +1079,14 @@ function writeRegistry(home, paths) {
1034
1079
  fs.renameSync(tmp, target); // atomic on the same filesystem (POSIX + Windows)
1035
1080
  }
1036
1081
 
1037
- // The home mirrors the bundled layout (skill/add + tooling + docs at the SAME relative paths
1082
+ // The home mirrors the bundled layout (skill/add + tooling at the SAME relative paths
1038
1083
  // the package ships) so reconcile(args, project, home) reuses MANAGED unchanged.
1039
1084
  const GLOBAL_TREES = [
1040
1085
  ["skill/add", ["skill", "add"], false],
1086
+ // roster-drift fix: absent here, `update --global` propagation (sourced FROM the home)
1087
+ // soft-skipped the roster forever — no refresh, no retired-agent tombstones.
1088
+ ["agents", ["agents"], false],
1041
1089
  ["tooling", ["tooling"], true],
1042
- ["docs", ["docs"], false],
1043
1090
  ["personas-teacher", ["personas-teacher"], false],
1044
1091
  ];
1045
1092
 
@@ -1062,7 +1109,7 @@ function reconcileGlobal(home, claudeDir, noSkill) {
1062
1109
  // --- global DATA: an OPT-IN per-project user-data snapshot under <home>/data/<key> ----------
1063
1110
  // Strictly additive; copies ONLY user-data (managed trees + transient excluded), clean-replaced,
1064
1111
  // one-way (project->home). Mirror of _installer.py (identical key + include/exclude rule).
1065
- const DATA_EXCLUDE = ["tooling", "docs", ".update-cache", STAMP_FILE, LOCK_FILE, PROJECT_LOCK_FILE]; // managed trees + meta + both locks
1112
+ const DATA_EXCLUDE = ["tooling", "docs", ".update-cache", STAMP_FILE, LOCK_FILE, PROJECT_LOCK_FILE]; // managed trees + meta + both locks ("docs" = legacy 1.x tree: still never user-data)
1066
1113
 
1067
1114
  // data_key twin: <sanitized-basename>-<sha1(abspath_utf8)[:12]>. Pure · total · separator-free.
1068
1115
  function dataKey(projectAbspath) {
@@ -1840,6 +1887,26 @@ function cmdUpdate(args) {
1840
1887
  log("ADD updated " + (cur || "(unstamped)") + " -> " + version +
1841
1888
  " · managed layer reconciled (" + roll.restored + " restored · " + roll.refreshed +
1842
1889
  " refreshed) · your project state untouched.");
1890
+ // crossing nudges — engine-owned follow-ups the updater must NAME, never run (python3
1891
+ // may be absent on this PATH; both commands are idempotent). Twin of _installer.py.
1892
+ if (cur !== version) {
1893
+ log("next: python3 .add/tooling/add.py sync-guidelines # refresh the CLAUDE.md guidance block to this version");
1894
+ }
1895
+ const tasksDir = path.join(addDir, "tasks");
1896
+ let legacyBoard = false;
1897
+ if (fs.existsSync(tasksDir)) {
1898
+ for (const entry of fs.readdirSync(tasksDir, { withFileTypes: true })) {
1899
+ if (entry.isDirectory()
1900
+ && fs.existsSync(path.join(tasksDir, entry.name, "TASK.md"))
1901
+ && !fs.existsSync(path.join(tasksDir, entry.name, "PLAN.md"))) {
1902
+ legacyBoard = true;
1903
+ break;
1904
+ }
1905
+ }
1906
+ }
1907
+ if (legacyBoard) {
1908
+ log("next: python3 .add/tooling/add.py migrate # 1.x board detected: TASK.md -> PLAN.md, live + archived");
1909
+ }
1843
1910
  }
1844
1911
 
1845
1912
  // js-reclaim-lock-heartbeat: a test-only entrypoint so the Python subprocess suite can drive
@@ -1888,13 +1955,13 @@ async function main() {
1888
1955
  case "help":
1889
1956
  case "--help":
1890
1957
  log("usage: npx @pilotspace/add <init|update|prune-data> [targetDir] [--force] [--check] [--no-skill] [--global] [--yes|--non-interactive]");
1891
- log(" init install the ADD skill + tooling + book into a project");
1892
- log(" (--no-skill drops the engine + book only — used by the Claude Code plugin)");
1958
+ log(" init install the ADD skill + tooling into a project");
1959
+ log(" (--no-skill drops the engine only — used by the Claude Code plugin)");
1893
1960
  log(" (--global ALSO installs to a shared home [ADD_HOME|XDG_DATA_HOME/add|~/.add] + registers the project)");
1894
1961
  log(" (--global-data implies --global + persists this project's user-data under <home>/data/<key>)");
1895
1962
  log(" (--from-global-data rehydrates this project's user-data FROM the shared home on a fresh clone)");
1896
1963
  log(" (interactive in a real terminal; --yes / --non-interactive force the plain path)");
1897
- log(" update re-materialize skill/tooling/docs to this package version (preserves your state)");
1964
+ log(" update re-materialize skill/tooling to this package version (preserves your state)");
1898
1965
  log(" (--global refreshes the shared home + propagates to every registered project)");
1899
1966
  log(" prune-data remove orphaned per-project snapshots from the shared home (dry-run; --force deletes)");
1900
1967
  break;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pilotspace/add",
3
- "version": "1.17.0",
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.",
3
+ "version": "2.1.0",
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"
7
7
  },
@@ -24,7 +24,6 @@
24
24
  "!tooling/add_engine/__pycache__",
25
25
  "!**/*.pyc",
26
26
  "tooling/templates/",
27
- "docs/",
28
27
  "personas-teacher/",
29
28
  "THIRD_PARTY_NOTICES.md",
30
29
  "README.md",
@@ -11,3 +11,9 @@ KEEP: the agent-definition domain folders (engineering, security, design, produc
11
11
  DROP: the upstream `.github/` CI, `scripts/`, other-tool `integrations/`, `CONTRIBUTING*`, `SECURITY.md`, and dotfiles.
12
12
 
13
13
  Content is RAW + verbatim — regenerate with `python3 add-method/scripts/update_teacher.py`. Attribution: see the repo-root `THIRD_PARTY_NOTICES.md` and the retained `LICENSE` in this folder (MIT).
14
+
15
+ ## Refresh-drift check (run on every refresh PR)
16
+
17
+ Distilled personas keep `source:` provenance pointing into this snapshot. In the refresh PR
18
+ description, list every `.add/personas/*.md` whose `source:` file(s) changed or moved in the
19
+ diff — those personas are candidates for re-distillation, otherwise their provenance rots silently.
@@ -1,16 +1,13 @@
1
1
  ---
2
2
  name: add
3
3
  description: >-
4
- ADD (AI-Driven Development) — a minimal, state-tracked workflow for building
5
- software where the AI writes the code and the human owns direction and
6
- verification. Drives every feature through one lean TASK.md: Specify →
7
- Scenarios Contract Tests Build Verify Observe, with red/green TDD
8
- built in. Use this skill whenever working in a repo that has a `.add/`
9
- directory, when the user says "add", "start a task", "next phase", "specify
10
- this feature", "ADD method", or "AI-driven development", or when scaffolding a
11
- new feature and you want spec/tests-first discipline instead of vague-prompt
12
- coding. Also use it to resume work across sessions (it reads `.add/state.json`
13
- so you never re-read the whole repo).
4
+ ADD (AI-Driven Development) — a minimal, state-tracked workflow: the AI writes
5
+ the code, the human owns direction and verification. Drives every feature through
6
+ one lean PLAN.md: Specify → Scenarios → Plan → Tests → Build → Verify → Observe,
7
+ red/green TDD built in. Use whenever a repo has `.add/`, or the user says "add",
8
+ "start a task", "next phase", "specify this feature", "ADD method", "AI-driven
9
+ development", or wants spec/tests-first discipline over vague-prompt coding. Also
10
+ resumes work across sessions via `.add/state.json` (never re-read the whole repo).
14
11
  user-invocable: true
15
12
  category: workflows
16
13
  keywords: [add, aidd, ai-driven-development, spec-first, tdd, contract, scenarios, verify, milestone, task-orchestration]
@@ -18,138 +15,93 @@ argument-hint: "status | init | continue | --todo <text> | [describe new short g
18
15
  license: MIT
19
16
  metadata:
20
17
  author: add
21
- version: "1.8.0"
18
+ version: "2.0.0"
22
19
  ---
23
20
 
24
- # ADD — the orchestration engine
21
+ # ADD — memory · judgment · conscience (the agent is the hands)
25
22
 
26
- You are the orchestrator. ADD keeps the AI fast *and* safe by fixing direction
23
+ You turn intent into the right task, then drive it. ADD keeps the AI fast *and* safe by fixing direction
27
24
  (spec, scenarios, contract, failing tests) **before** the build, and trusting the
28
- result through passing evidence rather than a plausible-looking diff.
25
+ result through passing evidence, not a plausible diff.
29
26
 
30
- **One file = one task.** Each feature is one `.add/tasks/<slug>/TASK.md` a §0 ground
31
- preamble plus seven step sections, filled top to bottom. The Python tool tracks where you
32
- are so context never rots across sessions.
27
+ **One task = one atomic node.** Each feature is one `.add/tasks/<slug>/PLAN.md`; its frozen §3
28
+ (contract · scope · Target) is the interface neighbor nodes depend on edges compile from the
29
+ milestone, `graph` renders the DAG, `locate` walks a failure to its node. Shard context beside it.
33
30
 
34
- **The `--todo` fast-path.** When the skill ARGUMENTS begin with `--todo`, skip orienting: route to
35
- `add.py todo` and print its output — `--todo <text>` captures · `--todo` lists open todos ·
36
- `--todo --done <id>` closes (engine errors surfaced verbatim) — then STOP.
31
+ **The `--todo` fast-path.** ARGUMENTS begin with `--todo`? Skip orienting: run `add.py todo`, print
32
+ it — `--todo <text>` captures · `--todo` lists · `--todo --done <id>` closes — then STOP.
37
33
 
38
34
  ## Always start here (orient — do not skip)
39
35
 
40
- Engine: `.add/tooling/add.py` · book: `.add/docs/`. Ensure the engine is in the project first:
36
+ Engine: `.add/tooling/add.py`. Missing (a plugin install)? Materialize it once
37
+ `node "${CLAUDE_PLUGIN_ROOT}/bin/cli.js" init --no-skill` drops `.add/tooling/` + the agent-agnostic
38
+ `CLAUDE.md` block; the skill stays in the plugin.
41
39
 
42
- - It exists go straight to `status` below.
43
- - It does NOT (ADD installed as a Claude Code plugin — engine + book ride in the plugin) →
44
- materialize once: `node "${CLAUDE_PLUGIN_ROOT}/bin/cli.js" init --no-skill`. That drops
45
- `.add/tooling/` (engine) + `.add/docs/` (book) + the agent-agnostic `CLAUDE.md` block — like an
46
- npm/pip install; the skill stays in the plugin, nothing duplicated.
40
+ Resume from the tool, never re-read the repo — run `add.py status --brief` (cookbook), then
41
+ the foundation map `status --foundation` (`--all` full) + `.add/SOUL.md` (**voice**); mid-flow, trust
42
+ each verb's `next:` footer. Then branch on state:
47
43
 
48
- Find the resume point from the tool, not by re-reading the repo:
44
+ - **No `.add/state.json` yet** (`status` says `no .add/ project found`) **autonomous setup**: read
45
+ `.add/.intent` if present (the installer's first-build intent — a NOTE, never an init trigger), then
46
+ YOU run `add.py init --name "<inferred>" --stage <picked> --await-lock` and drive setup via
47
+ `phases/direction.md` (brownfield repo → map it silently, `adopt.md`) — to the human baseline `lock`.
48
+ - **A task is active** → open its `.add/tasks/<active>/PLAN.md`, read the `phase:` marker, work that
49
+ beat per the loop below.
50
+ - **No active task** → first SIZE the request (Intake below), then `add.py new-task`.
49
51
 
50
- ```bash
51
- python3 .add/tooling/add.py status
52
- ```
53
-
54
- `status` names two files to read when orienting: `.add/PROJECT.md` (the foundation) and `.add/SOUL.md`
55
- (your **voice** — tone, style, what keeps the human's trust; read it each session — human-owned and
56
- self-improving via the `soul-self-improve` path). Then branch on state:
57
-
58
- - **No `.add/state.json` yet** (`status` says `no .add/ project found`) → **autonomous setup**: if
59
- `.add/.intent` exists, read it — the installer's one-line first-build intent (a NOTE, never an init
60
- trigger) — to seed your kickoff; then YOU run init — `add.py init --name "<inferred>" --stage <picked>
61
- --await-lock` — and read `phases/0-setup.md` to draft the foundation + §1–§3 through to the human
62
- baseline approval.
63
- - **A task is active** → open its `.add/tasks/<active>/TASK.md`, read the `phase:` marker, load the
64
- matching `phases/<n>-<phase>.md`. Work *only* that phase.
65
- - **No active task** → first SIZE the request (Intake below), then `add.py new-task <slug> --title "..."`.
66
-
67
- **Quick ref** — `status` resume · `init` bootstrap · `advance` continue · `gate PASS` at verify.
68
- **Flag mode** — two human-owned settings (never auto-picked): **fast** (task) · **auto** (mode).
69
- - **fast** — `new-task --fast`: minimal template, freeze-gated; a milestone-free `--fast` task is a
70
- blessed standalone low-ceremony lane. Jot ideas first with `add.py todo "<text>"` (then `todo` to
71
- list · `todo --done <id>`).
72
- - **auto** — `autonomy: auto` (default) auto-gates verify on evidence; lower the autonomy level with
73
- `add.py autonomy set conservative|manual` for a human gate · `new-milestone --await-confirm`
74
- confirm-gates a milestone's tasks.
52
+ **Flag mode** — ONE atomic template serves every task (no lanes); flags are header declarations.
53
+ - **gate_mode** — headless/agent-crossed freeze: declare `gate_mode: ai-plan-verify` in the PLAN.md
54
+ header + fill the §3 AI-verify record; security|data|architecture stay human-frozen (unstrikeable).
55
+ - **auto** — `autonomy: auto` (default) auto-gates verify on evidence; `add.py autonomy set
56
+ conservative|manual` restores a human gate.
75
57
 
76
58
  ## Intake — size a request before creating scope
77
59
 
78
- Classify a raw request BEFORE any milestone or task: read `intake.md`, place it in one bucket
79
- `new-major` · `sub-milestone` · `task` · `change-request` propose `{ bucket, rationale, command }`;
80
- the human confirms. A question or unsharp intent? **Interview before you size** (`intake.md`). Once
81
- `new-major`/`sub-milestone`, draft the `MILESTONE.md` (goal · scope · exit criteria · breadth-first
82
- tasks) read `scope.md`. Create it `new-milestone --await-confirm`, then `milestone-confirm <slug>`
83
- gates `new-task` until the parent is agreed. For `task`/`change-request`: `add.py new-task` then the
84
- first phase guide.
85
-
86
- ## The flow and which file to load
87
-
88
- Load the phase guide **only for the phase you are in** (progressive disclosure):
89
-
90
- | Phase | Guide | Produces (TASK.md section) | Who leads |
91
- |-------|-------|----------------------------|-----------|
92
- | setup | `phases/0-setup.md` | `.add/` + living docs + first §1–§3 + `SETUP-REVIEW.md` | AI drafts **human locks** (the baseline approval) |
93
- | ground | `phases/0-ground.md` | §0 GROUND map (real files · symbols · the anchors §3 cites) | **AI** (the §0 preamble — no new gate) |
94
- | specify | `phases/1-specify.md` | §1 rules + ranked lowest-confidence flag | AI drafts (co-specify)† |
95
- | scenarios | `phases/2-scenarios.md` | §2 Given/When/Then | AI drafts† |
96
- | contract | `phases/3-contract.md` | §3 frozen shape | AI drafts **human approves once** (the decision point)† |
97
- | tests | `phases/4-tests.md` | §4 + red suite in `tests/` | AI drafts† |
98
- | build | `phases/5-build.md` | code in `src/`, tests green | **AI** |
99
- | verify | `phases/6-verify.md` | §6 checks + gate record | **AI auto-gates on evidence**; human on residue/security‡ |
100
- | observe | `phases/7-observe.md` | §7 spec delta | human + AI |
101
-
102
- † **The specification bundle (v7).** §1–§4 are one bundle; the human gives **one approval at the
103
- contract freeze**, lowest-confidence-first see `run.md`.
104
- **Verify auto-gate (v6–v7).** Under `autonomy: auto` (default) a run may auto-PASS on complete
105
- evidence (*auto-resolved* — an explicit PASS, not a skip). **Security always escalates** (HARD-STOP);
106
- so do concurrency / architecture residue and a lowered autonomy level (`conservative` / `manual`) `run.md`.
107
-
108
- At every human decision point (intake · bundle approval · gate · milestone close) follow
109
- `report-template.md`: open with the banner then the ARC (goal · done · plan, engine-sourced), then PLAN/SHAPE → SUMMARY →
110
- FLAGS → DECIDED → EVIDENCE → APPROVE → NEXT; show-before-ask; never pre-stamp; the question is a summary, never the artifact.
111
-
112
- In **observe**, emit **lessons learned** tagged by which of the five (`DDD · SDD · UDD · TDD · ADD`)
113
- they improve (write them `open`; the human consolidates into `PROJECT.md`) grammar + lifecycle in
114
- `deltas.md`. At milestone close (or on demand) the retrospective consolidation gathers confirmed deltas
115
- into a versioned foundation — `fold.md`; then (separately, after) compact each foundation spec's stable
116
- tail`compact-foundation.md`. Observe also tunes your voice: propose a confirmable voice delta that,
117
- once the human confirms, rewrites `SOUL.md` (the human is the only writer) — `soul.md`.
118
-
119
- ## Beyond the bundle load on demand
120
-
121
- - **§3 CONTRACT FROZEN** build→verify is a dynamic, auto-gated run (`autonomy: auto` default; lower to
122
- `conservative`/`manual` for a human gate) `run.md`. Pipeline ready tasks behind frozen
123
- contracts — `streams.md`. Delegate one piece of your plan to a subagent — prefer the named roster
124
- (`add-design`/`add-build`/`add-verify`/`add-persona`/`add-advisor`) over an ad-hoc spawn; when to
125
- spawn, the prompt template, the tier — `advisor.md`. Self-score a draft (0–1 across six dimensions, refine if any < 0.9)
126
- — `confidence.md`. Both advisory; the engine never spawns.
127
- - **Small, low-risk task**, less ceremony → the **fast lane**: `new-task --fast` scaffolds the minimal
128
- `TASK.fast.md`, bundle approved in one freeze — `phases/fast-lane.md`. Floor held (frozen contract ·
129
- red test · verify gate; freeze-gated under any milestone). Collapse, never skip; opt-in.
130
- - **UI feature** at specify → the **design-definition loop** (UDD): intake the design axes → review the
131
- domain → research and reuse components → wireframe → a captured screen the human confirms **before** build — `design.md`.
132
- Tool-agnostic; the engine never renders.
133
- - Tasks all done but the milestone **goal** unmet → `milestone-done` holds it open; the loop turns open
134
- deltas + extras into the next tasks until the goal is met — `loop.md`.
135
- - `status` prints **`MVP covered → propose graduation`** (every milestone done AND stage criteria all
136
- `[x]`) → `graduate.md`: `graduation-report` → co-specify interview → draft ≥1 production milestone →
137
- human confirm → then `stage production`. Guarded (`stage_no_roadmap`); the FINAL step, never a bare flip.
138
- - `status` prints **`→ releasable: N milestone(s) closed since last release`** → `release.md` (the 5th
139
- scope level): `release-report` → draft notes from the consolidated deltas → meet the readiness floor
140
- (security HARD-STOP is un-forceable) → human confirms → `add.py release <version>` records the cut
141
- (CHANGELOG + `RELEASES.md` ledger + milestone attribution). The engine records; the human runs the
142
- tag/publish/deploy. A release bundles ≥1 milestone, orthogonal to stage.
143
- - **Monorepo / multi-repo** — a milestone spans more than one green bar (a BE + its FE) → the
144
- **component pillar**: declare components in `.add/components.toml`, gate each task on its component's
145
- green-bar, freeze cross-component contracts (`produces:`/`consumes:`), hold the FE until the BE
146
- freezes, `federate pull` across repos — `components.md`. Opt-in; no components = today.
147
- - **Project-fit personas** — the **persona loop** seeds `.add/personas/<slug>.md`, grows them via
148
- observe→delta→consolidate, applies them in design/streams/advisor/build (advisory; never lowers a gate) — `docs/18-personas.md`.
149
- - **Risk-class of a task** — declare `sensitivity:` in the TASK header (base `security|data|architecture|
150
- mechanical`, always valid). EXTEND it with your project's domain classes in `GLOSSARY.md`'s `## Sensitivity
151
- classes` section; freeze/status/check read base ∪ project. The AI keeps the domain vocabulary current —
152
- `sensitivity.md`. Security is a human floor in every tier; only `mechanical` is advisor-gatable — see `advisor-gate-relax` in `run.md`.
60
+ Classify a raw request BEFORE any scope: read `intake.md`. Too small for scope the **inline lane**
61
+ (diff + `delta-append` receipt; security·data·architecture escalates). Else one bucket `new-major` ·
62
+ `sub-milestone` · `task` · `change-request` propose `{ bucket, rationale, command }`; the human
63
+ confirms. Unsharp intent? **Interview before you size** (`intake.md`). A milestone bucket: draft
64
+ `MILESTONE.md` (goal · scope · exit criteria · breadth-first tasks `phases/direction.md`), then the
65
+ `new-milestone`/`milestone-confirm` pair below (new-task inherits each node's depends-on). A
66
+ `task`/`change-request`: `add.py new-task`, then beat 1 above.
67
+
68
+ ## The 3-beat loop (this file IS the loop; references load on demand)
69
+
70
+ Every task is three beats (seven steps, folded), three engine calls, ONE human decision:
71
+
72
+ 1. **DIRECTION** load the domain-fit persona (seed via add-worker persona-mode if none), then draft
73
+ the whole bundle top-to-bottom in PLAN.md: §1 rules + ranked ⚠ flag (co-specify) ·
74
+ §2 scenarios · §3 PLAN (grounding frozen contract shape build-strategy + Scope + Target) · §4 red suite
75
+ (run it red for the RIGHT reason; fill each bullet's `covers:` clause key). Then the ONE approval,
76
+ presented lowest-confidence-first: `add.py freeze` (a setup session's baseline `lock` IS this approval).
77
+ 2. **BUILD** code in `src/` until every red is green; change no test, no frozen contract; stay
78
+ inside the §3 Scope. A test OUTSIDE your suite failing? `add.py locate` names the owning node, the
79
+ failure class, the frozen §3 clause it proves, and who re-verifies if a settled contract must move.
80
+ 3. **VERIFY** confirm evidence · 3 lenses (**security always HARD-STOP**) · earned-green
81
+ refute-read · then `add.py gate PASS` (from build it compound-crosses; under `autonomy: auto` a
82
+ run auto-PASSes on complete no-residue evidence *auto-resolved*, an explicit PASS, never a skip; residue or
83
+ lowered autonomy → human — `run.md`).
84
+
85
+ Stuck or deep? On demand: `phases/direction.md` · `phases/build.md` · `phases/verify.md` · opaque
86
+ term? `terms.md`. Delegating? Spawn the roster agent it loads its own refs (you read ONLY this file).
87
+
88
+ At each decision point (intake · bundle · gate · close) the fitting persona OWNS the gate report
89
+ `gate-udd.md` (read once per session) holds the principles: CONVEY decision + ARC (engine-sourced) ·
90
+ shape · flags (lowest-first) · evidence · a guided APPROVE. The persona owns the form, never the four
91
+ floors (security stays HARD-STOP) the question is a summary, never the artifact.
92
+
93
+ Emit **lessons learned** tagged by which of the five (`DDD · SDD · UDD · TDD · ADD`) they improve —
94
+ in-flight, via `delta-append` its living spec in `.add/specs/`. The living specs
95
+ ARE the foundation; the close counts what §7 still holds open. Observe also tunes your voice: a
96
+ confirmable delta the human confirms rewrites `SOUL.md` (the human is the only writer) `deltas.md`.
97
+
98
+ ## Beyond the bundle one trigger = one guide (full prose: `beyond.md`); load only on a trigger
99
+
100
+ - §3 FROZEN → auto-gated run `run.md` · subagent roster + pipelines (agent-call-preferred, the
101
+ default execution mode) `phases/verify.md` · self-score → `phases/direction.md`
102
+ - UI/experience surface → UDD loop `design.md` · milestone goal unmet at `milestone-done` → `loop.md`
103
+ - graduation · release · monorepo green-bars persona-owned playbooks, `beyond.md` ·
104
+ the persona loop (`.add/personas/`) `docs/18-personas.md` · `sensitivity:`/`advisor-gate-relax` `phases/verify.md`
153
105
 
154
106
  ## Non-negotiable rules (from the method)
155
107
 
@@ -158,35 +110,39 @@ once the human confirms, rewrites `SOUL.md` (the human is the only writer) — `
158
110
  2. **Trust evidence, not inspection.** A feature is trusted because its tests pass and the
159
111
  non-functional risks (concurrency, security, architecture) were checked — not because the code
160
112
  reads plausibly.
161
- 3. **Never weaken a test or edit a frozen contract to make the build pass.** That inverts the method.
162
- A real change is a *change request* back to Specify.
113
+ 3. **Never weaken a test or edit a frozen contract to make the build pass.** That inverts the
114
+ method. A real change is a *change request* back to Specify.
163
115
  4. **No silent skips.** Every Verify ends in exactly one recorded outcome: `PASS`, `RISK-ACCEPTED`
164
116
  (signed, non-security only), or `HARD-STOP`. A security finding is always `HARD-STOP`.
165
- 5. **Ask, don't guess.** If a requirement is unclear, stop and ask the user.
166
117
  </constraints>
167
118
 
168
- ## Advancing
119
+ ## Command cookbook — copy a line; `-h` only off-menu
169
120
 
170
- After a phase's exit gate is met, advance the state (this also syncs the TASK.md marker):
121
+ `add.py` = `python3 .add/tooling/add.py`; lines 2–4 = the 3-call walk (`advance --fill <draft>` = step-wise).
171
122
 
172
123
  ```bash
173
- python3 .add/tooling/add.py advance # next phase of the active task
174
- python3 .add/tooling/add.py gate PASS # at verify: records PASS, marks done
175
- python3 .add/tooling/add.py use <slug> # switch the active task (e.g. across parallel streams)
124
+ add.py status --brief # resume · status --section <n|phase> = §body · --foundation · --json
125
+ add.py new-task <slug> --title "..." # --milestone m · --depends-on a,b · --sensitivity security
126
+ add.py freeze --by "<name>" --cross # the ONE approval -> build (--ai-plan-verify = headless)
127
+ add.py gate PASS --target-hit yes # partial|no · RISK-ACCEPTED --owner --ticket --expires
128
+ add.py locate tests/x.py::test_y # failure -> owning node + its frozen §3 clause
129
+ add.py graph --milestone <slug> # mermaid DAG · relate <slug> --depends-on|--extends
130
+ add.py delta-append tdd "<lesson>" # lens: ddd|sdd|udd|tdd|add
131
+ add.py new-milestone <slug> --title "..." --goal "..." --await-confirm # confirm-gates its tasks
132
+ add.py milestone-confirm <slug> --by "<name>" # compiles Tasks -> DAG; unlocks new-task
133
+ add.py report [<milestone>|<task>] --decide # rollup/drill-in · check · search · use
176
134
  ```
177
135
 
178
136
  ## Depth by stage
179
137
 
180
- The steps never change; their depth does (read the stage from `add.py status`):
138
+ Steps never change; depth does (`add.py status`):
181
139
 
182
- - **prototype** — run light; code is throwaway; design/experience is the point.
183
- - **poc** — run contract/tests/build deeply on the single riskiest slice only.
140
+ - **prototype** — light; throwaway code; design/experience is the point.
141
+ - **poc** — contract/tests/build deep on the single riskiest slice only.
184
142
  - **mvp** — full flow, narrow scope, light observation.
185
- - **production** — every step at full rigor + the observe loop. Reach it via the `graduate.md`
186
- orchestration when status shows `MVP covered → propose graduation`, never a bare `stage production` flip.
143
+ - **production** — full rigor + the observe loop; reached via the graduation playbook
144
+ (`beyond.md`), never a bare `stage production` flip.
187
145
 
188
- ## The method rationale
146
+ The **method rationale** (the *why*) lives in the AIDD book — https://pilotspace.github.io/ADD/ (the `docs/…` chapters the
147
+ guides cite). Read it when a decision is genuinely unclear; never duplicate it here.
189
148
 
190
- The full method (the *why* behind every rule) is the AIDD book in `.add/docs/`. When a phase decision is
191
- genuinely unclear, read the linked chapter — each phase guide points to its chapter. Do not duplicate
192
- the book here; load it on demand.
@@ -35,6 +35,34 @@ Fill each living-doc file in `.add/` from what the code shows — **ask nothing*
35
35
  2. **Tag every drafted decision `evidence-grounded` vs `guessed`.** A line you read from the code is *evidence-grounded* (cite the file). A line you inferred because the code was silent is *guessed*. The human's single baseline approval is only honest if they can see which is which — the guesses are what they actually need to check. (The tags feed `SETUP-REVIEW.md`.)
36
36
  </constraints>
37
37
 
38
+ ## Setup review — the one page the human signs
39
+
40
+ Both setup paths (this brownfield map AND the greenfield draft, `phases/direction.md`) end at
41
+ the same single human gate, and `SETUP-REVIEW.md` is that page: every decision you made while
42
+ drafting the foundation, first-scope, and first contract, ordered **lowest-confidence-first** so
43
+ the riskiest guesses meet the human's eye first. The engine never reads it — `add.py lock` is
44
+ judgment-free; the human *reading* this page is the review. Write ONE artifact at
45
+ `.add/SETUP-REVIEW.md`, beside `PROJECT.md` (never clobber a human-edited one — append/update):
46
+
47
+ ```markdown
48
+ # SETUP REVIEW — <project>
49
+
50
+ <stage> · <brownfield | greenfield> · drafted by <model> @ <date>
51
+
52
+ | # | Decision | Lands in | Tag | Why / Evidence |
53
+ |---|----------|----------|-----|----------------|
54
+ | 1 | <the drafted decision> | PROJECT.md \| scope \| first-contract | `guessed` | <the inference + why you had to guess> |
55
+ | 2 | <…> | <…> | `evidence-grounded` | <cite the source file/line you read it from> |
56
+
57
+ Sign: confirm in chat → the agent runs `add.py lock --by "<name>"` (typing it yourself works too)
58
+ ```
59
+
60
+ The two rules that make it honest: rows sort by confidence **ascending** — a `guessed` row
61
+ always floats above an `evidence-grounded` one (the top of the table is what the human must
62
+ actually challenge); and EVERY row is tagged with the shared vocabulary above (`guessed` = the
63
+ repo was silent, state the inference; `evidence-grounded` = cite the file). Rows are numbered
64
+ for reference at the gate. Present it lowest-confidence-first, not field-by-field.
65
+
38
66
  ## Where it ends — the baseline approval
39
67
 
40
68
  Brownfield onboarding draws no per-step approvals: map the foundation, draft the first milestone's scope and first task's candidate specification bundle, then present it all at **one** human gate. The human reviews decisions (`guessed` first) and confirms; you run the lock: