projectstore-claude 0.29.2 → 0.29.4

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 (76) hide show
  1. package/README.md +1 -1
  2. package/bin/projectstore-claude.mjs +1 -1
  3. package/node_modules/projectstore/.claude-plugin/marketplace.json +1 -1
  4. package/node_modules/projectstore/.claude-plugin/plugin.json +2 -1
  5. package/node_modules/projectstore/README.md +44 -7
  6. package/node_modules/projectstore/commands/bar.md +30 -0
  7. package/node_modules/projectstore/commands/bind.md +16 -20
  8. package/node_modules/projectstore/commands/doctor.md +12 -7
  9. package/node_modules/projectstore/commands/scaffold.md +24 -16
  10. package/node_modules/projectstore/commands/status.md +1 -1
  11. package/node_modules/projectstore/commands/statusline.md +2 -2
  12. package/node_modules/projectstore/commands/story.md +15 -2
  13. package/node_modules/projectstore/docs/alongside.md +167 -0
  14. package/node_modules/projectstore/docs/extending.md +17 -3
  15. package/node_modules/projectstore/docs/getting-started.md +18 -9
  16. package/node_modules/projectstore/docs/harnesses.md +1 -1
  17. package/node_modules/projectstore/docs/how-it-works.md +12 -3
  18. package/node_modules/projectstore/harnesses/claude-code.json +23 -8
  19. package/node_modules/projectstore/harnesses/codex.json +16 -6
  20. package/node_modules/projectstore/hooks/band-state.d.ts +44 -0
  21. package/node_modules/projectstore/hooks/band.tsx +622 -0
  22. package/node_modules/projectstore/hooks/hooks.json +1 -0
  23. package/node_modules/projectstore/hooks/pre-compact.mjs +7 -10
  24. package/node_modules/projectstore/hooks/session-rules.mjs +14 -8
  25. package/node_modules/projectstore/hooks/session-start.mjs +56 -20
  26. package/node_modules/projectstore/hooks/session-stop.mjs +8 -6
  27. package/node_modules/projectstore/package.json +12 -2
  28. package/node_modules/projectstore/scaffold/headings.json +8 -0
  29. package/node_modules/projectstore/scripts/band-shared.mjs +446 -0
  30. package/node_modules/projectstore/scripts/band.mjs +207 -0
  31. package/node_modules/projectstore/scripts/binding.mjs +733 -62
  32. package/node_modules/projectstore/scripts/build-adapters.mjs +98 -35
  33. package/node_modules/projectstore/scripts/cli.mjs +1463 -267
  34. package/node_modules/projectstore/scripts/codemap.mjs +22 -7
  35. package/node_modules/projectstore/scripts/convergence.mjs +638 -0
  36. package/node_modules/projectstore/scripts/diff-refs.mjs +14 -8
  37. package/node_modules/projectstore/scripts/doctor-report.mjs +253 -0
  38. package/node_modules/projectstore/scripts/doctor.mjs +1384 -420
  39. package/node_modules/projectstore/scripts/draft.mjs +5 -2
  40. package/node_modules/projectstore/scripts/fetch-shell.mjs +369 -0
  41. package/node_modules/projectstore/scripts/graph.mjs +19 -13
  42. package/node_modules/projectstore/scripts/harness.mjs +283 -37
  43. package/node_modules/projectstore/scripts/install-harness.mjs +4701 -575
  44. package/node_modules/projectstore/scripts/kanban.mjs +6 -21
  45. package/node_modules/projectstore/scripts/lib.mjs +933 -199
  46. package/node_modules/projectstore/scripts/mcp.mjs +386 -105
  47. package/node_modules/projectstore/scripts/portable-registration.mjs +276 -56
  48. package/node_modules/projectstore/scripts/provenance.mjs +26 -10
  49. package/node_modules/projectstore/scripts/query.mjs +441 -72
  50. package/node_modules/projectstore/scripts/reconcile.mjs +55 -18
  51. package/node_modules/projectstore/scripts/run-host.mjs +139 -0
  52. package/node_modules/projectstore/scripts/scaffold.mjs +244 -0
  53. package/node_modules/projectstore/scripts/setup.mjs +987 -0
  54. package/node_modules/projectstore/scripts/stages.mjs +84 -0
  55. package/node_modules/projectstore/scripts/statusline-launcher.mjs +36 -11
  56. package/node_modules/projectstore/scripts/statusline.mjs +55 -14
  57. package/node_modules/projectstore/scripts/story-section.mjs +39 -17
  58. package/node_modules/projectstore/scripts/surfaces.mjs +485 -99
  59. package/node_modules/projectstore/scripts/term.mjs +1027 -52
  60. package/node_modules/projectstore/scripts/tokens.mjs +106 -28
  61. package/node_modules/projectstore/scripts/touch-session.mjs +109 -70
  62. package/node_modules/projectstore/scripts/version-guard.mjs +79 -27
  63. package/node_modules/projectstore/scripts/worktree.mjs +16 -5
  64. package/node_modules/projectstore/templates/de/strings.json +63 -1
  65. package/node_modules/projectstore/templates/de/vault-readme.md.tmpl +13 -0
  66. package/node_modules/projectstore/templates/en/strings.json +63 -1
  67. package/node_modules/projectstore/templates/en/vault-readme.md.tmpl +13 -0
  68. package/node_modules/projectstore/templates/es/strings.json +63 -1
  69. package/node_modules/projectstore/templates/es/vault-readme.md.tmpl +13 -0
  70. package/node_modules/projectstore/templates/fr/strings.json +63 -1
  71. package/node_modules/projectstore/templates/fr/vault-readme.md.tmpl +13 -0
  72. package/node_modules/projectstore/templates/ru/strings.json +63 -1
  73. package/node_modules/projectstore/templates/ru/vault-readme.md.tmpl +13 -0
  74. package/node_modules/projectstore/templates/zh/strings.json +63 -1
  75. package/node_modules/projectstore/templates/zh/vault-readme.md.tmpl +13 -0
  76. package/package.json +2 -2
@@ -0,0 +1,167 @@
1
+ # ProjectStore beside agent memory and spec-driven tools
2
+
3
+ People who meet ProjectStore compare it with what they already run next to a coding agent: a
4
+ memory plugin, an instruction file, a spec-driven tool. This page says what each of those keeps,
5
+ what ProjectStore keeps instead, and which parts of ProjectStore exist elsewhere. The README and
6
+ the site name three kinds of tools; the first table here has four kinds, because agent memory kept
7
+ in the repository gets its own column.
8
+
9
+ The claims about other tools come from their own documentation, repositories and release notes,
10
+ **read on 2026-10-09**. Tools move fast; if a cell below is wrong or out of date,
11
+ [open an issue](https://github.com/SmartAndPoint/ProjectStore/issues/new?title=docs%2Falongside.md%3A+a+wrong+cell)
12
+ and name the cell and your source.
13
+
14
+ ## The question each kind of tool answers
15
+
16
+ | | Agent memory | Instruction files | Agent notes in the repository | Spec-driven tools | ProjectStore |
17
+ |---|---|---|---|---|---|
18
+ | **Examples** | Mem0, Zep, claude-mem, Codex memories, Claude Code auto memory | `CLAUDE.md`, `AGENTS.md`, rules, Kiro steering | Cline Memory Bank, Serena memories, Basic Memory, Letta | Spec Kit, Kiro specs, OpenSpec, BMAD | |
19
+ | **One entry is** | a fact or an observation | a rule | a note the agent keeps | a change: spec, plan, tasks | a decision, a spec or a work item, with a status, a date and links |
20
+ | **Written by** | the model, automatically | a person, or the agent on request | the agent, sometimes reviewed in pull requests | the agent; phase approval in Kiro and Tessl, a clear yes in OpenSpec's Explore, write previews in one BMAD skill | the agent drafts; a person approves the full text; a fresh-context critic reviews it by rule |
21
+ | **Lives in** | a hosted or local index (vector, graph, SQLite), or machine-local files | the code repository | the code repository, or a memory repository | the code repository; OpenSpec Stores (beta) in a planning repository | a folder kept in git, usually its own repository |
22
+ | **Read by** | the model, by retrieval | the model, at session start or when a file pattern or request matches | the model, on demand | the model and the team, during the feature | Claude Code sessions from the start (Codex: experimental); any agent through the CLI and MCP; people in pull requests and Obsidian |
23
+ | **Scope** | an agent, a user or a machine | the project | the project | a feature, plus a constitution or steering | the project, across features and harnesses |
24
+ | **Changes by** | expiry, invalidation, pruning | rewriting | rewriting, git history | per feature: discarded, or merged into living specs | supersede with reasons; status changes with evidence; `doctor` and `reconcile` |
25
+ | **Answers** | "What does this agent recall?" | "How should an agent behave here?" | "What has this agent learned about the project?" | "How do we build this change?" | "What has the project decided, what is in flight, and was it checked?" |
26
+
27
+ ## Why ProjectStore is not agent memory
28
+
29
+ 1. **Nothing is written because it was said.** A memory system writes when the model notices
30
+ something. A vault artifact is written through a ProjectStore command, after a person approved
31
+ its path and full text. The skill that watches the conversation only suggests a command.
32
+ 2. **Nothing is read by similarity.** Agents navigate: folder indexes, the link graph grepped by
33
+ path, the kanban, then the artifact. `search` is a literal substring search. What an agent read
34
+ is a file a person can open.
35
+
36
+ The price: an agent must know a word, a title or a path. Nothing finds a note that says the
37
+ same thing in other words.
38
+ 3. **Nothing belongs to an agent, a user or a machine.** The vault travels through git to whoever
39
+ has the repository. Claude Code and Codex read it through ProjectStore's commands; any other
40
+ agent can read it through the CLI or the MCP read surface. Codex memories and Claude Code auto
41
+ memory are per machine; Mem0's are per user or agent.
42
+ 4. **It can be wrong in a way that is reviewed.** A memory that turned false is expired, pruned or
43
+ invalidated. A decision that turned false is superseded by a newer ADR that says why, and the
44
+ chain stays.
45
+ 5. **What survives `/compact` is paths into the record, not knowledge from the session.** In
46
+ Claude Code, the SessionStart hook runs after compaction too. It hands back a navigation
47
+ skeleton of the vault plus the vault paths the session touched: the session's own activity log,
48
+ machine-local and git-ignored, resolved against the vault. Nothing the conversation said is
49
+ stored. Codex runs the same hook in its experimental shell, but what it reports after
50
+ compaction has not been measured.
51
+
52
+ **The overlap.** ProjectStore keeps a little session state on the machine — a per-session pointer
53
+ and the last 50 activity entries — for orientation, never committed. It is not knowledge, and
54
+ deleting it changes nothing in the vault.
55
+
56
+ **Where the data goes.** A memory tool stores what it derives from conversations, and some ship it
57
+ off the machine (Mem0's platform, claude-mem's optional cloud sync). The vault holds only text a
58
+ person approved. What reaches the model provider still depends on your harness and its
59
+ permissions.
60
+
61
+ ## Memory and the vault, side by side
62
+
63
+ They are not rivals. Use both, each for its own thing:
64
+
65
+ - **Memory for the person and the machine:** how you like to work, your environment's quirks,
66
+ corrections you gave the agent.
67
+ - **The vault for the project:** what was decided and why, what is in flight, what was checked.
68
+
69
+ The vendors say the same about their own memory. Codex: "Keep required team guidance in AGENTS.md
70
+ or checked-in documentation. Treat memories as a helpful recall layer, not as the only source for
71
+ rules that must always apply." Claude Code's auto memory skips what your `CLAUDE.md` already says.
72
+
73
+ The rule needs upkeep, because memory fills up on its own. When a memory states a project decision
74
+ or an idea the team should see, move it into the vault as an artifact, and let the memory keep only
75
+ a pointer to it.
76
+
77
+ ## The ingredients, tool by tool
78
+
79
+ Every ingredient of ProjectStore's loop exists somewhere else. This matrix shows where. "Core"
80
+ means without extensions; "?" means the documentation we read says nothing either way.
81
+
82
+ | Tool | Decision record with status and supersede | Person approves the full text before a write | Fresh-context review of planning artifacts | Fresh-context review of the diff against acceptance criteria | Orientation from the record at session start | Consistency checks with no model | Read surface for any agent |
83
+ |---|---|---|---|---|---|---|---|
84
+ | Spec Kit 1.1, core | no | no (a convention between phases) | no (in-context `/speckit.analyze` and `/speckit.checklist` only) | no | no | ? | commands for about forty agents |
85
+ | Spec Kit with community extensions | `adrkit`: MADR records with `status`, `adr accept`, superseded retrieval (pinned below 1.1.0) | no, before a write. `plan-review-gate` requires spec and plan merged by PR before tasks; `spec-validate` adds approval state as "a hard gate before /speckit.implement" | `red-team`, `critique`, `multi-model-review` | `maqa`, a QA workflow (fresh context unstated) | the official `agent-context` extension keeps a static block in `CLAUDE.md`/`AGENTS.md`; `memory`, `dubsar` (resume) | ? (`speckit-utils` "validate project health", `sync`; model use unverified) | same |
86
+ | Kiro | no | yes, per phase (Quick Spec skips the gates) | ? | ? | steering, always included | ? | Kiro only |
87
+ | OpenSpec 1.14 | a section per change; the archive keeps history | Explore only: waits for "a clear yes" | ? | ? | marker blocks in `CLAUDE.md`/`AGENTS.md`; no session hook | **yes**: `openspec validate` | many tools |
88
+ | BMAD 6.12.1 | spine `AD-n`: IDs can be retired, never reused; append-only rationale; no supersede chain documented | the project-context skill shows every write first | **yes**: reviewer gates on PRD, spine, UX | fresh subagent lenses (edge cases, verification gaps); the edge-case lens reads the spec's acceptance as claims, not per criterion | its `AGENTS.md` block (project-context skill); no SessionStart hook found | **yes**: `sprint_plan.py validate` | installer for several agents |
89
+ | Beads 1.3.1 | no: issues, not decisions (`bd supersede` marks an issue superseded by a newer one) | no | no | no | **yes**: `bd prime` through SessionStart hooks (Claude Code, Gemini CLI, Codex) | **yes**: `bd doctor`, `bd lint` (missing sections), `bd orphans` (referenced in commits, still open) | CLI with JSON; Dolt in git, JSONL export |
90
+ | Letta, Serena | no | no | no | no | Letta loads memory-root files into the system prompt every turn | no | Serena: any MCP client |
91
+ | Mem0, claude-mem | no | no | no | no | claude-mem injects memory at session start | no | many harnesses |
92
+ | ProjectStore 0.29.2 | **yes**: ADR status, `superseded_by` | **yes**, through its commands | a standing rule for every kind (critic) | a standing rule (reviewer), per criterion with evidence | **yes** in Claude Code; Codex experimental | **yes**: `doctor`, `reconcile`, regenerated views | CLI and MCP; Claude Code and Codex shells |
93
+
94
+ **What it shows.** No single column is ProjectStore's alone:
95
+ - `adrkit` keeps decision status and supersession;
96
+ - OpenSpec, BMAD and Beads validate artifacts without a model;
97
+ - Beads injects ready work at session start;
98
+ - BMAD reviews plans and diffs in fresh contexts.
99
+
100
+ What none of the tools above documents is all of them over one record: decisions, specs and work
101
+ items in one linked graph with a lifecycle, where the same `doctor` checks the links between them
102
+ and down to code, the same views regenerate from them, one critic rule covers every kind, and each
103
+ session's starting map is computed from that record.
104
+
105
+ **The nearest composition is Spec Kit with extensions.** Read cell by cell, it covers three of the
106
+ four ingredients listed above — decision status (`adrkit`), fresh-context review (`red-team`,
107
+ `critique`, `multi-model-review`), session-start orientation (`agent-context`, `memory`, `dubsar`) —
108
+ and has a "?" on the fourth, checks with no model. But it spreads across three stores — `adrkit`'s
109
+ ADRs, `specs/`, and an issue tracker through `maqa` — and documents no links between them and no
110
+ check that reads across them. `adrkit`'s catalog entry also pins Spec Kit below 1.1.0, the current
111
+ core.
112
+
113
+ **Review is a rule, not a lock**, in ProjectStore and in BMAD alike. Both are only as good as their
114
+ being followed. In ProjectStore, ADRs, specs, epics and research notes carry `review_status:
115
+ pending` until a critic pass is applied, so "not yet reviewed" is a state the tools can read;
116
+ stories are checked instead by the reviewer, against their diff. Nothing stops a person from
117
+ accepting an ADR before the critic pass.
118
+
119
+ **When this table is re-read:** when BMAD ships its next release, when OpenSpec Stores leave beta,
120
+ or when a Spec Kit extension joins decision records to review — each of those could change a cell.
121
+
122
+ **Sources, read on 2026-10-09:**
123
+ - Spec Kit: [repository](https://github.com/github/spec-kit) — releases 1.0.0 (2026-08-21) and
124
+ 1.1.0 (2026-10-02), `docs/concepts/spec-persistence.md`, `docs/reference/integrations.md`,
125
+ `extensions/catalog.community.json`; [adrkit](https://github.com/mbeacom/adrkit).
126
+ - Kiro: [specs](https://kiro.dev/docs/specs/), [best practices](https://kiro.dev/docs/specs/best-practices/),
127
+ [steering](https://kiro.dev/docs/steering/).
128
+ - OpenSpec: [repository](https://github.com/Fission-AI/OpenSpec) — releases, `docs/concepts.md`,
129
+ `docs/cli.md`, `docs/installation.md`, `docs/stores-beta/user-guide.md`.
130
+ - BMAD-METHOD: [repository](https://github.com/bmad-code-org/BMAD-METHOD) — release 6.12.1
131
+ (2026-10-04), `src/bmm-skills/plan/bmad-architecture/references/reviewer-gate.md`,
132
+ `src/bmm-skills/plan/bmad-sprint-planning/references/validate.md`.
133
+ - Beads: [repository](https://github.com/gastownhall/beads) — release 1.3.1 (2026-09-30),
134
+ `docs/cli-reference/`.
135
+ - Letta: [context repositories](https://www.letta.com/blog/context-repositories),
136
+ [MemFS](https://docs.letta.com/concepts/memfs). Serena:
137
+ [memories](https://oraios.github.io/serena/02-usage/045_memories.html).
138
+ - Zep / Graphiti: [concepts](https://help.getzep.com/concepts),
139
+ [Graphiti](https://github.com/getzep/graphiti). Cline: [Memory Bank](https://docs.cline.bot/best-practices/memory-bank).
140
+ Basic Memory: [repository](https://github.com/basicmachines-co/basic-memory). Tessl:
141
+ [overview](https://docs.tessl.io/overview/readme.md),
142
+ [spec-driven development tile](https://github.com/tesslio/spec-driven-development-tile).
143
+ - Mem0: [how it works](https://docs.mem0.ai/core-concepts/how-it-works),
144
+ [memory expiration](https://docs.mem0.ai/platform/features/memory-expiration),
145
+ [OpenMemory's removal](https://github.com/mem0ai/mem0/pull/6530). claude-mem:
146
+ [repository](https://github.com/thedotmack/claude-mem).
147
+ - Claude Code: [memory](https://code.claude.com/docs/en/memory). Codex:
148
+ [memories](https://learn.chatgpt.com/docs/customization/memories),
149
+ [AGENTS.md](https://learn.chatgpt.com/docs/agent-configuration/agents-md).
150
+ - ProjectStore: this repository.
151
+
152
+ ## What the checks cost
153
+
154
+ The critic and reviewer runs are model calls, and they are not free. On this repository, where
155
+ every change goes through the full loop, vault work measures 22.5% of total spend; on a typical
156
+ project, budget 10–15% of a weekly limit. The number is the price of the critic and reviewer
157
+ runs, not of storing files. See
158
+ [What it costs — measured, not promised](../README.md#what-it-costs--measured-not-promised).
159
+
160
+ ## Spec-driven tools
161
+
162
+ Running ProjectStore beside a spec-driven tool such as Spec Kit, Kiro or OpenSpec is a design that
163
+ has not been tried. The idea is that the spec-driven tool would own one feature's spec, plan and
164
+ tasks, while ProjectStore keeps the decisions, the backlog and the checks around them. Whether the
165
+ two tools' agent instructions, entry points and acceptance criteria stay out of each other's way is
166
+ an open question, and so is how ProjectStore's spec-first policy should be set beside them. A trial
167
+ and a decision on that policy are proposed; until they land, this page recommends no setting.
@@ -4,8 +4,8 @@
4
4
 
5
5
  Since v0.14 the kind machinery is layout-driven: `draft.mjs` builds ANY kind
6
6
  declared in the layout, and doctor's template check follows the layout instead
7
- of a hardcoded list. A new kind needs **five touch points** — note that **all
8
- five live inside the plugin installation**, not in your vault (there is no
7
+ of a hardcoded list. A new kind needs **six touch points** — note that **all
8
+ six live inside the plugin installation**, not in your vault (there is no
9
9
  vault-side layout or template override):
10
10
 
11
11
  1. **Layout folder entry** — `scaffold/layouts/<name>.json` → `folders`:
@@ -56,6 +56,16 @@ vault-side layout or template override):
56
56
  `collision`/`warnings` fields and updates an index, `commands/spec.md`
57
57
  for one with status transitions.
58
58
 
59
+ 6. **Folder strings** — `templates/<lang>/strings.json` → `folders.<kind>`,
60
+ a `name` and a one-line `description`, in **every** bundled language's
61
+ file. `scaffold` (and `init`) render the folder's README and its row in
62
+ the vault's top-level README from them, and refuse a layout whose folder
63
+ kind has no string in the bound language, naming the kind and the
64
+ language; doctor warns about the same gap. Every folder kind needs one,
65
+ with or without a command (`diagram` too). Keep the description to 160
66
+ characters with no `|`: the SessionStart skeleton shows it as the
67
+ folder's Purpose cell. Machine tokens such as `stories/` stay as they are.
68
+
59
69
  If the kind introduces **new section headings or inline keywords** that
60
70
  deterministic checks must recognize (doctor, reconcile, story-section),
61
71
  register a form per bundled language (en, ru, es, de, fr, zh) in
@@ -108,7 +118,11 @@ Frontmatter keys **and their values** stay English (`status: planned` is
108
118
  machine-read; only prose and table labels get translated). Then register the
109
119
  language's heading/keyword/index-column forms in `scaffold/headings.json`, and
110
120
  add the locale to `LOCALES` in `tests/locales.test.mjs` so the suite actually
111
- runs over it. `templates/<lang>/strings.json` localizes the statusline only.
121
+ runs over it. `templates/<lang>/strings.json` localizes the statusline and the
122
+ folder names and descriptions `scaffold` writes into the READMEs
123
+ (`folders.<kind>`, one per kind the layout declares — touch point 6 above),
124
+ and `vault-readme.md.tmpl` is the vault's top-level README. There is no English
125
+ fallback for either: a language that lacks one is refused by `scaffold`.
112
126
 
113
127
  Skipping the registry does not produce one clean error — it degrades *unevenly*,
114
128
  which is why the spec exists: an unregistered index header raises a doctor
@@ -37,11 +37,7 @@ You should see `projectstore` (displayName) with prefix `projectstore`.
37
37
 
38
38
  ## First-time setup
39
39
 
40
- 1. **Pick a vault directory** — any folder where you want your project artifacts to live. Obsidian opens it natively. Git tracks it cleanly.
41
-
42
- ```bash
43
- mkdir -p ~/Documents/projects/my-project-vault
44
- ```
40
+ 1. **Pick a vault directory** — any folder where you want your project artifacts to live. Obsidian opens it natively. Git tracks it cleanly. There is nothing to create by hand: step 2 creates the vault when the folder does not exist yet or is empty.
45
41
 
46
42
  2. **Bind your current project to that vault**:
47
43
 
@@ -49,7 +45,15 @@ You should see `projectstore` (displayName) with prefix `projectstore`.
49
45
  /projectstore:bind ~/Documents/projects/my-project-vault
50
46
  ```
51
47
 
52
- This creates `.projectstore/projectstore.json` in your project root (machine-local, gitignored) — and then walks you through a short interview: gitignore entries → scaffold offer → agent registration in `CLAUDE.md` (recommended: Yes) → model preset for the review agents (the default `opus` is fine) → status line offer (you'll see a preview of the exact line). Every step shows what it wants to write and waits for your approval.
48
+ This creates `.projectstore/projectstore.json` in your project root (machine-local, gitignored) — and then walks you through a short interview: gitignore entries → scaffold offer → vault policy → agent registration in `CLAUDE.md` (recommended: Yes) → model preset for the review agents (the default `opus` is fine) → status line offer (you'll see a preview of the exact line). Every step shows what it wants to write and waits for your approval. When the folder is missing or empty, the interview offers to create the whole vault there through `init` — the directory, its own git repository, the layout's folders and their README indexes — and then has no scaffold to offer.
49
+
50
+ **From a terminal instead**, outside a session, one command creates the same vault and binds this project to it:
51
+
52
+ ```bash
53
+ npx projectstore init ~/Documents/projects/my-project-vault
54
+ ```
55
+
56
+ It skips the rest of the interview: no agents block, no status line, no vault policy, no model preset. A later `/projectstore:bind` on that project only reports "Already bound" — it does not run those steps either. Choose this path when you want the vault and the binding alone.
53
57
 
54
58
  **Working in a git worktree?** That config is gitignored, so a worktree of a bound checkout starts unbound and `/projectstore:*` will not run there. Session start says so and names the fix:
55
59
 
@@ -59,13 +63,17 @@ You should see `projectstore` (displayName) with prefix `projectstore`.
59
63
 
60
64
  It copies the binding of the checkout the worktree was forked from — same vault, shared and unchanged, no session state carried over — and skips the interview, since the parent already answered it.
61
65
 
62
- 3. **Scaffold the layout** if the vault is empty (bind offers this automatically):
66
+ 3. **Scaffold the layout** of a vault that was bound without its folders (bind offers this automatically; a vault `init` made already has them):
63
67
 
64
68
  ```
65
- /projectstore:scaffold engineering
69
+ /projectstore:scaffold
66
70
  ```
67
71
 
68
- Creates `adr/`, `specs/`, `epics/`, `research/`, `concepts/`, `meetings/`, `ops/`, `diagrams/` and a top-level `README.md`.
72
+ Creates whichever of `adr/`, `specs/`, `epics/`, `research/`, `concepts/`, `meetings/`, `ops/`, `diagrams/`, their `README.md` indexes and the top-level `README.md` are missing, in the vault's language, and never rewrites a file that is there. The layout is the binding's. From a terminal:
73
+
74
+ ```bash
75
+ npx projectstore scaffold --write
76
+ ```
69
77
 
70
78
  ## Daily flow
71
79
 
@@ -81,6 +89,7 @@ You should see `projectstore` (displayName) with prefix `projectstore`.
81
89
  /projectstore:codemap # epic ↔ code mapping view
82
90
  /projectstore:graph # vault link graph: nodes + typed edges
83
91
  /projectstore:agents status # routing block + model config state
92
+ /projectstore:bar status # the band above the prompt: on/off, a pinned epic, why it is not drawing
84
93
  ```
85
94
 
86
95
  ## How approval works
@@ -13,7 +13,7 @@ This page says which harnesses exist, how far each one is trusted, and what
13
13
 
14
14
  | Harness | id | Status | Verified | Surfaces installed |
15
15
  |---|---|---|---|---|
16
- | Claude Code | `claude-code` | **supported** | 2026-08-30 | hooks, commands, agents, skills, MCP, status line, agents block |
16
+ | Claude Code | `claude-code` | **supported** | 2026-08-30 | hooks, commands, agents, skills, MCP, status line, agents block; the band above the prompt (experimental until its own live run) |
17
17
  | Codex | `codex` | **experimental** | — | portable plugin, hooks, rendered workflow skills, agents block |
18
18
 
19
19
  **supported** means the manifest carries a `verified` block: a session id and a
@@ -67,8 +67,10 @@ sessions can't silently overwrite each other's new artifact.
67
67
 
68
68
  **The status line is stricter still**: it renders from a *per-session* pointer
69
69
  (`<project>/.projectstore/state/sessions/<session_id>.json`, written by the
70
- PreToolUse hook with denormalized titles) and performs **zero cross-session and
71
- zero vault reads**. 2–6 parallel sessions each see exactly their own epic/story;
70
+ tool hooks with denormalized titles — after a write, from the file as written —
71
+ by `story close` through the core, and refreshed at session start) and performs
72
+ **zero cross-session and zero vault reads**. A story that is done, closed or
73
+ parked leaves the line: it shows the epic alone, as the band does. 2–6 parallel sessions each see exactly their own epic/story;
72
74
  a fresh session gets a localized "no epic or story in this session yet" line; a
73
75
  corrupt pointer shows an error marker, never a false "no work". The renderer also
74
76
  drops a `.last-render.json` breadcrumb so `doctor` can detect session-id
@@ -134,6 +136,13 @@ has one, else `~/.claude/settings.json`), prints its output
134
136
  verbatim, and adds one `[PS#version] 📚 …` line above it (`statusline.position`:
135
137
  `above`/`below`). With no base command it renders a standalone line.
136
138
 
139
+ While this session's band above the prompt is drawing, the line gives way to
140
+ it: the band keeps a heartbeat file fresh in the session-state directory, and
141
+ the renderer leaves its own line out while that file is younger than 30 s —
142
+ the base HUD prints as it always does. A band that stops, or never starts
143
+ (an older Claude Code, modules switched off), lets the heartbeat go stale, and
144
+ the line is back on its own.
145
+
137
146
  ## Doctor and reconcile: the trust layer
138
147
 
139
148
  The vault's guarantees used to depend on everyone using the gated commands —
@@ -155,7 +164,7 @@ resistance. v0.13 makes that safe instead of forbidden:
155
164
  (`--write`): each approved target is recomputed from the vault state at
156
165
  write time and replaced atomically, so a stale preview is never what lands;
157
166
  `--write` is also a sanctioned headless entry point (cron/CI repair job).
158
- - A throttled PreToolUse **nudge** fires when vault files are edited directly:
167
+ - A throttled PostToolUse **nudge** fires when vault files are edited directly:
159
168
  "run reconcile afterwards so the derived views stay in sync" (disable with
160
169
  `"guard": "off"` in `projectstore.json`).
161
170
  - A once-per-session **entry reminder** fires on PostToolUse when a session has
@@ -57,9 +57,14 @@
57
57
  }
58
58
  ],
59
59
  "session_env": [
60
- "CLAUDECODE"
60
+ "CLAUDECODE",
61
+ "CLAUDE_CODE_SESSION_ID"
61
62
  ],
62
- "session_env_reason": "set to 1 in every Bash tool of a live session (measured 2026-09-05, 2.1.261); detect_env names the variables a hook or plugin process receives, which a Bash tool does not — the two questions differ.",
63
+ "session_env_reason": "set to 1 in every Bash tool of a live session (measured 2026-09-05, 2.1.261); detect_env names the variables a hook or plugin process receives, which a Bash tool does not — the two questions differ. CLAUDE_CODE_SESSION_ID is set there too (measured 2026-10-10, 2.1.296).",
64
+ "session_id_env": "CLAUDE_CODE_SESSION_ID",
65
+ "session_id_env_reason": "the session's id in every Bash tool of a live session (measured 2026-10-10 and 2026-10-11, 2.1.296): the id the session-state files are keyed by, which `band status` needs to find this session's pointer and heartbeat (the band spec, contract 13). Read only through hostSessionId(), since scripts/ names no branded variable.",
66
+ "registration_defer_env": [],
67
+ "registration_defer_env_reason": "Empty: session_env already defers this harness's registration inside its own session (measured: the host's CLI and the session's exit rewrite the same settings files), and registrationDeferred reads both lists. Present on every manifest, an array, so an absent key is never a forgotten one (story: projectstore setup asks, shows one plan and installs every harness it finds, with the vault, rule 15).",
63
68
  "overlay": "claude-code",
64
69
  "overlay_reason": "the file under <project>/.projectstore/harness/ that carries this harness's agents block — the models, per agent, that plugin surfaces pass per invocation (ADR-008; the layout ADR decision 3)"
65
70
  },
@@ -129,16 +134,16 @@
129
134
  "system_message": true,
130
135
  "decision": "permissionDecision",
131
136
  "evidence": "measured",
132
- "note": "systemMessage measured — scripts/touch-session.mjs uses it for the pointer nudge and the name offer. additionalContext and permissionDecision (allow|deny|ask) are documented; projectstore never emits them. A separate PermissionRequest event carries its own decision object."
137
+ "note": "systemMessage measured — scripts/touch-session.mjs used it for the raw-edit nudge and uses it for the name offer (the nudge moved to PostToolUse with the write's pointer patch, ADR-006 amended 2026-10-12). additionalContext and permissionDecision (allow|deny|ask) are documented; projectstore never emits them. A separate PermissionRequest event carries its own decision object."
133
138
  },
134
139
  "PostToolUse": {
135
140
  "fields": [
136
141
  "additionalContext"
137
142
  ],
138
- "system_message": null,
143
+ "system_message": true,
139
144
  "decision": null,
140
145
  "evidence": "measured",
141
- "note": "scripts/touch-session.mjs — the entry-rule reminder's primary carrier (entry-rule spec, contract 14)."
146
+ "note": "scripts/touch-session.mjs — the entry-rule reminder's primary carrier (entry-rule spec, contract 14). The measurement covers additionalContext only. systemMessage carries the raw-edit nudge since the pointer patch moved after the write (ADR-006, amended 2026-10-12): documented for every event, not yet observed on this one — the closed-story story's live check records it."
142
147
  },
143
148
  "PostToolUseFailure": {
144
149
  "fields": [
@@ -246,6 +251,15 @@
246
251
  "scope_reason": "Claude Code loads the plugin's hooks.json from the plugin installation itself; per-project hooks live in settings, which projectstore does not write.",
247
252
  "registered_by": "plugin"
248
253
  },
254
+ "band": {
255
+ "supported": true,
256
+ "kind": "host",
257
+ "registered_by": "plugin",
258
+ "scope": "user",
259
+ "scope_reason": "Claude Code loads the band as a hooks module named under `modules` in the plugin's own hooks.json, from the plugin installation itself; nothing is written into a project to draw it.",
260
+ "verified": null,
261
+ "verified_reason": "null until a recorded live session (terminal and Desktop) observes it drawing, hiding during a question, and the status line yielding and coming back (the band spec, contract 15). The harness's own `verified` block predates the surface and does not cover it."
262
+ },
249
263
  "agents_block": {
250
264
  "supported": true,
251
265
  "kind": "shared",
@@ -285,7 +299,7 @@
285
299
  "file": ".projectstore/state/claude-code/statusline.mjs",
286
300
  "source": "scripts/statusline-launcher.mjs",
287
301
  "condition": "plugin_cache_install",
288
- "file_reason": "the harness's generated runtime files live under .projectstore/state/<harness id>/ (layout ADR decision 4); the 0.27.x path .claude/.projectstore/statusline.mjs is read as ours through 0.29",
302
+ "file_reason": "the harness's generated runtime files live under .projectstore/state/<harness id>/ (layout ADR decision 4); the 0.27.x path .claude/.projectstore/statusline.mjs is read as ours through 0.30",
289
303
  "legacy_file": ".claude/.projectstore/statusline.mjs"
290
304
  },
291
305
  "mcp": {
@@ -385,7 +399,8 @@
385
399
  "-y accepts a marketplace-declared command; this marketplace declares none",
386
400
  "the project of a --scope local command is the process cwd; there is no --project flag",
387
401
  "a live session marks its Bash environment with CLAUDECODE=1 (not the plugin-root or project-dir variables, which reach hooks only); the registration defers on that marker",
388
- "`plugin update` at an unchanged version answers \"already at the latest version\" and copies nothing, even after `marketplace update`: a same-version content refresh is uninstall + install"
402
+ "`plugin update` at an unchanged version answers \"already at the latest version\" and copies nothing, even after `marketplace update`: a same-version content refresh is uninstall + install",
403
+ "2.1.296, 2026-10-10: the plugin of this directory marketplace loads in place from <dir>/<plugin_subdir> — the MCP server's argv, the slash commands' plugin root and the SessionStart hook all name it — while the registry row's installPath stays the cache copy the launcher renders; the SessionStart refresh therefore never demotes a launcher entry (install spec, contract 0 as amended 2026-10-10)"
389
404
  ]
390
405
  },
391
406
  "commands": {
@@ -479,7 +494,7 @@
479
494
  "ui_vocabulary_reason": "This harness's UI affordances and tool names: words that mean nothing on another harness. The generator refuses them in another harness's rendered tree, and the runtime vocabulary lint refuses them in what the core prints for another harness (generation spec, contracts 6 and 18). A word here must be followed by a non-word character to count, so `/plugins/` in a path is not `/plugin`.",
480
495
  "update_hint": {
481
496
  "line": "See /plugin → Marketplaces to enable auto-update.",
482
- "welcome": ["**About future updates**: Claude Code does NOT auto-update third-party marketplaces by default. To get notified of new releases (v0.7+):", "1. Open `/plugin` → **Marketplaces** tab.", "2. Find **SmartAndPoint**.", "3. Toggle **auto-update** on.", "", "Without it, you'd run `/plugin marketplace update SmartAndPoint` manually. See https://github.com/SmartAndPoint/ProjectStore#updates for details."],
497
+ "welcome": ["**About future updates**: Claude Code does NOT auto-update third-party marketplaces by default. To get notified of new releases (v0.7+):", "1. Open `/plugin` → **Marketplaces** tab.", "2. Find **SmartAndPoint**.", "3. Toggle **auto-update** on.", "", "Without it, you'd run `/plugin marketplace update SmartAndPoint` manually. See https://github.com/SmartAndPoint/ProjectStore#upgrading for details."],
483
498
  "reason": "What the first-run welcome and its one-line notice say about updates (generation spec, contract 18): `line` ends the notice, `welcome` is the welcome's update block. update_instructions is the long-form guidance; this is the part a session prints, kept here so no hook names a harness's update path."
484
499
  },
485
500
  "update_instructions": [
@@ -29,7 +29,11 @@
29
29
  ],
30
30
  "shared_env_reason": "Codex sets Claude Code's plugin-root names too, for compatibility — measured in every one of the 759 captured hook payloads. Without declaring them, a Codex session scores a strong detection hit for claude-code, ties with codex, and loses the tie to manifest filename order. A variable two harnesses both set identifies neither, so these are demoted to weak for every manifest (generation spec, contract 1, amended 2026-09-08).",
31
31
  "session_env": [],
32
- "session_env_reason": "Deliberately empty, though measured. Codex's exec tool sets CODEX_THREAD_ID and CODEX_SESSION_ID in every command (measured 2026-10-05, codex-cli 0.160.0; CODEX_SANDBOX* depend on the sandbox mode), and CODEX_HOME never appeared in a hook environment. Declaring them would identify a session, but session_env also defers the registration and the layout move inside a session (insideHostSession), which would stop the doctor skill's upgrade --json fix from running there. Splitting identity from deferral is the question of *Codex hook contract measured in a live session* (PS-HARNESS); until then a core run from a rendered skill is identified by the shell that bundles it (generation spec, contract 18)."
32
+ "session_env_reason": "Deliberately empty, though measured. Codex's exec tool sets CODEX_THREAD_ID and CODEX_SESSION_ID in every command (measured 2026-10-05, codex-cli 0.160.0; CODEX_SANDBOX* depend on the sandbox mode), and CODEX_HOME never appeared in a hook environment. Declaring them would identify a session, but session_env also defers the registration and the layout move inside a session (insideHostSession), which would stop the doctor skill's upgrade --json fix from running there. Splitting identity from deferral is the question of *Codex hook contract measured in a live session* (PS-HARNESS); until then a core run from a rendered skill is identified by the shell that bundles it (generation spec, contract 18). The deferral half of that split is registration_defer_env below (the maintainer's decision of 2026-10-08).",
33
+ "registration_defer_env": [
34
+ "CODEX_THREAD_ID"
35
+ ],
36
+ "registration_defer_env_reason": "Defers this harness's registration, and the shell fetch that would feed it, and nothing else (harness.mjs registrationDeferred): install, upgrade and setup leave the registration for a terminal outside the session, and so does uninstall --global's removal, which runs the same host CLI against the same CODEX_HOME. Codex's exec tool sets CODEX_THREAD_ID in every command (measured 2026-10-05, codex-cli 0.160.0; session_env_reason above). Whether a Codex session rewrites config.toml at exit is not measured; the maintainer chose deferral on 2026-10-08, answering the front-door ADR's first open question (story: projectstore setup asks, shows one plan and installs every harness it finds, with the vault, rule 15). isInteractive, the layout move and session identity do not read this key, so the doctor skill's upgrade --json still moves the layout inside a session. Lifting the deferral needs a measurement of its own."
33
37
  },
34
38
  "tools": {
35
39
  "write_tools": [
@@ -242,6 +246,13 @@
242
246
  "scope_reason": "There is no per-project status-line slot to occupy: Codex has no status-line surface at all, so nothing of ours is written anywhere and the scope is the host's, not a file's.",
243
247
  "why_unsupported": "No status-line mechanism was found in the harness — no settings slot, no plugin field, no handler contract. Recorded as a row rather than an absence so the generator's coverage invariant sees a stated omission (contract 9) instead of a surface that quietly does not exist here."
244
248
  },
249
+ "band": {
250
+ "supported": false,
251
+ "kind": "host",
252
+ "scope": "user",
253
+ "scope_reason": "There is no surface above the prompt to draw into: nothing of ours is written anywhere, so the scope is the host's, not a file's.",
254
+ "why_unsupported": "Codex has no plugin surface that draws above the prompt and no hooks module runtime. The generator drops the module from this tree's hooks.json and renders the bar command as a skill that says so (the band spec, contract 1)."
255
+ },
245
256
  "plugin": {
246
257
  "supported": true,
247
258
  "kind": "registration",
@@ -310,8 +321,7 @@
310
321
  "run `$projectstore-bind <vault-path>` in Codex"
311
322
  ],
312
323
  "next": [
313
- "restart Codex from a terminal and approve the ProjectStore hooks when it asks",
314
- "in an unbound project, run `$projectstore-bind <vault-path>` in Codex"
324
+ "restart Codex from a terminal and approve the ProjectStore hooks when it asks"
315
325
  ],
316
326
  "notes": [
317
327
  "The installation is user-global because Codex's marketplace, plugin row and cache live in CODEX_HOME; the AGENTS.md block is project-local.",
@@ -322,9 +332,9 @@
322
332
  "docs": "https://github.com/SmartAndPoint/ProjectStore#install--one-message"
323
333
  },
324
334
  "update_hint": {
325
- "line": "Update with `{upgrade}`.",
326
- "welcome": ["**About future updates**: run `{upgrade}` from a terminal, then restart Codex and approve any hook it asks about.", "", "See https://github.com/SmartAndPoint/ProjectStore#updates for details."],
327
- "reason": "What the first-run welcome and its one-line notice say about updates (generation spec, contract 18): `line` ends the notice, `welcome` is the welcome's update block, and `{upgrade}` is filled with this harness's shell command at latest, so what is printed runs as printed. update_instructions is the long-form guidance; this is the part a session prints, kept here so no hook names a harness's update path."
335
+ "line": "Update from a terminal in this project:\n{upgrade}",
336
+ "welcome": ["**About future updates**: from a terminal in this project, run:", "", "```", "{upgrade}", "```", "", "Then restart Codex and approve any hook it asks about. See https://github.com/SmartAndPoint/ProjectStore#upgrading for details."],
337
+ "reason": "What the first-run welcome and its one-line notice say about updates (generation spec, contract 18): `line` ends the notice, `welcome` is the welcome's update block, and `{upgrade}` is filled with the core's upgrade for this harness at latest (`--harness codex`, no `--project`), so what is printed runs as printed. Each says where to run it and puts the command alone on its line (the story \"User-facing text says where to run and names no project path and no shell\", rules 4 and 5). update_instructions is the long-form guidance; this is the part a session prints, kept here so no hook names a harness's update path."
328
338
  },
329
339
  "update_instructions": "Run `npx projectstore-codex@<version> upgrade --project <dir>`. The installer atomically replaces its stable source and `codex plugin add projectstore@projectstore-npx` materialises the new version; this was measured across two dev builds on codex-cli 0.153.4. Restart Codex afterwards so the new skills and hooks are loaded.",
330
340
  "agent_translation": {
@@ -0,0 +1,44 @@
1
+ // projectstore — the band's values in the host's session state ($.state):
2
+ // what hooks/band.tsx draws from. Named in .claude-plugin/plugin.json under
3
+ // "types", so `claude plugin validate` holds every key the module names to it.
4
+
5
+ export type BandCounts = { done: number; active: number; backlog: number }
6
+
7
+ // The epic the band shows and everything its rows need, written by the
8
+ // module's clock only when it changed (a write redraws the band).
9
+ export type BandView = {
10
+ id: string
11
+ title: string
12
+ goal: string
13
+ // null until the stories have been read whole once: no progress row.
14
+ counts: BandCounts | null
15
+ why: 'this' | 'pinned'
16
+ story: { title: string; status: string | null } | null
17
+ version: string | null
18
+ hint: boolean
19
+ words: Record<string, string>
20
+ }
21
+
22
+ export type BandAgentStatus = 'running' | 'done' | 'error'
23
+
24
+ // A ProjectStore agent this session spawned: its role, the model and effort
25
+ // its own requests name, and the vault document its prompt names.
26
+ export type BandAgent = {
27
+ id: string
28
+ role: string
29
+ model: string
30
+ effort: string | null
31
+ subject: string | null
32
+ description: string
33
+ status: BandAgentStatus
34
+ startedAt: number
35
+ endedAt?: number
36
+ }
37
+
38
+ declare module 'claude-code' {
39
+ interface PluginState {
40
+ // `steps` is apart from `crew` on purpose: only the terminal's band reads
41
+ // it, so an agent's every step never redraws Desktop's drawing.
42
+ projectstore: { band: BandView | null; crew: BandAgent[]; steps: Record<string, string> }
43
+ }
44
+ }