projectstore-codex 0.0.1 → 0.28.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/.codex-plugin/plugin.json +48 -0
- package/README.md +15 -7
- package/bin/projectstore-codex.mjs +88 -0
- package/hooks/hooks.json +59 -0
- package/node_modules/projectstore/.claude-plugin/marketplace.json +40 -0
- package/node_modules/projectstore/.claude-plugin/plugin.json +23 -0
- package/node_modules/projectstore/.mcp.json +14 -0
- package/node_modules/projectstore/AGENTS.md +26 -0
- package/node_modules/projectstore/LICENSE +21 -0
- package/node_modules/projectstore/README.md +284 -0
- package/node_modules/projectstore/agents/archaeologist.md +76 -0
- package/node_modules/projectstore/agents/clerk.md +93 -0
- package/node_modules/projectstore/agents/critic.md +94 -0
- package/node_modules/projectstore/agents/librarian.md +81 -0
- package/node_modules/projectstore/agents/planner.md +80 -0
- package/node_modules/projectstore/agents/reviewer.md +98 -0
- package/node_modules/projectstore/bin/projectstore.mjs +7 -0
- package/node_modules/projectstore/commands/adr.md +57 -0
- package/node_modules/projectstore/commands/agents.md +180 -0
- package/node_modules/projectstore/commands/bind.md +128 -0
- package/node_modules/projectstore/commands/codemap.md +50 -0
- package/node_modules/projectstore/commands/concept.md +17 -0
- package/node_modules/projectstore/commands/doctor.md +166 -0
- package/node_modules/projectstore/commands/epic.md +40 -0
- package/node_modules/projectstore/commands/graph.md +56 -0
- package/node_modules/projectstore/commands/kanban.md +40 -0
- package/node_modules/projectstore/commands/meeting.md +17 -0
- package/node_modules/projectstore/commands/reconcile.md +73 -0
- package/node_modules/projectstore/commands/research.md +17 -0
- package/node_modules/projectstore/commands/review.md +89 -0
- package/node_modules/projectstore/commands/runbook.md +17 -0
- package/node_modules/projectstore/commands/scaffold.md +23 -0
- package/node_modules/projectstore/commands/search.md +22 -0
- package/node_modules/projectstore/commands/spec.md +91 -0
- package/node_modules/projectstore/commands/status.md +27 -0
- package/node_modules/projectstore/commands/statusline.md +46 -0
- package/node_modules/projectstore/commands/story.md +113 -0
- package/node_modules/projectstore/docs/extending.md +172 -0
- package/node_modules/projectstore/docs/getting-started.md +133 -0
- package/node_modules/projectstore/docs/harnesses.md +163 -0
- package/node_modules/projectstore/docs/how-it-works.md +263 -0
- package/node_modules/projectstore/docs/images/loop-light.svg +94 -0
- package/node_modules/projectstore/docs/images/loop.svg +93 -0
- package/node_modules/projectstore/docs/images/statusline-hud.png +0 -0
- package/node_modules/projectstore/docs/images/team-light.svg +79 -0
- package/node_modules/projectstore/docs/images/team.svg +79 -0
- package/node_modules/projectstore/harnesses/claude-code.json +483 -0
- package/node_modules/projectstore/harnesses/codex.json +332 -0
- package/node_modules/projectstore/hooks/hooks.json +59 -0
- package/node_modules/projectstore/hooks/pre-compact.mjs +121 -0
- package/node_modules/projectstore/hooks/session-rules.mjs +63 -0
- package/node_modules/projectstore/hooks/session-start.mjs +301 -0
- package/node_modules/projectstore/hooks/session-stop.mjs +84 -0
- package/node_modules/projectstore/package.json +70 -0
- package/node_modules/projectstore/scaffold/checklists.json +88 -0
- package/node_modules/projectstore/scaffold/headings.json +171 -0
- package/node_modules/projectstore/scaffold/layouts/engineering.json +85 -0
- package/node_modules/projectstore/scripts/binding.mjs +165 -0
- package/node_modules/projectstore/scripts/build-adapters.mjs +264 -0
- package/node_modules/projectstore/scripts/cli.mjs +595 -0
- package/node_modules/projectstore/scripts/codemap.mjs +99 -0
- package/node_modules/projectstore/scripts/diff-refs.mjs +127 -0
- package/node_modules/projectstore/scripts/doctor.mjs +2127 -0
- package/node_modules/projectstore/scripts/draft.mjs +261 -0
- package/node_modules/projectstore/scripts/graph.mjs +219 -0
- package/node_modules/projectstore/scripts/harness.mjs +608 -0
- package/node_modules/projectstore/scripts/install-harness.mjs +1387 -0
- package/node_modules/projectstore/scripts/kanban.mjs +174 -0
- package/node_modules/projectstore/scripts/lib.mjs +3085 -0
- package/node_modules/projectstore/scripts/mcp.mjs +391 -0
- package/node_modules/projectstore/scripts/portable-registration.mjs +198 -0
- package/node_modules/projectstore/scripts/provenance.mjs +375 -0
- package/node_modules/projectstore/scripts/query.mjs +490 -0
- package/node_modules/projectstore/scripts/reconcile.mjs +422 -0
- package/node_modules/projectstore/scripts/statusline-launcher.mjs +141 -0
- package/node_modules/projectstore/scripts/statusline.mjs +253 -0
- package/node_modules/projectstore/scripts/story-section.mjs +209 -0
- package/node_modules/projectstore/scripts/surfaces.mjs +421 -0
- package/node_modules/projectstore/scripts/tokens.mjs +449 -0
- package/node_modules/projectstore/scripts/touch-session.mjs +336 -0
- package/node_modules/projectstore/scripts/version-guard.mjs +255 -0
- package/node_modules/projectstore/scripts/worktree.mjs +109 -0
- package/node_modules/projectstore/skills/projectstore-decision-detector/SKILL.md +40 -0
- package/node_modules/projectstore/skills/projectstore-peer-reviewer/SKILL.md +38 -0
- package/node_modules/projectstore/skills/projectstore-story-completion/SKILL.md +50 -0
- package/node_modules/projectstore/skills/projectstore-vault-communication/SKILL.md +96 -0
- package/node_modules/projectstore/templates/claude-md-block.md.tmpl +26 -0
- package/node_modules/projectstore/templates/de/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/de/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/de/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/de/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/de/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/de/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/de/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/de/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/de/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/de/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/de/strings.json +6 -0
- package/node_modules/projectstore/templates/en/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/en/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/en/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/en/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/en/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/en/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/en/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/en/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/en/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/en/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/en/strings.json +6 -0
- package/node_modules/projectstore/templates/es/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/es/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/es/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/es/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/es/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/es/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/es/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/es/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/es/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/es/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/es/strings.json +6 -0
- package/node_modules/projectstore/templates/fr/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/fr/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/fr/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/fr/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/fr/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/fr/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/fr/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/fr/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/fr/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/fr/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/fr/strings.json +6 -0
- package/node_modules/projectstore/templates/ru/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/ru/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/ru/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/ru/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/ru/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/ru/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/ru/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/ru/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/ru/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/ru/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/ru/strings.json +6 -0
- package/node_modules/projectstore/templates/zh/adr.md.tmpl +67 -0
- package/node_modules/projectstore/templates/zh/concept.md.tmpl +43 -0
- package/node_modules/projectstore/templates/zh/epic.md.tmpl +59 -0
- package/node_modules/projectstore/templates/zh/folder-readme.md.tmpl +14 -0
- package/node_modules/projectstore/templates/zh/kanban.md.tmpl +36 -0
- package/node_modules/projectstore/templates/zh/meeting.md.tmpl +38 -0
- package/node_modules/projectstore/templates/zh/research.md.tmpl +47 -0
- package/node_modules/projectstore/templates/zh/runbook.md.tmpl +53 -0
- package/node_modules/projectstore/templates/zh/spec.md.tmpl +64 -0
- package/node_modules/projectstore/templates/zh/story.md.tmpl +76 -0
- package/node_modules/projectstore/templates/zh/strings.json +6 -0
- package/package.json +36 -14
- package/plugin.json +53 -0
- package/skills/projectstore-adr/SKILL.md +76 -0
- package/skills/projectstore-agents/SKILL.md +50 -0
- package/skills/projectstore-archaeologist/SKILL.md +109 -0
- package/skills/projectstore-bind/SKILL.md +44 -0
- package/skills/projectstore-clerk/SKILL.md +126 -0
- package/skills/projectstore-codemap/SKILL.md +69 -0
- package/skills/projectstore-concept/SKILL.md +36 -0
- package/skills/projectstore-critic/SKILL.md +127 -0
- package/skills/projectstore-decision-detector/SKILL.md +59 -0
- package/skills/projectstore-doctor/SKILL.md +33 -0
- package/skills/projectstore-epic/SKILL.md +59 -0
- package/skills/projectstore-graph/SKILL.md +75 -0
- package/skills/projectstore-kanban/SKILL.md +60 -0
- package/skills/projectstore-librarian/SKILL.md +114 -0
- package/skills/projectstore-meeting/SKILL.md +36 -0
- package/skills/projectstore-peer-reviewer/SKILL.md +57 -0
- package/skills/projectstore-planner/SKILL.md +113 -0
- package/skills/projectstore-reconcile/SKILL.md +92 -0
- package/skills/projectstore-research/SKILL.md +36 -0
- package/skills/projectstore-review/SKILL.md +108 -0
- package/skills/projectstore-reviewer/SKILL.md +131 -0
- package/skills/projectstore-runbook/SKILL.md +36 -0
- package/skills/projectstore-scaffold/SKILL.md +42 -0
- package/skills/projectstore-search/SKILL.md +41 -0
- package/skills/projectstore-spec/SKILL.md +110 -0
- package/skills/projectstore-status/SKILL.md +47 -0
- package/skills/projectstore-statusline/SKILL.md +29 -0
- package/skills/projectstore-story/SKILL.md +132 -0
- package/skills/projectstore-story-completion/SKILL.md +69 -0
- package/skills/projectstore-vault-communication/SKILL.md +115 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# How projectstore works under the hood
|
|
2
|
+
|
|
3
|
+
The README gives the short version; this is the deep dive for the curious. Nothing
|
|
4
|
+
here is required reading to use the plugin.
|
|
5
|
+
|
|
6
|
+
## The write path: draft → approval → file
|
|
7
|
+
|
|
8
|
+
Every create command follows the same shape:
|
|
9
|
+
|
|
10
|
+
1. `scripts/draft.mjs` renders the artifact **in memory** (it never touches the
|
|
11
|
+
disk — no writes, no mkdir; declining leaves the vault byte-for-byte unchanged).
|
|
12
|
+
2. The command shows you the target path + full content via `AskUserQuestion`.
|
|
13
|
+
3. Only on **Yes** does the file land — and that same Yes covers the folder's
|
|
14
|
+
index. The index row is not appended: the command regenerates the folder's
|
|
15
|
+
managed table through the core (`reconcile --write --only indexes=<folder>`),
|
|
16
|
+
so the row arrives in canonical order, the file is replaced atomically, and
|
|
17
|
+
your own prose around the table is preserved. One consequence worth knowing:
|
|
18
|
+
the regeneration rewrites the whole table, so creating one artifact can also
|
|
19
|
+
repair a stale row for another.
|
|
20
|
+
|
|
21
|
+
**Who holds the pen.** Content and the gate never delegate: the session's main
|
|
22
|
+
agent composes the artifact (it holds the conversation the artifact captures)
|
|
23
|
+
and answers to you at the approval gate. What *can* delegate is everything after
|
|
24
|
+
"yes" — for the long ceremonies (a story close, a multi-target reconcile) the
|
|
25
|
+
command hands execution to the `clerk` agent, which copies the approved content
|
|
26
|
+
from a scratch file (never re-emitting it through a model — fidelity mechanical,
|
|
27
|
+
proven per write by a byte-level diff), runs reconcile and doctor, and returns a one-line report instead
|
|
28
|
+
of pages of tool output. The clerk composes nothing, decides nothing, and asks
|
|
29
|
+
nothing; the advisors (critic, planner, reviewer, librarian, archaeologist)
|
|
30
|
+
stay read-only.
|
|
31
|
+
|
|
32
|
+
Frontmatter scalars are rendered through a JSON-escaping form (`{{title_json}}`),
|
|
33
|
+
so titles containing `"` or `:` cannot corrupt the YAML. Slugs transliterate
|
|
34
|
+
Cyrillic (`Кэширование запросов` → `keshirovanie-zaprosov`) and never come out
|
|
35
|
+
empty.
|
|
36
|
+
|
|
37
|
+
## Sessions: how parallel Claude instances coexist
|
|
38
|
+
|
|
39
|
+
Each Claude Code session registers itself in the vault under its own
|
|
40
|
+
`session_id`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
$ ls <vault>/.projectstore/sessions/
|
|
44
|
+
d9149e0d-9169-43ef-b2c6-3e005a00e133.json # session A — plugin dev
|
|
45
|
+
f05e61c5-f809-46e1-aa3e-b7c3366bc723.json # session B — feature work
|
|
46
|
+
|
|
47
|
+
$ cat <vault>/.projectstore/sessions/f05e61c5….json
|
|
48
|
+
{
|
|
49
|
+
"id": "f05e61c5-f809-46e1-aa3e-b7c3366bc723",
|
|
50
|
+
"project_root": "/Users/me/projects/myapp",
|
|
51
|
+
"started_at": "2026-05-19T13:35:36Z",
|
|
52
|
+
"recent_activity": [
|
|
53
|
+
{ "path": "epics/WEB-101/epic.md", "tool": "Edit", "at": "…" },
|
|
54
|
+
{ "path": "epics/WEB-101/stories/001-oidc-flow.md", "tool": "Write", "at": "…" }
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
When another session starts, SessionStart sees fresh sibling files (mtime < 30
|
|
60
|
+
min) and warns the new agent:
|
|
61
|
+
|
|
62
|
+
> ⚠️ Multi-session warning — 1 other projectstore session active on this vault.
|
|
63
|
+
> Run `/projectstore:search <topic>` before creating new artifacts.
|
|
64
|
+
|
|
65
|
+
Create commands additionally re-check file existence right before writing, so two
|
|
66
|
+
sessions can't silently overwrite each other's new artifact.
|
|
67
|
+
|
|
68
|
+
**The status line is stricter still**: it renders from a *per-session* pointer
|
|
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;
|
|
72
|
+
a fresh session gets a localized "no epic or story in this session yet" line; a
|
|
73
|
+
corrupt pointer shows an error marker, never a false "no work". The renderer also
|
|
74
|
+
drops a `.last-render.json` breadcrumb so `doctor` can detect session-id
|
|
75
|
+
divergence between the status line process and the hooks.
|
|
76
|
+
|
|
77
|
+
## Surviving `/compact`
|
|
78
|
+
|
|
79
|
+
Continuity across a compaction is delivered by **SessionStart**, not by
|
|
80
|
+
PreCompact — and that is a correction, not a design flourish. PreCompact has no
|
|
81
|
+
model-facing channel: it accepts a top-level `systemMessage` and nothing else,
|
|
82
|
+
so for its whole life the hook assembled a rich packet, printed a red *"Hook
|
|
83
|
+
JSON output validation failed"*, and reached nobody. Worse, the invalid field
|
|
84
|
+
sank the whole object, so the one line PreCompact *does* support never landed
|
|
85
|
+
either.
|
|
86
|
+
|
|
87
|
+
So the two hooks now split the work by what each can actually do.
|
|
88
|
+
|
|
89
|
+
PreCompact prints one line, for you:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
PreCompact [...pre-compact.mjs] completed successfully: {
|
|
93
|
+
"systemMessage": "projectstore: compacting — vault myapp-vault,
|
|
94
|
+
in flight: `epics/WEB-101/epic.md`,
|
|
95
|
+
orientation and this session's recent files return
|
|
96
|
+
at session start"
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
That last clause is conditional on purpose. It appears only when the compaction
|
|
101
|
+
is **manual** and `auto_inject` is on — the two things the hook can check at the
|
|
102
|
+
moment it speaks. On an automatic compaction the plugin makes no claim that
|
|
103
|
+
SessionStart fires at all, and under `auto_inject: false` the claim would be
|
|
104
|
+
flatly false, so the line offers `/projectstore:status` instead. The
|
|
105
|
+
recent-files half needs one more condition — a nonempty activity log — because
|
|
106
|
+
an empty one renders no continuity section at all.
|
|
107
|
+
|
|
108
|
+
SessionStart then fires with `source: "compact"` and renders a **Where this
|
|
109
|
+
session left off** block above the derived-views section: up to five vault files
|
|
110
|
+
the previous conversation touched, newest first, plus the newest structured
|
|
111
|
+
write as the in-flight artifact. Both hooks resolve that artifact through one
|
|
112
|
+
shared function, so the compaction line and the section that follows cannot name
|
|
113
|
+
different files seconds apart.
|
|
114
|
+
|
|
115
|
+
(Fine-grained "where exactly was my cursor" resume is the job of your task list
|
|
116
|
+
and `git status`; the vault answers "where were we going".)
|
|
117
|
+
|
|
118
|
+
## The status line composition trick
|
|
119
|
+
|
|
120
|
+
`statusLine` in Claude Code is a single slot, not plugin-declarable, and read
|
|
121
|
+
once when the session starts. So `/projectstore:statusline on` runs the
|
|
122
|
+
install verb, which points the project's `.claude/settings.local.json` at a
|
|
123
|
+
launcher it writes (provenance-stamped) at `.projectstore/state/claude-code/statusline.mjs`;
|
|
124
|
+
the SessionStart hook keeps an existing entry current across updates and
|
|
125
|
+
never creates one. Pointing
|
|
126
|
+
it straight at the plugin would pin a versioned cache path
|
|
127
|
+
(`…/projectstore/<version>/scripts/statusline.mjs`) and render the version
|
|
128
|
+
installed at the *previous* session start — every update arrived a restart late.
|
|
129
|
+
The launcher's path never changes, and it resolves the installed plugin from
|
|
130
|
+
Claude Code's own registry on each render. The script then **composes** instead of
|
|
131
|
+
clobbering: it re-runs whatever base statusLine command you already had (e.g.
|
|
132
|
+
oh-my-claudecode's HUD, taken from the project's `.claude/settings.json` if it
|
|
133
|
+
has one, else `~/.claude/settings.json`), prints its output
|
|
134
|
+
verbatim, and adds one `[PS#version] 📚 …` line above it (`statusline.position`:
|
|
135
|
+
`above`/`below`). With no base command it renders a standalone line.
|
|
136
|
+
|
|
137
|
+
## Doctor and reconcile: the trust layer
|
|
138
|
+
|
|
139
|
+
The vault's guarantees used to depend on everyone using the gated commands —
|
|
140
|
+
but agents (and humans) hand-edit markdown, because it's the path of least
|
|
141
|
+
resistance. v0.13 makes that safe instead of forbidden:
|
|
142
|
+
|
|
143
|
+
- **`doctor`** is a deterministic, no-LLM check engine (`scripts/doctor.mjs`).
|
|
144
|
+
`--install` verifies the wiring (config, vault path, hooks firing, statusline,
|
|
145
|
+
agents block, leftover agent copies, gitignore, marketplace auto-update);
|
|
146
|
+
`--vault` verifies content consistency (status ↔ board ↔ indexes, acceptance
|
|
147
|
+
boxes, dead and ambiguous wiki/relative links — resolved by the same shared
|
|
148
|
+
resolver the link graph uses, so the two can never disagree about a body
|
|
149
|
+
link — `code_refs`,
|
|
150
|
+
code-map and graph staleness). A cheap
|
|
151
|
+
subset runs at session start and prints one line only when something is wrong.
|
|
152
|
+
- **`reconcile`** rebuilds every generated view (kanban, folder indexes,
|
|
153
|
+
code-map, the link graph) from the vault — the repair partner. Idempotent: a clean vault
|
|
154
|
+
yields zero changes. Since v0.19 reconcile applies the write itself
|
|
155
|
+
(`--write`): each approved target is recomputed from the vault state at
|
|
156
|
+
write time and replaced atomically, so a stale preview is never what lands;
|
|
157
|
+
`--write` is also a sanctioned headless entry point (cron/CI repair job).
|
|
158
|
+
- A throttled PreToolUse **nudge** fires when vault files are edited directly:
|
|
159
|
+
"run reconcile afterwards so the derived views stay in sync" (disable with
|
|
160
|
+
`"guard": "off"` in `projectstore.json`).
|
|
161
|
+
- A once-per-session **entry reminder** fires on PostToolUse when a session has
|
|
162
|
+
written to three or more distinct *source* files and no story is `in-progress`:
|
|
163
|
+
"open it in the vault before going further". PostToolUse, not PreToolUse, so
|
|
164
|
+
declined edits are not counted as work that happened; `Stop` is the fallback
|
|
165
|
+
carrier for a session that delegates all its writing to subagents and then
|
|
166
|
+
answers without a tool call of its own. Subagent writes count toward the score
|
|
167
|
+
but never receive the reminder — a subagent cannot open a story. A session
|
|
168
|
+
launched with `--agent` carries an agent identity on every call and is
|
|
169
|
+
therefore never reminded either; for those sessions `doctor`'s
|
|
170
|
+
`work-without-story` is the only coverage. The same
|
|
171
|
+
`"guard": "off"` silences it, and silences both nudges together. Firings are
|
|
172
|
+
appended to `.projectstore/state/entry-log.jsonl` (machine-local, since
|
|
173
|
+
`.claude/` is gitignored) so `doctor` can report whether the prompt was ever
|
|
174
|
+
delivered — a mechanism that cannot say whether it worked is indistinguishable
|
|
175
|
+
from one that does not.
|
|
176
|
+
- A **session-name offer** fires on PreToolUse once a session's vault work has
|
|
177
|
+
settled on an anchor — see below. Same `"guard": "off"` switch, same log, and
|
|
178
|
+
its records carry `kind: "name-offer"` so `doctor`'s reminder count does not
|
|
179
|
+
quietly absorb them.
|
|
180
|
+
- `doctor` carries the after-the-fact half: **work-without-story** warns when the
|
|
181
|
+
project tree is dirty and no story is in progress. It is the only seam that
|
|
182
|
+
sees Bash-mediated writes, which bypass hook path extraction entirely.
|
|
183
|
+
|
|
184
|
+
The division of labor: deterministic checks catch the mechanical 90% for free;
|
|
185
|
+
the LLM critic (`/projectstore:review`) is saved for the judgment calls.
|
|
186
|
+
|
|
187
|
+
## Naming a session after the work it settled on
|
|
188
|
+
|
|
189
|
+
A Claude Code session has a name, and it is an **address**: live peers route to
|
|
190
|
+
each other by it, which is why names are arbitrated for uniqueness across a
|
|
191
|
+
machine. So a session named after its work is addressable by unit of work.
|
|
192
|
+
|
|
193
|
+
No plugin can set that name. The authoritative value lives in the session
|
|
194
|
+
process's memory behind no reachable API — writing the registry file or the
|
|
195
|
+
transcript record reaches neither the tab nor the arbitration, and only
|
|
196
|
+
desynchronises the three surfaces from each other. What a plugin can do is
|
|
197
|
+
compose the right name and **offer** it:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
projectstore: this session looks like "ps-agents-statusline-v2" — /rename ps-agents-statusline-v2
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The whole design question is **when to speak**, because an offer is an
|
|
204
|
+
interruption. Replaying nine recorded sessions, the obvious rule — offer on every
|
|
205
|
+
epic/story change — fires **137 times, 37 in the worst session**. Work moves
|
|
206
|
+
between a story, its epic and a sibling many times an hour; that motion is not a
|
|
207
|
+
change of subject.
|
|
208
|
+
|
|
209
|
+
What is stable is the **anchor**: the cluster a session's writes settle on. Seven
|
|
210
|
+
of nine sessions had a dominant epic holding 62–100% of their epic writes. So:
|
|
211
|
+
|
|
212
|
+
- every vault write maps to one anchor key — `epic:<ID>` for anything under an
|
|
213
|
+
epic, or the document itself for an ADR, spec or research note (two of the nine
|
|
214
|
+
sessions touched no epic at all, and an epic-only rule leaves those permanently
|
|
215
|
+
nameless);
|
|
216
|
+
- an anchor **settles** at five writes and is offered;
|
|
217
|
+
- a challenger takes over — and is offered — only at a **ten-write lead**;
|
|
218
|
+
- the name is `<epic-id>-<its most-written story>`, or the document's slug;
|
|
219
|
+
kebab-case, 48 characters, cut on a word boundary.
|
|
220
|
+
|
|
221
|
+
That is **12 offers across nine sessions, at most two in any one**, and six
|
|
222
|
+
sessions naming themselves exactly once. Re-offering is deliberate: in three
|
|
223
|
+
sessions the anchor moved, and the shape is a session that decides in a document
|
|
224
|
+
and then builds in an epic — a name that does not follow that is a name for the
|
|
225
|
+
first hour only.
|
|
226
|
+
|
|
227
|
+
Only **write-family calls by the main agent** count. A review session that greps
|
|
228
|
+
thirty files has not done work worth naming, and a subagent shares the session id
|
|
229
|
+
but cannot accept a name. Neither gate is visible in the fixtures — every
|
|
230
|
+
recorded session is an authoring session — so both are pinned by their own drives
|
|
231
|
+
instead.
|
|
232
|
+
|
|
233
|
+
If a live peer already holds the name it is offered as `-2`, then `-3`; a third
|
|
234
|
+
collision means the name is not discriminating and nothing is said. And a name
|
|
235
|
+
you chose yourself is never overwritten — but note that a session usually
|
|
236
|
+
*arrives* with a harness-assigned name, so "not the name we offered" is not
|
|
237
|
+
enough to infer choice: the plugin treats a name as yours only after it has made
|
|
238
|
+
at least one offer of its own.
|
|
239
|
+
|
|
240
|
+
**The known blind spot**: vault writes made through Bash never reach this seam,
|
|
241
|
+
because the input is tool-call path extraction. The consequence that matters is
|
|
242
|
+
not a missing name but a **wrong** one — if the bulk of a session's work went
|
|
243
|
+
through scripts, the anchor is computed from the visible minority. And the gap is
|
|
244
|
+
correlated with plugin-idiomatic behaviour: the more work goes through
|
|
245
|
+
`/projectstore:*` and `reconcile`, the less nameable the session becomes.
|
|
246
|
+
|
|
247
|
+
The rule is a pure fold in `lib.mjs` with no clock and no disk, so the fixture
|
|
248
|
+
replay and the live hook run one implementation. Its tallies are files that grow
|
|
249
|
+
by one byte — the count is the file size — because the shared session-state file
|
|
250
|
+
is an unguarded read-modify-write, and a tally incremented on every vault write
|
|
251
|
+
would eventually truncate the ADR-006 statusline pointer out from under an
|
|
252
|
+
unrelated feature.
|
|
253
|
+
|
|
254
|
+
## The epic ↔ code mapping
|
|
255
|
+
|
|
256
|
+
Epics and stories carry a `code_refs` frontmatter list — the paths that feature
|
|
257
|
+
actually owns in the codebase (`["src/auth/", "adapters/csv/"]`). The
|
|
258
|
+
`/projectstore:codemap` command is the only writer (`codemap set`), the
|
|
259
|
+
`planner` agent reads them to keep new epics consistent with how old ones
|
|
260
|
+
landed, the `reviewer` proposes updates when a story completes, and
|
|
261
|
+
`code-map.md` is the generated overview. Doctor checks refs status-aware:
|
|
262
|
+
`planned` work may point at code that doesn't exist yet; `in-progress`/`done`
|
|
263
|
+
refs must resolve.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<svg width="960" height="470" viewBox="0 0 960 470" fill="none" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="lab" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
4
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#6B84AD"/>
|
|
5
|
+
</marker>
|
|
6
|
+
<marker id="lar" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
7
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#E11D48"/>
|
|
8
|
+
</marker>
|
|
9
|
+
<marker id="lag" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
10
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#059669"/>
|
|
11
|
+
</marker>
|
|
12
|
+
</defs>
|
|
13
|
+
|
|
14
|
+
<rect width="960" height="470" rx="18" fill="#FFFFFF"/>
|
|
15
|
+
<rect x="1" y="1" width="958" height="468" rx="17" stroke="#E2E8F0"/>
|
|
16
|
+
|
|
17
|
+
<text x="44" y="48" fill="#94A3B8" font-size="11" letter-spacing="3">DECIDE</text>
|
|
18
|
+
<text x="104" y="218" fill="#94A3B8" font-size="11" letter-spacing="3">BUILD</text>
|
|
19
|
+
|
|
20
|
+
<!-- ── lane 1: decide ─────────────────────────────────────────── -->
|
|
21
|
+
<rect x="44" y="70" width="104" height="64" rx="11" fill="#F1F5F9" stroke="#CBD5E1"/>
|
|
22
|
+
<text x="96" y="97" fill="#0F172A" font-size="15" font-weight="600" text-anchor="middle">Task</text>
|
|
23
|
+
<text x="96" y="117" fill="#64748B" font-size="11" text-anchor="middle">from you</text>
|
|
24
|
+
|
|
25
|
+
<path d="M152 102 L188 102" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
26
|
+
|
|
27
|
+
<rect x="192" y="70" width="232" height="64" rx="11" fill="#F1F5F9" stroke="#CBD5E1"/>
|
|
28
|
+
<text x="308" y="97" fill="#0F172A" font-size="15" font-weight="600" text-anchor="middle">ADR · Spec · Epic · Story</text>
|
|
29
|
+
<text x="308" y="117" fill="#64748B" font-size="11" text-anchor="middle">the why, on disk</text>
|
|
30
|
+
|
|
31
|
+
<path d="M428 102 L462 102" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
32
|
+
|
|
33
|
+
<rect x="492" y="44" width="64" height="18" rx="9" fill="#E11D48" fill-opacity="0.10"/>
|
|
34
|
+
<text x="524" y="57" fill="#E11D48" font-size="10" letter-spacing="1.5" text-anchor="middle">VERIFY</text>
|
|
35
|
+
<rect x="466" y="70" width="152" height="64" rx="11" fill="#FFF1F2" stroke="#E11D48"/>
|
|
36
|
+
<text x="542" y="97" fill="#BE123C" font-size="15" font-weight="600" text-anchor="middle">critic</text>
|
|
37
|
+
<text x="542" y="117" fill="#B25B70" font-size="11" text-anchor="middle">fresh context, adversarial</text>
|
|
38
|
+
|
|
39
|
+
<path d="M486 68 C 462 40, 442 40, 416 66" stroke="#E11D48" stroke-width="1.4" stroke-dasharray="4 4" marker-end="url(#lar)"/>
|
|
40
|
+
<text x="446" y="34" fill="#E11D48" font-size="11" text-anchor="middle">revise</text>
|
|
41
|
+
|
|
42
|
+
<path d="M622 102 L656 102" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
43
|
+
|
|
44
|
+
<rect x="660" y="70" width="150" height="64" rx="11" fill="#F1F5F9" stroke="#CBD5E1"/>
|
|
45
|
+
<text x="735" y="97" fill="#0F172A" font-size="15" font-weight="600" text-anchor="middle">Backlog</text>
|
|
46
|
+
<text x="735" y="117" fill="#64748B" font-size="11" text-anchor="middle">kanban.md — ready</text>
|
|
47
|
+
|
|
48
|
+
<!-- hand-off to the build lane (lane 2 sits 60px right: a gantt cascade,
|
|
49
|
+
and the return arrow below gets a clear left margin) -->
|
|
50
|
+
<path d="M735 138 C 735 192, 210 168, 164 234" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
51
|
+
<text x="470" y="163" fill="#64748B" font-size="12" text-anchor="middle">an agent picks it up</text>
|
|
52
|
+
|
|
53
|
+
<!-- ── lane 2: build ──────────────────────────────────────────── -->
|
|
54
|
+
<rect x="104" y="240" width="116" height="64" rx="11" fill="#F1F5F9" stroke="#CBD5E1"/>
|
|
55
|
+
<text x="162" y="267" fill="#0F172A" font-size="15" font-weight="600" text-anchor="middle">Story</text>
|
|
56
|
+
<text x="162" y="287" fill="#64748B" font-size="11" text-anchor="middle">in-progress</text>
|
|
57
|
+
|
|
58
|
+
<path d="M224 272 L258 272" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
59
|
+
|
|
60
|
+
<rect x="262" y="240" width="136" height="64" rx="11" fill="#F5F3FF" stroke="#7C3AED"/>
|
|
61
|
+
<text x="330" y="267" fill="#6D28D9" font-size="15" font-weight="600" text-anchor="middle">planner</text>
|
|
62
|
+
<text x="330" y="287" fill="#8B7BB5" font-size="11" text-anchor="middle">where in the code</text>
|
|
63
|
+
|
|
64
|
+
<path d="M402 272 L436 272" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
65
|
+
|
|
66
|
+
<rect x="440" y="240" width="140" height="64" rx="11" fill="#F1F5F9" stroke="#CBD5E1"/>
|
|
67
|
+
<text x="510" y="267" fill="#0F172A" font-size="15" font-weight="600" text-anchor="middle">Implement</text>
|
|
68
|
+
<text x="510" y="287" fill="#64748B" font-size="11" text-anchor="middle">code + tests</text>
|
|
69
|
+
|
|
70
|
+
<path d="M584 272 L618 272" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
71
|
+
|
|
72
|
+
<rect x="668" y="214" width="64" height="18" rx="9" fill="#E11D48" fill-opacity="0.10"/>
|
|
73
|
+
<text x="700" y="227" fill="#E11D48" font-size="10" letter-spacing="1.5" text-anchor="middle">VERIFY</text>
|
|
74
|
+
<rect x="622" y="240" width="156" height="64" rx="11" fill="#FFF1F2" stroke="#E11D48"/>
|
|
75
|
+
<text x="700" y="267" fill="#BE123C" font-size="15" font-weight="600" text-anchor="middle">reviewer</text>
|
|
76
|
+
<text x="700" y="287" fill="#B25B70" font-size="11" text-anchor="middle">evidence per criterion</text>
|
|
77
|
+
|
|
78
|
+
<path d="M638 238 C 616 212, 600 212, 576 236" stroke="#E11D48" stroke-width="1.4" stroke-dasharray="4 4" marker-end="url(#lar)"/>
|
|
79
|
+
<text x="606" y="206" fill="#E11D48" font-size="11" text-anchor="middle">fix</text>
|
|
80
|
+
|
|
81
|
+
<path d="M782 272 L816 272" stroke="#059669" stroke-width="1.6" marker-end="url(#lag)"/>
|
|
82
|
+
|
|
83
|
+
<rect x="820" y="240" width="126" height="64" rx="11" fill="#ECFDF5" stroke="#059669"/>
|
|
84
|
+
<text x="883" y="267" fill="#047857" font-size="15" font-weight="600" text-anchor="middle">Done ✓</text>
|
|
85
|
+
<text x="883" y="287" fill="#5F9E86" font-size="11" text-anchor="middle">criteria met</text>
|
|
86
|
+
|
|
87
|
+
<!-- ── the feedback that closes the loop ──────────────────────── -->
|
|
88
|
+
<path d="M883 308 C 883 344, 856 364, 776 370" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
89
|
+
<rect x="250" y="352" width="520" height="36" rx="18" fill="#F1F5F9" stroke="#E2E8F0"/>
|
|
90
|
+
<text x="510" y="375" fill="#475569" font-size="12.5" text-anchor="middle">kanban · graph · code-map regenerate — the next session starts oriented</text>
|
|
91
|
+
<path d="M246 370 C 90 370, 48 290, 76 142" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#lab)"/>
|
|
92
|
+
|
|
93
|
+
<text x="480" y="444" fill="#94A3B8" font-size="12.5" text-anchor="middle">gather context → act → verify — the agentic loop, run over the project itself, not just the code</text>
|
|
94
|
+
</svg>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<svg width="960" height="470" viewBox="0 0 960 470" fill="none" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="ab" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
4
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#5B7BB4"/>
|
|
5
|
+
</marker>
|
|
6
|
+
<marker id="ar" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
7
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#F43F5E"/>
|
|
8
|
+
</marker>
|
|
9
|
+
<marker id="ag" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
10
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#10B981"/>
|
|
11
|
+
</marker>
|
|
12
|
+
</defs>
|
|
13
|
+
|
|
14
|
+
<rect width="960" height="470" rx="18" fill="#0C1322"/>
|
|
15
|
+
<rect x="1" y="1" width="958" height="468" rx="17" stroke="#1E2A44"/>
|
|
16
|
+
|
|
17
|
+
<text x="44" y="48" fill="#64748B" font-size="11" letter-spacing="3">DECIDE</text>
|
|
18
|
+
<text x="104" y="218" fill="#64748B" font-size="11" letter-spacing="3">BUILD</text>
|
|
19
|
+
|
|
20
|
+
<!-- ── lane 1: decide ─────────────────────────────────────────── -->
|
|
21
|
+
<rect x="44" y="70" width="104" height="64" rx="11" fill="#131F36" stroke="#2C3E5F"/>
|
|
22
|
+
<text x="96" y="97" fill="#E2E8F0" font-size="15" font-weight="600" text-anchor="middle">Task</text>
|
|
23
|
+
<text x="96" y="117" fill="#7C8DB0" font-size="11" text-anchor="middle">from you</text>
|
|
24
|
+
|
|
25
|
+
<path d="M152 102 L188 102" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
26
|
+
|
|
27
|
+
<rect x="192" y="70" width="232" height="64" rx="11" fill="#131F36" stroke="#2C3E5F"/>
|
|
28
|
+
<text x="308" y="97" fill="#E2E8F0" font-size="15" font-weight="600" text-anchor="middle">ADR · Spec · Epic · Story</text>
|
|
29
|
+
<text x="308" y="117" fill="#7C8DB0" font-size="11" text-anchor="middle">the why, on disk</text>
|
|
30
|
+
|
|
31
|
+
<path d="M428 102 L462 102" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
32
|
+
|
|
33
|
+
<rect x="492" y="44" width="64" height="18" rx="9" fill="#F43F5E" fill-opacity="0.14"/>
|
|
34
|
+
<text x="524" y="57" fill="#FB7185" font-size="10" letter-spacing="1.5" text-anchor="middle">VERIFY</text>
|
|
35
|
+
<rect x="466" y="70" width="152" height="64" rx="11" fill="#2A1220" stroke="#F43F5E"/>
|
|
36
|
+
<text x="542" y="97" fill="#FDA4AF" font-size="15" font-weight="600" text-anchor="middle">critic</text>
|
|
37
|
+
<text x="542" y="117" fill="#B07A8C" font-size="11" text-anchor="middle">fresh context, adversarial</text>
|
|
38
|
+
|
|
39
|
+
<path d="M486 68 C 462 40, 442 40, 416 66" stroke="#F43F5E" stroke-width="1.4" stroke-dasharray="4 4" marker-end="url(#ar)"/>
|
|
40
|
+
<text x="446" y="34" fill="#FB7185" font-size="11" text-anchor="middle">revise</text>
|
|
41
|
+
|
|
42
|
+
<path d="M622 102 L656 102" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
43
|
+
|
|
44
|
+
<rect x="660" y="70" width="150" height="64" rx="11" fill="#131F36" stroke="#2C3E5F"/>
|
|
45
|
+
<text x="735" y="97" fill="#E2E8F0" font-size="15" font-weight="600" text-anchor="middle">Backlog</text>
|
|
46
|
+
<text x="735" y="117" fill="#7C8DB0" font-size="11" text-anchor="middle">kanban.md — ready</text>
|
|
47
|
+
|
|
48
|
+
<!-- hand-off to the build lane -->
|
|
49
|
+
<path d="M735 138 C 735 192, 210 168, 164 234" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
50
|
+
<text x="470" y="163" fill="#7C8DB0" font-size="12" text-anchor="middle">an agent picks it up</text>
|
|
51
|
+
|
|
52
|
+
<!-- ── lane 2: build ──────────────────────────────────────────── -->
|
|
53
|
+
<rect x="104" y="240" width="116" height="64" rx="11" fill="#131F36" stroke="#2C3E5F"/>
|
|
54
|
+
<text x="162" y="267" fill="#E2E8F0" font-size="15" font-weight="600" text-anchor="middle">Story</text>
|
|
55
|
+
<text x="162" y="287" fill="#7C8DB0" font-size="11" text-anchor="middle">in-progress</text>
|
|
56
|
+
|
|
57
|
+
<path d="M224 272 L258 272" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
58
|
+
|
|
59
|
+
<rect x="262" y="240" width="136" height="64" rx="11" fill="#1D1733" stroke="#8B5CF6"/>
|
|
60
|
+
<text x="330" y="267" fill="#C4B5FD" font-size="15" font-weight="600" text-anchor="middle">planner</text>
|
|
61
|
+
<text x="330" y="287" fill="#9D8FC7" font-size="11" text-anchor="middle">where in the code</text>
|
|
62
|
+
|
|
63
|
+
<path d="M402 272 L436 272" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
64
|
+
|
|
65
|
+
<rect x="440" y="240" width="140" height="64" rx="11" fill="#131F36" stroke="#2C3E5F"/>
|
|
66
|
+
<text x="510" y="267" fill="#E2E8F0" font-size="15" font-weight="600" text-anchor="middle">Implement</text>
|
|
67
|
+
<text x="510" y="287" fill="#7C8DB0" font-size="11" text-anchor="middle">code + tests</text>
|
|
68
|
+
|
|
69
|
+
<path d="M584 272 L618 272" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
70
|
+
|
|
71
|
+
<rect x="668" y="214" width="64" height="18" rx="9" fill="#F43F5E" fill-opacity="0.14"/>
|
|
72
|
+
<text x="700" y="227" fill="#FB7185" font-size="10" letter-spacing="1.5" text-anchor="middle">VERIFY</text>
|
|
73
|
+
<rect x="622" y="240" width="156" height="64" rx="11" fill="#2A1220" stroke="#F43F5E"/>
|
|
74
|
+
<text x="700" y="267" fill="#FDA4AF" font-size="15" font-weight="600" text-anchor="middle">reviewer</text>
|
|
75
|
+
<text x="700" y="287" fill="#B07A8C" font-size="11" text-anchor="middle">evidence per criterion</text>
|
|
76
|
+
|
|
77
|
+
<path d="M638 238 C 616 212, 600 212, 576 236" stroke="#F43F5E" stroke-width="1.4" stroke-dasharray="4 4" marker-end="url(#ar)"/>
|
|
78
|
+
<text x="606" y="206" fill="#FB7185" font-size="11" text-anchor="middle">fix</text>
|
|
79
|
+
|
|
80
|
+
<path d="M782 272 L816 272" stroke="#10B981" stroke-width="1.6" marker-end="url(#ag)"/>
|
|
81
|
+
|
|
82
|
+
<rect x="820" y="240" width="126" height="64" rx="11" fill="#0C2A1E" stroke="#10B981"/>
|
|
83
|
+
<text x="883" y="267" fill="#6EE7B7" font-size="15" font-weight="600" text-anchor="middle">Done ✓</text>
|
|
84
|
+
<text x="883" y="287" fill="#79A893" font-size="11" text-anchor="middle">criteria met</text>
|
|
85
|
+
|
|
86
|
+
<!-- ── the feedback that closes the loop ──────────────────────── -->
|
|
87
|
+
<path d="M883 308 C 883 344, 856 364, 776 370" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
88
|
+
<rect x="250" y="352" width="520" height="36" rx="18" fill="#101B31" stroke="#24344F"/>
|
|
89
|
+
<text x="510" y="375" fill="#9FB0CE" font-size="12.5" text-anchor="middle">kanban · graph · code-map regenerate — the next session starts oriented</text>
|
|
90
|
+
<path d="M246 370 C 100 370, 56 292, 84 142" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#ab)"/>
|
|
91
|
+
|
|
92
|
+
<text x="480" y="444" fill="#5F6E8C" font-size="12.5" text-anchor="middle">gather context → act → verify — the agentic loop, run over the project itself, not just the code</text>
|
|
93
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<svg width="960" height="430" viewBox="0 0 960 430" fill="none" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="ltb" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
4
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#6B84AD"/>
|
|
5
|
+
</marker>
|
|
6
|
+
</defs>
|
|
7
|
+
|
|
8
|
+
<rect width="960" height="430" rx="18" fill="#FFFFFF"/>
|
|
9
|
+
<rect x="1" y="1" width="958" height="428" rx="17" stroke="#E2E8F0"/>
|
|
10
|
+
|
|
11
|
+
<!-- ── the people ─────────────────────────────────────────────── -->
|
|
12
|
+
<g>
|
|
13
|
+
<rect x="44" y="56" width="232" height="76" rx="12" fill="#F8FAFC" stroke="#E2E8F0"/>
|
|
14
|
+
<circle cx="78" cy="94" r="15" fill="#E2E8F0" stroke="#CBD5E1"/>
|
|
15
|
+
<circle cx="78" cy="90" r="4.5" fill="#64748B"/>
|
|
16
|
+
<path d="M71 103 a7 5.5 0 0 1 14 0" fill="#64748B"/>
|
|
17
|
+
<text x="106" y="89" fill="#0F172A" font-size="15" font-weight="600">Dev A</text>
|
|
18
|
+
<text x="106" y="109" fill="#64748B" font-size="11.5">Claude Code + projectstore</text>
|
|
19
|
+
</g>
|
|
20
|
+
<g>
|
|
21
|
+
<rect x="44" y="166" width="232" height="76" rx="12" fill="#F8FAFC" stroke="#E2E8F0"/>
|
|
22
|
+
<circle cx="78" cy="204" r="15" fill="#E2E8F0" stroke="#CBD5E1"/>
|
|
23
|
+
<circle cx="78" cy="200" r="4.5" fill="#64748B"/>
|
|
24
|
+
<path d="M71 213 a7 5.5 0 0 1 14 0" fill="#64748B"/>
|
|
25
|
+
<text x="106" y="199" fill="#0F172A" font-size="15" font-weight="600">Dev B</text>
|
|
26
|
+
<text x="106" y="219" fill="#64748B" font-size="11.5">Claude Code + projectstore</text>
|
|
27
|
+
</g>
|
|
28
|
+
<g>
|
|
29
|
+
<rect x="44" y="276" width="232" height="76" rx="12" fill="#F8FAFC" stroke="#E2E8F0"/>
|
|
30
|
+
<circle cx="78" cy="314" r="15" fill="#E2E8F0" stroke="#CBD5E1"/>
|
|
31
|
+
<circle cx="78" cy="310" r="4.5" fill="#64748B"/>
|
|
32
|
+
<path d="M71 323 a7 5.5 0 0 1 14 0" fill="#64748B"/>
|
|
33
|
+
<text x="106" y="309" fill="#0F172A" font-size="15" font-weight="600">Dev C</text>
|
|
34
|
+
<text x="106" y="329" fill="#64748B" font-size="11.5">reviews on GitHub or Obsidian</text>
|
|
35
|
+
</g>
|
|
36
|
+
|
|
37
|
+
<!-- bind arrows -->
|
|
38
|
+
<path d="M280 94 C 320 94, 330 106, 356 116" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#ltb)"/>
|
|
39
|
+
<path d="M280 204 L356 206" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#ltb)"/>
|
|
40
|
+
<path d="M280 314 C 320 314, 330 302, 356 294" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#ltb)"/>
|
|
41
|
+
<text x="308" y="196" fill="#64748B" font-size="10.5" text-anchor="middle">bind</text>
|
|
42
|
+
|
|
43
|
+
<!-- ── the vault ──────────────────────────────────────────────── -->
|
|
44
|
+
<rect x="360" y="52" width="252" height="310" rx="14" fill="#EFF6FF" stroke="#3B82F6"/>
|
|
45
|
+
<text x="486" y="86" fill="#1D4ED8" font-size="16" font-weight="600" text-anchor="middle">The vault</text>
|
|
46
|
+
<text x="486" y="106" fill="#64748B" font-size="11" text-anchor="middle">its own git repo · plain markdown</text>
|
|
47
|
+
<path d="M384 122 L588 122" stroke="#DBEAFE"/>
|
|
48
|
+
<text x="384" y="150" fill="#334155" font-size="12.5">adr/ — decisions, with dates</text>
|
|
49
|
+
<text x="384" y="177" fill="#334155" font-size="12.5">specs/ — the normative how</text>
|
|
50
|
+
<text x="384" y="204" fill="#334155" font-size="12.5">epics/ · stories/ — the backlog</text>
|
|
51
|
+
<text x="384" y="231" fill="#334155" font-size="12.5">kanban.md — the board</text>
|
|
52
|
+
<text x="384" y="258" fill="#334155" font-size="12.5">graph.md — every link, typed</text>
|
|
53
|
+
<text x="384" y="285" fill="#334155" font-size="12.5">code-map.md — epic ↔ code</text>
|
|
54
|
+
<text x="384" y="330" fill="#94A3B8" font-size="11">every write previewed and</text>
|
|
55
|
+
<text x="384" y="346" fill="#94A3B8" font-size="11">approved — by whoever binds</text>
|
|
56
|
+
|
|
57
|
+
<!-- ── the remote ─────────────────────────────────────────────── -->
|
|
58
|
+
<path d="M616 128 L696 128" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#ltb)"/>
|
|
59
|
+
<text x="656" y="118" fill="#64748B" font-size="10.5" text-anchor="middle">push</text>
|
|
60
|
+
<path d="M696 172 L616 172" stroke="#6B84AD" stroke-width="1.6" marker-end="url(#ltb)"/>
|
|
61
|
+
<text x="656" y="192" fill="#64748B" font-size="10.5" text-anchor="middle">review & pull</text>
|
|
62
|
+
|
|
63
|
+
<rect x="700" y="88" width="216" height="132" rx="12" fill="#F8FAFC" stroke="#CBD5E1"/>
|
|
64
|
+
<text x="808" y="118" fill="#0F172A" font-size="15" font-weight="600" text-anchor="middle">git remote</text>
|
|
65
|
+
<text x="808" y="144" fill="#64748B" font-size="11.5" text-anchor="middle">push / pull</text>
|
|
66
|
+
<text x="808" y="164" fill="#64748B" font-size="11.5" text-anchor="middle">ADRs & specs reviewed</text>
|
|
67
|
+
<text x="808" y="182" fill="#64748B" font-size="11.5" text-anchor="middle">as merge requests</text>
|
|
68
|
+
|
|
69
|
+
<text x="806" y="252" fill="#94A3B8" font-size="11.5" text-anchor="middle">the why gets reviewed,</text>
|
|
70
|
+
<text x="806" y="269" fill="#94A3B8" font-size="11.5" text-anchor="middle">not just the code</text>
|
|
71
|
+
|
|
72
|
+
<!-- ── the guarantees ─────────────────────────────────────────── -->
|
|
73
|
+
<rect x="284" y="384" width="86" height="26" rx="13" fill="#F1F5F9" stroke="#E2E8F0"/>
|
|
74
|
+
<text x="327" y="401" fill="#64748B" font-size="11.5" text-anchor="middle">no server</text>
|
|
75
|
+
<rect x="382" y="384" width="122" height="26" rx="13" fill="#F1F5F9" stroke="#E2E8F0"/>
|
|
76
|
+
<text x="443" y="401" fill="#64748B" font-size="11.5" text-anchor="middle">plain markdown</text>
|
|
77
|
+
<rect x="516" y="384" width="160" height="26" rx="13" fill="#F1F5F9" stroke="#E2E8F0"/>
|
|
78
|
+
<text x="596" y="401" fill="#64748B" font-size="11.5" text-anchor="middle">any model can read it</text>
|
|
79
|
+
</svg>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<svg width="960" height="430" viewBox="0 0 960 430" fill="none" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="tb" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
4
|
+
<path d="M0 0 L10 5 L0 10 z" fill="#5B7BB4"/>
|
|
5
|
+
</marker>
|
|
6
|
+
</defs>
|
|
7
|
+
|
|
8
|
+
<rect width="960" height="430" rx="18" fill="#0C1322"/>
|
|
9
|
+
<rect x="1" y="1" width="958" height="428" rx="17" stroke="#1E2A44"/>
|
|
10
|
+
|
|
11
|
+
<!-- ── the people ─────────────────────────────────────────────── -->
|
|
12
|
+
<g>
|
|
13
|
+
<rect x="44" y="56" width="232" height="76" rx="12" fill="#101B31" stroke="#24344F"/>
|
|
14
|
+
<circle cx="78" cy="94" r="15" fill="#1B2A45" stroke="#3D5378"/>
|
|
15
|
+
<circle cx="78" cy="90" r="4.5" fill="#93A6C8"/>
|
|
16
|
+
<path d="M71 103 a7 5.5 0 0 1 14 0" fill="#93A6C8"/>
|
|
17
|
+
<text x="106" y="89" fill="#E2E8F0" font-size="15" font-weight="600">Dev A</text>
|
|
18
|
+
<text x="106" y="109" fill="#7C8DB0" font-size="11.5">Claude Code + projectstore</text>
|
|
19
|
+
</g>
|
|
20
|
+
<g>
|
|
21
|
+
<rect x="44" y="166" width="232" height="76" rx="12" fill="#101B31" stroke="#24344F"/>
|
|
22
|
+
<circle cx="78" cy="204" r="15" fill="#1B2A45" stroke="#3D5378"/>
|
|
23
|
+
<circle cx="78" cy="200" r="4.5" fill="#93A6C8"/>
|
|
24
|
+
<path d="M71 213 a7 5.5 0 0 1 14 0" fill="#93A6C8"/>
|
|
25
|
+
<text x="106" y="199" fill="#E2E8F0" font-size="15" font-weight="600">Dev B</text>
|
|
26
|
+
<text x="106" y="219" fill="#7C8DB0" font-size="11.5">Claude Code + projectstore</text>
|
|
27
|
+
</g>
|
|
28
|
+
<g>
|
|
29
|
+
<rect x="44" y="276" width="232" height="76" rx="12" fill="#101B31" stroke="#24344F"/>
|
|
30
|
+
<circle cx="78" cy="314" r="15" fill="#1B2A45" stroke="#3D5378"/>
|
|
31
|
+
<circle cx="78" cy="310" r="4.5" fill="#93A6C8"/>
|
|
32
|
+
<path d="M71 323 a7 5.5 0 0 1 14 0" fill="#93A6C8"/>
|
|
33
|
+
<text x="106" y="309" fill="#E2E8F0" font-size="15" font-weight="600">Dev C</text>
|
|
34
|
+
<text x="106" y="329" fill="#7C8DB0" font-size="11.5">reviews on GitHub or Obsidian</text>
|
|
35
|
+
</g>
|
|
36
|
+
|
|
37
|
+
<!-- bind arrows -->
|
|
38
|
+
<path d="M280 94 C 320 94, 330 106, 356 116" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#tb)"/>
|
|
39
|
+
<path d="M280 204 L356 206" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#tb)"/>
|
|
40
|
+
<path d="M280 314 C 320 314, 330 302, 356 294" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#tb)"/>
|
|
41
|
+
<text x="308" y="196" fill="#7C8DB0" font-size="10.5" text-anchor="middle">bind</text>
|
|
42
|
+
|
|
43
|
+
<!-- ── the vault ──────────────────────────────────────────────── -->
|
|
44
|
+
<rect x="360" y="52" width="252" height="310" rx="14" fill="#0F2038" stroke="#3B82F6"/>
|
|
45
|
+
<text x="486" y="86" fill="#93C5FD" font-size="16" font-weight="600" text-anchor="middle">The vault</text>
|
|
46
|
+
<text x="486" y="106" fill="#7C8DB0" font-size="11" text-anchor="middle">its own git repo · plain markdown</text>
|
|
47
|
+
<path d="M384 122 L588 122" stroke="#1E3355"/>
|
|
48
|
+
<text x="384" y="150" fill="#A9B8D4" font-size="12.5">adr/ — decisions, with dates</text>
|
|
49
|
+
<text x="384" y="177" fill="#A9B8D4" font-size="12.5">specs/ — the normative how</text>
|
|
50
|
+
<text x="384" y="204" fill="#A9B8D4" font-size="12.5">epics/ · stories/ — the backlog</text>
|
|
51
|
+
<text x="384" y="231" fill="#A9B8D4" font-size="12.5">kanban.md — the board</text>
|
|
52
|
+
<text x="384" y="258" fill="#A9B8D4" font-size="12.5">graph.md — every link, typed</text>
|
|
53
|
+
<text x="384" y="285" fill="#A9B8D4" font-size="12.5">code-map.md — epic ↔ code</text>
|
|
54
|
+
<text x="384" y="330" fill="#64748B" font-size="11">every write previewed and</text>
|
|
55
|
+
<text x="384" y="346" fill="#64748B" font-size="11">approved — by whoever binds</text>
|
|
56
|
+
|
|
57
|
+
<!-- ── the remote ─────────────────────────────────────────────── -->
|
|
58
|
+
<path d="M616 128 L696 128" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#tb)"/>
|
|
59
|
+
<text x="656" y="118" fill="#7C8DB0" font-size="10.5" text-anchor="middle">push</text>
|
|
60
|
+
<path d="M696 172 L616 172" stroke="#5B7BB4" stroke-width="1.6" marker-end="url(#tb)"/>
|
|
61
|
+
<text x="656" y="192" fill="#7C8DB0" font-size="10.5" text-anchor="middle">review & pull</text>
|
|
62
|
+
|
|
63
|
+
<rect x="700" y="88" width="216" height="132" rx="12" fill="#131F36" stroke="#2C3E5F"/>
|
|
64
|
+
<text x="808" y="118" fill="#E2E8F0" font-size="15" font-weight="600" text-anchor="middle">git remote</text>
|
|
65
|
+
<text x="808" y="144" fill="#7C8DB0" font-size="11.5" text-anchor="middle">push / pull</text>
|
|
66
|
+
<text x="808" y="164" fill="#7C8DB0" font-size="11.5" text-anchor="middle">ADRs & specs reviewed</text>
|
|
67
|
+
<text x="808" y="182" fill="#7C8DB0" font-size="11.5" text-anchor="middle">as merge requests</text>
|
|
68
|
+
|
|
69
|
+
<text x="806" y="252" fill="#64748B" font-size="11.5" text-anchor="middle">the why gets reviewed,</text>
|
|
70
|
+
<text x="806" y="269" fill="#64748B" font-size="11.5" text-anchor="middle">not just the code</text>
|
|
71
|
+
|
|
72
|
+
<!-- ── the guarantees ─────────────────────────────────────────── -->
|
|
73
|
+
<rect x="284" y="384" width="86" height="26" rx="13" fill="#101B31" stroke="#24344F"/>
|
|
74
|
+
<text x="327" y="401" fill="#8FA1BF" font-size="11.5" text-anchor="middle">no server</text>
|
|
75
|
+
<rect x="382" y="384" width="122" height="26" rx="13" fill="#101B31" stroke="#24344F"/>
|
|
76
|
+
<text x="443" y="401" fill="#8FA1BF" font-size="11.5" text-anchor="middle">plain markdown</text>
|
|
77
|
+
<rect x="516" y="384" width="160" height="26" rx="13" fill="#101B31" stroke="#24344F"/>
|
|
78
|
+
<text x="596" y="401" fill="#8FA1BF" font-size="11.5" text-anchor="middle">any model can read it</text>
|
|
79
|
+
</svg>
|