@erclx/aitk 1.5.0 โ†’ 1.6.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": "1.5.0",
4
+ "version": "1.6.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -13,6 +13,8 @@ A decision's verification anchor has the same shape of gap in the other directio
13
13
 
14
14
  A handoff file has the same shape of gap as an unmarked outcome. A page a learning workspace produced and an operator already picked a destination for sits in gitignored scratch until something lands it, and the session that produced it is gone by the time a branch exists to carry the write. Left unfolded it reads as promoted while the destination holds nothing.
15
15
 
16
+ The receipt half of that sweep was missing entirely. A review receipt is deleted per shipped branch and a memory-review receipt was skipped, because the exclusion protecting the checklist and audit prefixes caught a third by accident. Nothing but an operator asking collected it, and a collection that waits on someone remembering to ask is one a folder outgrows, so the skipped population grew per shipped branch and never shrank until it was most of the folder.
17
+
16
18
  The trigger side carries a gap of its own. "Sync the docs" names either corpus to the person saying it, so a description leaving its corpus to the opening clause alone competes with its public-facing sibling on nothing the routing field states, and the planning surface the request was about goes untouched.
17
19
 
18
20
  ## Must
@@ -26,6 +28,9 @@ The trigger side carries a gap of its own. "Sync the docs" names either corpus t
26
28
  - Retarget a closed task at the archived plan, so the reasoning behind finished work stays reachable
27
29
  - 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
28
30
  - Report an anchored decision whose cited path the diff touched, since the number was read before the branch moved what it counted
31
+ - Scan every memory-review receipt rather than the one matching this slug, since the skill that writes them runs after this one in the ship chain and a slug is unique per feature
32
+ - Collect a memory-review receipt whose items are all decided, folding each skip into its memory entry first, since a declined item is recorded nowhere else and a promoted one is already in git
33
+ - Leave a memory-review receipt holding a pending item, and report the count. A branch shipping is not an operator deciding what the receipt proposed.
29
34
  - Land each block of a promotion handoff at the destination its heading names, then delete the file so a later run does not fold it twice
30
35
  - Take a promotion destination as already decided, since the operator confirmed it where the page was produced
31
36
 
@@ -215,7 +215,9 @@ Sweep reviews this session consumed, and sweep plans across the whole board. Res
215
215
 
216
216
  Every move and delete below is a shell operation, so send each as a plain single `Bash` command rather than joining a `mkdir -p` to the `mv` with `&&`, which is refused as compound from a linked worktree. The one edit inside an existing file is the `Plan:` retarget, and no verb covers it: read the task file and write it back whole with a heredoc, which the file-editing tools refuse from a linked worktree and no shell stream editor may do.
217
217
 
218
- **Plans.** Scan every file in `.claude/tasks/`, not only the ones this session touched. For each task file whose outcomes are now all `[x]`, check for a `Plan:` line directly under the title and parse the target.
218
+ ### Plans
219
+
220
+ Scan every file in `.claude/tasks/`, not only the ones this session touched. For each task file whose outcomes are now all `[x]`, check for a `Plan:` line directly under the title and parse the target.
219
221
 
220
222
  The line carries a markdown link, so read the target out of the parentheses rather than taking the rest of the line. A task still carrying the older bare-path form parses the same way once the link is absent, so accept both. Resolve the target against `.claude/tasks/` before routing on it, which lands `../plans/x.md` and `.claude/plans/x.md` on the same file.
221
223
 
@@ -242,17 +244,30 @@ A plan can serve more than one task, and archiving on the first task to close st
242
244
 
243
245
  Write the retarget as a markdown link, `Plan: [feature-<slug>](../plans-archive/feature-<slug>.md)`, updating both halves so the text and the target stay in step. This branch is the only writer that produces a `Plan:` line nobody authored by hand, so a retarget that emits a bare path converts every task to the old form as it closes and drifts the board back to two shapes on its own.
244
246
 
245
- **Reviews.** Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
247
+ ### Reviews
248
+
249
+ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
250
+
251
+ If `.claude/review/review-<slug>.md` exists, delete it. `claude-review` writes with this convention.
252
+
253
+ Memory receipts sweep board-wide, like plans above and unlike the review receipt. Scan every `.claude/review/memory-review-*.md`, not only the one matching this slug. `claude-memory-review` writes its receipt after this skill has run in every ship chain, so a sweep keyed on the current slug looks for a file that does not exist yet, and no later branch looks for it either because a slug is unique per feature. Scanning the folder is what makes the sweep fire at all.
254
+
255
+ For each receipt, count the H2 items still marked ๐Ÿ“ pending:
256
+
257
+ - No pending item: fold it per the collection rule in `${CLAUDE_SKILL_DIR}/../../standards/memory.md`, then delete the receipt.
258
+ - Any pending item: leave it and report the count. Pending items are decision state, and a branch shipping is not an operator deciding them.
246
259
 
247
- If `.claude/review/review-<slug>.md` exists, delete it. `claude-review` writes with this convention. Do not sweep any other `review-*.md` file.
260
+ That standard owns what a fold writes and which entry types take one. `claude-memory-review` collects a receipt on the same rule, so neither body restates it.
248
261
 
249
- Do not sweep `ui-checklist-*.md` (pending human verification), `ux-audit-*.md`, or `ux-measure-*.md` (standalone deliverables).
262
+ Do not sweep `ui-checklist-*.md` (pending human verification), `ux-audit-*.md`, or `ux-measure-*.md` (standalone deliverables), or any other `review-*.md` file.
250
263
 
251
264
  Output one line per file swept:
252
265
 
253
266
  - `๐Ÿ“ฆ Archived: <path>` for a plan moved into `.claude/plans-archive/`
254
267
  - `โญ Kept: <path>, still cited by <task-file>` for a plan another live task shares
255
268
  - `๐Ÿงน Deleted: <path>` for a swept review
269
+ - `๐Ÿงน Deleted: <path>, folded <n> skips` for a swept memory receipt
270
+ - `โญ Kept: <path>, <n> items pending` for a memory receipt still holding decisions
256
271
 
257
272
  If nothing qualifies, skip this step silently.
258
273
 
@@ -21,7 +21,10 @@ A pen the caller cannot face is the same gap wearing a different shape. Routing
21
21
  - Write the proposal to a receipt on disk and take no action until the user decides per item
22
22
  - Route every decision channel through the receipt, writing a decision given in chat into its item's slot before the parse reads the file, so a channel the skill advertises drains the pen rather than passing over it
23
23
  - Keep a promotion on its own commit, since a change to how the agent operates should not ride inside a feature a reviewer is vetting for something else
24
- - Confine the pass that runs after application to the one receipt it tested, so tidying up removes a file whose decisions are known to be resolved and leaves the pen and every untested receipt alone
24
+ - Collect a receipt as soon as its last item resolves, rather than waiting for an operator to ask, since a collection nobody triggers is a folder that only grows
25
+ - Fold each declined item into its memory entry before the receipt goes, because a promoted item survives in its target and in git while a decline is recorded nowhere else
26
+ - Record that decline by rewriting the entry rather than appending to it, so the file states one current claim
27
+ - Confine the pass that runs after application to the one receipt it tested, so tidying up removes a file whose decisions are known to be resolved and leaves every untested receipt alone
25
28
 
26
29
  ## Must not
27
30
 
@@ -15,7 +15,7 @@ What an entry looks like and why a retired one is moved rather than deleted are
15
15
  | "challenge the promotes" (receipt exists) | Challenge | review file only |
16
16
  | "discuss", "respond to questions" | Discuss | review file only |
17
17
  | "apply decisions", "commit", "ship the review" | Apply | tracked files + memory files |
18
- | "cleanup", "delete the receipt" | Cleanup | one review file |
18
+ | "cleanup", "delete the receipt" | Cleanup | one receipt + its skips |
19
19
 
20
20
  If the user re-pings the skill with no new phrase and a receipt exists, default to Discuss when any `Decision:` contains `?`, otherwise Apply.
21
21
 
@@ -168,25 +168,34 @@ Apply promotion edits one at a time via `Edit`. Claude Code's tool permission di
168
168
 
169
169
  This governs the tracked surfaces a promote lands in, which sit at `pwd` and take `Edit` from anywhere. The receipt and the memory entries are main-root scratch and follow the guard instead.
170
170
 
171
- As each item resolves, update its status in the review file: flip the H2 emoji from ๐Ÿ“ to โœ… for applied, โญ for skipped, ๐Ÿ“ฆ for retired, or ๐Ÿค for handed off. Refresh the summary block counts at the top. Do not delete the review file. It stays as a receipt until Cleanup runs or the next Propose pass overwrites it.
171
+ As each item resolves, update its status in the review file: flip the H2 emoji from ๐Ÿ“ to โœ… for applied, โญ for skipped, ๐Ÿ“ฆ for retired, or ๐Ÿค for handed off. Refresh the summary block counts at the top. Do not delete the file here. The sweep below decides whether it goes.
172
172
 
173
173
  **Chat shortcut:** the user replies with `all`, `none`, a comma-separated list of numbers, or `skip <nums>`. Write the matching verb into the `Decision:` slot of every item the reply names, `apply` for `all` or a bare list and `skip` for a `skip` reply, then run the parse above against the file. A reply of `none` writes nothing. A slot the reply does not name keeps its own value, so the receipt stays the source of truth and an empty slot still means take no action.
174
174
 
175
+ ### Sweep the receipt
176
+
177
+ Count the items still ๐Ÿ“ pending once the parse above has run. Apply leaves one pending on `defer`, on empty, and on any unrecognized verb, so a receipt reaching this point may still be holding decisions.
178
+
179
+ Leave the receipt in place when any remain. When none do, collect it per the collection rule in `${CLAUDE_SKILL_DIR}/../../standards/memory.md`, which owns what a fold writes and which entry types take one.
180
+
181
+ `claude-docs` Step 10 sweeps the same folder on the same rule once per shipped branch, and either may reach a receipt first. Whichever does, the other finds no file and moves on.
182
+
175
183
  End with: `โœ… Applied: <nums> | โญ Skipped: <nums> | ๐Ÿ“ Pending: <nums>`. Omit empty buckets. If anything is pending, remind the user they can refine `Decision:` lines and re-ping, run "discuss" for question items, or commit a skip with `skip <nums>` in chat.
176
184
 
177
185
  ## Cleanup phase
178
186
 
179
187
  Trigger: user says "cleanup" or "delete the receipt" after Apply has run.
180
188
 
181
- Cleanup removes one receipt and nothing else. Apply is the only phase that moves a memory entry out of the pen, and it does so per approved item into `.claude/.tmp/memory-archive/`. A user asking to sweep stale memories wants Propose, which classifies entries and writes a decision slot per entry.
189
+ Cleanup folds one receipt's skips and removes that receipt, and does nothing else. It is the fallback route now that Apply and `claude-docs` Step 10 each collect a resolved receipt on their own, so it reaches a file those two left behind rather than being the only collector. Apply is still the only phase that moves a memory entry out of the pen, and it does so per approved item into `.claude/.tmp/memory-archive/`. A user asking to sweep stale memories wants Propose, which classifies entries and writes a decision slot per entry.
182
190
 
183
191
  If no `.claude/review/memory-review-*.md` exists at the main root, stop: `โœ… No review receipt to clean up.` Every other refusal in this skill carries a message, and the phase reads a receipt before it does anything else.
184
192
 
185
193
  1. Read the latest `.claude/review/memory-review-*.md` at the main root and confirm Apply has run against it. If any item is still ๐Ÿ“ pending, stop and name the pending numbers.
186
- 2. Delete that one file. Leave every other receipt beside it in place, because the pending test above covers the file it read and nothing has tested the rest.
187
- 3. Leave every memory entry in place. A `Skip` decision is terminal, and applied promotions, governance handoffs, and user-type memories each stay as the review left them.
194
+ 2. Collect it per the collection rule in `${CLAUDE_SKILL_DIR}/../../standards/memory.md`, folding each โญ skipped item before the file goes. The fold happens wherever a receipt is collected, so this phase runs the same rule the Apply sweep does.
195
+ 3. Delete that one file. Leave every other receipt beside it in place, because the pending test above covers the file it read and nothing has tested the rest.
196
+ 4. Leave every memory entry in the pen. A skip records the decline on the entry and keeps the file, and applied promotions, governance handoffs, and user-type memories each stay as the review left them.
188
197
 
189
- Do not promote, rewrite, or archive a memory entry. Receipts only.
198
+ Do not promote or archive a memory entry. The skip fold is the one rewrite this phase makes, and it records a decline on an entry that stays in the pen.
190
199
 
191
200
  ## After completion
192
201
 
@@ -195,6 +204,7 @@ Output one line per action taken in the most recent phase:
195
204
  - `โœ… Promoted: .claude/memory/<memory-file> โ†’ <target>`
196
205
  - `โœ… Handed off: .claude/memory/<memory-file> โ†’ governance`
197
206
  - `๐Ÿ“ฆ Retired: .claude/memory/<memory-file> โ†’ .claude/.tmp/memory-archive/`
198
- - `๐Ÿ—‘ Swept: .claude/review/<review-file>`
207
+ - `๐Ÿ—‘ Swept: .claude/review/<review-file>, folded <n> skips`
208
+ - `โญ Kept: .claude/review/<review-file>, <n> items pending`
199
209
 
200
210
  If the user accepted nothing, output: `โœ… No changes applied.`
@@ -74,7 +74,7 @@ For the shapes each check enforces, see `.claude/standards/plan.md`, `.claude/st
74
74
 
75
75
  ## Size
76
76
 
77
- `aitk records size` reports what each record folder holds and how much of it is recent. It reads the nine backed folders named under Push and pull, plus `.claude/.tmp`, and it gates nothing.
77
+ `aitk records size` reports what each record folder holds and how much of it is recent. It reads the ten backed folders named under Push and pull, plus `.claude/.tmp`, and it gates nothing.
78
78
 
79
79
  ```bash
80
80
  aitk records size
@@ -110,9 +110,9 @@ aitk records push --json
110
110
  aitk records pull
111
111
  ```
112
112
 
113
- The backed folders are `groundwork`, `intake`, `memory`, `plans`, `plans-archive`, `review`, `task-archive`, `tasks`, and `teach`, all under `.claude/`. They are the gitignored Claude group minus `.claude/.tmp`, which is deletable without loss, and `.claude/worktrees/`, whose contents belong to the project repository already. The list is a constant rather than configuration, matching the four folder names `validate` hardcodes.
113
+ The backed folders are `groundwork`, `intake`, `memory`, `plans`, `plans-archive`, `review`, `review-archive`, `task-archive`, `tasks`, and `teach`, all under `.claude/`. They are the gitignored Claude group minus `.claude/.tmp`, which is deletable without loss, and `.claude/worktrees/`, whose contents belong to the project repository already. The list is a constant rather than configuration, matching the four folder names `validate` hardcodes.
114
114
 
115
- 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.
115
+ 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.
116
116
 
117
117
  ### Setup
118
118
 
@@ -141,7 +141,7 @@ Point it at a private repository, and at one that is not a remote of the project
141
141
  | `local-ahead` | `pull` found local commits that never reached the origin |
142
142
  | `git-failed` | A git call failed, with its stderr in the message |
143
143
 
144
- The two `pull` refusals exist because the directions are not symmetric. A push only adds, while a pull onto a machine holding work that never left it would discard that work. Resolve either by running `push` first, or by moving the local folders aside. A machine holding none of the nine has nothing to lose, so a restore onto a fresh checkout runs straight through.
144
+ The two `pull` refusals exist because the directions are not symmetric. A push only adds, while a pull onto a machine holding work that never left it would discard that work. Resolve either by running `push` first, or by moving the local folders aside. A machine holding none of the ten has nothing to lose, so a restore onto a fresh checkout runs straight through.
145
145
 
146
146
  ### When it runs
147
147
 
@@ -93,7 +93,7 @@ An execution that picks other than the suggestion rewrites the `- Suggested:` li
93
93
 
94
94
  `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.
95
95
 
96
- `aitk records push` carries these folders off the disk they live on, and `aitk records pull` brings them back. Nine of them are backed: `groundwork`, `intake`, `memory`, `plans`, `plans-archive`, `review`, `task-archive`, `tasks`, and `teach`. 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.
96
+ `aitk records push` carries these folders off the disk they live on, and `aitk records pull` brings them back. Ten of them are backed: `groundwork`, `intake`, `memory`, `plans`, `plans-archive`, `review`, `review-archive`, `task-archive`, `tasks`, and `teach`. 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.
97
97
 
98
98
  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.
99
99
 
@@ -150,6 +150,8 @@ If capture wrote at least one memory file, `claude-memory-review` then proposes
150
150
 
151
151
  Run `claude-memory-review` standalone to curate the whole pen. An entry it retires moves to `.claude/.tmp/memory-archive/` rather than being deleted, since the folder is gitignored and a bulk pass has no undo.
152
152
 
153
+ The receipt is collected once every item on it has been decided, and it survives untouched while any item is still pending. Whichever runs first takes it: Apply collects the receipt it has resolved, and `claude-docs` scans the folder on every shipped branch for one an earlier session left behind. Before the file goes, each declined item is folded into the entry it was about, since a promotion survives in its target and in git while a decline is recorded nowhere else. `aitk standards memory` states what a fold writes and which entry types take one.
154
+
153
155
  ### UI polish
154
156
 
155
157
  Verify the change manually in the browser. Invoke `aitk:claude-ui-test` if you need e2e tests and a visual verification checklist for the session. For the fix itself, describe the change in Claude Code directly.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "1.5.0",
4
+ "version": "1.6.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -22,6 +22,7 @@ export const BACKED_FOLDERS = [
22
22
  'plans',
23
23
  'plans-archive',
24
24
  'review',
25
+ 'review-archive',
25
26
  'task-archive',
26
27
  'tasks',
27
28
  'teach',
@@ -103,6 +103,19 @@ Link a related entry as `[[name]]`, where `name` is the target's filename stem w
103
103
 
104
104
  The catalog is generated from sibling frontmatter rather than authored. Never hand-edit it, since the next regeneration discards whatever was added by hand.
105
105
 
106
+ ## Collecting a review receipt
107
+
108
+ A review of the pen writes a receipt recording what it proposed per entry and what was decided. The receipt is collected once every item on it has resolved, and it is held while any item is still pending, since a pending item is decision state the next round reads back.
109
+
110
+ Fold the declines before the receipt goes. A promoted entry survives in its target and in git and a retired one survives in the archive, so the one thing a receipt uniquely holds is the record that a rule was considered and turned down.
111
+
112
+ - Fold into the entry the item was about, and only into that entry. A decline whose proposed target was another surface still lands here.
113
+ - Fold a `feedback` or `project` entry alone. The decline belongs in the `**Why:**` line, which is what a later reader tests the rule against.
114
+ - Fold nothing into a `user` or `reference` entry. Its body is one sentence carrying neither marker, and such an entry is declined for having no in-repo target, which its type already states. Writing that on the entry restates the type and breaks the body shape.
115
+ - Record the decline by rewriting the entry, never by appending to it, per the lifecycle rule above.
116
+
117
+ Which surface runs the collection is project policy. More than one may, so a collector finding no receipt has been beaten to it rather than misconfigured.
118
+
106
119
  ## Anti-patterns
107
120
 
108
121
  - **The domain fact filed as memory.** It reads as a capture and lands in the one folder no session opens while working that domain.
@@ -8,4 +8,4 @@ runtime = ""
8
8
  scaffold = ""
9
9
 
10
10
  [gitignore]
11
- "# Claude" = [".claude/.tmp/", ".claude/groundwork/", ".claude/intake/", ".claude/memory/", ".claude/plans/", ".claude/plans-archive/", ".claude/review/", ".claude/task-archive/", ".claude/worktrees/", ".claude/tasks/"]
11
+ "# Claude" = [".claude/.tmp/", ".claude/groundwork/", ".claude/intake/", ".claude/memory/", ".claude/plans/", ".claude/plans-archive/", ".claude/review/", ".claude/review-archive/", ".claude/task-archive/", ".claude/worktrees/", ".claude/tasks/"]
@@ -19,6 +19,7 @@ The claude stack installs the `.claude/` workflow directory into a project. Stat
19
19
  โ”œโ”€โ”€ settings.json โ† seeded. Project-level Claude Code config (PreToolUse and PostToolUse hooks). User-level config installed separately via `aitk claude setup`.
20
20
  โ”œโ”€โ”€ plans/ โ† execution detail for multi-step tasks, gitignored. `feature-*.md` entries swept by claude-docs.
21
21
  โ”œโ”€โ”€ review/ โ† scratch for claude-review and claude-ui-test output, gitignored
22
+ โ”œโ”€โ”€ review-archive/ โ† memory-review receipts a triage took out of review/, gitignored
22
23
  โ”œโ”€โ”€ .tmp/ โ† ephemeral scratch space, gitignored
23
24
  โ””โ”€โ”€ memory/ โ† session facts no context entry owns, gitignored. `index.md` regenerated by a hook.
24
25
  ```
@@ -49,7 +50,7 @@ A project installed before the diagram surface became a folder still holds `.cla
49
50
 
50
51
  ## Gitignore
51
52
 
52
- - `# Claude`: `.claude/.tmp/`, `.claude/groundwork/`, `.claude/intake/`, `.claude/memory/`, `.claude/plans/`, `.claude/plans-archive/`, `.claude/review/`, `.claude/task-archive/`, `.claude/worktrees/`, `.claude/tasks/`
53
+ - `# Claude`: `.claude/.tmp/`, `.claude/groundwork/`, `.claude/intake/`, `.claude/memory/`, `.claude/plans/`, `.claude/plans-archive/`, `.claude/review/`, `.claude/review-archive/`, `.claude/task-archive/`, `.claude/worktrees/`, `.claude/tasks/`
53
54
 
54
55
  ## CLI
55
56