@erclx/aitk 0.78.1 → 0.79.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": "0.78.1",
4
+ "version": "0.79.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -9,6 +9,8 @@ description: What the planning-doc reconcile is for, the gaps it closes, and why
9
9
 
10
10
  Without this skill, the planning docs describe the scope the session opened with. An outcome the diff shipped stays unchecked, so the board reports finished work as open and the next session re-plans it. A requirement or architecture decision that changed mid-cycle lives only in the conversation and dies with it. Plans for closed tasks accumulate in the live folder, so the folder stops indicating what is in flight.
11
11
 
12
+ A decision's verification anchor has the same shape of gap in the other direction. The reasoning keeps reading as current while the number it cites moves underneath, and an amendment written without an anchor leaves nothing recording which numbers were checked and which nobody has read since.
13
+
12
14
  ## Must
13
15
 
14
16
  - Take completion from the diff and everything else from the session, since completion is a fact about the repository rather than about the conversation
@@ -17,6 +19,8 @@ Without this skill, the planning docs describe the scope the session opened with
17
19
  - Write tracked docs at the current worktree root and the task board at the main root, since only the first commits with the branch
18
20
  - Count every other citation before archiving a plan, comparing resolved targets rather than raw strings or bare filenames
19
21
  - Retarget a closed task at the archived plan, so the reasoning behind finished work stays reachable
22
+ - Anchor a decision entry this run writes or amends whose reasoning cites a measured number, re-reading the number against the tree before writing the marker
23
+ - Report an anchored decision whose cited path the diff touched, since the number was read before the branch moved what it counted
20
24
 
21
25
  ## Must not
22
26
 
@@ -25,6 +29,8 @@ Without this skill, the planning docs describe the scope the session opened with
25
29
  - Widen what a writing step reads when the baseline is unusable. Widening a read is safe and widening a write stubs a surface for every file in the repository.
26
30
  - Edit `CLAUDE.md` inline. Every change there goes through a diff-and-approve gate, so this skill only flags.
27
31
  - Create a context entry or delete a plan
32
+ - Write an anchor onto a decision the run did not amend, or refresh one without re-reading the number. A date from a pass that measured nothing is the false confidence the marker exists to prevent.
33
+ - Anchor an entry written before the rule, which dates it by blame rather than by a read
28
34
 
29
35
  ## Guards
30
36
 
@@ -37,3 +43,4 @@ Without this skill, the planning docs describe the scope the session opened with
37
43
  - Public-facing docs, which `docs-sync` owns. This skill reconciles the `.claude/` planning surface.
38
44
  - Regenerating the task index, owned by a hook
39
45
  - Redrawing diagrams, which `claude-diagram` owns. This skill flags staleness and leaves the re-run to the author.
46
+ - 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 and 5 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, 5, and 6 still run.
13
13
 
14
14
  ## Diff baseline
15
15
 
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:
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:
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,13 @@ 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, 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.
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.
36
36
 
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. These three 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 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.
38
38
 
39
- Widening what a step reads is safe. Widening what a step writes is not.
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.
40
+
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.
40
42
 
41
43
  ## Step 1: read current docs
42
44
 
@@ -49,7 +51,7 @@ Read these in parallel from the current worktree root (`pwd`), not the main work
49
51
 
50
52
  Read the task board from the main worktree root instead, per Worktrees in `CLAUDE.md`. It is gitignored scratch and never commits with the branch:
51
53
 
52
- - `.claude/tasks/index.md` first, then the task files this session touched. That narrow read serves the marking step. Step 8 reads every file in the folder for its plans sweep and states that where it gives the instruction.
54
+ - `.claude/tasks/index.md` first, then the task files this session touched. That narrow read serves the marking step. Step 9 reads every file in the folder for its plans sweep and states that where it gives the instruction.
53
55
 
54
56
  ## Step 2: identify what changed
55
57
 
@@ -72,19 +74,20 @@ Keep the match conservative:
72
74
 
73
75
  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.
74
76
 
75
- Then run Steps 4 through 8. 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.
77
+ 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.
76
78
 
77
- Three of the steps that follow write, so each earns the reach separately:
79
+ The steps that follow reach past the session, so each earns the reach separately:
78
80
 
79
81
  - 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.
80
- - 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.
81
- - Step 8 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.
82
+ - 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.
83
+ - 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.
84
+ - Step 9 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.
82
85
 
83
- 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 write is handed rather than about which writes run.
86
+ 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.
84
87
 
85
88
  ## Step 3: update
86
89
 
87
- For each doc with relevant changes, apply updates following these rules. Read a standard this skill names, here or in Step 7, from `${CLAUDE_SKILL_DIR}/../../standards/` when the project does not have it.
90
+ For each doc with relevant changes, apply updates following these rules. Read a standard this skill names, here or in a later step, from `${CLAUDE_SKILL_DIR}/../../standards/` when the project does not have it.
88
91
 
89
92
  **`.claude/tasks/`**
90
93
 
@@ -98,6 +101,8 @@ For each doc with relevant changes, apply updates following these rules. Read a
98
101
  - Update only the sections affected by session decisions.
99
102
  - Do not rewrite sections unrelated to what changed.
100
103
  - Follow `.claude/standards/prose.md` and `.claude/standards/markdown.md` for all edits.
104
+ - 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/standards/architecture.md` fixes the sentence.
105
+ - 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.
101
106
 
102
107
  Write each updated file immediately. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
103
108
 
@@ -121,7 +126,19 @@ Both findings key on something literally entering or leaving the tree. Anything
121
126
 
122
127
  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.
123
128
 
124
- ## Step 6: flag CLAUDE.md drift
129
+ ## Step 6: architecture anchor sweep
130
+
131
+ 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.`
132
+
133
+ 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.
134
+
135
+ 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.
136
+
137
+ Follow `.claude/standards/architecture.md` for the anchor sentence this step matches on.
138
+
139
+ 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.
140
+
141
+ ## Step 7: flag CLAUDE.md drift
125
142
 
126
143
  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:
127
144
 
@@ -129,7 +146,7 @@ If this session established or changed a cross-cutting behavior rule that belong
129
146
 
130
147
  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.
131
148
 
132
- ## Step 7: refresh context entries
149
+ ## Step 8: refresh context entries
133
150
 
134
151
  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.
135
152
 
@@ -160,7 +177,7 @@ Add a line naming the handoff when one was consumed:
160
177
 
161
178
  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.
162
179
 
163
- ## Step 8: sweep consumed scratch
180
+ ## Step 9: sweep consumed scratch
164
181
 
165
182
  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`.
166
183
 
@@ -0,0 +1,58 @@
1
+ ---
2
+ title: Architecture anchor staleness sweep
3
+ description: How an anchored decision's cited paths are collected, the finding the diff fires, and the report line
4
+ ---
5
+
6
+ # Architecture anchor staleness sweep
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.
9
+
10
+ ## Anchored entries
11
+
12
+ Read `.claude/ARCHITECTURE.md` and take the H3 entries under `## Key technical decisions`. An entry is anchored when its reasoning closes on the marker the standard fixes:
13
+
14
+ ```plaintext
15
+ Measured at <short-sha> on <YYYY-MM-DD>.
16
+ ```
17
+
18
+ Skip every entry without one. An unanchored entry either predates the rule or cites no measured number, and the standard calls both correct, so the sweep has nothing to say about either.
19
+
20
+ For each anchored entry, collect the backticked code paths its reasoning cites. Same read the diagram sweep runs over an explanation, against a paragraph instead of a diagram.
21
+
22
+ Most of these name a folder rather than a file, because the number an entry anchors is usually a count over a tree. Match accordingly:
23
+
24
+ - A citation naming a file matches when the diff carries that file, wherever it sits. A file at the repository root such as `CLAUDE.md` is a file citation like any other.
25
+ - A folder citation, which is one ending in a slash, matches when the diff carries any path under it.
26
+ - A folder citation of a single segment matches nothing and is skipped.
27
+
28
+ The third rule reaches folders alone, which is what keeps it off `CLAUDE.md`. Breadth is the whole reason it exists, and a root file has none: it names one path the diff either carries or does not.
29
+
30
+ What it does stop is a citation of `.claude/` matching every branch. `src/`, `scripts/`, and `.claude/` each name a tree a project organizes most of its work under, so a prefix match on one fires constantly and rebuilds the ignored warning this sweep exists to avoid. Measured against this repository's record at `87b11e87`, the skip drops 13 of the 26 folder citations and keeps the ones carrying a signal, among them `src/tooling/`, `.claude/rules/`, and `governance/rules/`.
31
+
32
+ A decision whose folder citations are all a single segment, and which cites no file, therefore never fires. That is the correct outcome rather than a gap: a count over a whole tree moves on nearly every branch, so flagging it every time tells a reader that time has passed and nothing else.
33
+
34
+ ## The finding
35
+
36
+ Report an entry when the diff touches one of its cited paths, however it was touched. A delete, a rename, and an edit inside the file all move a count of what sits under that path, and the entry's number was read before any of them landed. The diagram sweep narrows to deletes because a diagram survives a body edit, and a number does not.
37
+
38
+ The anchor's own SHA settles nothing here. A branch is compared against its merge base rather than against the commit the anchor names, so an entry anchored at a commit this branch already contains is still due a read once the branch moves what it counted.
39
+
40
+ Report an entry once however many of its cited paths the diff carries. Name the first as the evidence and leave the rest, since the reader opens the entry either way and a line per path buries the entry it is about.
41
+
42
+ What this misses is a claim whose number moved with no matching citation in the diff, whether because the branch never touched the tree it counts or because the entry cites nothing narrower than one segment. That is the recall this trades for precision, and the alternative is re-running an arbitrary measurement read out of prose, which no sweep does reliably.
43
+
44
+ ## What the sweep never does
45
+
46
+ - Write into the entry. The record carries no frontmatter, so the marker and the claim share one paragraph and an edit reaching one reaches the other.
47
+ - Refresh an anchor. Re-reading the number is the act the marker records, so a date written by a pass that measured nothing is the false confidence the marker exists to prevent.
48
+ - Flag an unanchored entry. The standard scopes the rule forward, and an entry written before it is dated by blame rather than by a read.
49
+
50
+ The session amending a decision writes its anchor, which Step 3 already requires.
51
+
52
+ ## Output
53
+
54
+ Output one line per finding:
55
+
56
+ `⚠ Anchor stale: "<decision name>" cites <path>, which this branch changed. Re-measure and refresh the anchor.`
57
+
58
+ If no anchored entry cites a changed path, skip silently. A record carrying no anchored entry produces no output on any branch, which is every project until a decision is written or amended under the rule.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "0.78.1",
4
+ "version": "0.79.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {