@pilotspace/add 1.16.0 → 1.16.1

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,24 @@ 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.16.1] — 2026-07-04
8
+
9
+ Patch: two loose, additive persona-loop improvements found while dogfooding
10
+ ADD in a real consumer project. No engine validation changed; no CLI
11
+ behavior changed; nothing removed or renamed.
12
+
13
+ ### Changed
14
+ - **Persona seed nudge is project-scoped.** The setup/status/check/new-milestone
15
+ hint to draft a project's missing personas now names the project by scope
16
+ instead of a generic reminder, so it fires once per genuinely-uncovered
17
+ project rather than repeating a one-size-fits-all message.
18
+ - **Persona schema template recommends `flow:` + `## Abilities`.** A seeded
19
+ persona can now state which ADD apply-surface (design/build/advisor) loads
20
+ it and what it can concretely do, distinct from `## Critical Rules`
21
+ (always-enforced constraints) and the optional `## Playbook`. Recommended,
22
+ not engine-checked — existing personas anywhere stay schema-conformant
23
+ with no forced re-seed.
24
+
7
25
  ## [1.16.0] — 2026-07-03
8
26
 
9
27
  Closes the **install-update-hardening** milestone: `add.py init`/`update` (both
package/README.md CHANGED
@@ -39,7 +39,7 @@ pip install pilotspace-add && pilotspace-add init
39
39
 
40
40
  Then, in your coding agent, say what you want to build:
41
41
 
42
- > `/add` — *"I want to let users transfer money between their own accounts."*
42
+ > `/add` — *"Let users log in with email + password / SSO, and keep them signed in for 30 days unless they explicitly log out."*
43
43
 
44
44
  The agent sizes it into a milestone (you confirm the shape), drafts the spec →
45
45
  scenarios → contract → tests as one bundle (you approve once, at the frozen
@@ -182,7 +182,7 @@ exactly what that means, so there are no surprises:
182
182
  ADD is AI-first: you talk to the agent; it drives the method. In Claude Code, run
183
183
  **`/add`** and say what you want to build:
184
184
 
185
- > `/add` — *"I want to let users transfer money between their own accounts."*
185
+ > `/add` — *"Let users log in with email + password / SSO, and keep them signed in for 30 days unless they explicitly log out."*
186
186
 
187
187
  **Works with your agent.** The installer detects which coding agent you're in and
188
188
  drops the context file it reads — so ADD drives through the CLI under **Claude Code,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pilotspace/add",
3
- "version": "1.16.0",
3
+ "version": "1.16.1",
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"
@@ -52,7 +52,7 @@ Capture each surfaced decision as an **ADR** in `PROJECT.md` **Key Decisions** a
52
52
  ## 3 · Draft to the lock (both paths)
53
53
 
54
54
  1. **Fill the living documentation**: `.add/PROJECT.md` (Domain · Spec · UI/UX · Key Decisions), `CONVENTIONS.md`, `GLOSSARY.md`, `MODEL_REGISTRY.md`, `dependencies.allowlist`, and — for a UI project — `DESIGN.md` (delete if no UI; `design.md`). Brownfield: from code. Greenfield: from interview, gaps flagged `guessed`.
55
- - **Seed personas** (`.add/personas/`): `init` scaffolds `_template.md` (the schema). **Author one per role** from PROJECT.md + the vendored teacher library `.add/personas-teacher/` (read off-build; engine never fetches) — citing the teacher in `source:` and carrying its top `## Playbook` are the two optional parts, not the authoring. Covered by the **baseline approval**; `add.py check` validates; never clobber.
55
+ - **Seed personas** (`.add/personas/`): `init` scaffolds `_template.md` (the schema). **Author one per role** from PROJECT.md + the vendored teacher library `.add/personas-teacher/` (read off-build; engine never fetches) — citing the teacher in `source:` and carrying its top `## Playbook` are the two optional parts, not the authoring. Covered by the **baseline approval**; `add.py check` validates; never clobber. Still unseeded later? `status`/`check`/`new-milestone`'s hint means: return here, draft every missing project persona — not just one.
56
56
  2. **Propose, then size it.** Float a **kickoff suggestion** for the first milestone: a **goal** (one sentence), a **flow** (task order), **scenarios** (examples of what ships). Not the frozen `MILESTONE.md`. On their reaction, draft `MILESTONE.md` (read `scope.md`).
57
57
  3. **Create the first task and draft its candidate specification bundle.** `new-task` is allowed pre-lock:
58
58
  ```bash
package/tooling/add.py CHANGED
@@ -100,6 +100,7 @@ from add_engine.io_state import ( # re-exported as module globals: callers use
100
100
  _CONFLICT_MARKER_RE, # conflict-marker re
101
101
  _load_state_for_json, # --json state loader
102
102
  _md5_text, _md5_file, # md5 hashing helpers
103
+ _personas_unseeded, # persona-seed-nudge predicate
103
104
  )
104
105
 
105
106
 
@@ -1886,6 +1887,11 @@ def cmd_status(args: argparse.Namespace) -> None:
1886
1887
  # Existence-only: no open/parse, so the pointer adds no IO failure path (a non-file is no voice).
1887
1888
  if (root / "SOUL.md").exists():
1888
1889
  print("voice : .add/SOUL.md (how I sound & what keeps your trust — read each session)")
1890
+ # persona pointer (persona-seed-nudge v2): project-wide, read every session like context/voice
1891
+ # above — fires until >=1 REAL persona is seeded, self-clears once one lands. Advisory only;
1892
+ # never gates, never touches the --json branch (human-readable orientation surface only).
1893
+ if _personas_unseeded(root):
1894
+ print(f"persona : {PERSONA_HINT}")
1889
1895
  # wave resume hint — a live ledger outranks memory (streams.md "Wave ledger").
1890
1896
  # Existence-only: no open/read/parse, so the hint adds no IO failure path; a
1891
1897
  # non-file at the path is not a ledger. One line PER live ledger — more than
@@ -2930,6 +2936,11 @@ def cmd_check(args: argparse.Namespace) -> None:
2930
2936
  "persona_schema_incomplete: missing " + ", ".join(missing)))
2931
2937
  else:
2932
2938
  infos.append((f"persona '{slug}'", "schema-conformant"))
2939
+ # persona-seed-nudge: surface the SAME "no real persona" gap `new-milestone` nudges on, so
2940
+ # it is also visible on a plain `check`/`status` sweep — an INFO affirmation-of-absence,
2941
+ # never a WARN (measure-not-block; a project with no personas behaves exactly as before).
2942
+ if _personas_unseeded(root):
2943
+ infos.append(("personas", f"unseeded — {PERSONA_HINT}"))
2933
2944
 
2934
2945
  # drift: a done milestone must have no unfinished tasks
2935
2946
  for mslug, m in milestones.items():
@@ -3431,6 +3442,12 @@ def cmd_new_milestone(args: argparse.Namespace) -> None:
3431
3442
  else:
3432
3443
  print("active milestone set." + ("" if not await_confirm else
3433
3444
  " (unconfirmed — show the MILESTONE.md, then: add.py milestone-confirm " + slug + ")"))
3445
+ # persona-seed-nudge: a non-blocking hint (never a gate) when this project has no
3446
+ # REAL project-fit persona yet — points at the cross-cutting selection/drafting
3447
+ # service rather than inventing a second mechanism. Fires only on the ACTIVE arm
3448
+ # (a queued milestone isn't yet in flight, so the nudge would be premature there).
3449
+ if _personas_unseeded(root):
3450
+ print(f"note: {PERSONA_HINT}")
3434
3451
  print(_next_footer(root, state)) # converges the old "Decompose it into tasks: …" hint
3435
3452
 
3436
3453
 
@@ -24,6 +24,7 @@ __all__ = [
24
24
  "SETUP_FILES",
25
25
  "PERSONA_FRONTMATTER_KEYS",
26
26
  "PERSONA_REQUIRED_SECTIONS",
27
+ "PERSONA_HINT",
27
28
  "GUIDELINE_FILES",
28
29
  "RULES_FILE_REL",
29
30
  "WORKFLOW_HEADINGS",
@@ -99,6 +100,14 @@ SETUP_FILES = ("PROJECT.md", "CONVENTIONS.md", "GLOSSARY.md", "MODEL_REGISTRY.md
99
100
  PERSONA_FRONTMATTER_KEYS = ("name", "vibe")
100
101
  PERSONA_REQUIRED_SECTIONS = ("## Identity", "## Critical Rules", "## Default Requirement", "## Success Metrics")
101
102
 
103
+ # persona-seed-nudge v2: ONE hint, single-sourced — `new-milestone`/`check`/`status` all print
104
+ # THIS constant (not their own copy) so the wording can never drift across the three surfaces.
105
+ # Project-scoped (not "this milestone's domain") per the confirmed v2 amendment: the AI should
106
+ # catch up ALL of a project's missing personas, not draft a single milestone-fit one.
107
+ PERSONA_HINT = ("no project-fit persona seeded yet under .add/personas/ — spawn the add-persona "
108
+ "agent (or read docs/18-personas.md) to seed the project's persona(s) from "
109
+ "PROJECT.md's domain")
110
+
102
111
  # Scaffolded into .add/.gitignore at init so the engine's transient LOCAL artifacts
103
112
  # never reach git. Bare-filename patterns match at any depth under .add/ (tasks/,
104
113
  # milestones/, archive/). These are working state, not records: scope-snapshot.json
@@ -199,3 +199,17 @@ def _md5_file(p: Path) -> str | None:
199
199
  return hashlib.md5(p.read_bytes()).hexdigest()
200
200
  except OSError:
201
201
  return None
202
+
203
+
204
+ def _personas_unseeded(root: Path) -> bool:
205
+ """True when `.add/personas/` has no REAL (non-template) authored persona: the
206
+ directory is absent, empty, or holds only the seeded `_template.md` scaffold
207
+ (persona-seed-nudge). Fail-soft: an unreadable directory counts as unseeded
208
+ rather than raising — this feeds a `note:`/INFO hint, never a gate."""
209
+ d = root / "personas"
210
+ if not d.is_dir():
211
+ return True
212
+ try:
213
+ return not any(p.stem != "_template" for p in d.glob("*.md"))
214
+ except OSError:
215
+ return True
@@ -1,6 +1,10 @@
1
1
  ---
2
2
  name: <persona name — e.g. Frontend Engineer, UX Researcher>
3
3
  vibe: <one-line essence — what this persona keeps true>
4
+ flow: <RECOMMENDED — which of the three apply-surfaces this persona is loaded at (see
5
+ docs/18-personas.md "Apply — three surfaces"): design (the UDD requirements lens) | build
6
+ (the domain-identity overlay on SOUL.md) | advisor (subagent/streams delegation, incl. the
7
+ verify refute-read) — comma-separate if more than one, e.g. `build, advisor`>
4
8
  source: <OPTIONAL — the teacher file(s) this was distilled from, e.g. `.add/personas-teacher/engineering/engineering-software-architect.md` (provenance; omit if hand-authored)>
5
9
  ---
6
10
  <!-- A PERSONA is a project-fit requirements persona, distilled from the vendored teacher
@@ -9,8 +13,11 @@ source: <OPTIONAL — the teacher file(s) this was distilled from, e.g. `.add/pe
9
13
  the teacher; the engine only seeds + validates this schema (presence-based). This
10
14
  `_template.md` is the schema reference — copy it to `<slug>.md` and fill it.
11
15
 
12
- REQUIRED: `name` + `vibe` frontmatter and the Identity / Critical Rules /
16
+ REQUIRED (engine-checked): `name` + `vibe` frontmatter and the Identity / Critical Rules /
13
17
  Default Requirement / Success Metrics sections.
18
+ RECOMMENDED (not engine-checked, but expected on every persona for consistency): `flow:`
19
+ frontmatter and the `## Abilities` section — a persona with no stated flow or abilities is
20
+ hard for the design/build/advisor surfaces to actually pick up and use.
14
21
  OPTIONAL (recommended for a faithful distillation): `source:` frontmatter, and the
15
22
  `## Anti-patterns` + `## Playbook` sections. The engine never requires the optional
16
23
  parts; absence is conformant.
@@ -23,12 +30,25 @@ source: <OPTIONAL — the teacher file(s) this was distilled from, e.g. `.add/pe
23
30
  3. TAG provenance honestly. In `## Playbook`, mark each item teacher-derived vs
24
31
  ADD-native. Never credit home-grown project scaffolding to the teacher.
25
32
  4. METRICS are rules, not snapshots. Prefer an invariant ("suite matches the last
26
- green run") over a volatile literal ("2491/0") that rots as the project grows. -->
33
+ green run") over a volatile literal ("2491/0") that rots as the project grows.
34
+ 5. NAME the flow. State which apply-surface(s) actually load this persona — a persona
35
+ that fits none of design/build/advisor is dead weight nobody will ever pick up.
36
+ 6. ABILITIES are checkable skills, not aspirations. Anchor each to a real file, tool, or
37
+ command this project already has — the same anchoring discipline as Critical Rules
38
+ and Success Metrics, applied to "what this persona can concretely do." -->
27
39
 
28
40
  ## Identity
29
41
  <who this persona is — role, domain depth, and the EARNED perspective it brings (what it has
30
42
  seen succeed/fail that shapes its judgement). One short paragraph.>
31
43
 
44
+ ## Abilities
45
+ <concrete, checkable things this persona can actually DO — a capability list, distinct from
46
+ Critical Rules (always-enforced constraints) and Playbook (optional step-by-step scaffolding).
47
+ State each as something the agent can perform right now, anchored to a real file/tool/command
48
+ where possible — not an aspiration.>
49
+ - <a concrete capability — e.g. "can diff two response fixtures byte-for-byte to prove passthrough">
50
+ - <another concrete capability>
51
+
32
52
  ## Critical Rules
33
53
  <non-negotiables this persona ALWAYS enforces. Lead with 1–2 carried from the teacher (its
34
54
  signature stance), then add project-specific ones.>