@erclx/aitk 3.36.1 → 3.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aitk",
3
3
  "description": "Automated governance, versioning, and discovery tools for Claude Code.",
4
- "version": "3.36.1",
4
+ "version": "3.37.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -78,7 +78,7 @@ Write `verified` as the literal `TODO: never verified` here, quoted so the colon
78
78
 
79
79
  When sources came from a code scan rather than planning prose, lead the explanation with `Source: code.` and add `Fidelity is lower than prose-driven diagrams. Verify against the project's intent.`
80
80
 
81
- The code paths the explanation cites are what the `claude-docs` sweep watches for staleness, so cite paths that exist and spell them exactly.
81
+ A reader deciding whether the entry still holds starts from the code paths the explanation cites, so cite paths that exist and spell them exactly.
82
82
 
83
83
  Quote node labels containing spaces or special characters with double quotes (`A["Web shell"]`). Avoid parentheses inside labels, they break some renderers. Use `<br/>` for line breaks inside labels.
84
84
 
@@ -132,7 +132,7 @@ When a defect survives, keep the entry and name the defect in the chat output. A
132
132
 
133
133
  ### Stamp the marker
134
134
 
135
- Stamp every entry that passed. Set `verified` to the short SHA of `HEAD` and today's ISO date, and delete any `stale` key the `claude-docs` sweep left on it:
135
+ Stamp every entry that passed. Set `verified` to the short SHA of `HEAD` and today's ISO date, and delete any `stale` key the entry carries:
136
136
 
137
137
  ```bash
138
138
  git rev-parse --short HEAD
@@ -56,5 +56,4 @@ The trigger side carries a gap of its own. "Sync the docs" names either corpus t
56
56
  - Public-facing docs, which `docs-sync` owns, apart from landing a page a promotion handoff already carries a confirmed destination for. This skill reconciles the `.claude/` planning surface, and both descriptions name their corpus in the trigger so a request saying only "sync the docs" lands on one of the pair rather than on either.
57
57
  - Deciding where a promoted page belongs, which is settled with the operator by the surface that produced the page
58
58
  - Regenerating the task index, owned by a hook
59
- - Redrawing diagrams, which `claude-diagram` owns. This skill flags staleness and leaves the re-run to the author.
60
59
  - Re-measuring an architecture claim to decide whether its number moved. The sweep keys on a cited path entering the diff, so a claim whose number moved with no cited path in the diff goes unflagged.
@@ -9,11 +9,11 @@ description: Updates `.claude/` planning docs to reflect decisions made during t
9
9
 
10
10
  - If no `.claude/` directory exists, stop: `❌ No .claude/ directory found. Run aitk claude init to set up the workflow.`
11
11
 
12
- The skip for a session that changed nothing lives at the end of Step 2, because it needs the diff to decide. It drops the doc rewrite alone. The diff-driven sweeps in Steps 4, 5, and 6 still run.
12
+ The skip for a session that changed nothing lives at the end of Step 2, because it needs the diff to decide. It drops the doc rewrite alone. The diff-driven sweeps in Steps 4 and 5 still run.
13
13
 
14
14
  ## Diff baseline
15
15
 
16
- Steps 2, 4, 5, 6, and 8 share one diff on the usable path. An unusable baseline splits them, per the rule below. Resolve the base ref once and reuse it:
16
+ Steps 2, 4, 5, and 7 share one diff on the usable path. An unusable baseline splits them, per the rule below. Resolve the base ref once and reuse it:
17
17
 
18
18
  ```bash
19
19
  git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main 2>/dev/null
@@ -32,11 +32,11 @@ An unusable baseline costs only the committed half. `git diff <base> HEAD` is em
32
32
 
33
33
  **Step 2 recovers the committed half.** Read `git log -p -1`, widening to `git log -p -<n>` when the session spans several commits, and read the candidate task files against the working tree. That yields names and content both, which is what lets Step 2 decide on behavior rather than on filenames. A fresh `git init` on `main` with no remote is the ordinary shape of a scaffolded project, so this path carries the evidence rather than covering an edge case.
34
34
 
35
- **Steps 4, 5, 6, and 8 keep the scoped set.** Run them on the working tree and untracked files alone, and skip only when that set comes out empty, each reporting the warning its own step names.
35
+ **Steps 4, 5, and 7 keep the scoped set.** Run them on the working tree and untracked files alone, and skip only when that set comes out empty, each reporting the warning its own step names.
36
36
 
37
- Never substitute the whole tree for a missing baseline, and do not reuse Step 2's commit read in these four for consistency. On a fresh `git init` project the last commit is the scaffold commit, so `git log -p -1` is the whole tree by another route. Step 2 tolerates that because it only reads, and it matches conservatively against outcomes already on the board. Steps 4, 5, and 8 write, so the same set stubs a wireframe for every uncovered surface in the repository, stubs a diagram for every source signal the scaffold introduced, and rewrites every context entry that tree touches.
37
+ Never substitute the whole tree for a missing baseline, and do not reuse Step 2's commit read in these three for consistency. On a fresh `git init` project the last commit is the scaffold commit, so `git log -p -1` is the whole tree by another route. Step 2 tolerates that because it only reads, and it matches conservatively against outcomes already on the board. Steps 4 and 7 write, so the same set stubs a wireframe for every uncovered surface in the repository and rewrites every context entry that tree touches.
38
38
 
39
- Step 6 only reports, and the whole tree costs it a different way. Every anchored decision cites a path the scaffold commit carries, so the sweep flags the entire record and the reader learns nothing about which number moved.
39
+ Step 5 only reports, and the whole tree costs it a different way. Every anchored decision cites a path the scaffold commit carries, so the sweep flags the entire record and the reader learns nothing about which number moved.
40
40
 
41
41
  Widening what a step reads is safe. Widening what a step writes is not, and widening what a step flags spends the reader's attention on entries nothing put in doubt.
42
42
 
@@ -78,16 +78,16 @@ Keep the match conservative:
78
78
 
79
79
  Skip Step 3 when the session shows no divergence **and** the diff matches no queued outcome, reporting `✅ No doc updates needed. Session matched the original plan.` Both conditions have to hold. Shipping a queued task exactly as planned is the ordinary case and it reads as no divergence, so a session-only skip would drop the marking step with it.
80
80
 
81
- Then run Steps 4 through 9. Step 3 is the only one this skips, because it is the only one driven by the session rather than by the diff or the board. A project with an empty task board making a mechanical change satisfies both conditions above, and stopping here would put an uncovered surface and an uncovered diagram kind out of reach in every such project.
81
+ Then run Steps 4 through 9. Step 3 is the only one this skips, because it is the only one driven by the session rather than by the diff or the board. A project with an empty task board making a mechanical change satisfies both conditions above, and stopping here would put an uncovered surface out of reach in every such project.
82
82
 
83
83
  The steps that follow reach past the session, so each earns the reach separately:
84
84
 
85
- - Steps 4 and 5 stub against the diff. These are why the skip is not a stop. A session that changed no docs is exactly when an uncovered surface or diagram kind goes unnoticed.
86
- - Step 6 reads the architecture record against the diff. A run that amended no decision is the one where an anchored number moves under a reasoning nobody reread, which is the case the marker exists to surface.
87
- - Step 8 rewrites context entries against the diff and against the facts `claude-memory-capture` routed. The Diff baseline section above groups its diff half with Steps 4 and 5 as a scoped-set step, so a quiet session is no different from any other for it. The routed half reads a named file and runs whatever the diff shows.
85
+ - Step 4 stubs against the diff. That is why the skip is not a stop. A session that changed no docs is exactly when an uncovered surface goes unnoticed.
86
+ - Step 5 reads the architecture record against the diff. A run that amended no decision is the one where an anchored number moves under a reasoning nobody reread, which is the case the marker exists to surface.
87
+ - Step 7 rewrites context entries against the diff and against the facts `claude-memory-capture` routed. The Diff baseline section above groups its diff half with Steps 4 and 5 as a scoped-set step, so a quiet session is no different from any other for it. The routed half reads a named file and runs whatever the diff shows.
88
88
  - The scratch sweep reads the board rather than the session. Its board-wide scan exists to clear a plan an earlier run stranded, and a run that stops at Step 2 can never reach one.
89
89
 
90
- This changes which steps the skill reaches. It does not widen what any of them reads. Steps 4, 5, 6, and 8 still take the same scoped set the Diff baseline section defines, and that section's rule is about the input a step is handed rather than about which steps run.
90
+ This changes which steps the skill reaches. It does not widen what any of them reads. Steps 4, 5, and 7 still take the same scoped set the Diff baseline section defines, and that section's rule is about the input a step is handed rather than about which steps run.
91
91
 
92
92
  ## Step 3: update
93
93
 
@@ -110,7 +110,7 @@ Read `ok` and `reason` out of that record rather than the exit, for the reason t
110
110
  - Do not rewrite sections unrelated to what changed.
111
111
  - Follow `${CLAUDE_SKILL_DIR}/../../standards/markdown.md` and the `write-human` skill for all edits.
112
112
  - Close a decision entry in `.claude/ARCHITECTURE.md` with its verification anchor whenever this run writes that entry or amends its reasoning and that reasoning cites a measured number. Re-read the number against the tree first, since the marker records the read rather than the edit. `${CLAUDE_SKILL_DIR}/../../standards/architecture.md` fixes the sentence.
113
- - Leave every decision entry this run did not write alone, anchored or not. The rule is scoped forward, so an entry written before it is dated by blame rather than by a read. Step 6 reports a stale anchor and no step writes one on an entry it did not amend.
113
+ - Leave every decision entry this run did not write alone, anchored or not. The rule is scoped forward, so an entry written before it is dated by blame rather than by a read. Step 5 reports a stale anchor and no step writes one on an entry it did not amend.
114
114
 
115
115
  Write each updated file immediately. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
116
116
 
@@ -122,23 +122,11 @@ Reuse the diff from the baseline above and filter for UI-affecting paths. UI-aff
122
122
 
123
123
  Skip silently when the filter leaves nothing, which is every branch touching no UI. Otherwise read `${CLAUDE_SKILL_DIR}/references/wireframe-sweep.md` for the slug derivation, the two findings it reports, the stub it writes, and the output lines.
124
124
 
125
- ## Step 5: diagram staleness sweep
126
-
127
- Skip this step silently when `.claude/diagrams/` does not exist at `pwd` or holds no entry. An entry is any `*.md` other than `index.md`, so a folder carrying the catalog alone is an empty set. A project that has never run `claude-diagram` is not told on every ship that it has holes. When the baseline is unusable, scope the sweep to the working tree and untracked files, and skip it only when that set is empty, reporting `⚠ No diff to scope against. Skipped the diagram sweep.`
128
-
129
- This step writes frontmatter and never content. Mermaid bodies and explanation paragraphs are off limits to it. A change that removes a module does not carry the new correct shape of the picture, so rewriting a diagram from it produces a confident wrong diagram, which is worse than the stale one it replaced. The author redraws by running `claude-diagram`.
130
-
131
- Follow `${CLAUDE_SKILL_DIR}/../../standards/diagrams.md` for the marker fields this step writes.
132
-
133
- Both findings key on something literally entering or leaving the tree. Anything looser fires on ordinary feature work and rebuilds the ignored warning this sweep replaced.
134
-
135
- Past the skip above, read `${CLAUDE_SKILL_DIR}/references/diagram-sweep.md` for the two findings, the signal table deciding an uncovered kind, the stub it writes, and the output lines. Both tests need the cited paths and the signal list that file carries, so the folder check is the only one the body can settle on its own.
136
-
137
- ## Step 6: architecture anchor sweep
125
+ ## Step 5: architecture anchor sweep
138
126
 
139
127
  Skip this step silently when `.claude/ARCHITECTURE.md` does not exist at `pwd` or carries no decision entry with a verification anchor. A record written before the rule holds none, and a project is not told on every ship that nothing has been checked when the standard calls that state correct. When the baseline is unusable, scope the sweep to the working tree and untracked files, and skip it only when that set is empty, reporting `⚠ No diff to scope against. Skipped the anchor sweep.`
140
128
 
141
- This step reports and never writes. The record carries no frontmatter, so an anchor is a sentence sharing a paragraph with the claim it marks, and a pass editing prose to mark prose has no structural guard against editing the claim beside it. The diagram sweep gets that separation from YAML and this one cannot.
129
+ This step reports and never writes. The record carries no frontmatter, so an anchor is a sentence sharing a paragraph with the claim it marks, and a pass editing prose to mark prose has no structural guard against editing the claim beside it. A surface whose marker sits in YAML gets that separation for free and this one cannot.
142
130
 
143
131
  Step 3 holds the writer, and the two never meet. Anchoring fires when this run amends a decision, and this sweep fires when the diff moves a path under one, so a single step covering both would gate the anchor obligation on a signal that has nothing to do with it.
144
132
 
@@ -146,7 +134,7 @@ Follow `${CLAUDE_SKILL_DIR}/../../standards/architecture.md` for the anchor sent
146
134
 
147
135
  Past the skip above, read `${CLAUDE_SKILL_DIR}/references/anchor-sweep.md` for how an entry's cited paths are collected, the finding the diff fires, and the report line.
148
136
 
149
- ## Step 7: flag CLAUDE.md drift
137
+ ## Step 6: flag CLAUDE.md drift
150
138
 
151
139
  If this session established or changed a cross-cutting behavior rule that belongs in root `CLAUDE.md` (a new always-on convention, a revised workflow rule), surface a one-line warning:
152
140
 
@@ -154,7 +142,7 @@ If this session established or changed a cross-cutting behavior rule that belong
154
142
 
155
143
  Do not edit `CLAUDE.md` inline. Every `CLAUDE.md` change goes through the show-diff-and-approve gate, so this step only flags. Skip silently when the session made no cross-cutting behavior decision.
156
144
 
157
- ## Step 8: refresh context entries
145
+ ## Step 7: refresh context entries
158
146
 
159
147
  Read `.claude/context/index.md` at `pwd` to see which domain entries exist. Skip this step silently if the directory does not exist or has no entries.
160
148
 
@@ -197,7 +185,7 @@ Add a line naming the handoff when one was consumed:
197
185
 
198
186
  The base lint-staged config runs `aitk indexes regen` on every committed `*.md`, so `.claude/context/index.md` refreshes automatically on commit. No manual step needed.
199
187
 
200
- ## Step 9: fold promoted pages
188
+ ## Step 8: fold promoted pages
201
189
 
202
190
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`, falling back to `latest` on an empty result, and read `.claude/.tmp/teach-promotion/<slug>.md` at the main worktree root. `claude-teach` writes it, one H2 per destination naming the path, with a source line under the heading and the page body in a fenced block below that. Read the body out of the fence rather than off the heading level, since a reference page carries headings of its own and only the fence separates them from the next destination. Skip this step silently when the file is absent, which is every run where nothing was promoted.
203
191
 
@@ -220,7 +208,7 @@ Report a block left unfolded rather than dropping it:
220
208
 
221
209
  `⚠ Skipped: <destination path> already exists. Merge by hand.`
222
210
 
223
- ## Step 10: sweep consumed scratch
211
+ ## Step 9: sweep consumed scratch
224
212
 
225
213
  Sweep reviews this session consumed, and sweep plans across the whole board. Resolve all paths at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`.
226
214
 
@@ -5,7 +5,7 @@ description: How an anchored decision's cited paths are collected, the finding t
5
5
 
6
6
  # Architecture anchor staleness sweep
7
7
 
8
- Mechanics for Step 6 of `claude-docs`. The body owns the skip conditions, the report-only constraint, and the standard citation, and this file owns what the sweep does once the diff touches a path an anchored decision cites.
8
+ Mechanics for Step 5 of `claude-docs`. The body owns the skip conditions, the report-only constraint, and the standard citation, and this file owns what the sweep does once the diff touches a path an anchored decision cites.
9
9
 
10
10
  ## Anchored entries
11
11
 
@@ -132,9 +132,9 @@ aitk records push --json
132
132
  aitk records pull
133
133
  ```
134
134
 
135
- The backed folders are `groundwork`, `intake`, `memory`, `plans`, `review`, `tasks`, and `teach`, all under `.claude/`. They are the Claude ignore group the claude manifest ships, minus three entries: `.claude/.tmp`, which is deletable without loss, `.claude/worktrees/`, whose contents belong to the project repository already, and `.claude/.records.git/`, which is the history the other seven are pushed into. Each name is a top-level record folder and every archive sits inside the one it archives, so the list stays at one entry per surface however many archives appear. It is a constant rather than configuration, matching the six record kinds `validate` hardcodes.
135
+ The backed folders are `diagrams`, `groundwork`, `intake`, `memory`, `plans`, `proposals`, `review`, `tasks`, and `teach`, all under `.claude/`. Seven of them are the Claude ignore group the claude manifest ships, minus three entries: `.claude/.tmp`, which is deletable without loss, `.claude/worktrees/`, whose contents belong to the project repository already, and `.claude/.records.git/`, which is the history the rest are pushed into. `diagrams` and `proposals` are the two that group does not carry at all, since a target still tracks its own copies of both, which is why the list is spelled out rather than derived. Each name is a top-level record folder and every archive sits inside the one it archives, so the list stays at one entry per surface however many archives appear. It is a constant rather than configuration, and it deliberately does not match the six record kinds `validate` hardcodes.
136
136
 
137
- Records are gitignored by design, so the history lives in a second git directory at `.claude/.records.git` with `.claude/` as its work tree. Every path stays where it is, which is what a separate checkout could not do. The verbs stage the ten folders by explicit pathspec with `--force`, so nothing outside them can enter the index however the ignore rules read, and the project working tree and its index are never touched.
137
+ Records are gitignored by design, so the history lives in a second git directory at `.claude/.records.git` with `.claude/` as its work tree. Every path stays where it is, which is what a separate checkout could not do. The verbs stage the nine folders by explicit pathspec with `--force`, so nothing outside them can enter the index however the ignore rules read, and the project working tree and its index are never touched. Those pathspecs are relative to the process cwd, so run either verb from the project root rather than from a linked worktree, which sits inside the records work tree and makes every one of them resolve against the wrong directory.
138
138
 
139
139
  ### Setup
140
140
 
@@ -20,7 +20,7 @@ Project docs live in `.claude/` at the project root.
20
20
  ├── ARCHITECTURE.md ← technical design decisions
21
21
  ├── DESIGN.md ← visual intent and token decisions (UI projects)
22
22
  ├── WIREFRAMES.md ← ASCII wireframes: layout, UI copy, and interaction rules (UI projects)
23
- ├── diagrams/ ← one Mermaid entry per diagram kind with a generated index.md
23
+ ├── diagrams/ ← one Mermaid entry per diagram kind with a generated index.md, redrawn on demand
24
24
  ├── tasks/ ← one file per task with a generated index.md, gitignored local scratch
25
25
  ├── context/ ← per-domain narrative loaded on demand via index.md
26
26
  └── rules/ ← path-scoped governance rules, written by aitk gov install
@@ -95,7 +95,7 @@ An execution that picks other than the suggestion rewrites the `- Suggested:` li
95
95
 
96
96
  `aitk records validate plans` reports where a plan and that standard disagree: a filename that is not `feature-<slug>.md`, a missing required section, a files-to-touch entry naming no file, and a question carrying a suggestion with no answer slot. The same verb takes `groundwork`, `intake`, `memory`, and `teach`, which are governed the same way and were unreachable for the same reason. Nothing fires it automatically, because all five folders are gitignored and every check the repository runs reads changed files from git. It reports and never writes, since the folders are per-machine scratch with no history to recover a wrong repair from.
97
97
 
98
- `aitk records push` carries these folders off the disk they live on, and `aitk records pull` brings them back. Seven of them are backed: `groundwork`, `intake`, `memory`, `plans`, `review`, `tasks`, and `teach`, each carrying whatever it has archived inside it. The history lives in a second git directory at `.claude/.records.git` with `.claude/` as its work tree, so every path a task file cites stays where it is.
98
+ `aitk records push` carries these folders off the disk they live on, and `aitk records pull` brings them back. Nine of them are backed: `diagrams`, `groundwork`, `intake`, `memory`, `plans`, `proposals`, `review`, `tasks`, and `teach`, each carrying whatever it has archived inside it. The history lives in a second git directory at `.claude/.records.git` with `.claude/` as its work tree, so every path a task file cites stays where it is.
99
99
 
100
100
  A person points it at a private repository once and both verbs refuse until they have, and `push` refuses when that origin is also a remote of the project, since the payload is the memory pen and the groundwork trails. `.husky/post-merge` runs the push after its archive loop, on every merge rather than only on one that closed a task. See [records](agents/records.md) for the refusal table.
101
101
 
@@ -64,7 +64,7 @@ Scaffold installs tooling and seeds. It does not fill the planning docs or the d
64
64
 
65
65
  A machine without a renderer still gets the diagrams and is told which check was skipped.
66
66
 
67
- Each diagram entry records the commit and date it was last verified against, and `aitk:claude-docs` maintains that record on every ship: it annotates an entry whose cited code path left the tree and stubs a kind whose source signal arrived uncovered. The sweep writes frontmatter only, so a diagram's picture and prose change when you redraw them and at no other time.
67
+ Each diagram entry records the commit and date it was last verified against, and nothing maintains that record for you. The folder is redrawn on demand rather than swept on every ship, so `verified` carries the whole signal: an entry whose date sits far behind your branch is due a read, and no pass will name which one. Run `aitk:claude-diagram` again when the code a kind is drawn from moves.
68
68
 
69
69
  `.claude/ARCHITECTURE.md` carries the same mechanism on the same ship. `aitk:claude-docs` anchors a decision it amends to the paths that decision cites, and reports an anchored decision whose cited path the branch touched.
70
70
 
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Route every git operation through the aitk git skills rather than built-in commit and pull request behavior
3
+ ---
4
+
5
+ # Git standards
6
+
7
+ ## Skill precedence
8
+
9
+ - Route every git operation through the `aitk:git-*` skills.
10
+ - Do not follow built-in commit, pull request, or branch instructions for an operation a `git-*` skill covers.
11
+ - Report it rather than proceeding silently when no `git-*` skill resolves. They ship with the plugin and this rule ships with the CLI, so a project that installed governance alone does not have them.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "3.36.1",
4
+ "version": "3.37.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -4,18 +4,22 @@ import { $ } from 'bun'
4
4
  import { gitEnv } from '@/git-env'
5
5
 
6
6
  /**
7
- * The folders a backup carries, relative to `.claude/`. They are the `# Claude`
8
- * group the claude manifest ships, minus three: `.claude/.tmp`, which is
9
- * defined as deletable without loss, `.claude/worktrees/`, whose contents
10
- * belong to the enclosing repository already, and `.claude/.records.git/`,
11
- * which is the history the other seven are pushed into. The list is spelled out
12
- * rather than read off that group so adding an ignore entry cannot silently
13
- * enlarge the payload.
7
+ * The folders a backup carries, relative to `.claude/`. Most of them are the
8
+ * `# Claude` group the claude manifest ships, minus three: `.claude/.tmp`,
9
+ * which is defined as deletable without loss, `.claude/worktrees/`, whose
10
+ * contents belong to the enclosing repository already, and
11
+ * `.claude/.records.git/`, which is the history the rest are pushed into. The
12
+ * list is spelled out rather than read off that group so adding an ignore entry
13
+ * cannot silently enlarge the payload.
14
+ *
15
+ * `diagrams` and `proposals` are the two names the manifest group does not
16
+ * carry, so a target tracks both where this repository ignores them. That is
17
+ * the second reason to spell the list out: the manifest bounds it rather than
18
+ * producing it, and no count taken off that group matches this one.
14
19
  *
15
20
  * The manifest group is the one this reads rather than the enclosing
16
21
  * repository's own `.gitignore`, which spreads the same entries across two
17
- * headers and carries `.claude/README.md` that no target receives. Subtracting
18
- * three from that file instead yields eight names against this list of seven.
22
+ * headers and carries `.claude/README.md` that no target receives.
19
23
  *
20
24
  * Each entry is a top-level record folder and every archive sits inside the one
21
25
  * it archives, so the three former archive entries are covered by their parents
@@ -28,6 +32,7 @@ import { gitEnv } from '@/git-env'
28
32
  * tracked so a backup would carry a second copy of committed files.
29
33
  */
30
34
  export const BACKED_FOLDERS = [
35
+ 'diagrams',
31
36
  'groundwork',
32
37
  'intake',
33
38
  'memory',
@@ -37,13 +37,13 @@ An entry that fails these is non-conforming regardless of whether it satisfies e
37
37
  - `description` (required): one line on which question the entry settles and which source signal drives it.
38
38
  - `category` (required): the diagram kind, one of the five in Entry kinds. It is the grouping field `aitk indexes regen` renders headings from.
39
39
  - `verified` (required): the short commit SHA an entry was last checked against and the ISO date of that check, separated by a space (`73e9a3f8 2026-08-02`). A stub nobody has drawn yet carries the literal `TODO: never verified` instead, which is the one other accepted value.
40
- - `stale` (optional): one line naming what changed under the entry since that check. Absent on an entry nothing has flagged.
40
+ - `stale` (optional): one line naming what changed under the entry since that check. Nothing writes it on its own, so it sits on an entry because a reader put it there and is absent everywhere else.
41
41
 
42
42
  The first three feed `.claude/diagrams/index.md` when regenerated. The catalog sorts categories alphabetically rather than in narrative order, so an entry cannot rely on its position to introduce another. Each entry names its own starting point, and the catalog's subtitle routes a first-time reader to the system context entry.
43
43
 
44
44
  The marker fields reach the catalog through neither route. `aitk indexes regen` reads `title`, `description`, and `category` and ignores every other key, so a marker changes no generated file. A reader picks it up by opening the entry, which is where it sits above the diagram and where anyone deciding whether to trust the picture is already standing.
45
45
 
46
- Two writers share the marker and neither touches the other's field. A pass that renders an entry and reads the picture back sets `verified` and clears `stale`. The `claude-docs` sweep appends `stale` and never edits `verified`. Keeping them separate is what lets a reader tell a diagram nobody has checked since the code moved from one that was checked and found correct.
46
+ One writer touches `verified`, which is the pass that renders an entry and reads the picture back, and it clears `stale` at the same time. A reader who notices the picture has drifted writes `stale` by hand. Keeping the two fields apart is what lets a reader tell a diagram nobody has checked since the code moved from one that was checked and found correct.
47
47
 
48
48
  ## Entry kinds
49
49
 
@@ -90,7 +90,7 @@ A second entry for one kind takes a suffixed name (`request-flow-admin.md`) and
90
90
 
91
91
  - One to three short paragraphs below each diagram. Plain English and pedagogical.
92
92
  - Lead with what the diagram shows. Follow with why this shape was chosen and what alternative was rejected, when the choice was non-obvious.
93
- - Reference one or two specific code paths the reader can open. Do not enumerate every file. Backticked paths here are also the set the `claude-docs` sweep watches, so a path cited in this section is one a later session gets told about when it leaves the tree.
93
+ - Reference one or two specific code paths the reader can open. Do not enumerate every file. Spell each one exactly, since a reader deciding whether the entry still holds starts by opening the paths it names and a path that resolves to nothing costs them that read.
94
94
  - Do not duplicate prose across entries. An entry that restates its neighbor has taken the neighbor's job.
95
95
  - The audience is mixed, so vocabulary runs as a gradient across the set. `System context` assumes no knowledge of the repository. `Deployment` may assume the reader has read the others.
96
96
 
@@ -119,8 +119,7 @@ Reference the context entry by path when a reader needs the mechanism. The diagr
119
119
  - When the system changes, update the entries whose source signal changed and leave the rest alone. Rewriting the folder wholesale reproduces the defect the per-kind split exists to end.
120
120
  - A diagram showing a defunct host or library is worse than no diagram. Audit the affected entry in the same PR.
121
121
  - `System context` has no named source signal beyond `.claude/REQUIREMENTS.md`, so nothing tells a session it went stale. Re-read it when the boundary or the set of external dependencies moves.
122
- - The `claude-docs` sweep watches two things and writes frontmatter only. It appends `stale` when a path an entry cites leaves the tree, and it stubs a kind when a diff adds the source signal that kind is drawn from. Diagram bodies and explanation paragraphs are off limits to it, because a change that removes a module does not carry the new correct shape of the picture.
123
- - That watch samples thinly. It sees the one or two paths an entry happened to cite and nothing else, so a change elsewhere leaves the entry looking current. `verified` is what covers the gap, and an entry whose date sits far behind the branch is due a read whether or not anything flagged it.
122
+ - Nothing watches the folder for you. The entries are redrawn on demand rather than swept on every ship, so `verified` carries the whole signal: an entry whose date sits far behind the branch is due a read, and no pass is going to name which one.
124
123
  - The explanation paragraphs around a Mermaid block are prose and follow `markdown.md` and the `write-human` skill. The fenced block itself is not, which is why a check scoped to prose is the wrong thing to rely on for what sits inside it.
125
124
  - The punctuation bans still apply to node and subgraph labels, and nothing checks them there. An em dash in a label passes every gate the repository has, so read the labels before shipping the entry.
126
125
 
@@ -1,58 +0,0 @@
1
- ---
2
- title: Diagram staleness sweep
3
- description: The contradicted-entry marker, the source-signal table that decides an uncovered kind, the stub it writes, and the report lines
4
- ---
5
-
6
- # Diagram staleness sweep
7
-
8
- Mechanics for Step 5 of `claude-docs`. The body owns the skip conditions, the frontmatter-only constraint, and the standard citation, and this file owns what the sweep does once the diff carries a delete or a new source signal.
9
-
10
- ## Contradicted entries
11
-
12
- For each entry, collect the backticked code paths its explanation cites. When a cited path is in the diff as a delete or a rename and no longer exists in the tree, append a `stale` key to that entry's frontmatter naming the path:
13
-
14
- ```yaml
15
- stale: 'src/gov/install.ts no longer exists'
16
- ```
17
-
18
- Append that key alone. Never edit `verified`, `title`, `description`, or `category`, and never touch the body. When the entry already carries `stale`, extend the existing line rather than adding a second key.
19
-
20
- ## Uncovered kinds
21
-
22
- The standard fixes one source signal per kind. Stub a kind when the diff adds its signal file and no entry covers that kind. The trigger is the signal appearing, never a file under it changing, so a branch editing a component folder that `components.md` already covers produces nothing here.
23
-
24
- | Signal added by the diff | Kind stubbed when absent |
25
- | ------------------------------------------------------------------------------------------------------------------ | ------------------------ |
26
- | `.claude/REQUIREMENTS.md` | `system-context.md` |
27
- | `.claude/ARCHITECTURE.md` | `components.md` |
28
- | A deploy or infrastructure config (`Dockerfile`, `.github/workflows/*`, `vercel.json`, `fly.toml`, `compose.yaml`) | `deployment.md` |
29
-
30
- Leave `request-flow.md` and `data-pipeline.md` out. Neither has a source signal a diff can point at, so a rule covering them would guess at when they went stale.
31
-
32
- Write the stub at `.claude/diagrams/<kind>.md`:
33
-
34
- ```markdown
35
- ---
36
- title: <Kind as title case>
37
- description: 'TODO: name the question this entry settles.'
38
- category: <the category the standard fixes for this kind>
39
- verified: 'TODO: never verified'
40
- ---
41
-
42
- # <Kind as title case>
43
-
44
- TODO: draw this. `<signal path>` entered the tree with no entry covering this kind.
45
-
46
- Run `/claude-diagram <kind>` to replace the stub.
47
- ```
48
-
49
- No mermaid fence. An empty stub is visible debt that reaches review through the branch diff, while a generated diagram nobody rendered is invisible debt that reads as verified. A fence here invites the next session to fill it in without a render.
50
-
51
- ## Output
52
-
53
- Output one line per finding:
54
-
55
- - `⚠ Diagram stale: .claude/diagrams/<kind>.md cites <path>, which left the tree`
56
- - `📝 Stubbed: .claude/diagrams/<kind>.md`
57
-
58
- If the sweep finds nothing, skip silently. An ordinary change that adds no signal and deletes no cited path produces no output at all.