@erclx/aitk 1.7.1 → 2.1.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 (49) hide show
  1. package/README.md +2 -2
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/claude-autoship/SKILL.md +2 -2
  4. package/claude/skills/claude-docs/SKILL.md +11 -0
  5. package/claude/skills/claude-groundwork/SKILL.md +1 -1
  6. package/claude/skills/claude-seed-sync/REQUIREMENT.md +2 -2
  7. package/claude/skills/claude-seed-sync/SKILL.md +15 -18
  8. package/claude/skills/create-standard/REQUIREMENT.md +7 -10
  9. package/claude/skills/create-standard/SKILL.md +10 -11
  10. package/claude/skills/git-pr/references/labels.md +7 -1
  11. package/claude/skills/migration-standards/REQUIREMENT.md +10 -7
  12. package/claude/skills/migration-standards/SKILL.md +24 -22
  13. package/claude/skills/migration-superseded/REQUIREMENT.md +2 -2
  14. package/claude/skills/migration-superseded/SKILL.md +7 -9
  15. package/claude/skills/setup-gov/REQUIREMENT.md +2 -2
  16. package/claude/skills/toolkit-cli/SKILL.md +13 -14
  17. package/docs/agents/commands.md +1 -1
  18. package/docs/agents/install-and-sync.md +27 -41
  19. package/docs/agents/scripting.md +2 -9
  20. package/docs/target-projects.md +14 -15
  21. package/package.json +1 -1
  22. package/scripts/core/install-check.sh +5 -1
  23. package/scripts/lib/sandbox-git.sh +56 -4
  24. package/scripts/manage-sandbox.sh +4 -7
  25. package/scripts/standards/list.sh +6 -4
  26. package/src/cli.ts +1 -1
  27. package/src/commands/gov.ts +1 -7
  28. package/src/commands/init.ts +1 -4
  29. package/src/commands/standards.ts +9 -141
  30. package/src/commands/sync.ts +1 -2
  31. package/src/gov/install.ts +0 -9
  32. package/src/init/flags.ts +3 -10
  33. package/src/init/plan.ts +8 -26
  34. package/src/init/steps.ts +0 -24
  35. package/src/standards/read.ts +16 -14
  36. package/src/sync/check.ts +4 -7
  37. package/src/sync/layout.ts +8 -10
  38. package/src/sync/stamp.ts +18 -15
  39. package/src/sync/target.ts +1 -8
  40. package/standards/skill.md +6 -6
  41. package/standards/standard.md +1 -1
  42. package/tooling/claude/seeds/.claude/ARCHITECTURE.md +1 -1
  43. package/tooling/claude/seeds/.claude/DESIGN.md +1 -1
  44. package/tooling/claude/seeds/.claude/REQUIREMENTS.md +1 -1
  45. package/tooling/claude/seeds/CLAUDE.md +2 -2
  46. package/src/standards/adapter.ts +0 -51
  47. package/src/standards/closure.ts +0 -200
  48. package/src/standards/index-refresh.ts +0 -44
  49. package/src/standards/install.ts +0 -52
package/README.md CHANGED
@@ -67,7 +67,7 @@ Each domain has a canonical source in this repo and a thin install or sync CLI o
67
67
 
68
68
  - [Claude Code plugin](.claude/context/claude-plugin/index.md): skills for planning, review, docs sync, and the git ship chain
69
69
  - [Governance rules](.claude/context/governance/index.md): Claude rules and stacks, installable per project
70
- - [Standards](.claude/context/standards/index.md): shared authoring conventions, synced to projects
70
+ - [Standards](.claude/context/standards/index.md): shared authoring conventions, read by name rather than installed
71
71
  - [Snippets](.claude/context/snippets.md): reusable prompts for Claude and Gemini chat
72
72
  - [Tooling stacks](.claude/context/tooling.md): golden configs, seeds, and references per framework
73
73
  - [Design system](.claude/context/design.md): `DESIGN.md` token shape, extract skill and its two paths, render command
@@ -116,7 +116,7 @@ git init
116
116
  aitk init
117
117
  ```
118
118
 
119
- `aitk init` installs base tooling configs, Claude seeds, governance rules, standards, and snippets 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/` alongside the standards they route to. Pass `--stack <name>` for a framework stack, or `--skip governance` to leave rules out. Run `aitk tooling list --json` to see the catalog.
119
+ `aitk init` installs base tooling configs, Claude seeds, governance rules, and snippets 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. 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": "1.7.1",
4
+ "version": "2.1.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -75,11 +75,11 @@ The two causes want different responses. A plan that has yet to produce its outp
75
75
 
76
76
  The skip needs both tests to pass: every changed file matches `*.md` or `*.txt`, and no changed file sits under a behavior path. On a pass, skip review entirely and continue to Step 7. Otherwise invoke `aitk:claude-review`.
77
77
 
78
- Behavior paths carry two spellings, the one a surface authors at and the one it installs to, so the rule reads the same in a toolkit and in a project that consumed one:
78
+ Behavior paths carry two spellings, the one a surface authors at and the one it reaches a session at, so the rule reads the same in a toolkit and in a project that consumed one:
79
79
 
80
80
  - `claude/skills/` and `.claude/skills/`
81
81
  - `governance/rules/` and `.claude/rules/`
82
- - `standards/` and `.claude/standards/`
82
+ - `standards/` and `.claude/standards/`, which is the authoring root and this repository's generated mirror rather than an install destination, since the corpus installs into no project
83
83
  - `snippets/` and `.claude/snippets/`
84
84
  - `internal/` and `tooling/`, which hold the stack references and the seed documents a target is handed
85
85
  - `CLAUDE.md` at the repository root, named as a file because a path prefix reaches nothing that sits in no folder
@@ -174,6 +174,17 @@ Reuse the diff from the baseline above, names and content both. For each existin
174
174
  - For each relevant entry, rewrite only the sections affected by the diff. Same pattern as `docs-sync`. Do not touch unrelated sections.
175
175
  - Write a reference to another entry as the path that entry sits at, rather than as its bare filename. `${CLAUDE_SKILL_DIR}/../../standards/context.md` states the form, and a bare name strands the reference once a domain splits into subfolders.
176
176
 
177
+ ### When the diff removes a capability
178
+
179
+ The mapping above is scoped by file, and a removal invalidates claims that mapping cannot reach. Run this only when the diff deletes a command, a flag, a constant, or a folder. Ordinary feature work takes the narrow rule alone, since widening it on every ship churns prose nothing put in doubt.
180
+
181
+ Grep the tree for the name that went, rather than for the paths the diff carries. A capability removed by name is cited by that name, which reaches a file the diff never touched.
182
+
183
+ - An entry this run already rewrote is read whole before it is left. A refresh that updates the top and leaves a contradicting claim below reads worse than an untouched entry, because the current opening lends authority to the stale remainder. This is the one case that overrides "do not touch unrelated sections", and it overrides it only inside an entry the run edited anyway.
184
+ - A claim comparing two surfaces is checked even where its file is outside the diff. Such a claim holds only while both surfaces do, so moving one inverts it with nobody editing the file it sits in.
185
+
186
+ Report each hit as an ordinary rewrite.
187
+
177
188
  Do not create new entries automatically. New entries are a deliberate decision: the user invokes `claude-docs --new-context <domain>` (future flag) or hand-creates the file following `${CLAUDE_SKILL_DIR}/../../standards/context.md`. Auto-creation risks padding `.claude/context/` with low-signal entries.
178
189
 
179
190
  Write each updated entry immediately. Output one line per file:
@@ -35,7 +35,7 @@ A track may run an experiment to settle an open question without stopping to ask
35
35
  - Writing a fixture this session reads or provisions itself: run it, under the fixtures path above. Provisioning is the usual blocker rather than spend, and it costs nothing.
36
36
  - Spawning a billed headless session: run up to three, then ask before spawning more. The bound is a run count rather than a budget, because a headless run reports its total cost only after it finishes, so a dollar ceiling is reportable and not enforceable while a run count is checkable before spawning.
37
37
 
38
- A fixture a headless run is pointed at goes outside the repository, under `mktemp -d`, and never under `.claude/.tmp/`. A session started anywhere beneath the project root loads that project's `CLAUDE.md`, `.claude/rules/`, and `.claude/standards/` through the ancestor chain, so an in-repo fixture measures the repository instead of the arm. Record the fixture as contaminated and re-run it outside if this is discovered after the fact, because the result reads as evidence either way.
38
+ A fixture a headless run is pointed at goes outside the repository, under `mktemp -d`, and never under `.claude/.tmp/`. A session started anywhere beneath the project root loads that project's `CLAUDE.md` and `.claude/rules/` through the ancestor chain, so an in-repo fixture measures the repository instead of the arm. Record the fixture as contaminated and re-run it outside if this is discovered after the fact, because the result reads as evidence either way.
39
39
 
40
40
  Record method, result, measured cost, and caveats in `08-spikes.md`. Put whatever the run produced that the record cites in `evidence/` beside it, so a reader checking a claim opens the artifact rather than taking the prose for it. Reach for a test harness the project already carries before building one, and copy how it isolates its fixture rather than only what it asserts.
41
41
 
@@ -7,7 +7,7 @@ description: Scope boundary for section-granular seed reconciliation against the
7
7
 
8
8
  ## Gap
9
9
 
10
- Without this skill, a project that edited an installed seed or standard has two ways to take an upstream change and both lose something. `aitk standards install` overwrites every file, so the edits are gone with no record of what they were. `aitk standards sync` updates only files it already finds and adds none, so a standard written after the project installed never arrives at all. Neither can deliver one upstream section into a file the project has customized, which is the case a grown project is always in.
10
+ Without this skill, a project that edited a seed has no way to take an upstream change without losing something. No `aitk` command touches a seed at all, so the only route is a hand copy that overwrites the file and takes the edits with it, unrecorded. Nothing can deliver one upstream section into a file the project has customized, which is the case a grown project is always in.
11
11
 
12
12
  A whole-file diff does not close it either. It cannot separate a section the user rewrote on purpose from a section the toolkit moved on without them, so the choice reaches the user as accept everything or lose everything, and the safe answer is always to skip.
13
13
 
@@ -17,7 +17,7 @@ Two failures belong to the audit rather than to the diff. A decision taken in ch
17
17
 
18
18
  ## Must
19
19
 
20
- - Read seed and standard content from the CLI rather than holding a copy, so the audit and the install cannot disagree
20
+ - Read seed content from the CLI rather than holding a copy, so the audit and the install cannot disagree
21
21
  - Diff per section, treating the preamble as a section of its own
22
22
  - Separate a customized section from a stale one by reading the attribution the drift report records, not by how the section looks, and default the customized one to no action
23
23
  - Fall back to appearance only when attribution is unavailable, and mark every verdict reached that way as unverified
@@ -14,27 +14,24 @@ Surfaces drift between the toolkit's current seed docs and what was installed in
14
14
 
15
15
  ## Step 1: read toolkit sources and the drift report
16
16
 
17
- Run all three in parallel from the project root:
17
+ Run both in parallel from the project root:
18
18
 
19
19
  ```bash
20
20
  aitk claude seeds list --json 2>/dev/null
21
- aitk standards list --json 2>/dev/null
22
21
  aitk sync --check . --json 2>/dev/null
23
22
  ```
24
23
 
25
- Seeds emit an array of `{name, source, target, content}`. Standards emit `{standards: [{name, description, target, content}]}`. In both cases `target` is the path relative to the project root where the file installs. Merge the two into one list of entries tagged by source (`seed` or `standard`).
24
+ Seeds emit an array of `{name, source, target, content}`, where `target` is the path relative to the project root where the file installs.
26
25
 
27
- If the target project has no `.claude/standards/` directory, skip the standards stage silently.
26
+ Seeds are the whole subject. No standard installs into a project, so there is no installed copy to audit and nothing to reconcile against the corpus. A standard a session needs is read with `aitk standards <name>`, which resolves against the copy inside the package.
28
27
 
29
28
  ### Narrow the set by attribution
30
29
 
31
- The report is what separates a file the project edited from one the toolkit moved on without it. Read `seeds.entries` for seed paths and `domains[].entries` for standards, then drop from the merged list every entry the report attributes as `stale`. A stale file matches a version the toolkit published, so it carries no edits to lose and `aitk standards sync` takes it whole. Section-merging it is work with no decision behind it.
30
+ The report is what separates a file the project edited from one the toolkit moved on without it. Read `seeds.entries` for seed paths.
32
31
 
33
32
  Keep every seed regardless of state. `CLAUDE.md` is the file a project edits most, and its `drifted` verdict is the case this skill exists for.
34
33
 
35
- Record the dropped standards as one line in the scope table rather than as rows: `<n> standards stale, taken by aitk standards sync`.
36
-
37
- Read the `toolkit-cli` skill before naming that command in the output. It states which surfaces a sync overwrites, merges, or writes once, and this skill hands the user a command against files its own attribution pass cleared as carrying no edits.
34
+ Read the `toolkit-cli` skill before naming a sync command in the output. It states which surfaces a sync overwrites, merges, or writes once.
38
35
 
39
36
  Fall back to the appearance heuristic in step 3 when the report cannot attribute, which is `historyUnavailable` set on the relevant section or the command failing outright. Say so in the summary block, because a fallback audit reports guesses rather than facts.
40
37
 
@@ -53,7 +50,8 @@ Note on `settings.json`: the seed now ships only the PostToolUse hook block. If
53
50
  For each seed file present in both sides, parse the body into a preamble (everything between H1 and the first H2) plus one part per `##` header, then compare part by part. Treat the preamble as a single unit with the same verdicts as a section. Use `(preamble)` as its label in the proposal.
54
51
 
55
52
  - **Identical:** ignore.
56
- - **Toolkit-only section** (present in source, absent in target): candidate to **Add**.
53
+ - **Toolkit-only section** (present in source, absent in target): candidate to **Add**. Number it whatever the file's own verdict is. The verdict rules below govern a section present in both, and a section the project never had cannot be the customization a `drifted` file is being credited with. A pass that reads the file-level verdict first proposes nothing on a target missing eleven sections, which is the shape this bullet exists to catch.
54
+ - A deliberate removal reads the same as one that never arrived, and no decline is carried between runs, so a section the user skips is proposed again on the next branch. Say so beside the item rather than letting a reader meet it a third time wondering. The way to settle it for good is to keep the heading and write the project's own content under it, which moves the section onto the drifted path below, where the customization rule protects it and stops numbering it.
57
55
  - **Target-only section** (present in target, absent in source): preserve, never propose removal. These are user customizations.
58
56
  - **Drifted section** (present in both, content differs): candidate to **Update**.
59
57
  - Read the file's verdict from the report rather than judging it by eye. `drifted` means the content matches no version the toolkit ever published, so the project wrote it: call it **Customized**, default to skip, record in the scope table only, never numbered.
@@ -87,16 +85,15 @@ How to respond: fill in `Decision:` per item (`apply` or `skip`), then ping. Cha
87
85
 
88
86
  ## Scope
89
87
 
90
- Group rows by source. `Seeds` first, then `Standards`. Mark target-only files (present in target, absent in source) as `local-only` and leave them untouched.
88
+ Mark target-only files (present in target, absent in source) as `local-only` and leave them untouched.
91
89
 
92
- | Source | File | Status | Note |
93
- | -------- | ---------- | ---------- | ---------------------------- |
94
- | seed | `<target>` | diffed | <counts> |
95
- | seed | `<target>` | in sync | |
96
- | seed | `<target>` | skipped | non-text, compare manually |
97
- | seed | `<target>` | customized | <section> skipped by default |
98
- | standard | `<target>` | diffed | <counts> |
99
- | standard | `<target>` | local-only | not in toolkit, preserved |
90
+ | Source | File | Status | Note |
91
+ | ------ | ---------- | ---------- | ---------------------------- |
92
+ | seed | `<target>` | diffed | <counts> |
93
+ | seed | `<target>` | in sync | |
94
+ | seed | `<target>` | skipped | non-text, compare manually |
95
+ | seed | `<target>` | customized | <section> skipped by default |
96
+ | seed | `<target>` | local-only | not in toolkit, preserved |
100
97
 
101
98
  ## 1. 📝 Update → `<target-path>` / <section>
102
99
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: create-standard
3
- description: Why a standard needs its shape read from the meta-standard and its write surface resolved before anything is drafted
3
+ description: Why a standard needs its shape read from the meta-standard before anything is drafted, and why the follow-up depends on who owns the folder it landed in
4
4
  ---
5
5
 
6
6
  # Create standard requirement
@@ -9,30 +9,27 @@ description: Why a standard needs its shape read from the meta-standard and its
9
9
 
10
10
  Without this skill, a standard is written from memory of what other standards look like. It arrives without the scope section that says what the file does not govern, so the next author cannot tell whether a rule belongs to it or to a sibling, and two standards end up claiming the same subject with no way to settle which one wins.
11
11
 
12
- The write surface is the second failure. The toolkit authors at `standards/` and a target project holds only the installed copy under `.claude/standards/`, so a session picks whichever folder it noticed first. A toolkit standard written into the consumed copy fails the drift assertion that regenerates that folder. A standard 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 consumed copy is the second failure. This repository mirrors `standards/` into `.claude/standards/` and asserts the two match, so a toolkit standard written into the mirror fails that assertion while looking like a correct file. One write surface removes the choice: `standards/` is what the resolver reads first and what every author writes to, in the toolkit and in a project alike.
13
13
 
14
- A standard written at the root and left there is the third. The index entry and the context table are both generated or maintained downstream of the write, so a file that ships without them is catalogued nowhere and reached only by whoever already knew the path.
14
+ A standard written and left there is the third. The index entry and the context table are both generated or maintained downstream of the write, so a file that ships without them is catalogued nowhere and reached only by whoever already knew the path.
15
15
 
16
16
  ## Must
17
17
 
18
18
  - Read the meta-standard before drafting, since the shape is what makes the file arguable against a sibling
19
- - Resolve the write surface from which standards folder the project has, rather than from whichever one the session noticed first
19
+ - Write to `standards/`, creating it when absent, since it is the one root the resolver reads and the only surface either kind of author has
20
20
  - Confirm the slug and the full body with the user before writing
21
21
  - Emit the written path in full, so the terminal can resolve it
22
- - State what the resolved surface implies after writing, since a root file needs the consumed copy and the index regenerated and a project-local one needs copying to the toolkit to ship
22
+ - State what the write implies for whoever owns the folder, since a toolkit standard needs the consumed copy and the index regenerated and a project-local one needs copying to the toolkit to ship
23
23
 
24
24
  ## Must not
25
25
 
26
26
  - Work the standard's shape or frontmatter from memory
27
27
  - Write a snippet, which carries no frontmatter and answers to a different authoring contract
28
-
29
- ## Guards
30
-
31
- - Neither standards folder exists: stop, since there is nowhere for the standard to live
28
+ - Write into `.claude/standards/`, which is this repository's generated mirror and reaches no resolver
32
29
 
33
30
  ## Out of scope
34
31
 
35
32
  - Editing a standard that already exists
36
33
  - A snippet, which `create-snippet` owns
37
34
  - A path-scoped coding rule, which `create-rule` owns
38
- - Installing and syncing the standards the toolkit ships, which the `aitk standards` commands own
35
+ - Reading a standard the toolkit ships, which `aitk standards <name>` owns
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: create-standard
3
- description: Creates a new standard file in `standards/` or `.claude/standards/`. Use when asked to create a standard, add a standard, or write a new authoring convention. Do NOT use to edit an existing standard.
3
+ description: Creates a new standard file in `standards/`. Use when asked to create a standard, add a standard, or write a new authoring convention. Do NOT use to edit an existing standard.
4
4
  ---
5
5
 
6
6
  # Create standard
@@ -11,20 +11,19 @@ Creates one standard file. Read these files in parallel:
11
11
  - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
12
12
  - `${CLAUDE_SKILL_DIR}/../../standards/standard.md`: the meta-standard for shape, frontmatter, and structure
13
13
 
14
- ## Guards
15
-
16
- - If neither `standards/` nor `.claude/standards/` exists, stop: `❌ No standards/ or .claude/standards/ directory found.`
17
-
18
14
  ## Steps
19
15
 
20
- 1. Resolve the write surface: `standards/` at the root if present, which is the toolkit's own authoring source. Otherwise `.claude/standards/`, a target project's installed copy.
21
- 2. Draft the content from the user's description. The meta-standard governs frontmatter, headings, and structure.
22
- 3. Confirm the slug and full content with the user before writing
23
- 4. Write the file to `<surface>/<slug>.md`
16
+ 1. Draft the content from the user's description. The meta-standard governs frontmatter, headings, and structure.
17
+ 2. Confirm the slug and full content with the user before writing
18
+ 3. Write the file to `standards/<slug>.md`, creating the folder when it is absent
19
+
20
+ `standards/` is the one write surface. It is the toolkit's authoring source in this repository and a project's own folder anywhere else, and both are the root `aitk standards <name>` resolves against first. No corpus installs into a project, so there is no second surface to pick between and no guard on a folder the skill can create itself.
24
21
 
25
22
  ## After writing
26
23
 
27
24
  Emit the full path on its own line.
28
25
 
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/`. That pass also regenerates the `standards/index.md` entry, and the user adds a row to the standards table in `.claude/context/standards/overview.md`.
30
- - `.claude/` surface: the file is project-local. `aitk standards sync` leaves it alone, since sync only updates filenames it recognizes from the toolkit. Remind the user to copy it to the toolkit repo, under `standards/<slug>.md`, if it should ship to every project.
26
+ - In the toolkit: this is the authoring source. Remind the user to run `bun run check` to regenerate the consumed copy under `.claude/`. That pass also regenerates the `standards/index.md` entry, and the user adds a row to the standards table in `.claude/context/standards/overview.md`.
27
+ - In a project: the file is project-local and no toolkit command touches it. Remind the user to copy it to the toolkit repo, under `standards/<slug>.md`, if it should ship to every project.
28
+
29
+ Separate the two by whether the folder already held toolkit-authored standards before this write, since a project authoring its own uses the same path.
@@ -27,7 +27,13 @@ web = ["apps/web/", "packages/ui/"]
27
27
 
28
28
  A label takes more than one prefix when two folders read as one surface. Two labels may claim overlapping prefixes, and a path under both earns both.
29
29
 
30
- The map is authored by hand and nothing detects a directory it fails to cover, so a surface added after the map was written labels nothing until someone adds a row.
30
+ Matching is prefix-anchored, so a row written for an authoring root reaches nothing under the copy a project consumes. A surface living only under a dotted folder carries its own prefix on the row that owns its subject, and a folder holding several subjects rather than one splits across the rows that own them.
31
+
32
+ The map is authored by hand and nothing detects a directory it fails to cover, so a surface added after the map was written labels nothing until someone adds a row. A map that has been censused against its own history says in its comment where that check is owned, so a reader meeting the gap is sent somewhere rather than left with the prediction.
33
+
34
+ ## Paths a map declines to label
35
+
36
+ A path that moves only when a release or a generator rewrites it earns no row. Release automation applies its own label, and a domain label on a generated file gives a mechanical edit a subject it does not have. Neither is covered, so both are recorded in the map's comment with the reason, which is what separates a path nobody has gotten to from one somebody decided against.
31
37
 
32
38
  ## Matching
33
39
 
@@ -1,27 +1,30 @@
1
1
  ---
2
2
  name: migration-standards
3
- description: Why the root-to-.claude relocation ships as git mv commands the user runs, and which inbound references are worth fixing
3
+ description: Why the root-to-.claude snippets relocation ships as git mv commands the user runs, which inbound references are worth fixing, and why standards no longer travel with it
4
4
  ---
5
5
 
6
6
  # Migration standards requirement
7
7
 
8
8
  ## Gap
9
9
 
10
- Without this skill, a project whose rules cite `.claude/standards/` while the files sit at the root gets fixed by hand, and the hand fix loses what version control was holding. A plain `mv` breaks the rename chain, so every relocated standard reads as a delete beside an unrelated add and its history stops at the move.
10
+ Without this skill, a project whose rules cite `.claude/snippets/` while the files sit at the root gets fixed by hand, and the hand fix loses what version control was holding. A plain `mv` breaks the rename chain, so every relocated snippet reads as a delete beside an unrelated add and its history stops at the move.
11
11
 
12
- A fourth failure comes before those three, from deciding what is unmigrated by listing the folder. A root `standards/` can hold the project's own docs and nothing the toolkit ever installed, and a listing cannot tell the two apart, so the skill proposes moving project files under `.claude/` where a sync walks them. The drift report already answers this, counting only files whose basename the toolkit ships, and it is the same report `toolkit-operator` reads to route here.
12
+ A fourth failure comes before those three, from deciding what is unmigrated by listing the folder. A root `snippets/` can hold the project's own prompts and nothing the toolkit ever installed, and a listing cannot tell the two apart, so the skill proposes moving project files under `.claude/` where a sync walks them. The drift report already answers this, counting only files whose basename the toolkit ships, and it is the same report `toolkit-operator` reads to route here.
13
+
14
+ Standards left this skill when the corpus stopped installing into a project. The report no longer names the domain, so a body still describing the move would propose relocating a folder the project authored, which is the exact failure the paragraph above records in the other direction.
13
15
 
14
16
  Taking detection from a command opens a failure the listing never had. A CLI predating the field exits zero with a well-formed report that never mentions it, so a skill treating an absent key as an empty answer tells a project whose every domain sits at the root that it has nothing to relocate. That is the population this skill exists for, and a silent false negative there costs more than the unfiltered count reading the folder would have produced.
15
17
 
16
18
  The re-sync the skill names has the same gap in the other direction. The relocation is what makes those commands land on a path that held nothing before, so the run hands over a command whose overwrite behavior it never states, and the reference holding that answer is named in the boundary below where no session reads it. Claude Code loads the skill entry alone.
17
19
 
18
- Three failures follow from acting without looking first. A move onto an existing `.claude/standards/` copy overwrites the files already installed there, which is the case the relocation was supposed to be unnecessary for. A `git mv` on a dirty tree lands the relocation in the same commit as unrelated work, so neither can be reviewed or reverted alone. And a session that rewrites every inbound reference spends its effort on toolkit-owned rules and skills, which the next sync overwrites, while the author-owned lines that actually break go unmentioned.
20
+ Three failures follow from acting without looking first. A move onto an existing `.claude/snippets/` copy overwrites the files already installed there, which is the case the relocation was supposed to be unnecessary for. A `git mv` on a dirty tree lands the relocation in the same commit as unrelated work, so neither can be reviewed or reverted alone. And a session that rewrites every inbound reference spends its effort on toolkit-owned rules and skills, which the next sync overwrites, while the author-owned lines that actually break go unmentioned.
19
21
 
20
22
  ## Must
21
23
 
22
- - Take the set of domains to relocate from `aitk sync --check --json`, and report its filtered count rather than a folder listing
24
+ - Take what to relocate from `aitk sync --check --json`, and report its filtered count rather than a folder listing
25
+ - Say in one line that a root `standards/` folder is left alone, since a user who came here expecting both domains reads silence as an oversight
23
26
  - Keep the listing as the fallback for a target where `aitk` is absent, the command fails, or the report carries no `unmigrated` key, and say that its counts are unfiltered
24
- - Detect an existing copy under `.claude/` and skip that folder's move rather than merging into it
27
+ - Detect an existing copy under `.claude/` and skip the move rather than merging into it
25
28
  - Read the working tree state and require it clean before the moves, since the relocation has to be revertible on its own
26
29
  - Propose `git mv` so history follows each file
27
30
  - Report author-owned inbound references as TODO lines the user fixes, and leave the reference itself untouched
@@ -36,7 +39,7 @@ Three failures follow from acting without looking first. A move onto an existing
36
39
 
37
40
  ## Guards
38
41
 
39
- - Neither root `standards/` nor root `snippets/` present stops, since there is nothing to relocate
42
+ - No root `snippets/` present stops, since there is nothing to relocate
40
43
  - A directory that is not a git work tree stops, since `git mv` needs version control and a plain move is the failure the skill exists to prevent
41
44
 
42
45
  ## Out of scope
@@ -1,30 +1,29 @@
1
1
  ---
2
2
  name: migration-standards
3
- description: Proposes `git mv` commands to relocate a target project's root `standards/` and `snippets/` folders into `.claude/standards/` and `.claude/snippets/`, the install layout newer toolkit versions expect. Use when asked to "relocate standards", "move standards to .claude", "migrate snippets to .claude", or after a toolkit upgrade leaves rules pointing at `.claude/standards/` while the files sit at the root. Do NOT auto-execute moves or edit rule files. Proposal only.
3
+ description: Proposes `git mv` commands to relocate a target project's root `snippets/` folder into `.claude/snippets/`, the install layout newer toolkit versions expect. Use when asked to "relocate snippets", "move snippets to .claude", "migrate snippets to .claude", or after a toolkit upgrade leaves a rule pointing at `.claude/snippets/` while the files sit at the root. Do NOT auto-execute moves or edit rule files. Proposal only.
4
4
  ---
5
5
 
6
6
  # Claude standards relocate
7
7
 
8
+ Snippets is the one domain this skill relocates. Standards used to travel beside it and the toolkit corpus now installs into no project at all, so a root `standards/` folder in a target holds work the project authored and nothing proposes moving it. `aitk standards <name>` reads a toolkit standard wherever a session needs one.
9
+
8
10
  ## Guards
9
11
 
10
- - If neither `standards/` nor `snippets/` exists at `pwd`, stop: `❌ No root standards/ or snippets/ to relocate.`
12
+ - If `snippets/` does not exist at `pwd`, stop: `❌ No root snippets/ to relocate.`
11
13
  - If `pwd` is not a git work tree, stop: `❌ Not a git repository. git mv needs version control.`
12
14
 
13
15
  ## Step 1: read the report
14
16
 
15
17
  Run `aitk sync --check . --json` from the project root. Its `unmigrated` array is the detection. Each entry carries `domain`, `rootPath`, `installPath`, and `files`, and a domain appears only when the root folder holds a file the toolkit ships and nothing sits at the install path. Report `files` as the count, since it excludes files the project wrote into the same folder.
16
18
 
17
- Run these beside it, in parallel. The report answers which domains to move and neither of these is derivable from it:
19
+ Run these beside it, in parallel. The report answers whether to move and neither of these is derivable from it:
18
20
 
19
- - `ls .claude/standards/ 2>/dev/null`: separate a domain already relocated from one never installed, which the report cannot, since both are absent from `unmigrated`
20
- - `ls .claude/snippets/ 2>/dev/null`: the same, for the other domain
21
+ - `ls .claude/snippets/ 2>/dev/null`: separate a domain already relocated from one never installed, which the report cannot, since both are absent from `unmigrated`
21
22
  - `git status --short 2>/dev/null`: confirm a clean tree before proposing moves
22
23
 
23
- Keep the two listings as separate commands. `ls` labels its output with a `dir:` header only when more than one operand succeeds, so a combined call with one directory present prints that directory's filenames bare while the redirect swallows the other's failure, and the result reads as whichever directory was expected.
24
-
25
24
  ### When the report is unavailable
26
25
 
27
- Fall back to `ls standards/*.md` and `ls snippets/` on any of three conditions. Say in the output that the counts are unfiltered, because a root folder can hold project-authored files the report would have excluded and the fallback counts every one of them.
26
+ Fall back to `ls snippets/` on any of three conditions. Say in the output that the count is unfiltered, because a root folder can hold project-authored files the report would have excluded and the fallback counts every one of them.
28
27
 
29
28
  - `aitk` is not on `PATH`
30
29
  - The command exits non-zero
@@ -38,19 +37,20 @@ Do not fall back on `historyUnavailable`. That field reports failed attribution
38
37
 
39
38
  ## Step 2: check conflicts
40
39
 
41
- - If `.claude/standards/` already holds `.md` files, mark standards as "already relocated" and skip its move.
42
- - If `.claude/snippets/` already holds `.md` files, mark snippets as "already relocated" and skip its move.
40
+ - If `.claude/snippets/` already holds `.md` files, mark snippets as "already relocated" and skip the move.
43
41
  - If `git status` is not clean, add a TODO line telling the user to commit or stash first. `git mv` on a dirty tree mixes the move with unrelated changes.
44
- - If a root folder holds files and no domain names it in a report that carried the key, propose nothing for it. The content is the project's own, and moving it under `.claude/` puts project files where a sync walks. This reads a present key alone. A report with no `unmigrated` key never reaches here, since Step 1 sends it to the fallback.
42
+ - If the root folder holds files and no domain names it in a report that carried the key, propose nothing. The content is the project's own, and moving it under `.claude/` puts project files where a sync walks. This reads a present key alone. A report with no `unmigrated` key never reaches here, since Step 1 sends it to the fallback.
43
+ - A root `standards/` folder is never a conflict and never a move. Say so in one line when one is present, since a user who came here expecting both domains reads silence as an oversight.
45
44
 
46
45
  ## Step 3: find author-owned inbound references
47
46
 
48
47
  Toolkit-owned rules and skills are re-synced, so do not rewrite them. Surface only references the user authored:
49
48
 
50
- - `git grep -n "standards/" -- 'CLAUDE.md' '.claude/rules/**' 'docs/**' 2>/dev/null`
51
- - `git grep -n "snippets/" -- 'CLAUDE.md' '.claude/rules/**' 'docs/**' 2>/dev/null`
49
+ ```bash
50
+ git grep -n "snippets/" -- 'CLAUDE.md' '.claude/rules/**' 'docs/**' 2>/dev/null
51
+ ```
52
52
 
53
- Report each hit as a TODO line. Exclude paths already under `.claude/standards/` or `.claude/snippets/`.
53
+ Report each hit as a TODO line. Exclude paths already under `.claude/snippets/`.
54
54
 
55
55
  ## Step 4: output
56
56
 
@@ -59,38 +59,40 @@ Print one grouped proposal block. Omit empty groups.
59
59
  ```markdown
60
60
  ## Relocate
61
61
 
62
- - standards/ → .claude/standards/ (<count> files)
63
62
  - snippets/ → .claude/snippets/ (<count> files)
64
63
 
65
64
  ## Already relocated
66
65
 
67
- - .claude/standards/ exists. Skipping.
66
+ - .claude/snippets/ exists. Skipping.
67
+
68
+ ## Left alone
69
+
70
+ - standards/ is the project's own. No toolkit standard installs into a project.
68
71
 
69
72
  ## Suggested git mv commands
70
73
 
71
74
  mkdir -p .claude
72
- git mv standards .claude/standards
73
75
  git mv snippets .claude/snippets
74
76
 
75
77
  ## Re-sync after moving
76
78
 
77
- aitk standards sync .
79
+ aitk snippets sync .
78
80
  aitk gov sync .
79
81
 
80
82
  ## Inbound references to verify
81
83
 
82
- - CLAUDE.md:42 references standards/markdown.md
84
+ - CLAUDE.md:42 references snippets/align.md
83
85
  - docs/contributing.md:8 references snippets/claude/feature
84
86
 
85
87
  ## Reminder
86
88
 
87
- Re-syncing reinstalls toolkit-owned rules and standards at the new path. Author-owned references above need a manual one-line fix.
89
+ Re-syncing reinstalls toolkit-owned rules and snippets at the new path. Author-owned references above need a manual one-line fix.
88
90
  ```
89
91
 
90
92
  Two states produce no proposal at all, and each gets its own line rather than an empty block:
91
93
 
92
- - Both folders already live under `.claude/`: `✅ standards/ and snippets/ already live under .claude/. Nothing to relocate.`
93
- - A root folder exists and no domain names it in `unmigrated`: `✅ <folder>/ holds no file the toolkit installed. Nothing to relocate.` Name every such folder. The guard passed because the folder is there, so a session that printed nothing would leave the user reading silence as a failed run rather than as the answer.
94
+ - The folder already lives under `.claude/`: `✅ snippets/ already lives under .claude/. Nothing to relocate.`
95
+ - The root folder exists and no domain names it in `unmigrated`: `✅ snippets/ holds no file the toolkit installed. Nothing to relocate.` The guard passed because the folder is there, so a session that printed nothing would leave the user reading silence as a failed run rather than as the answer.
94
96
 
95
97
  Read the `toolkit-cli` skill before printing the re-sync block, and name in the reminder any surface it lists as overwritten. The user runs those commands against a tree the moves above relocated, and that relocation is what puts an overwrite onto files never installed at the new path.
96
98
 
@@ -19,7 +19,7 @@ The last is the two-speed release skew arriving as a confident wrong answer. `su
19
19
 
20
20
  - Take detection from the report's `superseded` array alone, and stop when the key is absent rather than treating it as empty
21
21
  - Resolve the governing standard by matching the replacement folder against the `appliesTo` the standards catalog declares, so a seed folder added later resolves without an edit to the body
22
- - Read the destination shape from the project's own installed standard, and propose nothing for a folder whose standard is absent or unshipped
22
+ - Read the destination shape with `aitk standards <name>`, report the root it answered from, and propose nothing for a folder the catalog names no standard for
23
23
  - Separate a folder no standard governs from one whose governing standard could not be read, since the catalog derives `appliesTo` from prose and answers an unparsed scope statement with an empty array
24
24
  - Name the untrack command ahead of the ignore entry whenever a retired file is both tracked and ignored, and say when the check could not run
25
25
  - Report what the destination standard leaves open, such as a phase label the retired file never recorded, rather than supplying a value for it
@@ -38,7 +38,7 @@ 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 `standards/` and `snippets/` into `.claude/`: `migration-standards`
41
+ - Relocating root `snippets/` into `.claude/`: `migration-standards`
42
42
  - Classifying `CLAUDE.md` sections into the three-tier model: `migration-claude-md`
43
43
  - Relocating `docs/` files by audience: `migration-context`
44
44
  - Reconciling a seed file against its source section by section, which diffs two files rather than splitting one into a folder: `claude-seed-sync`
@@ -37,13 +37,13 @@ Run `aitk standards list --json` and match each entry's `replacedBy` against the
37
37
 
38
38
  Compare on the folder rather than on the exact string. An `appliesTo` value matches when it equals `replacedBy` or begins with `replacedBy` followed by a slash. The report spells the folder `.claude/tasks` and the catalog spells it `.claude/tasks/`, and `memory` declares a filename pattern beneath its folder rather than the folder itself, so string equality matches nothing the catalog actually carries and sends every entry to a decline below.
39
39
 
40
- ### Search both standards roots
40
+ ### Read the standard through the verb
41
41
 
42
- A match resolves to that standard's `name`. Then look for that standard in the target, reading `.claude/standards/<name>.md` first and `standards/<name>.md` when the first is absent. The catalog says which standard governs the folder and only the target says whether the project holds it.
42
+ A match resolves to that standard's `name`. Read it with `aitk standards <name>`, which writes the document to stdout and the root it answered from to stderr.
43
43
 
44
- Search both roots in that order, which is the order the toolkit's own standards resolution already uses. A project that has not relocated its standards keeps them at the root, and testing the installed path alone hands exactly that target a refusal plus a command that installs a second copy beside the one it already holds.
44
+ The verb is the one route. It resolves `standards/<name>.md` at the project root first, which is where a project that authors standards of its own keeps them, and falls back to the corpus inside the aitk package. No toolkit standard installs into a project, so there is no third path to test and no case where the shape is unreachable while the catalog names it.
45
45
 
46
- A standard found at the root rather than under `.claude/` is read the same way and produces a full proposal. Say where it was read from and name `migration-standards` as the skill that relocates it, since the split is answerable either way and the layout is a note beside the proposal rather than a reason to refuse.
46
+ Report the root the frame named beside the proposal. A shape read from the project's own `standards/` is the project's stated agreement, and one read from the package is the toolkit's default, which is a difference the user weighs rather than a reason to refuse.
47
47
 
48
48
  ### The states that end an entry
49
49
 
@@ -51,10 +51,8 @@ Four states end an entry with no proposal. Name whichever one fired rather than
51
51
 
52
52
  - The catalog carries no `appliesTo` key: `⚠️ This aitk emits no appliesTo, so which standard governs <replacedBy> is unread.`
53
53
  - No value covers `replacedBy` and some entry carries an empty `appliesTo`: an empty array is a scope statement that did not parse, so a no-match verdict is unread rather than negative. Name the standards that did not parse.
54
- - No value covers `replacedBy` and every array is populated: `⚠️ The toolkit ships no standard for <replacedBy>. Nothing states the destination shape.` Installing cannot fix it, so name no command.
55
- - The standard resolved and neither root holds it: name it, then name `aitk standards install --only <name> .` as the command that lands it.
56
-
57
- Do not read the toolkit's own copy through `${CLAUDE_SKILL_DIR}` when the target lacks the file. Sibling skills cite that fallback for a standard they follow themselves, and this one is different: the standard here is the project's agreement about the shape of its own folder. A proposal drawn from the plugin copy hands back a shape the project never adopted, against content only the user can place.
54
+ - No value covers `replacedBy` and every array is populated: `⚠️ The toolkit ships no standard for <replacedBy>. Nothing states the destination shape.` No command fixes it, so name none.
55
+ - The standard resolved in the catalog and `aitk standards <name>` exits non-zero: name the standard and the exit, since the catalog and the read disagree and only one of them can be right.
58
56
 
59
57
  ## Step 3: read the shape and map the file onto it
60
58
 
@@ -90,7 +88,7 @@ Print one block per superseded entry, then the shared reminder. Omit empty group
90
88
  ```markdown
91
89
  ## Split
92
90
 
93
- `.claude/TASKS.md` → `.claude/tasks/`, shaped by `.claude/standards/tasks.md`
91
+ `.claude/TASKS.md` → `.claude/tasks/`, shaped by `aitk standards tasks`
94
92
 
95
93
  ## Proposed files
96
94
 
@@ -32,6 +32,6 @@ The last failure sits at a boundary rather than inside a run. `setup-init` turns
32
32
 
33
33
  ## Out of scope
34
34
 
35
- - The rest of the onboarding chain. This skill installs governance and nothing else, and `setup-init` is the one-shot path that installs governance beside tooling, standards, snippets, and the seeds.
36
- - Scaffolding the rule file an unmatched technology needs. `create-rule` writes one into a target project, and a rule the toolkit should ship is authored under `governance/rules/` against `.claude/standards/rule.md`.
35
+ - The rest of the onboarding chain. This skill installs governance and nothing else, and `setup-init` is the one-shot path that installs governance beside tooling, snippets, and the seeds.
36
+ - Scaffolding the rule file an unmatched technology needs. `create-rule` writes one into a target project, and a rule the toolkit should ship is authored under `governance/rules/` against `aitk standards rule`.
37
37
  - Updating rules a project already has, which `aitk gov sync` owns
@@ -9,18 +9,17 @@ What each `aitk` sync or install command does to existing files in a target proj
9
9
 
10
10
  ## Overwrite contract
11
11
 
12
- | Surface | Command | Effect on existing files |
13
- | -------------------------------------------------------- | ------------------------ | ---------------------------------------------------------------- |
14
- | Golden configs, listed in full below | `aitk tooling sync` | Overwritten once `--write` is passed. Local edits are lost. |
15
- | Dictionary seeds (`.cspell/*.txt`) | `aitk tooling sync` | Merged and sorted. Existing terms preserved. |
16
- | Other seeds (`cspell.json`, `.lintstagedrc`, state docs) | `aitk tooling sync` | Copy-once. Dropped on first install, untouched after. |
17
- | Standards | `aitk standards install` | All overwritten. |
18
- | Standards | `aitk standards sync` | Only files already present are updated. None are added. |
19
- | Seed docs and `CLAUDE.md` | `aitk claude init` | Skipped when present. Never overwritten. |
20
- | Seed docs | `aitk claude sync` | Never touched. Only `.gitignore` is written. |
21
- | References (`.claude/tooling/<stack>.md`) | `aitk tooling ref` | Overwritten. |
22
- | `.gitignore`, deps, scripts | any sync | Additive. Existing entries preserved. Deps re-pin on major skew. |
23
- | Generated `index.md` | any sync or regen | Rewritten from target state. Hand edits are lost. |
12
+ | Surface | Command | Effect on existing files |
13
+ | -------------------------------------------------------- | ------------------- | ----------------------------------------------------------------- |
14
+ | Golden configs, listed in full below | `aitk tooling sync` | Overwritten once `--write` is passed. Local edits are lost. |
15
+ | Dictionary seeds (`.cspell/*.txt`) | `aitk tooling sync` | Merged and sorted. Existing terms preserved. |
16
+ | Other seeds (`cspell.json`, `.lintstagedrc`, state docs) | `aitk tooling sync` | Copy-once. Dropped on first install, untouched after. |
17
+ | Standards | none | Nothing installs. `aitk standards <name>` reads and never writes. |
18
+ | Seed docs and `CLAUDE.md` | `aitk claude init` | Skipped when present. Never overwritten. |
19
+ | Seed docs | `aitk claude sync` | Never touched. Only `.gitignore` is written. |
20
+ | References (`.claude/tooling/<stack>.md`) | `aitk tooling ref` | Overwritten. |
21
+ | `.gitignore`, deps, scripts | any sync | Additive. Existing entries preserved. Deps re-pin on major skew. |
22
+ | Generated `index.md` | any sync or regen | Rewritten from target state. Hand edits are lost. |
24
23
 
25
24
  ## What a tooling sync can overwrite
26
25
 
@@ -94,8 +93,8 @@ Run `aitk tooling sync <stack> <target> --check` for the list resolved against a
94
93
  - Run `--check` first when the project carries local edits to any path above. The report names each file it would replace, which is the warning the user needs before the write.
95
94
  - An interactive run still prompts. `--write` skips the prompt, and `--check` refuses to write even with a TTY.
96
95
  - Seeds are user-owned. Dictionary `.txt` files merge and sort. Other seeds are copy-once, so re-seeding a structured file means deleting it and syncing again.
97
- - Prefer `aitk standards sync` over `install` on an existing project. `install` overwrites every standard.
98
- - For section-level customizations of a standard or seed doc, use the `claude-seed-sync` skill, not `aitk ... sync`. It diffs per section and preserves edits.
96
+ - No command writes a standard into a project. A `.claude/standards/` folder from an older toolkit is inert, and deleting it costs nothing.
97
+ - For section-level customizations of a seed doc, use the `claude-seed-sync` skill, not `aitk ... sync`. It diffs per section and preserves edits.
99
98
 
100
99
  ## CLAUDE.md
101
100
 
@@ -60,7 +60,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
60
60
  | ----------- | ------------------------------------------------------------------------------------------- |
61
61
  | `tooling` | `list`, `sync`, `ref`, `create`, `verify`, `inject`, `prune-gitignore` |
62
62
  | `snippets` | `list`, `install`, `sync`, `create` |
63
- | `standards` | `list`, `install`, `sync`, `<name>` |
63
+ | `standards` | `list`, `<name>` |
64
64
  | `gov` | `list`, `install`, `sync`, `build`, `regen`, `test-order` |
65
65
  | `claude` | `init`, `sync`, `seeds list`, `skills list`, `skills audit`, `skills drift`, `setup [dest]` |
66
66
  | `wiki` | `init` |