@erclx/aitk 3.25.0 → 3.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/create-snippet/REQUIREMENT.md +3 -3
  4. package/claude/skills/create-snippet/SKILL.md +3 -3
  5. package/claude/skills/migration-claude-md/REQUIREMENT.md +0 -1
  6. package/claude/skills/migration-context/REQUIREMENT.md +0 -1
  7. package/claude/skills/migration-superseded/REQUIREMENT.md +0 -1
  8. package/claude/skills/setup-init/REQUIREMENT.md +1 -1
  9. package/claude/skills/setup-init/SKILL.md +4 -9
  10. package/claude/skills/toolkit-cli/REQUIREMENT.md +1 -2
  11. package/claude/skills/toolkit-operator/REQUIREMENT.md +1 -1
  12. package/claude/skills/toolkit-operator/SKILL.md +1 -1
  13. package/docs/agents/commands.md +1 -1
  14. package/docs/agents/context-audit.md +1 -1
  15. package/docs/agents/install-and-sync.md +30 -45
  16. package/docs/agents/scripting.md +0 -6
  17. package/docs/agents/skills-reach.md +1 -1
  18. package/docs/ai-workflow.md +0 -1
  19. package/docs/target-projects.md +12 -14
  20. package/governance/stacks/base.toml +5 -3
  21. package/package.json +1 -1
  22. package/scripts/core/install-check.sh +10 -12
  23. package/scripts/core/verify.sh +9 -7
  24. package/src/claude/cases/setup.ts +0 -5
  25. package/src/claude/skills-reach.ts +3 -3
  26. package/src/cli.ts +2 -3
  27. package/src/commands/context.ts +2 -2
  28. package/src/commands/init.ts +0 -3
  29. package/src/commands/snippets.ts +2 -157
  30. package/src/commands/sync.ts +2 -5
  31. package/src/context/citations.ts +41 -1
  32. package/src/init/flags.ts +3 -8
  33. package/src/init/plan.ts +1 -21
  34. package/src/init/steps.ts +1 -21
  35. package/src/sync/check.ts +6 -11
  36. package/src/sync/layout.ts +9 -6
  37. package/src/sync/reverse.ts +3 -5
  38. package/src/sync/stamp.ts +7 -7
  39. package/src/sync/target.ts +1 -3
  40. package/standards/skill.md +1 -1
  41. package/claude/skills/migration-standards/REQUIREMENT.md +0 -50
  42. package/claude/skills/migration-standards/SKILL.md +0 -99
  43. package/src/snippets/adapter.ts +0 -35
  44. package/src/snippets/install.ts +0 -172
package/README.md CHANGED
@@ -116,7 +116,7 @@ git init
116
116
  aitk init
117
117
  ```
118
118
 
119
- `aitk init` installs base tooling configs, Claude seeds, and governance rules in one pass, and scaffolds a `.claude/wiki/` stub for your project's own reference pages. Governance defaults to the `base` stack, so a bare init lands the coding and doc-authoring rules in `.claude/rules/`. Each rule names the standard it answers to and reads it with `aitk standards <name>`, so no corpus is copied into your project. Pass `--stack <name>` for a framework stack, or `--skip governance` to leave rules out. Snippets install only when you name a category with `--snippets <category>`, such as `--snippets essentials`. Run `aitk tooling list --json` to see the catalog.
119
+ `aitk init` installs base tooling configs, Claude seeds, and governance rules in one pass, and scaffolds a `.claude/wiki/` stub for your project's own reference pages. Governance defaults to the `base` stack, so a bare init lands the coding and doc-authoring rules in `.claude/rules/`. Each rule names the standard it answers to and reads it with `aitk standards <name>`, so no corpus is copied into your project. Pass `--stack <name>` for a framework stack, or `--skip governance` to leave rules out. A snippet resolves the same way, reached at its `@` reference through the plugin's live `claude/snippets` symlink rather than a copy. Run `aitk tooling list --json` to see the catalog.
120
120
 
121
121
  For the full journey from scaffold through adding a domain later to syncing upstream drift, see [target projects](docs/target-projects.md).
122
122
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aitk",
3
3
  "description": "Automated governance, versioning, and discovery tools for Claude Code.",
4
- "version": "3.25.0",
4
+ "version": "3.25.1",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -9,15 +9,15 @@ description: Why a snippet needs its shape read from the reference and its write
9
9
 
10
10
  Without this skill, a snippet is drafted the way any other markdown file is drafted, so it arrives carrying frontmatter, headings, and a fill-in placeholder. None of the invocation channels strip those. Typing `>slug` in a chat inserts the scaffolding verbatim, and the file that was meant to be one instruction reads as a document.
11
11
 
12
- The write surface is the second failure. The toolkit authors at `snippets/` and a target project holds only the installed copy under `.claude/snippets/`, so a session picks whichever folder it noticed first. A toolkit snippet written into the consumed copy fails the drift assertion that regenerates that folder. A snippet written there in a target project is correct and looks identical, which is why the surface has to be resolved from what the project has rather than guessed.
12
+ The write surface is the second failure. The toolkit authors at `snippets/` and a target project may still hold a stale `.claude/snippets/` copy from before that domain's install channel retired, so a session picks whichever folder it noticed first. A toolkit snippet written into the consumed copy fails the drift assertion that regenerates that folder. A snippet written there in a target project is correct and looks identical, which is why the surface has to be resolved from what the project has rather than guessed.
13
13
 
14
- Inside the project surface, a third failure sits one level deeper. A project-authored snippet sharing a name with a toolkit one used to be indistinguishable from it, so `aitk snippets sync` could not tell which side owned the file. The sync engine now reads ownership by location for anything under `.claude/snippets/project/`, so the skill has to write there rather than beside the toolkit-installed files.
14
+ Inside the project surface, a third failure sits one level deeper. A project-authored snippet sharing a name with a toolkit one used to be indistinguishable from it, back when `aitk snippets sync` walked that folder and could not tell which side owned the file. That verb retired with the domain's install channel, so nothing reads ownership by location there any more, but the `project/` subfolder still separates the two by eye, which is worth keeping even with no sync left to protect from.
15
15
 
16
16
  ## Must
17
17
 
18
18
  - Read the bundled snippet reference before drafting, since the shape rules are what the invocation channels depend on
19
19
  - Resolve the write surface from which snippet folder the project has, rather than from whichever one the session noticed first
20
- - On the project surface, write under its `project/` subfolder so the sync engine reads the file as project-authored by location
20
+ - On the project surface, write under its `project/` subfolder, keeping a project-authored file visually apart from a toolkit-installed one
21
21
  - Confirm the slug and the full body with the user before writing
22
22
  - Emit the written path in full, so the terminal can resolve it
23
23
  - State what the resolved surface implies after writing, since a root file needs the consumed copy regenerated and a project-local one needs copying to the toolkit to ship
@@ -17,14 +17,14 @@ Creates one snippet file. Read these files in parallel:
17
17
 
18
18
  ## Steps
19
19
 
20
- 1. Resolve the write surface: `snippets/` at the root if present, which is the toolkit's own authoring source. Otherwise `.claude/snippets/`, a target project's installed copy.
20
+ 1. Resolve the write surface: `snippets/` at the root if present, which is the toolkit's own authoring source. Otherwise `.claude/snippets/`, a stale copy a target project holds from before its install channel retired.
21
21
  2. Draft the content from the user's description. The snippet reference governs structure, invocation, and authoring conventions.
22
22
  3. Confirm the slug and full content with the user before writing
23
- 4. Write the file. On the root surface: `<surface>/<category>/<slug>.md`, or `<surface>/<slug>.md` when the snippet takes no category. On the `.claude/` surface: the same shape nested one level deeper under `project/`, so the sync engine's location rule holds it apart from a toolkit-installed snippet regardless of what its name matches.
23
+ 4. Write the file. On the root surface: `<surface>/<category>/<slug>.md`, or `<surface>/<slug>.md` when the snippet takes no category. On the `.claude/` surface: the same shape nested one level deeper under `project/`, a convention kept for its own sake now that nothing syncs that folder.
24
24
 
25
25
  ## After writing
26
26
 
27
27
  Emit the full path on its own line.
28
28
 
29
29
  - Root surface: this is the toolkit's authoring source. Remind the user to run `bun run check` to regenerate the consumed copy under `.claude/`.
30
- - `.claude/` surface: the file is project-local, under `.claude/snippets/project/`. `aitk snippets sync` leaves everything there alone by location rather than by a name it fails to recognize. Remind the user to copy it to the toolkit repo, under `snippets/<category>/<name>.md`, if it should ship to every project.
30
+ - `.claude/` surface: the file is project-local, under `.claude/snippets/project/`. Remind the user to copy it to the toolkit repo, under `snippets/<category>/<name>.md`, if it should ship to every project.
@@ -36,6 +36,5 @@ The skill also writes into `.claude/context/`, a folder `migration-context` move
36
36
  ## Out of scope
37
37
 
38
38
  - Relocating `docs/` files, which `migration-context` proposes into this same `.claude/context/` folder. Run that skill first when both apply, so Step 3 reads a folder its moves have already populated.
39
- - Relocating root `standards/` and `snippets/`: `migration-standards`
40
39
  - Scaffolding the rule files it proposes, which `create-rule` does with the numbering and frontmatter
41
40
  - Regenerating `.claude/context/index.md`, which `aitk indexes regen` does once the user has applied the moves
@@ -33,5 +33,4 @@ A seed-derived `development.md` moved out of `docs/` comes back on the next seed
33
33
  ## Out of scope
34
34
 
35
35
  - Classifying `CLAUDE.md` sections, which `migration-claude-md` proposes into this same `.claude/context/` folder. Run this skill first when both apply, so that skill's append-or-create check reads a folder the moves have already populated.
36
- - Relocating root `standards/` and `snippets/`: `migration-standards`
37
36
  - Regenerating `.claude/context/index.md`, which `aitk indexes regen` does once the user has applied the moves
@@ -38,7 +38,6 @@ The last is the two-speed release skew arriving as a confident wrong answer. `su
38
38
 
39
39
  ## Out of scope
40
40
 
41
- - Relocating root `snippets/` into `.claude/`: `migration-standards`
42
41
  - Classifying `CLAUDE.md` sections into the three-tier model: `migration-claude-md`
43
42
  - Relocating `docs/` files by audience: `migration-context`
44
43
  - Reconciling a seed file against its source section by section, which diffs two files rather than splitting one into a folder: `claude-seed-sync`
@@ -36,7 +36,7 @@ The other is the refusal that ends rather than routes. An existing project, an i
36
36
 
37
37
  ## Out of scope
38
38
 
39
- - Installing governance rules alone: `setup-gov`. This skill installs governance beside tooling, standards, snippets, and the seeds.
39
+ - Installing governance rules alone: `setup-gov`. This skill installs governance beside tooling and the seeds.
40
40
  - Bootstrapping the `index.md` system: `setup-indexes`. Neither `aitk init` nor this chain performs it.
41
41
  - Provisioning Claude Code plugins: `setup-plugins`. Those install once per machine rather than into a project, so no project-scoped chain can carry them.
42
42
  - Running the verification scripts, which `setup-verify` owns and this chain invokes as its last step
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: setup-init
3
- description: Detects a new project's type and runs `aitk init` with a resolved stack and snippets in one shot. Use when bootstrapping a new project with the toolkit, or when asked to "init this project", "bootstrap the toolkit", "set up toolkit", or "one-shot install". Assumes the `aitk` CLI is on PATH. Do NOT use when only installing governance rules. Use `setup-gov` instead.
3
+ description: Detects a new project's type and runs `aitk init` with a resolved stack in one shot. Use when bootstrapping a new project with the toolkit, or when asked to "init this project", "bootstrap the toolkit", "set up toolkit", or "one-shot install". Assumes the `aitk` CLI is on PATH. Do NOT use when only installing governance rules. Use `setup-gov` instead.
4
4
  ---
5
5
 
6
6
  # Init project
@@ -30,8 +30,6 @@ Run from the target project's current directory. Do not cd into the toolkit sour
30
30
 
31
31
  ```bash
32
32
  aitk gov list --json 2>/dev/null
33
- aitk snippets list --json 2>/dev/null
34
- aitk standards list --json 2>/dev/null
35
33
  aitk tooling list --json 2>/dev/null
36
34
  ```
37
35
 
@@ -49,8 +47,7 @@ Read these from the project root in parallel, skipping any that do not exist:
49
47
  - **Stack:** pick the closest governance stack by matching detected runtime or framework against stack names in the catalog. If nothing matches, fall back to `base` and carry the fallback into the preview.
50
48
  - **Tooling stack:** pick the closest tooling stack from `aitk tooling list --json` (e.g. `vite-react`, `astro`). Distinct from the governance stack. Fall back to `base` if no framework match, and carry that fallback into the preview too.
51
49
  - **Extras:** identify technologies not already covered by the picked stack. For each, find a rule whose `description` or `paths` points at that technology and pass it via `--add`. Do not add a rule the stack already pulls in.
52
- - **Snippets:** default to `all`. Narrow only if the user asked for a specific category.
53
- - **Skip (`--skip`):** `standards` and `wiki` are core and install by default. Add `--skip standards` or `--skip wiki` only when the user explicitly wants them left out.
50
+ - **Skip (`--skip`):** `wiki` installs by default. Add `--skip wiki` only when the user explicitly wants it left out.
54
51
 
55
52
  ## Gap handling
56
53
 
@@ -59,7 +56,7 @@ If a detected technology has no matching rule or stack, do not guess. Surface th
59
56
  1. Defer to `setup-gov`. Author a rule in the toolkit, then re-run this skill.
60
57
  2. Proceed with the matched layer, listing the gap in the final report.
61
58
 
62
- Rules, snippets, and stacks are authored in the toolkit repo, never in the target project on the fly.
59
+ Rules and stacks are authored in the toolkit repo, never in the target project on the fly.
63
60
 
64
61
  ## Preview
65
62
 
@@ -69,7 +66,6 @@ Before executing, output:
69
66
  - **Stack:** picked governance stack + resolved rule count. Mark it `fallback` when no detected runtime or framework matched a catalog name.
70
67
  - **Tooling stack:** picked tooling stack. Mark it `fallback` on the same test, and name what `base` lands: configs, seeds, and gitignore entries in every case, plus the JavaScript development dependencies, scripts, and hook activation wherever a `package.json` exists to carry them. A project outside that ecosystem runs none of the second group and keeps the first.
71
68
  - **Extras:** each `--add` rule with a one-line reason
72
- - **Snippets:** resolved category
73
69
  - **Skip:** any `--skip` entries with reason
74
70
  - **Target:** resolved target path
75
71
  - **Commands:** the full chain that will run
@@ -80,13 +76,12 @@ A resolved name and a fallback read alike once written, so mark the fallback her
80
76
 
81
77
  Run the chain in order, starting immediately after the preview. Each step's permission dialog is the confirmation gate. Do not pause for additional confirmation. Run from the target project's current directory.
82
78
 
83
- Step 1: `aitk init` installs base tooling, claude seeds, governance rules, standards, snippets, and wiki.
79
+ Step 1: `aitk init` installs base tooling, claude seeds, governance rules, and wiki.
84
80
 
85
81
  ```bash
86
82
  AITK_NON_INTERACTIVE=1 aitk init \
87
83
  --stack <stack> \
88
84
  --add <rules> \
89
- --snippets <category> \
90
85
  <target>
91
86
  ```
92
87
 
@@ -15,7 +15,7 @@ The inverse failure is quieter. A session that assumes a sync will pick up a cha
15
15
 
16
16
  Being reachable is a separate problem from being right. This is a pure reference whose moment happens inside another skill's run, so nothing brings it up unless a body names it. Three sibling requirement files named it and routed nothing, because Claude Code loads `SKILL.md` as the entry and never opens the sibling. A route lives in a body or it does not exist, and a fourth requirement mention would repeat the same defect.
17
17
 
18
- The three bodies now carrying an inline pointer are `claude-seed-sync`, `migration-standards`, and `toolkit-operator`, each at the point it runs or prints an overwriting command.
18
+ The two bodies now carrying an inline pointer are `claude-seed-sync` and `toolkit-operator`, each at the point it runs or prints an overwriting command.
19
19
 
20
20
  ## Must
21
21
 
@@ -38,5 +38,4 @@ The three bodies now carrying an inline pointer are `claude-seed-sync`, `migrati
38
38
 
39
39
  - Executing the sync, which the user runs or `toolkit-operator` routes
40
40
  - Reconciling a customized seed section by section: `claude-seed-sync`
41
- - Relocating a project's folders into the layout a newer version expects: `migration-standards`
42
41
  - Deciding which stack, rule, or standard a project should install, which the setup skills resolve from live catalogs
@@ -27,7 +27,7 @@ The last failure is a section no route reaches. `## Route` maps an intent or a d
27
27
  - Run the CLI non-interactively and report the command run, what changed, and the full path of anything written
28
28
  - Read the overwrite contract from the body before any install or sync, and name each surface it lists as overwritten before running one
29
29
  - Read the reverse walk beside the forward sections, so a folder the toolkit stopped shipping and a migration with a live case both reach the user
30
- - Hand off a named migration to the skill the report names, the way an unmigrated domain reaches `migration-standards`
30
+ - Hand off a named migration to the skill the report names, and name an unmigrated domain's root and install path for the user to move themselves when no skill covers it
31
31
  - Route a measurement intent to the audit offers from the route table itself, rather than leaving the section reachable only by reading past the table
32
32
  - Rank a lifecycle row against the audit offers where the route table itself states it, so a session acting on the lifecycle row reads the ranking without opening the section being ranked
33
33
  - Offer every audit whose surface the target carries, and offer none whose surface it lacks
@@ -42,7 +42,7 @@ Map the stated intent, or what `## Diagnose` found, to one lifecycle phase, then
42
42
 
43
43
  The two can name different rows, and a reply answers both rather than picking one. Run or hand off what the finding names, then answer the intent in the same reply. A measurement intent therefore reaches the audit offers below even on a target whose diagnostic found scaffold work, which is the case a session leaving from the scaffold row would otherwise never read.
44
44
 
45
- - A domain in `unmigrated`: hand off to `migration-standards`
45
+ - A domain in `unmigrated`: name it, the root path, and the install path. No command moves it, so the user runs the relocation themselves
46
46
  - An entry in `migrations`: hand off to the skill its `skill` field names, spelled as the report spells it. Both of them propose without writing, so the handoff is where this stops
47
47
  - Anything in `superseded`: name which files and what replaced them, then hand off to `migration-superseded`. Both skills propose, so neither moves nor deletes the file
48
48
  - A folder in `unclaimed`: name it and the attribution it carries. No command moves it and the content may be the project's own, so the decision is the user's
@@ -71,7 +71,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
71
71
  | Domain | Subcommands |
72
72
  | ----------- | ------------------------------------------------------------------------------------------------------------------------------------- |
73
73
  | `tooling` | `list`, `sync`, `ref`, `create`, `verify`, `inject`, `prune-gitignore` |
74
- | `snippets` | `list`, `install`, `sync`, `create` |
74
+ | `snippets` | `list`, `create` |
75
75
  | `standards` | `list`, `<name>` |
76
76
  | `gov` | `list`, `install`, `sync`, `build`, `regen`, `test-order`, `superseded` |
77
77
  | `claude` | `init`, `sync`, `routing`, `seeds list`, `skills list`, `skills audit`, `skills drift`, `skills reach`, `skills rank`, `setup [dest]` |
@@ -76,7 +76,7 @@ Three exclusions keep it from firing on prose about paths. Fenced blocks are ski
76
76
 
77
77
  Two cases remain, and no syntax separates either from a real reference. One is a sentence naming a hypothetical entry to show the shape of a name. The other is a line instructing a target project about its own tree, which resolves against the target rather than against this repository and passes here only while the two layouts agree. Splitting a seeded domain into a folder ends that agreement and turns every such line red at once.
78
78
 
79
- Append `<!-- audit-ignore-citations -->` to the source line in either case. The marker suppresses citation checking for its own line only, and the reference-form check reads it too, since both ask whether a line points at a file and the marker is how a line says it displays a name instead.
79
+ Append `<!-- audit-ignore-citations: <path> -->` to the source line in either case, naming the exact path the sentence displays. The marker excuses only the paths it names, so a line carrying a real reference beside the displayed one keeps that reference checked. A bare `<!-- audit-ignore-citations -->` with no path excuses every citation the line carries instead, and the reference-form check reads either form the same way, since both ask whether a line points at a file and the marker is how a line says it displays a name instead.
80
80
 
81
81
  The marker itself stays out of anything that installs. A seed, a plugin skill body, and a stack reference all reach a target, so a marker there lands as toolkit bookkeeping in someone else's tree. Reword those lines to drop the path instead, and where a stop message has to spell it, move that message into a fenced block, which this check already skips.
82
82
 
@@ -26,10 +26,8 @@ rules, skills, and docs may cite. `aitk standards rule` carries the reserved
26
26
  number bands behind that placement, where `900-999` is the range a
27
27
  project-authored rule takes and everything below it belongs to the toolkit.
28
28
 
29
- `aitk snippets sync` reports the same way for a snippet outside
30
- `.claude/snippets/project/`, since both adapters declare the subfolder.
31
- `aitk sync --check` does not. It skips every orphaned entry, so the destination
32
- reaches the two domain sync verbs alone.
29
+ `aitk sync --check` does not report an orphaned entry. It skips every one, so
30
+ the destination reaches `aitk gov sync` alone, the one domain sync verb left.
33
31
 
34
32
  When the target's install recorded a stack, `aitk gov sync` also reports a
35
33
  rule that stack lists and `.claude/rules/` does not hold, as a `missing` entry
@@ -46,30 +44,27 @@ installs into no project, so the domain has nothing in a target to reconcile.
46
44
  and then the corpus inside the package, and `aitk standards list --json` carries
47
45
  the catalog.
48
46
 
49
- `aitk snippets sync` matches by path relative to `.claude/snippets/`. It
50
- matches by path relative to that directory, so a snippet the toolkit no longer
51
- ships, or one authored directly in the target, is reported and skipped rather
52
- than deleted, and a snippet under `.claude/snippets/project/` skips the same
53
- way regardless of path, since that subfolder is project-authored by location.
54
- It is not preset-aware, so a project that installed `essentials`
55
- does not grow new snippets on a sync. Use `aitk snippets install` to add them.
47
+ There is no `aitk snippets sync` and no `aitk snippets install` either, on the
48
+ same ground: `claude/snippets` in the plugin cache symlinks live to the
49
+ toolkit's own `snippets/`, so a session reaches one at its `@` reference with
50
+ no copy to reconcile. `aitk snippets list --json` carries the catalog and
51
+ `aitk snippets create` is the one verb left that still writes a file.
56
52
 
57
53
  ## Install guards
58
54
 
59
- `aitk gov install` and `aitk snippets install` require their first argument
60
- under `AITK_NON_INTERACTIVE=1`. Both used to fall back to an interactive picker
61
- that resolved to its first option headlessly, so `aitk gov install` with no
62
- stack installed whichever stack sorted first and `aitk snippets install` with no
63
- category installed every category. Each now reports the valid names on stderr
64
- and exits 1.
55
+ `aitk gov install` requires its first argument under
56
+ `AITK_NON_INTERACTIVE=1`. It used to fall back to an interactive picker that
57
+ resolved to its first option headlessly, so a call with no stack installed
58
+ whichever stack sorted first. It now reports the valid names on stderr and
59
+ exits 1.
65
60
 
66
61
  Every documented agent path already passes the argument, including
67
62
  `aitk init`. The confirm-then-apply prompt after it still resolves to `Yes`
68
- headlessly, so a call that names its stack or category is unchanged.
63
+ headlessly, so a call that names its stack is unchanged.
69
64
 
70
- `aitk gov install` also refuses the toolkit root as a target, matching
71
- `aitk snippets install`. Both resolve the target before anything else, so a path
72
- that does not exist fails rather than being scaffolded.
65
+ `aitk gov install` also refuses the toolkit root as a target. It resolves the
66
+ target before anything else, so a path that does not exist fails rather than
67
+ being scaffolded.
73
68
 
74
69
  ## Standards resolution
75
70
 
@@ -227,14 +222,13 @@ refusal rather than a shape nobody stated.
227
222
  to, with nothing at the path the current one reads. It carries `rootPath`,
228
223
  `installPath`, and a file count. Without it a project holding `standards/` at its
229
224
  root reports zero entries for that domain and reads as clean, which is the most
230
- misleading state the report can produce. Route it to `migration-standards`.
225
+ misleading state the report can produce.
231
226
 
232
- That skill reads this field rather than listing the folder itself, so the entry
233
- is the detection on both sides of the handoff and the two cannot disagree. The
234
- count is what makes the difference visible: it counts only files whose basename
235
- the toolkit ships, so a root folder holding the project's own documents beside
236
- the installed ones reports the installed subset, where a listing reports every
237
- file and proposes relocating the lot.
227
+ The field currently names no domain. Standards and snippets are the two the
228
+ toolkit ever installed at a project root, and both closed their install channel,
229
+ so a project still holding a root `standards/` or `snippets/` folder is carrying
230
+ its own authoring surface rather than an unfinished install. Nothing proposes
231
+ moving either, and no command relocates the content. Move it yourself.
238
232
 
239
233
  #### Rules the target never received
240
234
 
@@ -268,8 +262,8 @@ rule the chain lists reaches both surfaces the same way.
268
262
  A target stamped before governance recorded a chain falls back to the older
269
263
  band-inference read below. The measurement there anchors on governance's own
270
264
  stamp rather than on the oldest anchor across domains, since rules are
271
- domain-scoped and a shared anchor would let a snippets sync move the revision
272
- rules are measured from. A target carrying no chain and no governance anchor
265
+ domain-scoped and a shared anchor would let another domain's sync move the
266
+ revision rules are measured from. A target carrying no chain and no governance anchor
273
267
  reports nothing at all: it has no date to measure against, and diffing from the
274
268
  start of history would read the whole catalog as new.
275
269
 
@@ -343,9 +337,8 @@ colliding on a retired name costs the walk no reads. The cost is that a file the
343
337
  toolkit shipped and the target renamed goes unmatched, the same limit the
344
338
  `unmigrated` count carries.
345
339
 
346
- `migrations` names a proposal-only skill with a live case in this target, which
347
- is the treatment `unmigrated` already gives `migration-standards`. It fires on a
348
- `CLAUDE.md` past 250 lines for `migration-claude-md`, and on a `docs/` folder
340
+ `migrations` names a proposal-only skill with a live case in this target. It
341
+ fires on a `CLAUDE.md` past 250 lines for `migration-claude-md`, and on a `docs/` folder
349
342
  holding markdown with no populated `.claude/context/` for `migration-context`.
350
343
  Each entry carries the skill name and the measurement behind it, so a consumer
351
344
  can check the proposal before running it. Without the field both skills are
@@ -371,24 +364,16 @@ so this section reports and gates nothing.
371
364
 
372
365
  ## Bootstrap
373
366
 
374
- `aitk init` installs up to six core domains and reports each one independently. A
367
+ `aitk init` installs up to four core domains and reports each one independently. A
375
368
  domain that fails does not abort the run, so the command finishes the rest and
376
369
  exits 1 naming the failures. Passing any flag skips the confirmation prompt,
377
370
  which is what makes it scriptable.
378
371
 
379
372
  `--stack` defaults to `base`, and the default
380
373
  does not read as a passed flag, so a bare `aitk init` installs governance and
381
- still prompts. `--skip` takes `wiki`, `governance`, and `snippets`, and warns
382
- without aborting on any other value. There is no `--standards`, since no run
383
- writes a standard into the target.
384
-
385
- `--snippets` carries no default. A bare `aitk init` installs no snippets and
386
- reports the domain as skipped, the same way an explicit `--skip snippets`
387
- does, both naming `aitk snippets install essentials <target>` as the recovery
388
- command. `--snippets none` is a distinct, deliberate way to reach the same
389
- zero-file result while still running the step, which is what lets a scripted
390
- caller assert "install nothing" without depending on an empty string, which
391
- `aitk snippets install` refuses.
374
+ still prompts. `--skip` takes `wiki` and `governance`, and warns
375
+ without aborting on any other value. There is no `--standards` and no
376
+ `--snippets`, since no run writes either corpus into the target.
392
377
 
393
378
  ## Unguarded tooling primitives
394
379
 
@@ -106,12 +106,6 @@ aitk tooling inject base /path/to/project --configs --seeds
106
106
  # Prints the number removed on stdout, diagnostics on stderr
107
107
  aitk tooling prune-gitignore base /path/to/project
108
108
 
109
- # Install a snippet preset
110
- AITK_NON_INTERACTIVE=1 aitk snippets install essentials /path/to/project
111
-
112
- # Update snippets already installed, leaving project-authored ones alone
113
- AITK_NON_INTERACTIVE=1 aitk snippets sync /path/to/project
114
-
115
109
  # Print one standard. Nothing installs the corpus, so this is how a target reads one
116
110
  AITK_NON_INTERACTIVE=1 aitk standards slug >slug.md
117
111
 
@@ -34,7 +34,7 @@ A path the toolkit does not hold is dropped rather than reported. The measure as
34
34
 
35
35
  ## The ownership key
36
36
 
37
- A cited path counts when it sits under an authoring root no install channel delivers. Standards install nowhere and are read through the plugin corpus, snippets land under `.claude/snippets/`, governance rules under `.claude/rules/`, and the rest is this repository's own source, catalogs, and contract pages.
37
+ A cited path counts when it sits under an authoring root no install channel delivers. Standards and snippets install nowhere and are read through the plugin corpus, governance rules install under `.claude/rules/`, and the rest is this repository's own source, catalogs, and contract pages.
38
38
 
39
39
  `src/`, `scripts/`, and bare `docs/` are deliberately outside the list. A body naming one of those is describing the reader's own tree, so listing them reports a correct citation on every run and buries the finding under the pass.
40
40
 
@@ -262,7 +262,6 @@ This section is the corpus the coverage claim is measured against: every name `a
262
262
  | `aitk:claude-seed-sync` | After a toolkit update, to reconcile installed seeds without losing customizations |
263
263
  | `aitk:migration-claude-md` | When `CLAUDE.md` grew past what always-load context should carry |
264
264
  | `aitk:migration-context` | When `docs/` holds agent-flavored files belonging in `.claude/context/` |
265
- | `aitk:migration-standards` | When standards sit at the root while rules point into `.claude/` |
266
265
  | `aitk:migration-superseded` | When a drift report names a `.claude/` file a folder has replaced |
267
266
  | `aitk:toolkit-feedback` | When something in the toolkit is broken, missing, or off |
268
267
  | `aitk:toolkit-triage` | In the toolkit repo, to work through the open feedback issues |
@@ -27,7 +27,7 @@ The `aitk` CLI is separate. Twenty skills invoke it in a command position, and a
27
27
  bun install --global @erclx/aitk
28
28
  ```
29
29
 
30
- The package ships the catalogs the CLI reads, not only `src/`, so `aitk init` resolves snippets, governance, tooling, and the seeds from wherever the package landed, and `aitk standards <name>` reads the corpus from there too.
30
+ The package ships the catalogs the CLI reads, not only `src/`, so `aitk init` resolves governance, tooling, and the seeds from wherever the package landed, and `aitk standards <name>` reads the corpus from there too.
31
31
 
32
32
  Pointing Claude Code at a checkout stays the development path, where a local skill edit overrides the installed copy for that session.
33
33
 
@@ -46,12 +46,12 @@ The chain is:
46
46
 
47
47
  - `aitk init` installs base tooling, Claude seeds, and governance rules into `.claude/rules/` in the same pass
48
48
  - `aitk tooling sync <stack> --write` adds stack-specific deps, scripts, and gitignore entries
49
- - The agent reads `aitk tooling reference <stack>` (plus parents) as its audit context, follows it to generate eslint, vitest, playwright configs and the stack's setup script, and extends `.claude/context/ci.md` and `.claude/context/development.md` per the reference's extend sections <!-- audit-ignore-citations -->
49
+ - The agent reads `aitk tooling reference <stack>` (plus parents) as its audit context, follows it to generate eslint, vitest, playwright configs and the stack's setup script, and extends `.claude/context/ci.md` and `.claude/context/development.md` per the reference's extend sections <!-- audit-ignore-citations: .claude/context/development.md -->
50
50
  - `setup-verify` runs the installed `package.json` scripts (lint, typecheck, check, test, build) and reports pass or fail
51
51
 
52
52
  The chain serves a fresh scaffold and names a destination for the three states it does not. An existing project goes to `aitk:toolkit-operator`, which reads what the project already carries before naming a per-domain command. An install wanting the Claude layer without the tooling chain runs `aitk claude init` for the seed docs and then `aitk:setup-indexes` for the index system. A language the toolkit ships no stack for is the one of the three the chain still runs for, on `base`, with the fallback marked in the preview so it can be declined there.
53
53
 
54
- Keep the `## Scripts` table in `.claude/context/development.md` current as scripts are added. Base tooling seeds that entry with the commands it installs, and each stack reference extends the table. `project-commands` reads it to start the app or run a check on request, so a command missing from the table cannot be run that way. A project whose entry outgrew one file and split into `.claude/context/development/` keeps the table in `overview.md`, which is where the skill looks next. <!-- audit-ignore-citations -->
54
+ Keep the `## Scripts` table in `.claude/context/development.md` current as scripts are added. Base tooling seeds that entry with the commands it installs, and each stack reference extends the table. `project-commands` reads it to start the app or run a check on request, so a command missing from the table cannot be run that way. A project whose entry outgrew one file and split into `.claude/context/development/` keeps the table in `overview.md`, which is where the skill looks next. <!-- audit-ignore-citations: .claude/context/development.md -->
55
55
 
56
56
  ### From scaffold to first feature
57
57
 
@@ -88,12 +88,11 @@ Run `aitk tooling list --json` and `aitk gov list --json` to see the current cat
88
88
 
89
89
  No standard is written into the project. Each governance rule's authority line names `aitk standards <name>`, which answers from the corpus inside the CLI's own package, and every toolkit skill names the copy in its own plugin root. `aitk markdown audit` needs no standard at all, its ban sets and checkpoints shipping with the package as data.
90
90
 
91
- Snippets does not install by default. Pass `--snippets <category>`, such as `--snippets essentials`, to take it. Its own rule describing the `@` reference convention installs alongside it, so a project that declines snippets never receives a rule for a behavior it holds no snippet to exercise.
91
+ No snippet is written into the project either. `claude/snippets` in the plugin cache symlinks to the toolkit's own `snippets/`, so a session reaches one at its `@` reference with no install step, the same live resolution `claude/standards` gives a rule's authority line.
92
92
 
93
- `governance`, `snippets`, and `wiki` are skippable:
93
+ `governance` and `wiki` are skippable:
94
94
 
95
95
  - `--skip governance`: leave `.claude/rules/` empty, so no coding standard loads on a file match. The preview names any `--add` rules the skip drops, and the run prints the `aitk gov install <stack> <path>` command to add rules afterward, carrying those extras so one paste restores what the skip declined.
96
- - `--skip snippets`: the explicit spelling for what a bare init already does, since `--snippets` carries no default. Both print the `aitk snippets install essentials <path>` command afterward.
97
96
  - `--skip wiki`: skip the `.claude/wiki/` scaffold. A target that already carries a root `wiki/` keeps it, since the verb reports that folder rather than migrating it.
98
97
 
99
98
  The plugin corpus carries runtime behavior rather than reference prose alone, because the pre-publish scan and the branch-slug transform each have a standard of their own, `publish.md` and `slug.md`, cited by the skills that run them.
@@ -105,9 +104,8 @@ When a new need appears after scaffold, install the one domain without re-runnin
105
104
  - Governance rule for a newly adopted library: invoke `aitk:setup-gov`, or run `aitk gov install <stack> --add <rule> <path>`
106
105
  - Project-specific rule the toolkit does not ship: invoke `aitk:create-rule`. It scaffolds a rule into `.claude/rules/` with a non-colliding number, and `aitk gov sync` leaves it untouched.
107
106
  - Index.md system for a markdown-heavy folder that emerged: invoke `aitk:setup-indexes`
108
- - A snippet preset or category: `aitk snippets install <preset|category|all> <path>`. The argument is required, since the picker refuses headlessly rather than choosing for the caller
109
107
 
110
- Standards are not on that list, and there is nothing to add. No standard installs into a project, by default or by flag, so a session that needs one runs `aitk standards <name>` and reads it from the copy inside the package. A project holding a `.claude/standards/` folder from an older toolkit is carrying a stale artifact nothing reads, and deleting it is safe.
108
+ Standards and snippets are not on that list, and there is nothing to add for either. Neither installs into a project, by default or by flag, so a session reads a standard with `aitk standards <name>` and a snippet through its `@` reference off the live plugin symlink, both resolving against the toolkit rather than a project copy. A project holding a `.claude/standards/` or `.claude/snippets/` folder from an older toolkit is carrying a stale artifact nothing reads, and deleting it is safe.
111
109
 
112
110
  Per-domain mechanics live in the corresponding `docs/<domain>.md`. The skill body in `claude/skills/<skill>/SKILL.md` covers detection and preview.
113
111
 
@@ -125,17 +123,17 @@ The report opens by naming the binary running it. The installed version reads ag
125
123
 
126
124
  #### Then the causes
127
125
 
128
- A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `aitk:claude-seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is what `aitk:migration-standards` handles.
126
+ A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `aitk:claude-seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is a relocation the report names but no command runs.
129
127
 
130
- That attribution comes from `.claude/aitk/config.json`, a stamp every install and sync writes. A target stamped before that path shipped is read from the retired `.claude/aitk.json` instead, reported rather than migrated. Snippets and governance record a hash per installed file. Governance also records the stack `aitk gov install` was given, and tooling records the stack chain it resolved instead of any file hash, since its install runs no per-file walk to attribute.
128
+ That attribution comes from `.claude/aitk/config.json`, a stamp every install and sync writes. A target stamped before that path shipped is read from the retired `.claude/aitk.json` instead, reported rather than migrated. Governance records a hash per installed file, plus the stack `aitk gov install` was given, and tooling records the stack chain it resolved instead of any file hash, since its install runs no per-file walk to attribute.
131
129
 
132
- Each domain holds its own toolkit commit, so syncing governance today does not move the revision snippets measures against, and each domain reports the upstream commits touching its own source path. Running any sync stamps that domain, and the report names the ones still unstamped.
130
+ Each domain holds its own toolkit commit, so syncing governance today does not move the revision tooling measures against, and each domain reports the upstream commits touching its own source path. Running any sync stamps that domain, and the report names the ones still unstamped.
133
131
 
134
132
  A project that has never synced under a toolkit new enough to write a stamp falls back to the toolkit's own git history. Installed content matching any version that history published proves the file untouched, so it reports `stale` naming the commit it came from, and content matching no published version stays `drifted`. That fallback needs the toolkit as a git checkout. Installed from the registry it ships source without history, and the report says attribution was unavailable rather than reading every file as a local edit.
135
133
 
136
- Further causes sit outside the per-domain scan, each naming something that walk cannot see. A seed the project edited is reported under `seeds` and reconciled with `aitk:claude-seed-sync`, since no sync command touches a seed. A file a newer seed folder replaced is reported under `superseded`, such as `.claude/TASKS.md` against the `.claude/tasks/` that now ships, and nothing moves it because the content is the project's own. A domain sitting at the root layout with nothing under `.claude/` is reported under `unmigrated` and handed to `aitk:migration-standards`.
134
+ Further causes sit outside the per-domain scan, each naming something that walk cannot see. A seed the project edited is reported under `seeds` and reconciled with `aitk:claude-seed-sync`, since no sync command touches a seed. A file a newer seed folder replaced is reported under `superseded`, such as `.claude/TASKS.md` against the `.claude/tasks/` that now ships, and nothing moves it because the content is the project's own. A domain sitting at the root layout with nothing under `.claude/` is reported under `unmigrated`, and no command moves it either. The project moves the content itself.
137
135
 
138
- That third one matters most on an older project. Before it existed, a target holding `snippets/` at its root reported zero entries for that domain, so a project that had never migrated was indistinguishable from one that was fully current. It covers snippets alone, since a root `standards/` folder in a target is the project's own authoring surface and nothing proposes moving it.
136
+ `unmigrated` currently names no domain, since standards and snippets are the two the toolkit ever installed at the project root and both closed their install channel. A target still holding a root `standards/` or `snippets/` folder from an older toolkit is carrying its own authoring surface now, not an unfinished install, and nothing proposes moving either.
139
137
 
140
138
  #### Rules you never received
141
139
 
@@ -202,7 +200,7 @@ cd <your-project>
202
200
  claude
203
201
  ```
204
202
 
205
- In the session, invoke `aitk:setup-init`. The skill detects no framework and resolves tooling to `base`, governance to `base`, and snippets to `all`. The preview marks both stacks as fallbacks, since neither came from a match, then the chain runs `aitk init`.
203
+ In the session, invoke `aitk:setup-init`. The skill detects no framework and resolves tooling to `base` and governance to `base`. The preview marks both stacks as fallbacks, since neither came from a match, then the chain runs `aitk init`.
206
204
 
207
205
  Ongoing: run `aitk sync --check .` to see what has drifted, then invoke `aitk:claude-seed-sync` for seed drift or `aitk sync .` for a catch-all refresh.
208
206
 
@@ -1,4 +1,6 @@
1
1
  extends = ""
2
- # Both folders whole. Every rule authored under them ships to a base consumer,
3
- # so adding one is a single edit rather than a file and a name here.
4
- rules = ["core", "claude", "120-bash"]
2
+ # All three folders whole. Every rule authored under them ships to a base
3
+ # consumer, so adding one is a single edit rather than a file and a name here.
4
+ # `snippets` carries the `@`-reference convention rule, which lost its only
5
+ # other delivery path when `aitk snippets install` retired.
6
+ rules = ["core", "claude", "snippets", "120-bash"]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "3.25.0",
4
+ "version": "3.25.1",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -67,7 +67,7 @@ mkdir -p "$TARGET_DIR"
67
67
  log_info "Initialized git in $TARGET_DIR"
68
68
 
69
69
  log_step "Run aitk init"
70
- (cd "$TARGET_DIR" && AITK_NON_INTERACTIVE=1 bun run "$CLONE_DIR/src/cli.ts" init --stack base --snippets essentials 2>&1 | pipe_output) || log_error "aitk init failed"
70
+ (cd "$TARGET_DIR" && AITK_NON_INTERACTIVE=1 bun run "$CLONE_DIR/src/cli.ts" init --stack base 2>&1 | pipe_output) || log_error "aitk init failed"
71
71
  log_info "aitk init completed"
72
72
 
73
73
  log_step "Assert scaffold"
@@ -76,18 +76,16 @@ log_step "Assert scaffold"
76
76
  # catches a failed domain, and the gate stays green while the target is
77
77
  # missing everything that domain provides.
78
78
  #
79
- # Standards name no path because the corpus installs into no target. A scaffold
80
- # reads a standard through `aitk standards <name>`, which resolves against the
81
- # copy inside the package.
82
- #
83
- # Snippets carries no default, so the run above passes `--snippets essentials`
84
- # explicitly. The snippets path has to name a slug that preset still carries;
85
- # editing the preset without editing this line fails the gate on a correct
86
- # install. The rule path confirms the domain's own convention rule installs
87
- # alongside it, since a target that declined snippets never receives it.
88
- for path in "CLAUDE.md" ".claude/snippets/decision-help.md" ".claude/rules/snippets/505-at-references.md" ".claude/wiki/index.md" ".claude" ".claude/context/index.md" ".claude/wireframes/index.md" ".claude/diagrams/index.md" \
79
+ # Standards and snippets name no path because neither corpus installs into a
80
+ # target. A scaffold reads a standard through `aitk standards <name>` and a
81
+ # snippet through the plugin's live `claude/snippets` symlink, both resolving
82
+ # against the toolkit rather than a copy this gate could assert on. The
83
+ # `@`-reference convention rule is the one snippets-domain file that still
84
+ # installs, since `base` carries `governance/rules/snippets/` as a
85
+ # folder-whole entry the same way it does `core` and `claude`.
86
+ for path in "CLAUDE.md" ".claude/wiki/index.md" ".claude" ".claude/context/index.md" ".claude/wireframes/index.md" ".claude/diagrams/index.md" \
89
87
  ".prettierrc" ".editorconfig" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.sh" \
90
- ".claude/rules/core/000-constitution.md"; do
88
+ ".claude/rules/core/000-constitution.md" ".claude/rules/snippets/505-at-references.md"; do
91
89
  if [ ! -e "$TARGET_DIR/$path" ]; then
92
90
  log_error "Missing after aitk init: $path"
93
91
  fi
@@ -21,13 +21,15 @@ SANDBOX_UNDECLARED_CEILING=47
21
21
 
22
22
  # Rules no stack reaches, space separated and sorted the way `aitk gov list`
23
23
  # emits them. `260-shadcn` and `320-tanstack-query` are opt-in libraries a
24
- # project may not want; `505-at-references` ships with no stack on purpose,
25
- # since a rule under `claude/` would reach every base consumer through the
26
- # folder-whole entry, and only `aitk snippets install` writes it, alongside
27
- # the snippets a caller took. All three are recorded here rather than in a
28
- # config file: the list is what a reader compares a new arrival against, and a
29
- # config file would absorb the arrival silently.
30
- GOV_EXPECTED_UNREFERENCED="260-shadcn 320-tanstack-query 505-at-references"
24
+ # project may not want. `505-at-references` used to sit here too, shipping
25
+ # with no stack on purpose since a rule under `claude/` would reach every
26
+ # base consumer through the folder-whole entry there. Its own install
27
+ # channel, `aitk snippets install`, retired with nothing left to deliver it,
28
+ # so `base` now carries `snippets` as a folder-whole entry of its own and the
29
+ # rule reaches every base consumer through that instead. Both are recorded
30
+ # here rather than in a config file: the list is what a reader compares a
31
+ # new arrival against, and a config file would absorb the arrival silently.
32
+ GOV_EXPECTED_UNREFERENCED="260-shadcn 320-tanstack-query"
31
33
 
32
34
  # The retained counts the audit stage compares each run against. Spelled here
33
35
  # rather than derived, because this script only ever names the file in a remedy
@@ -40,11 +40,6 @@ export const SETUP_CASES: readonly SkillCase[] = [
40
40
  'Move the agent-flavored docs out of the docs folder and into context.',
41
41
  expect: 'migration-context',
42
42
  },
43
- {
44
- prompt:
45
- 'The snippets folder needs to move under .claude to match the current layout.',
46
- expect: 'migration-standards',
47
- },
48
43
  {
49
44
  prompt:
50
45
  'This file was replaced by a folder, help me split its content into it.',