@pilotspace/add 1.7.2 → 1.8.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 CHANGED
@@ -4,6 +4,70 @@ 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
+ ## [1.8.0] — 2026-06-23
8
+
9
+ Team collaboration: ADD becomes git-native and multi-user, with N
10
+ parallel-active milestones, plus a polish pass on the delta-resolution
11
+ machinery. Additive and backward-compatible — `add.py` ships a one-way state
12
+ migration (single-active → multi-active), and the non-interactive byte stream
13
+ for existing single-user flows is preserved. Bundles six closed milestones.
14
+
15
+ ### Added
16
+ - **Multi-active milestones (`team-collaboration`)** — work N milestones in
17
+ parallel: `add.py activate` / `deactivate` manage an active working SET,
18
+ `add.py mine` is a my-work lens over owned tasks, the `streams:` block shows a
19
+ per-stream owner, and waves can span all active milestones.
20
+ - **Git-native user identity** — `add.py whoami` resolves the actor from git
21
+ config; tasks carry an owner.
22
+ - **Ownership & assignment** — `add.py assign` / `unassign` attach a task to an
23
+ owner; ownership renders across status and reports.
24
+ - **Git-merge safety** — merge-base enforcement guards a stale worker base; the
25
+ drift vectors a parallel-wave merge can introduce are pinned suite fixtures.
26
+ - **Multi-file commit primitive** — `_atomic_write_many` is now true
27
+ all-or-nothing: stage every temp → fsync → rename-aside → rename-all, with
28
+ rollback-on-any-failure restoring prior bytes. `fold`, `release`, and the
29
+ delta seed all route through it, closing the prior mid-rename residual window.
30
+ - **`--match <substr>` selector** — `add.py new-task --from-delta` and
31
+ `add.py drop-delta` accept `--match` to target ONE open SPEC delta among
32
+ several; a 0-match or ambiguous match is a named reject. First-open behavior
33
+ is byte-identical when `--match` is absent.
34
+ - **`compact --force`** — `add.py compact --force` overrides the project-wide
35
+ `open_spec_deltas_unresolved` block ONLY (never a structural guard) so an
36
+ urgent compaction is not blocked by an UNRELATED open SPEC delta; the bypass
37
+ is warned and recorded as `force_bypassed_spec_deltas`.
38
+
39
+ ### Notes
40
+ - One version tag publishes both channels: `@pilotspace/add` (npm) and
41
+ `pilotspace-add` (PyPI). The engine (`add.py`) is mirrored byte-identical
42
+ across all three trees with `ENGINE_MD5` re-pinned.
43
+
44
+ ## [1.7.3] — 2026-06-18
45
+
46
+ Multi-agent installer reach (`multi-agent-installer`). Additive; no breaking
47
+ changes — the non-interactive byte stream is unchanged for existing agents and
48
+ the engine (`add.py`) is byte-identical.
49
+
50
+ ### Added
51
+ - **Seven new agent profiles in the installer** — `add init` now detects and
52
+ onboards **Cursor, Windsurf, Trae, GitHub Copilot, Cline, Aider, and Gemini
53
+ CLI** (best-effort env detection, overridable in the interactive picker), in
54
+ addition to Claude Code, Codex, and OpenCode. Each gets the context file it
55
+ actually auto-loads: `AGENTS.md` for most, `.clinerules` for Cline. Unknown
56
+ agents still degrade to the generic `AGENTS.md`. Mirrored byte-for-decision
57
+ across both installer twins (`bin/cli.js` + `src/add_method/_installer.py`).
58
+ - **Gemini CLI settings wiring (`.gemini/settings.json`)** — because Gemini CLI
59
+ auto-loads `GEMINI.md` (not `AGENTS.md`), the installer now performs a
60
+ fail-soft, idempotent, key-preserving merge of `.gemini/settings.json` so its
61
+ `context.fileName` includes `AGENTS.md` — the installer's first JSON-config
62
+ write. Re-running is a no-op; a malformed or unwritable settings file warns and
63
+ is skipped without aborting the install.
64
+
65
+ ### Changed
66
+ - **Onboarding docs name the full agent set** — the README ("Works with your
67
+ agent") and `GETTING-STARTED.md` now list all ten supported agents and how
68
+ each loads ADD; only Claude Code runs the `/add` skill natively, every other
69
+ agent follows the same loop through the phase guides via the CLI.
70
+
7
71
  ## [1.7.2] — 2026-06-18
8
72
 
9
73
  Test-coverage and project-hygiene patch. Additive; no breaking changes.
@@ -135,8 +135,11 @@ python3 .add/tooling/add.py status
135
135
  `add.py status` is the resume point: project stage, active task, current phase.
136
136
  And `add.py guide` tells you what the current phase needs — its `guide :` line
137
137
  names the exact phase-guide file to read (`.claude/skills/add/phases/…` — plain
138
- markdown), which is how **any** agent — Claude, Cursor, Copilot, Codex — follows
139
- ADD through the CLI alone.
138
+ markdown), which is how **any agent** — Claude Code, Codex, OpenCode, Cursor,
139
+ Windsurf, Trae, Gemini CLI, GitHub Copilot, Cline, Aider — follows ADD through the
140
+ CLI alone. The installer detects which one you're in and drops the file it reads
141
+ (`CLAUDE.md`, `AGENTS.md`, or `.clinerules`; for Gemini CLI it also wires
142
+ `.gemini/settings.json`).
140
143
 
141
144
  > Tip: shorten typing with an alias — `alias add="python3 .add/tooling/add.py"` —
142
145
  > then you can run `add status`, `add guide`, etc. These are override and resume
package/README.md CHANGED
@@ -117,6 +117,13 @@ ADD is AI-first: you talk to the agent; it drives the method. In Claude Code, ru
117
117
 
118
118
  > `/add` — *"I want to let users transfer money between their own accounts."*
119
119
 
120
+ **Works with your agent.** The installer detects which coding agent you're in and
121
+ drops the context file it reads — so ADD drives through the CLI under **Claude Code,
122
+ Codex, OpenCode, Cursor, Windsurf, Trae, Gemini CLI, GitHub Copilot, Cline, and
123
+ Aider** (anything else falls back to a generic `AGENTS.md`). Only Claude Code runs
124
+ the `/add` skill natively; every other agent follows the same loop through the
125
+ phase guides via `add.py status` / `guide`.
126
+
120
127
  The agent orients from `state.json`, **sizes your request into a milestone** (you
121
128
  confirm the shape), then drafts each feature's **specification bundle** — Spec +
122
129
  Scenarios + Contract + Tests as one bundle — and you give **one approval at the
package/bin/cli.js CHANGED
@@ -91,6 +91,27 @@ const AGENT_PROFILES = [
91
91
  { id: "opencode", label: "OpenCode", integration_file: "AGENTS.md",
92
92
  env: ["OPENCODE"], envPrefix: "OPENCODE",
93
93
  next_step: "Open OpenCode — it reads AGENTS.md; say what you want to build." },
94
+ { id: "cursor", label: "Cursor", integration_file: "AGENTS.md",
95
+ env: ["CURSOR_AGENT", "CURSOR_TRACE_ID"], envPrefix: "CURSOR_",
96
+ next_step: "Open Cursor — it reads AGENTS.md; say what you want to build." },
97
+ { id: "windsurf", label: "Windsurf", integration_file: "AGENTS.md",
98
+ env: ["WINDSURF", "WINDSURF_ENV"], envPrefix: "WINDSURF_",
99
+ next_step: "Open Windsurf — Cascade reads AGENTS.md; say what you want to build." },
100
+ { id: "trae", label: "Trae", integration_file: "AGENTS.md",
101
+ env: ["TRAE_AI_IDE"], envPrefix: "TRAE_",
102
+ next_step: "Open Trae — it reads AGENTS.md; say what you want to build." },
103
+ { id: "copilot", label: "GitHub Copilot", integration_file: "AGENTS.md",
104
+ env: ["COPILOT_AGENT"], envPrefix: null, // NOT a GITHUB_ prefix — too broad (CI sets GITHUB_*)
105
+ next_step: "Open GitHub Copilot — it reads AGENTS.md; say what you want to build." },
106
+ { id: "cline", label: "Cline", integration_file: ".clinerules",
107
+ env: ["CLINE_ACTIVE"], envPrefix: "CLINE_",
108
+ next_step: "Open Cline — it reads .clinerules; say what you want to build." },
109
+ { id: "aider", label: "Aider", integration_file: "AGENTS.md",
110
+ env: [], envPrefix: "AIDER_",
111
+ next_step: "Open Aider — add AGENTS.md to its context (`.aider.conf.yml` `read:` or `--read AGENTS.md`), then say what you want to build." },
112
+ { id: "gemini", label: "Gemini CLI", integration_file: "AGENTS.md",
113
+ env: ["GEMINI_CLI", "GEMINI_SANDBOX"], envPrefix: "GEMINI_",
114
+ next_step: "Open Gemini CLI — ADD wired .gemini/settings.json to load AGENTS.md; say what you want to build." },
94
115
  { id: "generic", label: "your AI agent", integration_file: "AGENTS.md",
95
116
  env: [], envPrefix: null, next_step: GENERIC_NEXT },
96
117
  ];
@@ -151,7 +172,7 @@ function detectAgentEnriched(env, target, which) {
151
172
  try {
152
173
  if (target && fs.existsSync(path.join(target, "CLAUDE.md"))) return byId.claude; // repo signal
153
174
  } catch (_e) { /* fall through */ }
154
- for (const id of ["claude", "codex", "opencode"]) {
175
+ for (const id of ["claude", "codex", "opencode", "cursor", "windsurf", "trae", "copilot", "cline", "aider"]) {
155
176
  try { if (which(id)) return byId[id]; } catch (_e) { /* probe absent */ } // machine signal
156
177
  }
157
178
  return base; // generic
@@ -376,6 +397,48 @@ function writeIntentNote(target, intent) {
376
397
  } catch (_e) { return false; }
377
398
  }
378
399
 
400
+ // Merge <target>/.gemini/settings.json so context.fileName includes "AGENTS.md" — the pointer
401
+ // ADD writes for the gemini profile. Gemini CLI defaults to GEMINI.md and lets it win when both
402
+ // exist, so AGENTS.md must be named in the config to load. Read-merge-write: preserves every other
403
+ // key; idempotent; fail-soft (an unparsable/unwritable file warns + skips, never aborts the drop).
404
+ // Returns created|updated|unchanged|skipped. Twin of _installer.py:_write_gemini_settings.
405
+ function writeGeminiSettings(target) {
406
+ const geminiDir = path.join(target, ".gemini");
407
+ const settings = path.join(geminiDir, "settings.json");
408
+ try {
409
+ let data = {};
410
+ let created = true;
411
+ if (fs.existsSync(settings)) {
412
+ created = false;
413
+ let raw;
414
+ try { raw = fs.readFileSync(settings, "utf8"); data = JSON.parse(raw); }
415
+ catch (_e) {
416
+ warn("could not parse " + settings + " — leaving it untouched; skipped");
417
+ return "skipped";
418
+ }
419
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
420
+ warn(settings + " is not a JSON object — leaving it untouched; skipped");
421
+ return "skipped";
422
+ }
423
+ }
424
+ let context = data.context;
425
+ if (context === null || typeof context !== "object" || Array.isArray(context)) context = {};
426
+ let names = context.fileName;
427
+ if (typeof names === "string") names = [names];
428
+ else if (!Array.isArray(names)) names = [];
429
+ if (names.includes("AGENTS.md")) return "unchanged"; // idempotent
430
+ names = names.concat(["AGENTS.md"]);
431
+ context.fileName = names;
432
+ data.context = context;
433
+ fs.mkdirSync(geminiDir, { recursive: true });
434
+ fs.writeFileSync(settings, JSON.stringify(data, null, 2) + "\n");
435
+ return created ? "created" : "updated";
436
+ } catch (e) {
437
+ warn("could not write " + settings + " — " + (e && e.message ? e.message : e) + "; skipped");
438
+ return "skipped"; // design-for-failure: never abort the install
439
+ }
440
+ }
441
+
379
442
  // The drop — now a RECONCILE: restore missing managed trees + refresh present ones
380
443
  // (sweep orphans) + report per-tree status. Byte-compatible handoff with the prior
381
444
  // installer. The interactive path resolves a target then calls straight into this.
@@ -389,6 +452,10 @@ function dropFiles(args, target, profile, intent) {
389
452
  // Best-effort + fail-soft — never aborts the successful drop above.
390
453
  writeAgentPointer(target, profile);
391
454
 
455
+ // Gemini CLI auto-loads GEMINI.md, not AGENTS.md — so for the gemini profile we ALSO merge
456
+ // .gemini/settings.json (context.fileName) to load the AGENTS.md pointer. Fail-soft + idempotent.
457
+ if (profile.id === "gemini") writeGeminiSettings(target);
458
+
392
459
  // Optional build-intent NOTE for `/add` to read — "" (skip / non-interactive) -> no-op.
393
460
  writeIntentNote(target, intent);
394
461
 
@@ -779,4 +846,5 @@ module.exports = {
779
846
  whichSync: whichSync,
780
847
  scopeOptions: scopeOptions,
781
848
  writeIntentNote: writeIntentNote,
849
+ writeGeminiSettings: writeGeminiSettings,
782
850
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pilotspace/add",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "ADD (AI-Driven Development). One skill. Eight steps. Five disciplines. Every feature ships through the loop — a minimal, state-tracked Claude Code skill that ships the AIDD book as its trust layer.",
5
5
  "bin": {
6
6
  "add": "bin/cli.js"