@erclx/aitk 3.6.0 → 3.8.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.
Files changed (59) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/claude-autoship/SKILL.md +5 -5
  3. package/claude/skills/claude-docs/SKILL.md +15 -10
  4. package/claude/skills/claude-memory-review/SKILL.md +7 -7
  5. package/claude/skills/claude-memory-review/references/receipt-format.md +1 -1
  6. package/claude/skills/claude-orchestrate/SKILL.md +2 -2
  7. package/claude/skills/claude-pr-review/SKILL.md +25 -7
  8. package/claude/skills/claude-review/SKILL.md +5 -3
  9. package/claude/skills/claude-screencast/SKILL.md +9 -4
  10. package/claude/skills/claude-tasks/SKILL.md +2 -2
  11. package/claude/skills/create-rule/REQUIREMENT.md +2 -1
  12. package/claude/skills/create-rule/SKILL.md +8 -8
  13. package/claude/skills/create-snippet/REQUIREMENT.md +3 -0
  14. package/claude/skills/create-snippet/SKILL.md +2 -2
  15. package/claude/skills/git-pr/references/pr.md +3 -0
  16. package/claude/skills/git-ship/SKILL.md +1 -1
  17. package/claude/skills/git-split/references/pr.md +3 -0
  18. package/claude/skills/restate/REQUIREMENT.md +41 -0
  19. package/claude/skills/restate/SKILL.md +39 -0
  20. package/claude/skills/toolkit-feedback/SKILL.md +2 -2
  21. package/claude/skills/write-human/REQUIREMENT.md +1 -1
  22. package/claude/skills/write-human/SKILL.md +1 -1
  23. package/docs/agents/capture.md +3 -1
  24. package/docs/agents/commands.md +25 -21
  25. package/docs/agents/demo.md +82 -0
  26. package/docs/agents/index.md +2 -0
  27. package/docs/agents/install-and-sync.md +6 -2
  28. package/docs/agents/records.md +2 -2
  29. package/docs/agents/routing.md +61 -0
  30. package/docs/agents/tasks.md +1 -1
  31. package/docs/ai-workflow.md +8 -5
  32. package/docs/operating-model.md +13 -4
  33. package/governance/rules/claude/558-plan.md +1 -2
  34. package/governance/rules/lib/300-testing-ts.md +1 -0
  35. package/package.json +3 -2
  36. package/src/claude/routing.ts +283 -0
  37. package/src/cli.ts +4 -1
  38. package/src/commands/claude.ts +130 -1
  39. package/src/commands/demo.ts +373 -0
  40. package/src/commands/feedback.ts +10 -3
  41. package/src/commands/tasks.ts +1 -1
  42. package/src/demo/beats.ts +135 -0
  43. package/src/demo/compile.ts +295 -0
  44. package/src/demo/cursors.ts +55 -0
  45. package/src/demo/drive.ts +256 -0
  46. package/src/demo/pointer.ts +178 -0
  47. package/src/demo/theme.ts +112 -0
  48. package/src/gov/adapter.ts +1 -0
  49. package/src/records/backup.ts +34 -8
  50. package/src/snippets/adapter.ts +1 -0
  51. package/src/sync/engine.ts +25 -1
  52. package/src/tasks/archive.ts +11 -4
  53. package/standards/bundled/pr.md +3 -0
  54. package/standards/plan.md +1 -1
  55. package/standards/tasks.md +4 -4
  56. package/tooling/claude/manifest.toml +1 -1
  57. package/tooling/claude/reference.md +6 -5
  58. package/tooling/claude/seeds/.claude/hooks/tasks-index.sh +4 -1
  59. package/tooling/claude/seeds/CLAUDE.md +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: toolkit-feedback
3
- description: Format a paste-back report about something broken, missing, or off in aitk and write it directly to the toolkit's `.claude/review/` folder via `aitk feedback`. Use when asked to "send this to the toolkit", "report this to aitk", "file toolkit feedback", or "give the toolkit feedback about X". Do NOT use for general complaints about other tooling, IDE issues, or in-project bugs that do not implicate aitk surfaces.
3
+ description: Format a paste-back report about something broken, missing, or off in aitk and write it directly to the toolkit's `.claude/review/feedback/` folder via `aitk feedback`. Use when asked to "send this to the toolkit", "report this to aitk", "file toolkit feedback", or "give the toolkit feedback about X". Do NOT use for general complaints about other tooling, IDE issues, or in-project bugs that do not implicate aitk surfaces.
4
4
  ---
5
5
 
6
6
  # Toolkit feedback
@@ -48,7 +48,7 @@ Detect whether `aitk` is on PATH:
48
48
  command -v aitk >/dev/null 2>&1
49
49
  ```
50
50
 
51
- If present, pipe the block to `aitk feedback`. The CLI writes to its own repo's `.claude/review/feedback-<slug>-<ts>.md` and prints the absolute path on stdout:
51
+ If present, pipe the block to `aitk feedback`. The CLI writes to its own repo's `.claude/review/feedback/feedback-<slug>-<ts>.md` and prints the absolute path on stdout:
52
52
 
53
53
  ```bash
54
54
  cat <<'EOF' | aitk feedback
@@ -41,6 +41,6 @@ Importing that catalog wholesale fails on a different measurement. External mate
41
41
 
42
42
  - The banned words, characters, and spellings, which `markdown.md` states for a reader and `aitk markdown audit` gates from package data
43
43
  - Markdown mechanics, being headings, lists, code spans, punctuation, and file references
44
- - Restating text that already exists in plainer words, which is a different job on a different trigger, since a restatement is asked for by name and this arrives on a glob match
44
+ - Restating text that already exists in plainer words, which `restate` owns on a different trigger, since a restatement is asked for by name and this arrives on a glob match. The rules here still govern how that restatement reads, and that body cites this one rather than carrying a copy.
45
45
  - What voice a given surface declares, which belongs to the standard governing that surface
46
46
  - Measuring whether finished output followed these rules, which needs a check this skill does not carry
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: write-human
3
- description: Carries the voice, rhythm, sentence construction, and information density rules a banned-word list cannot express, plus the catalog of machine tells that survive a clean ban scan. Use when writing or revising prose a person will read, when a passage reads flat or uniform, or when asked to "make this read like a person", "fix the cadence", "this reads like AI wrote it", "vary the sentences", or "tighten this without gutting it". Do NOT use for banned words, characters, or spellings, which `markdown.md` states and `aitk markdown audit` gates, and do NOT use to restate text that already exists in plainer words.
3
+ description: Carries the voice, rhythm, sentence construction, and information density rules a banned-word list cannot express, plus the catalog of machine tells that survive a clean ban scan. Use when writing or revising prose a person will read, when a passage reads flat or uniform, or when asked to "make this read like a person", "fix the cadence", "this reads like AI wrote it", "vary the sentences", or "tighten this without gutting it". Do NOT use for banned words, characters, or spellings, which `markdown.md` states and `aitk markdown audit` gates, and do NOT use to restate text that already exists in plainer words, which is `restate`, whose body loads these rules from here.
4
4
  ---
5
5
 
6
6
  # Write human
@@ -32,4 +32,6 @@ What is asserted is the font. The command reads the first family the captured el
32
32
 
33
33
  The browser binary installs separately from the package. A fresh clone runs `bunx playwright install chromium` once, and a run that cannot launch one reports the engine's own remediation inside the frame and exits 1 rather than escaping as a stack trace.
34
34
 
35
- The command is toolkit-only. Its render module holds every browser reference in the toolkit and `files` in `package.json` excludes it, so an installed `aitk` carries the command, reports it as absent on one line, and exits 1. Every other command is unaffected, which is the reason the browser import sits behind a dynamic import rather than at a command's top level.
35
+ The command is toolkit-only. Its render module holds every browser reference capture makes and `files` in `package.json` excludes it, so an installed `aitk` carries the command, reports it as absent on one line, and exits 1. Every other command is unaffected, which is the reason the browser import sits behind a dynamic import rather than at a command's top level.
36
+
37
+ `aitk demo` is the other browser command and it ships, because the reason capture stays here is that it regenerates images committed to this repository and a target has nothing to regenerate. See `demo.md`.
@@ -24,7 +24,7 @@ Full help: `aitk <command> --help`. Behavior notes for the install and sync verb
24
24
  | `aitk design render` | Render `.claude/DESIGN.md` tokens to HTML and CSS |
25
25
  | `aitk slides render` | Render a `.claude/SLIDES.md` source into a PowerPoint deck |
26
26
  | `aitk slides list` | List the available slide layouts (`--json` for the catalog) |
27
- | `aitk feedback` | Write toolkit feedback from stdin to `.claude/review/`, or open a GitHub issue with `--github` |
27
+ | `aitk feedback` | Write toolkit feedback from stdin to `.claude/review/feedback/`, or open a GitHub issue with `--github` |
28
28
  | `aitk transcripts <url>` | Fetch a YouTube transcript with metadata frontmatter (needs `yt-dlp`) |
29
29
  | `aitk tasks archive` | Move a shipped task off the board, clear its ordering row, and regenerate the index |
30
30
  | `aitk tasks pull-request` | Record a pull request number on the task a branch closes, by stem or `--plan` (`--json`) |
@@ -47,6 +47,7 @@ Full help: `aitk <command> --help`. Behavior notes for the install and sync verb
47
47
  | `aitk claude skills audit` | Report both skill corpora against the mechanical rules in `standards/skill.md` |
48
48
  | `aitk claude skills drift` | Name the shipped skill bodies rewritten between a given ref and `HEAD`, and the installed version against the newest published (`--json`) |
49
49
  | `aitk claude skills reach` | Report the shipped bodies citing a toolkit path no target project receives, exiting 2 on an unqualified one |
50
+ | `aitk claude routing` | Report per `CLAUDE.md` section how many bullets name a path and how many of those a path-scoped rule already covers (`--json`) |
50
51
  | `aitk gov test-order` | Report where an implementation reached history ahead of the test covering it (`--json`) |
51
52
  | `aitk gov superseded` | Report where the tree still asserts a value a changed convention no longer produces, keyed on the value (`--json`) |
52
53
  | `aitk secrets scan` | Report credential-shaped values in the tree the package ships, keyed on issued values rather than on words (`--json`) |
@@ -57,30 +58,33 @@ Full help: `aitk <command> --help`. Behavior notes for the install and sync verb
57
58
  | `aitk capture [source]` | Render HTML capture sources to PNG, toolkit-only and absent from an installed package |
58
59
  | `aitk upgrade` | Reinstall the CLI globally with the package manager the install path names (`--json`) |
59
60
 
61
+ `aitk demo` is the second browser command and the one that ships, since its purpose is running in a target rather than regenerating what this repository commits. It needs a browser binary the package does not carry, installed once with `bunx playwright install chromium`.
62
+
60
63
  ## Domain commands
61
64
 
62
65
  Each domain exposes a consistent shape where applicable: `list`, `install`, `sync`, `create`.
63
66
 
64
- | Domain | Subcommands |
65
- | ----------- | ----------------------------------------------------------------------------------------------------------- |
66
- | `tooling` | `list`, `sync`, `ref`, `create`, `verify`, `inject`, `prune-gitignore` |
67
- | `snippets` | `list`, `install`, `sync`, `create` |
68
- | `standards` | `list`, `<name>` |
69
- | `gov` | `list`, `install`, `sync`, `build`, `regen`, `test-order`, `superseded` |
70
- | `claude` | `init`, `sync`, `seeds list`, `skills list`, `skills audit`, `skills drift`, `skills reach`, `setup [dest]` |
71
- | `wiki` | `init` |
72
- | `design` | `render` |
73
- | `slides` | `render`, `list` |
74
- | `tasks` | `archive`, `validate` |
75
- | `intake` | `list`, `answer` |
76
- | `teach` | `list`, `open`, `resource`, `glossary` |
77
- | `comments` | `scan` |
78
- | `context` | `audit` |
79
- | `markdown` | `audit` |
80
- | `secrets` | `scan` |
81
- | `deps` | `audit` |
82
- | `labels` | `audit` |
83
- | `audits` | `run`, `list` |
67
+ | Domain | Subcommands |
68
+ | ----------- | ---------------------------------------------------------------------------------------------------------------------- |
69
+ | `tooling` | `list`, `sync`, `ref`, `create`, `verify`, `inject`, `prune-gitignore` |
70
+ | `snippets` | `list`, `install`, `sync`, `create` |
71
+ | `standards` | `list`, `<name>` |
72
+ | `gov` | `list`, `install`, `sync`, `build`, `regen`, `test-order`, `superseded` |
73
+ | `claude` | `init`, `sync`, `routing`, `seeds list`, `skills list`, `skills audit`, `skills drift`, `skills reach`, `setup [dest]` |
74
+ | `demo` | `compile`, `run` |
75
+ | `wiki` | `init` |
76
+ | `design` | `render` |
77
+ | `slides` | `render`, `list` |
78
+ | `tasks` | `archive`, `validate` |
79
+ | `intake` | `list`, `answer` |
80
+ | `teach` | `list`, `open`, `resource`, `glossary` |
81
+ | `comments` | `scan` |
82
+ | `context` | `audit` |
83
+ | `markdown` | `audit` |
84
+ | `secrets` | `scan` |
85
+ | `deps` | `audit` |
86
+ | `labels` | `audit` |
87
+ | `audits` | `run`, `list` |
84
88
 
85
89
  Common patterns:
86
90
 
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: Demo
3
+ description: Compiling a screencast draft into a runnable plan, driving a served application to a recording and a still, the pointer the recording paints, and what each refusal reports
4
+ ---
5
+
6
+ # Demo
7
+
8
+ `aitk demo` drives a project's running application and writes a recording of what it did, plus a still frame of the same run. It exists so a project card and a short demo stop depending on someone sitting down to record one by hand.
9
+
10
+ Two verbs, and they are separate because the artifact between them is edited.
11
+
12
+ ```bash
13
+ aitk demo compile .claude/.tmp/screencast/inline-edit.md
14
+ aitk demo run demos/inline-edit.json
15
+ aitk demo run demos/inline-edit.json --cursor ~/cursors/theme --out assets
16
+ ```
17
+
18
+ ## The draft and the plan are different files
19
+
20
+ `claude-screencast` drafts beats for a person. A beat carries what is on screen, one verb, what to watch for, an emphasis, and a caption, and none of that names a selector, a URL, a wait condition, or a timing. Those four are what an executor needs and what would ruin the draft, since the format is pre-seeded so the operator edits down rather than fills blanks.
21
+
22
+ So `aitk demo compile` writes a second artifact rather than adding fields to a beat. It maps each beat's verb to a step, seeds the timing, marks which beat the still comes from, and leaves the target and the URL empty for a person to fill. The report names every field it could not supply.
23
+
24
+ The plan is committed, not scratch. Its timing is a starting point tuned by watching a recording, and the draft cannot reproduce a tuned value, so a recompile over an existing plan refuses and names `--force`.
25
+
26
+ | Option | Behavior |
27
+ | --------------- | ----------------------------------------------------------------- |
28
+ | `--out <dir>` | Directory the plan and its output paths point at, default `demos` |
29
+ | `--slug <slug>` | Plan name, defaulting to the draft filename |
30
+ | `--force` | Overwrite an existing plan, losing any timing tuned by hand |
31
+ | `--json` | Add a record on stdout carrying the beats and what is unfilled |
32
+
33
+ ## What a run does
34
+
35
+ `aitk demo run` reads the plan, refuses if a field is still empty, and drives the application the plan's URL names. It records the whole run to `webm` and writes the still from the beat the draft calls the hero, falling back to the last beat, since a demo's final state is the payoff and a cold open is usually an empty screen.
36
+
37
+ | Option | Behavior |
38
+ | ---------------- | ----------------------------------------------------------- |
39
+ | `--out <dir>` | Directory to write into, overriding what the plan names |
40
+ | `--cursor <dir>` | Cursor theme folder to draw the pointer from |
41
+ | `--no-video` | Write only the still |
42
+ | `--no-still` | Write only the recording |
43
+ | `--json` | Add a record on stdout carrying both paths and the duration |
44
+
45
+ A step waits on its `waitFor` selector becoming visible and then holds for its own `holdMs`, which is what puts a finished state on screen long enough to read. `navigate` uses the plan's URL unless the step names its own.
46
+
47
+ ## The pointer is painted inside the page
48
+
49
+ The browser engine's own annotation draws a red dot at the moment of a click and an action label in a corner. It paints no cursor, so a run without more looks like the pointer teleports between targets.
50
+
51
+ The recorder injects a pointer element before navigation and moves it through the engine's pointer with interpolated steps rather than through the element-clicking helper, which resolves a target and jumps to it. The step count is the whole difference between a cursor that travels and one that appears. The pointer reads the element under it on every move and switches between an arrow, a hand, and a text beam, so it reflects the page the way a real cursor does.
52
+
53
+ `--cursor` points at a folder of Windows cursor resources and the browser decodes them directly, with no conversion step and no image tooling. Each resource carries a hotspot per size, and the largest entry's hotspot scaled to the drawn size is what puts the artwork's tip where the click lands. A theme contributes per state, so a folder holding an arrow and no hand still supplies its arrow and the bundled artwork covers the rest.
54
+
55
+ Three of the nineteen states a theme carries are read. A drag, a resize, or a wait shows the arrow where a real session would show something else, and the two animated states have no still frame to draw.
56
+
57
+ ## What the refusals report
58
+
59
+ Every refusal exits 1 and names its reason in the `--json` record, so a skill branches on `reason` rather than on the exit code.
60
+
61
+ | Reason | What happened |
62
+ | --------------------- | ----------------------------------------------------------------------------------- |
63
+ | `draft-missing` | No file at the path given to `compile` |
64
+ | `draft-unreadable` | The draft carries no beat sheet, or a sheet with no beats |
65
+ | `plan-exists` | A plan is already there and `--force` was not passed |
66
+ | `plan-unresolved` | A URL or a target is still empty, named field by field |
67
+ | `no-output-requested` | `--no-video` and `--no-still` together, which would drive the app and write nothing |
68
+ | `plan-unreadable` | The plan is not JSON, or a step names a kind nothing drives |
69
+ | `browser-missing` | The browser binary is not installed, with `install` carrying the command |
70
+ | `engine-missing` | The browser package itself did not resolve |
71
+
72
+ ## The browser reaches every target
73
+
74
+ Unlike `aitk capture`, this command ships. Capture is toolkit-only because it regenerates images committed to this repository, and that reason does not transfer to a command whose whole purpose is running in someone else's project.
75
+
76
+ The cost is stated rather than hidden: the browser binary installs separately, so a target runs `bunx playwright install chromium` once before a recording works at all. A run that cannot launch reports that command inside the frame and exits 1.
77
+
78
+ ## What it does not do
79
+
80
+ A generated recording is a raw take. Nothing trims it, scores it, or narrates it, and the beat's caption does not reach the video, since the engine's overlay carries the action it performed rather than text from the draft.
81
+
82
+ It also does not replace a narrated screencast. That has a hero moment, a cut list, and a voice, none of which survives being generated. This answers the case where the alternative is recording nothing.
@@ -14,6 +14,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
14
14
  - [Comments](comments.md): Comment density by language and kind, the two structural exclusions, and how the degradation sweep finds its vocabulary
15
15
  - [Context audit checks](context-audit-checks.md): What each non-gating check reports, the unit each checkpoint is measured in, the architecture record's length gate and claim coverage, which folders each check reaches, and what moved to the attribute tier
16
16
  - [Context audit](context-audit.md): Running the audit, its flags and folder scope, the exit codes, the citation gate, and the widened gate the seed stage runs
17
+ - [Demo](demo.md): Compiling a screencast draft into a runnable plan, driving a served application to a recording and a still, the pointer the recording paints, and what each refusal reports
17
18
  - [Docs](docs.md): How aitk docs resolves the toolkit's own reference surface from an install root, and how a split domain is named
18
19
  - [Indexes](indexes.md): Flags, exit codes, and JSON shape for aitk indexes regen, plus when it auto-stages what it rewrote
19
20
  - [Install and sync](install-and-sync.md): What each install and sync verb writes, refuses, or leaves alone, and how drift is attributed in a target project
@@ -23,6 +24,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
23
24
  - [Output shape](output-shape.md): Two framed shapes every command renders into, how JSON and --names modes keep stdout clean, and the exit discipline that lets piped output drain
24
25
  - [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
25
26
  - [Records](records.md): Validating the session records under .claude/ and the standards corpus, the per-kind checks, the refusal reasons, reading each folder's size and growth, backing the folders to a private remote, and which root each kind defaults to
27
+ - [Routing report](routing.md): Reading per CLAUDE.md section how many bullets name a path, what counts as naming one, when a rule counts as covering it, the two refusals, and why the verb reports rather than gates
26
28
  - [Sandbox](sandbox.md): Scenario routing, the expectation scoring surface, and the coverage census over scenarios and skills
27
29
  - [Scripting](scripting.md): The runtime catalogs that replace hardcoded names, what each carries, and a headless invocation per domain
28
30
  - [Sessions](sessions.md): Resolving live peer sessions to the worktree and branch each holds, the liveness confidence field, the unresolved reasons, and what the read depends on
@@ -11,7 +11,9 @@ The behavior notes behind the verbs listed in `commands.md`. Each one records wh
11
11
 
12
12
  `aitk gov sync` updates only rules already present under `.claude/rules/` and
13
13
  never adds new ones. A rule the toolkit does not ship is left alone, which is
14
- how project-authored rules survive. It also removes a stale `.claude/GOV.md`
14
+ how project-authored rules survive, and one under `.claude/rules/project/`
15
+ is left alone regardless of its name, since that subfolder is project-authored
16
+ by location. It also removes a stale `.claude/GOV.md`
15
17
  from the retired build. Use `aitk gov install` to add rules.
16
18
 
17
19
  There is no `aitk standards sync` and no `aitk standards install`. The corpus
@@ -23,7 +25,9 @@ the catalog.
23
25
  `aitk snippets sync` matches by path relative to `.claude/snippets/`. It
24
26
  matches by path relative to that directory, so a snippet the toolkit no longer
25
27
  ships, or one authored directly in the target, is reported and skipped rather
26
- than deleted. It is not preset-aware, so a project that installed `essentials`
28
+ than deleted, and a snippet under `.claude/snippets/project/` skips the same
29
+ way regardless of path, since that subfolder is project-authored by location.
30
+ It is not preset-aware, so a project that installed `essentials`
27
31
  does not grow new snippets on a sync. Use `aitk snippets install` to add them.
28
32
 
29
33
  ## Install guards
@@ -110,7 +110,7 @@ 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`, `review-archive`, `task-archive`, `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 ten are pushed into. The list is a constant rather than configuration, matching the four folder names `validate` hardcodes.
113
+ 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.
114
114
 
115
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
 
@@ -145,4 +145,4 @@ The two `pull` refusals exist because the directions are not symmetric. A push o
145
145
 
146
146
  ### When it runs
147
147
 
148
- `.husky/post-merge` runs `push` after the task-archive loop, on every merge rather than only on one that archived a task. A review report and a memory entry both land on runs that close nothing. The call sits inside an `if` and last in the file, so an unreachable remote neither aborts the hook nor delays the archiving above it, and a checkout that never ran the setup reports nothing. Anything the hook misses is covered by running the verb by hand.
148
+ `.husky/post-merge` runs `push` after the task archiving loop, on every merge rather than only on one that archived a task. A review report and a memory entry both land on runs that close nothing. The call sits inside an `if` and last in the file, so an unreachable remote neither aborts the hook nor delays the archiving above it, and a checkout that never ran the setup reports nothing. Anything the hook misses is covered by running the verb by hand.
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: Routing report
3
+ description: Reading per CLAUDE.md section how many bullets name a path, what counts as naming one, when a rule counts as covering it, the two refusals, and why the verb reports rather than gates
4
+ ---
5
+
6
+ # Routing report
7
+
8
+ `aitk claude routing` reports, per `CLAUDE.md` section, how many top-level bullets name a path and how many of those a path-scoped rule already covers. It answers the tier test in `.claude/rules/claude/592-claude-md.md`, which asks whether a fact applies every session or fires on one path, and which until this verb existed was a judgment nothing counted.
9
+
10
+ ```bash
11
+ aitk claude routing
12
+ aitk claude routing --json
13
+ aitk claude routing ../my-app
14
+ ```
15
+
16
+ | Option | Behavior |
17
+ | -------- | ------------------------------------------------------------ |
18
+ | `[path]` | Repository root to read, defaulting to the current directory |
19
+ | `--json` | Add a machine-readable record on stdout, keeping the frame |
20
+
21
+ Under `--json` the record holds stdout alone and the frame still renders on stderr, refusals included, which is the split `output-shape.md` fixes for every mode.
22
+
23
+ The root is the argument rather than the toolkit, matching the reach and drift verbs, so a linked worktree reads its own branch and a target reads its own file.
24
+
25
+ ## What it reads
26
+
27
+ Every H2 and H3 owning at least one top-level bullet. An H3 is reported under the H2 containing it, as `Behavior / Scope discipline`, so a section and its subsections are counted apart rather than summed.
28
+
29
+ Three things are read past. A nested bullet belongs to the one above it rather than to the section. A bullet inside a fenced block is example text rather than instruction. A heading carrying no bullet answers nothing the report asks, so it is dropped rather than listed at zero.
30
+
31
+ ## What counts as naming a path
32
+
33
+ A bullet is path-scoped here when it names a path. That is evidence for the tier judgment rather than the judgment itself, and the gap runs both ways: a bullet naming a folder can still apply every session, and one firing on a path it never spells is invisible to the count. Read a section's number as a place to look rather than as a verdict on it.
34
+
35
+ A backticked token counts when it carries a separator or an alphabetic extension, which admits `src/cli.ts` and `cspell.json` while leaving a flag, a bare word, and a version string out.
36
+
37
+ A shape counts as the folder above its placeholder. `.claude/context/<domain>.md` names `.claude/context/` and nothing narrower, so dropping the token whole would report the section carrying it as naming no path at all. A placeholder opening the first segment has no openable prefix and is dropped.
38
+
39
+ ## When a rule counts as covering it
40
+
41
+ A rule covers a named path only when its glob anchors to a location. A glob opening `**` reaches every folder in the tree, so it answers that a file type is governed and never that a named path is.
42
+
43
+ The corpus-wide markdown rules are what force that. Counting one reports every markdown path as covered, which collapses the column to a constant and tells a reader nothing about which folder somebody actually scoped a rule to.
44
+
45
+ A folder is probed with a handful of extensions rather than matched literally, because a glob narrowed by file type reaches under a folder without ever matching the folder's own name. Globs are read from each rule's frontmatter block alone, so a rule quoting a path in its body does not register a scope it never declared.
46
+
47
+ The paths a section names that no rule reaches are listed beside it, which is where a reader looks first when deciding what a new rule would cover.
48
+
49
+ ## Refusals
50
+
51
+ Two, each naming what a reader does about it. `no-claude-md` is a tree with no always-loaded file. `no-rules` is a tree carrying no path-scoped rule under `.claude/rules/`, where every path would report as uncovered and the column would say nothing.
52
+
53
+ An always-on rule declaring no `paths` is skipped rather than refused. It applies at the same priority as the always-loaded file, so it covers no path in particular.
54
+
55
+ ## Exit codes
56
+
57
+ Exit codes are `0` when the file was read and `1` for a refusal. No finding moves the exit code.
58
+
59
+ Nothing wires this into `bun run check` or into a hook. Whether a bullet belongs in a rule is a judgment, and gating a measure that counts a judgment forces an escape hatch for every deliberate case.
60
+
61
+ An exit code says nothing about a call made from a session, since a shell profile may wrap the binary in a function taking its status from a later command. Read the JSON record's `sections` array rather than the exit when a skill consumes this.
@@ -7,7 +7,7 @@ description: Selecting a shipped task by stem or pull request, recording a numbe
7
7
 
8
8
  ## Archive
9
9
 
10
- `aitk tasks archive` moves a shipped task from `.claude/tasks/` into `.claude/task-archive/`, drops its row from `priority.md`, and regenerates the board index. The three run as one unit, so the attended and unattended callers cannot archive differently.
10
+ `aitk tasks archive` moves a shipped task from `.claude/tasks/` into `.claude/tasks/archive/`, drops its row from `priority.md`, and regenerates the board index. The three run as one unit, so the attended and unattended callers cannot archive differently.
11
11
 
12
12
  Name the task by its filename stem, or by the pull request it carries:
13
13
 
@@ -71,7 +71,7 @@ When features are independent, run them in parallel instead of sequentially. Use
71
71
 
72
72
  - Create a worktree per feature, then start a Claude Code session in each
73
73
  - Invoke `aitk:claude-feature` in each session. Plans land at the main worktree root as `.claude/plans/feature-<slug>.md`, one per feature, no collisions. Small features stay in chat and skip the file.
74
- - Implement, verify, and review each feature independently. `claude-review` and `claude-ui-test` write per-branch files at the main worktree root (`review-<slug>.md`, `ui-checklist-<slug>.md`), so parallel sessions do not overwrite each other. The slug is the branch name with any leading type segment dropped, so `feat/jwt-expiration` and the plan at `feature-jwt-expiration.md` meet on one name
74
+ - Implement, verify, and review each feature independently. `claude-review` and `claude-ui-test` write per-branch files at the main worktree root (`review/branch/review-<slug>.md`, `review/ui-checklist-<slug>.md`), so parallel sessions do not overwrite each other. The slug is the branch name with any leading type segment dropped, so `feat/jwt-expiration` and the plan at `feature-jwt-expiration.md` meet on one name
75
75
  - Ship each worktree separately with `aitk:git-ship`
76
76
  - For full autonomy per worktree, invoke `aitk:claude-autoship` instead of the manual chain. Approve the plan, walk away, come back to draft PRs.
77
77
 
@@ -93,15 +93,17 @@ 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. 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.
96
+ `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.
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
 
100
100
  `aitk records size` reports what each of these folders holds, heaviest first, along with `.claude/.tmp`. Each row carries the file count, the bytes, how many files were written in the last 7 and 30 days, and the dates of the least and most recently written one. Nothing fails on a number, because a record folder has no correct size. What the verb replaces is a reading somebody had to remember to take: the memory pen went from 44 entries to 236 between two counts made by hand a fortnight apart, and nothing reported the rate in between.
101
101
 
102
- A plan that ships is archived, never deleted. `aitk:claude-docs` moves it to `.claude/plans-archive/` and retargets the task file's `Plan:` line at the new location, so a completed task still leads to the reasoning behind it. Both folders are gitignored, which is why a deleted plan had no recovery path. A plan cited by more than one task stays put until the last of them closes, since moving it early would strand every other pointer.
102
+ A plan that ships is archived, never deleted. `aitk:claude-docs` moves it to `.claude/plans/archive/` and retargets the task file's `Plan:` line at the new location, so a completed task still leads to the reasoning behind it. An archive sits inside the record folder it archives rather than beside it, so one ignore entry and one backed-folder entry cover a record and everything it has retired. The folder is gitignored, which is why a deleted plan had no recovery path. A plan cited by more than one task stays put until the last of them closes, since moving it early would strand every other pointer.
103
103
 
104
- The sweep reads the whole board rather than the tasks the session touched. It is the one place the skill reaches past its own rule against editing a task file the session did not change, because a task that closed while an earlier run missed its archive is exactly what the sweep exists to clear. Reaching it is safe: the archive moves the plan and retargets the pointer in the same pass, so an untouched task ends up with a working link rather than a broken one.
104
+ A branch review report takes the other route and is swept rather than archived. `claude-review` writes it to `.claude/review/branch/`, the session addressing it reads it once, and the durable record of what a review found is the comment `claude-pr-review` posts on the pull request, so `claude-docs` deletes the report at ship and any report whose branch is gone. What that loses is a local-only review on a branch that never opened a pull request, which is why the report says so where a reader meets it.
105
+
106
+ The plans sweep reads the whole board rather than the tasks the session touched. It is the one place the skill reaches past its own rule against editing a task file the session did not change, because a task that closed while an earlier run missed its archive is exactly what the sweep exists to clear. Reaching it is safe: the archive moves the plan and retargets the pointer in the same pass, so an untouched task ends up with a working link rather than a broken one.
105
107
 
106
108
  `aitk:claude-docs` decides which task closed by reading the diff rather than the conversation. It resolves a merge base against `origin/main`, unions the committed diff with the working tree and untracked files, then matches unchecked outcomes on the board against what shipped. A task that shipped without ever being discussed still gets marked. Requirements, architecture, and design stay session-sourced, because a diff cannot carry a judgment.
107
109
 
@@ -111,7 +113,7 @@ The sweep reads the whole board rather than the tasks the session touched. It is
111
113
 
112
114
  `aitk tasks validate` checks what those rows claim against what the tree holds: every plan pointer resolves, every task file is named by a board row or a backlog line and never by both, no task sits in two groups, and no two rows marked ready touch the same file. One check across both surfaces is what lets a task move between the board and the backlog without the move reading as a dropped file. That fourth check is the half a reader cannot run by eye, and it is what keeps two workers from being handed colliding work. A fifth re-takes what a parked row waits on, reporting one whose cited task reached the trunk and one whose cited file nothing running still holds. A cited task settles the row by being archived, or by closing every outcome and naming a pull request the trunk carries, since the checkbox alone is marked while the branch is still in review. Both halves read a citation out of the blocker cell, so a row citing neither is reported as untested rather than counted clean, and so is a cited task the trunk could not answer for. It reports and never writes, because a row is the orchestrator's claim and a validator repairing one would assert the claim it exists to test. Nothing fires it automatically, since the board is gitignored per-machine scratch with no shared moment to hang a hook on, so the orchestrator's sweep calls it at the point the readiness claim is made and follows it with the parked re-test.
113
115
 
114
- `aitk:claude-tasks` owns the two operations that bracket a task's life. It creates the file, holding the filename convention and the frontmatter contract so a malformed write cannot break the index for every sibling, and it moves a shipped task to `.claude/task-archive/`. Creation is where the origin invariant is enforced: every task names a plan, a groundwork folder, an intake folder, or an issue, since a task with no origin is either lost context or work nobody decided to do.
116
+ `aitk:claude-tasks` owns the two operations that bracket a task's life. It creates the file, holding the filename convention and the frontmatter contract so a malformed write cannot break the index for every sibling, and it moves a shipped task to `.claude/tasks/archive/`. Creation is where the origin invariant is enforced: every task names a plan, a groundwork folder, an intake folder, or an issue, since a task with no origin is either lost context or work nobody decided to do.
115
117
 
116
118
  Archiving a task leaves its plan alone, because `aitk:claude-docs` owns the plans sweep and already holds the last-live-citation rule. That makes the order load-bearing, so the archive verb refuses the last task pointing at a live plan. The sweep only reaches tasks still in the live folder, and archiving that task first would strand the plan there with nothing citing it. A task whose plan a sibling still cites archives freely, because the sweep is correct to leave that plan where it is and a gate reading the folder instead would park every task sharing one plan behind a sweep that will never move it.
117
119
 
@@ -286,6 +288,7 @@ This section is the corpus the coverage claim is measured against: every name `a
286
288
  | `aitk:youtube-transcripts` | When a video transcript is wanted in the repo as context |
287
289
  | `aitk:claude-teach` | To learn a subject across sessions, in a workspace that holds the progress |
288
290
  | `aitk:write-human` | Before drafting or revising prose, for voice, rhythm, and density |
291
+ | `aitk:restate` | When an answer or a document has to be read again in plain words |
289
292
 
290
293
  Every row answers a question rather than marking a point in a project's life, so a phase above would send a reader to the wrong group.
291
294
 
@@ -101,13 +101,22 @@ closed clean and then went stale still rebases when the skill is invoked. The
101
101
  re-read costs a full pass rather than a delta, since the prior reviewed commit no
102
102
  longer reaches the head, and `claude-pr-review` detects that itself.
103
103
 
104
- The heading carries the state rather than the pass number. A pass carrying a
105
- finding at any severity takes `## Review` and a pass carrying nothing takes
104
+ The heading carries the state rather than the pass number. A pass carrying
105
+ anything owed takes `## Review` and a pass carrying nothing takes
106
106
  `## Review closed`, so a thread can be scanned for what still owes work without
107
107
  opening a comment. One threshold governs the heading and the dispatch alike, and
108
108
  `claude-pr-review` is where it is stated, so every other surface cites that skill
109
- rather than restating the grades. The merge decision comes off the counts on the
110
- summary line, since an open heading now covers a minor as well as a critical.
109
+ rather than restating the grades.
110
+
111
+ The merge decision comes off the counts on the summary line, since an open
112
+ heading now covers a minor as well as a critical. One thing the pass posts sits
113
+ outside those counts and inside the threshold anyway. It reads the description's
114
+ Testing section against what the repository can drive, and asks about a box left
115
+ unchecked for a person where a harness already covers the run. The question
116
+ takes no severity, because whether a human is required is a judgment the author
117
+ may hold a reason for, and it still opens the heading and sends the dispatch,
118
+ because the author is the only party who can answer it.
119
+
111
120
  A minor the worker declines goes to the findings of the task the
112
121
  branch closes, since a thread does not survive the merge. The feedback
113
122
  becomes a durable artifact both sessions read, survives a session ending, and
@@ -2,7 +2,6 @@
2
2
  description: Route .claude/plans/ edits to the plan standard for sections, the answer contract, and the archive move
3
3
  paths:
4
4
  - '.claude/plans/**'
5
- - '.claude/plans-archive/**'
6
5
  ---
7
6
 
8
7
  # Plan standards
@@ -15,7 +14,7 @@ paths:
15
14
 
16
15
  ## Archiving
17
16
 
18
- - Move a shipped plan to `.claude/plans-archive/`. Never delete one.
17
+ - Move a shipped plan to `.claude/plans/archive/`. Never delete one.
19
18
  - Amend a plan in place when a decision changes. Do not append a second passage narrating the change.
20
19
 
21
20
  ## Authority
@@ -22,6 +22,7 @@ paths:
22
22
  - Use Playwright for end-to-end tests.
23
23
  - Place all Playwright tests within the `e2e/` directory.
24
24
  - Never place Playwright tests inside `src/`.
25
+ - Scope the three rules above to tests the Playwright runner executes. A Vitest test importing a browser driver to exercise project code stays beside its module, where Vitest looks for it.
25
26
 
26
27
  ## Timers and async
27
28
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "3.6.0",
4
+ "version": "3.8.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -46,6 +46,7 @@
46
46
  "dependencies": {
47
47
  "commander": "^13.1.0",
48
48
  "execa": "^9.5.2",
49
+ "playwright-core": "1.59.1",
49
50
  "pptxgenjs": "^4.0.1"
50
51
  },
51
52
  "devDependencies": {
@@ -53,7 +54,7 @@
53
54
  "@astrojs/react": "^5.0.4",
54
55
  "@commitlint/cli": "^20.4.1",
55
56
  "@commitlint/config-conventional": "^20.4.1",
56
- "@playwright/test": "^1.59.1",
57
+ "@playwright/test": "1.59.1",
57
58
  "@tailwindcss/vite": "^4.2.4",
58
59
  "@testing-library/jest-dom": "^6.9.1",
59
60
  "@types/bun": "^1.2.10",