@erclx/aitk 3.9.0 → 3.11.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 (64) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/claude-markdown-propose/REQUIREMENT.md +48 -0
  3. package/claude/skills/claude-markdown-propose/SKILL.md +118 -0
  4. package/claude/skills/claude-markdown-propose/references/format.md +107 -0
  5. package/claude/skills/claude-pr-review/SKILL.md +1 -1
  6. package/claude/skills/claude-teach/SKILL.md +1 -1
  7. package/claude/skills/claude-worktree/SKILL.md +1 -1
  8. package/claude/skills/create-snippet/SKILL.md +1 -1
  9. package/claude/skills/git-branch/SKILL.md +1 -1
  10. package/claude/skills/git-commit/SKILL.md +1 -1
  11. package/claude/skills/git-issue/SKILL.md +2 -2
  12. package/claude/skills/git-pr/SKILL.md +5 -5
  13. package/claude/skills/git-split/SKILL.md +2 -2
  14. package/claude/skills/git-stage/SKILL.md +1 -1
  15. package/claude/skills/toolkit-cli/SKILL.md +0 -2
  16. package/docs/agents/audits.md +4 -4
  17. package/docs/agents/census.md +23 -0
  18. package/docs/agents/commands.md +1 -0
  19. package/docs/agents/index.md +1 -0
  20. package/docs/agents/records.md +1 -1
  21. package/docs/agents/teach.md +1 -1
  22. package/docs/ai-workflow.md +7 -6
  23. package/package.json +1 -1
  24. package/scripts/core/check-skill-paths.sh +1 -2
  25. package/scripts/core/verify.sh +0 -5
  26. package/src/audits/catalog.ts +48 -0
  27. package/src/census/count.ts +113 -0
  28. package/src/claude/skills-audit.ts +7 -0
  29. package/src/cli.ts +4 -0
  30. package/src/commands/census.ts +105 -0
  31. package/src/commands/claude.ts +20 -6
  32. package/src/commands/comments.ts +6 -0
  33. package/src/commands/context.ts +32 -7
  34. package/src/commands/gov.ts +2 -2
  35. package/src/commands/markdown.ts +18 -2
  36. package/src/context/audit.ts +16 -0
  37. package/src/gov/test-order.ts +31 -7
  38. package/src/markdown/files.ts +10 -0
  39. package/src/records/backup.ts +1 -0
  40. package/src/records/validate.ts +1 -3
  41. package/{claude/skills/git-split/references → standards}/branch.md +0 -1
  42. package/{claude/skills/git-commit/references → standards}/commit.md +0 -1
  43. package/{claude/skills/claude-teach/references → standards}/glossary.md +0 -1
  44. package/standards/index.md +6 -0
  45. package/standards/{bundled/issue.md → issue.md} +0 -1
  46. package/standards/{bundled/pr.md → pr.md} +0 -1
  47. package/standards/{bundled/snippets.md → snippets.md} +0 -1
  48. package/tooling/base/manifest.toml +0 -2
  49. package/tooling/base/reference.md +12 -12
  50. package/tooling/base/seeds/.claude/context/development.md +4 -6
  51. package/claude/skills/claude-worktree/references/branch.md +0 -60
  52. package/claude/skills/create-snippet/references/snippets.md +0 -78
  53. package/claude/skills/git-branch/references/branch.md +0 -60
  54. package/claude/skills/git-issue/references/issue.md +0 -95
  55. package/claude/skills/git-pr/references/branch.md +0 -60
  56. package/claude/skills/git-pr/references/pr.md +0 -139
  57. package/claude/skills/git-split/references/pr.md +0 -139
  58. package/claude/skills/git-stage/references/commit.md +0 -73
  59. package/scripts/core/regen-skill-references.sh +0 -27
  60. package/standards/bundled/branch.md +0 -60
  61. package/standards/bundled/commit.md +0 -73
  62. package/standards/bundled/glossary.md +0 -76
  63. package/tooling/base/configs/scripts/clean.sh +0 -45
  64. package/tooling/base/configs/scripts/update.sh +0 -49
@@ -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.9.0",
4
+ "version": "3.11.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: claude-markdown-propose
3
+ description: Why a markdown rewrite is proposed per file and answered before anything applies, rather than edited live or argued in chat
4
+ ---
5
+
6
+ # Claude markdown propose requirement
7
+
8
+ ## Gap
9
+
10
+ Rewriting a passage in a governing document today means editing it live or arguing in chat, and three surfaces sit near this moment without covering it. `claude-standards-audit` maps changed markdown to the standards claiming it and reports violations, ending on its own description: `Do NOT fix violations. Reporting only.` `aitk markdown audit` measures bans and structural checkpoints from package data.
11
+
12
+ `claude-review` reports findings on a diff someone already wrote. None of the three drafts a replacement, carries an answer slot, or waits.
13
+
14
+ A review delivered in chat gets applied from memory across files nobody reopened, and nothing records which changes the operator approved. A change nobody agreed to either lands unreviewed, because the session acting on a chat review cannot tell an approved line from an inferred one, or never gets written down at all, because a finding with no draft behind it hands the rewrite back to whoever reads it next.
15
+
16
+ A second failure compounds the first. A claim copied across several files is corrected in the one a session happened to open, and the copies elsewhere now read as freshly reviewed while still disagreeing, since nothing reconciles a restatement against the source it was drawn from.
17
+
18
+ ## Must
19
+
20
+ - Take the concern and the surface as inputs and run one procedure against them, so a second concern reuses this skill rather than forking it
21
+ - Grep the named surface for the concern before proposing, so a defect's site count is measured rather than assumed
22
+ - Draft the replacement text, not only the finding
23
+ - Carry three labelled variants on a change whose replacement was invented, and one on a change that corrects text to a recorded fact
24
+ - Write one proposal file per source file under `.claude/proposals/<slug>/` and stop, leaving `You:` empty on every change
25
+ - Apply only a change carrying an answer, one file at a time, and re-grep its anchor before applying it
26
+ - Name a folder that does not collide with `.claude/audits/`, which holds generated data rather than decision state
27
+ - Report what each file leaves alone, so a proposal cannot be read as finding everything wanting
28
+
29
+ ## Must not
30
+
31
+ - Edit a source file during the Propose phase
32
+ - Apply an unanswered change, or a subset of a file's answered changes while leaving the rest for later
33
+ - Fill a `You:` slot, or infer a disposition from an empty one
34
+ - Name a specific concern in this skill's own procedure. A concern belongs in the invocation, and hardcoding one narrows the skill to the day it was written.
35
+ - Assume the skill earns its place because the gap is real. Whether anything invokes it beyond the operator typing its name has no answer at creation time, and is a review criterion to read against a later usage census rather than a gate this file can pass on its own.
36
+
37
+ ## Guards
38
+
39
+ - No concern named and none derivable: stop rather than inferring one
40
+ - No surface named and none derivable: stop rather than screening the whole tree
41
+ - The concern resolves to one file: stop and say a single-file change needs no proposal folder
42
+
43
+ ## Out of scope
44
+
45
+ - Reporting a violation with no drafted replacement, which `claude-standards-audit` and `aitk markdown audit` already own
46
+ - Reviewing a diff someone already wrote, which `claude-review` owns
47
+ - Filing a raw brain dump as findings, which `claude-intake` owns
48
+ - Reviewing `.claude/memory/` and proposing promote-or-retire actions per entry, which `claude-memory-review` owns on a different subject with a different answer contract
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: claude-markdown-propose
3
+ description: Reviews a named markdown surface against a named concern, drafts a per-file proposal under `.claude/proposals/<slug>/` carrying a diff and a reason for each change, and stops without editing a source file. Takes the concern and the surface as inputs, such as a claim stated stronger than the record, a fact gone stale, two files disagreeing, or a passage duplicated without derivation. A later invocation applies what the operator answered. Use when asked to "propose a change to CLAUDE.md", "draft a rewrite of this standard", "propose fixes to this doc", "draft alternatives for this passage", or "apply the answered proposals". Do NOT use to report without drafting a replacement (`claude-standards-audit` or `aitk markdown audit`), to review a diff already made (`claude-review`), or to file a raw brain dump as findings (`claude-intake`).
4
+ ---
5
+
6
+ # Claude markdown propose
7
+
8
+ Reviews what a markdown surface says against a named concern and proposes what it should say instead. Writes proposals and stops. The operator answers per change, and a later invocation applies the answered set.
9
+
10
+ The value is the gate. A rewrite delivered in chat gets applied from memory across files nobody reopened, and nothing records what was approved.
11
+
12
+ ## Guards
13
+
14
+ - No concern named and none derivable from the conversation. Stop: `❌ No concern to screen for. Name what looks wrong, or the surface to review.`
15
+ - No surface named and none derivable. Stop: `❌ No surface to review. Name the files, or the folder, to screen.`
16
+ - The concern resolves to one file only. Stop and say so: a single-file change needs no proposal folder.
17
+ - A named file cannot be read. Stop and name it. Do not screen what resolved and report a partial result.
18
+
19
+ ## Phase detection
20
+
21
+ Two phases share this body, picked by whether a proposal folder already exists for the request's slug.
22
+
23
+ Derive `<slug>` from the concern and the surface, kebab-case, naming the subject rather than the activity. List `.claude/proposals/` at the main worktree root and match the topic against the folders already there before deriving a fresh one, the same way `claude-intake` matches its own folder. Never match against `.claude/` itself.
24
+
25
+ - No matching folder, or the operator names a concern and a surface: **Propose**.
26
+ - A matching folder exists and the operator says apply, ship, or commit the answers: **Apply**.
27
+
28
+ All `.claude/proposals/` reads and writes resolve at the main worktree root, not the current worktree. See Worktrees in `CLAUDE.md`.
29
+
30
+ ## Write scope
31
+
32
+ Write only inside `.claude/proposals/<slug>/`. A source file, a standard, a rule, and a plan all live outside that folder, so this one rule forbids every one of them during the Propose phase. The Apply phase is the one exception, and only for a change carrying a `You:` answer.
33
+
34
+ ## Concerns
35
+
36
+ The concern is an input, not a flow toggle. The passes below are one procedure and the concern decides what pass 1 looks for.
37
+
38
+ | Concern | What it looks like |
39
+ | ------------- | -------------------------------------------------------------------- |
40
+ | Inflation | a claim stated stronger than the record supports |
41
+ | Staleness | a fact correct when written and wrong now, usually a date or a count |
42
+ | Contradiction | two files, or two sections, asserting incompatible things |
43
+ | Duplication | one passage copied across files with no derivation, drifting apart |
44
+
45
+ The operator may name a concern outside this table. Run the same procedure against it.
46
+
47
+ ## Propose phase
48
+
49
+ Read `${CLAUDE_SKILL_DIR}/references/format.md` before writing anything. Do not work the proposal format from memory.
50
+
51
+ ### 1. Find the sites
52
+
53
+ Grep the named surface for the concern and its near-variants. A defect rarely repeats verbatim, so search the habit rather than the string.
54
+
55
+ Count hits per file before reading them. A file with one hit and a file with eight are different problems.
56
+
57
+ ### 2. Find what it should say
58
+
59
+ Read whatever the operator names as the authoritative source for the concern. Absent one, grep the rest of the tree for a passage already stating the corrected form, since a correct version often already exists somewhere the defect has not reached.
60
+
61
+ Report a file that contradicts itself. A file holding both the defect and its corrected form is the strongest finding available, because the replacement is already drafted somewhere in the tree and needs no invention.
62
+
63
+ ### 3. Judge per line, not per match
64
+
65
+ A matched string means different things in different registers. A word describing a mechanism is a fact about how something works. The same word describing reach is a claim about who relies on it. Sweeping both because they share a string is what makes the next pass harder to trust.
66
+
67
+ ### 4. Write the proposals
68
+
69
+ One file per source file under `.claude/proposals/<slug>/`, per `${CLAUDE_SKILL_DIR}/references/format.md`.
70
+
71
+ Draft the replacement text. A proposal reporting a problem without a replacement hands the work back rather than doing it.
72
+
73
+ Carry an `Open:` on any change whose replacement was written rather than corrected, and give it three variants per the format reference. Correcting an overstatement to the recorded fact has one answer. Inventing a paragraph has no right answer, and one draft asks the operator to veto instead of to choose, which costs a round every time the intent lands wrong.
74
+
75
+ Separate the two kinds before drafting. A change that deletes a claim the record does not support is cheap and rarely argued. A change that writes new prose is where the effort belongs.
76
+
77
+ Close each file with what it leaves alone, and say why those lines survived.
78
+
79
+ ### 5. Report
80
+
81
+ Name the count, the files, and the single highest-value change. Point at the folder and stop.
82
+
83
+ Do not edit a source file. Do not fill a `You:` slot.
84
+
85
+ Propose in dependency order and state it in `00-overview.md` when the surface spans more than two files. A file other files quote is settled first, otherwise the same wording gets decided twice.
86
+
87
+ ## Apply phase
88
+
89
+ Read `${CLAUDE_SKILL_DIR}/references/format.md` before applying anything, if this session has not already read it this pass.
90
+
91
+ Follow the Applying section there: one file at a time in settle order, every answered change in that file and nothing unanswered, re-grepping each anchor before applying it, sweeping the other named surfaces for the same claim before committing, and moving an applied change into `applied.md`.
92
+
93
+ Report the counts once the pass stops: files committed, changes applied, changes still carrying an empty `You:`. Leave the folder in place. Neither phase deletes it.
94
+
95
+ ## Output
96
+
97
+ Chat output is the report. This skill persists only the proposal folder itself.
98
+
99
+ ```plaintext
100
+ 📂 Opened .claude/proposals/<slug>/
101
+
102
+ **Screened:** <N> files, <N> changes proposed, <N> carrying three variants
103
+
104
+ **Highest value:** <the single strongest change, one line>
105
+
106
+ Next: answer the `You:` slots in the files under .claude/proposals/<slug>/,
107
+ then re-invoke this skill to apply what you answered.
108
+ ```
109
+
110
+ Use `📂 Resumed` in place of `📂 Opened` on a resume pass. The Apply phase reports instead:
111
+
112
+ ```plaintext
113
+ ✅ Applied .claude/proposals/<slug>/
114
+
115
+ **Committed:** <N> files, <N> changes
116
+
117
+ **Still open:** <N> changes with an empty `You:`
118
+ ```
@@ -0,0 +1,107 @@
1
+ # Proposal format reference
2
+
3
+ Governs the proposal `claude-markdown-propose` writes before it edits anything. The concern being screened is an input and does not change the format.
4
+
5
+ ## Folder
6
+
7
+ - One folder per screening pass at `.claude/proposals/<slug>/`, where the slug names the subject rather than the activity
8
+ - One proposal file per source file, named `<nn>-<source filename, its own extension dropped>.md`, so a source already named `CLAUDE.md` becomes `01-CLAUDE.md` rather than `01-CLAUDE.md.md`
9
+ - `00-overview.md` when the pass spans more than two source files, holding the cross-file pattern, the change counts, and the settle order
10
+ - `applied.md` once the first change lands, holding every applied change with its reason and the answer it carried
11
+
12
+ The name carries both structures the folder has. The basename pairs a proposal to its source so a reader opens the two side by side, and the number is the settle order, which is a dependency rather than a preference: a file other files quote is settled first. Do not group proposals by theme.
13
+
14
+ A proposal opened after the initial pass takes the next free number, and the folder is never renumbered. Its number records when the site was found rather than where it belongs in the dependency order. Renumbering to restore the order would rewrite the names of files already carrying answers, which costs more than the ordering is worth once applying has started.
15
+
16
+ Settle a late proposal ahead of any unapplied proposal quoting the surface it covers, whatever the two numbers say. A proposal already applied is past the question, since the file it governs is committed.
17
+
18
+ ## Change format
19
+
20
+ Each proposal file opens with `# Proposal: <source path>`, one line naming the concern, the settle order, and the full surface the pass screened, then one `###` heading per change, ending with a `## Left alone` section. A change never sits at `##`, which the closing section reserves, and a variant never sits at `###`, which the change heading reserves. Skipping from `#` straight to `###` is deliberate: the file has exactly one layer of change between its title and its variants.
21
+
22
+ Naming the surface on every file, not only the first, is what lets Applying's cross-surface grep run cold. The Propose and Apply invocations are typically separate sessions days apart, so the surface the operator named has to survive on the file rather than in a conversation neither session shares.
23
+
24
+ A change carries an `###` heading, a fenced `diff` block holding the current text against the proposed, the reason beneath it, and its own answer slot.
25
+
26
+ - Heading: `### N. The sentence or section it sits in`
27
+ - Body: a `diff` fence, `-` for current and `+` for proposed
28
+ - `- **Why:** the reason, naming what the change fixes`
29
+ - `- **Open:** only where the replacement was drafted rather than corrected`
30
+ - `- **Recommended:** only where a pick is proposed ahead of the answer, directly above the slot`
31
+ - `- **You:**` last on every change, shipped empty
32
+
33
+ ### Variants
34
+
35
+ A corrected change carries one replacement. A drafted one carries three, because the intent behind invented prose is not recoverable from the source text and a single draft turns the answer slot into a veto.
36
+
37
+ - Ship three variants on any change carrying `Open:`, labelled `#### A`, `#### B`, `#### C`
38
+ - Make them differ in approach rather than in wording. Three phrasings of one bet are one variant.
39
+ - State the bet each one makes in a line above its block, so the choice is between strategies and not between paragraphs
40
+ - Ship one replacement everywhere else. A word swapped for the recorded fact has no second option worth reading.
41
+
42
+ Three is the cap as well as the count. A fourth splits attention without widening the space.
43
+
44
+ ### Placement
45
+
46
+ - Title a change by the section or sentence it sits in, never by its position in the file
47
+ - Quote text from another file in a `markdown` block rather than citing a line number, which goes stale on the first applied change
48
+ - Split a `Why:` into labelled halves when one change fixes two things (`**Why, the date:**`)
49
+ - Carry an `Open:` on any change whose replacement text was written rather than corrected, so a blanket answer cannot swallow it
50
+
51
+ Close each file with what it leaves alone. A pass reporting only what it would change reads as one that found everything wanting.
52
+
53
+ ## The answer contract
54
+
55
+ `You:` belongs to the operator and ships empty on every change. Empty means unread and never agreement, matching the intake contract in `${CLAUDE_SKILL_DIR}/../../standards/intake.md` rather than the plan file's, which reads a blank slot as accepting the suggestion above it. State the inversion at the top of `00-overview.md` when the folder spans more than one file, since a contract read from the wrong surface gets applied to the wrong document.
56
+
57
+ - One `You:` per change, last in its bullet list, so an answer lands where the change is read
58
+ - Never fill a `You:` slot and never infer a disposition from an empty one
59
+ - The slot takes free text, not only `ok`. A rejection, a caveat, or a rewrite of the proposed line are all valid answers and a later pass reads them correctly.
60
+ - A pick made on the operator's behalf goes on a `- **Recommended:**` line directly above the slot, never inside it, and states which variant it takes and why. The slot below it still ships empty, so a count of unread changes still reads the change as unread.
61
+
62
+ An answer rejecting the draft reopens the change rather than closing it. Move that answer to a `- **Answered:**` line above the variants it produced, and ship a fresh empty `- **You:**` beneath them. The change reads as unread again, which is what it is.
63
+
64
+ Per-change slots do not license a partial sweep. Answering a change records one decision, and the applying rule below is what holds the set together.
65
+
66
+ The overview file carries no slot, since it proposes no changes.
67
+
68
+ ## Applying
69
+
70
+ - Apply one file at a time, in the folder's settle order
71
+ - Apply every change in that file that carries an answer, and nothing that does not
72
+ - Re-grep each change's anchor against its source before applying it, and again after a rebase
73
+ - Grep the other named surfaces for the same claim before committing the file
74
+ - Write every hit that grep returns onto the proposal owning the file it sits in, as a change with its own answer slot, and open a proposal for a surface the pass has none for
75
+ - Commit the file once its own answered changes are applied. A hit in a sibling never holds it.
76
+ - Move an applied change into `applied.md` beside the proposals, carrying its reason and its answer
77
+
78
+ A partial pass is worse than none, and a file is the unit that can be finished. Settling one claim across every file at once touches all of them and closes none, so each file ends the pass looking reviewed while other changes in it sit answered and unapplied. The surface grep is what covers the cross-file half a per-file pass would otherwise miss.
79
+
80
+ Recording a hit rather than acting on it is what keeps the grep from rebuilding the whole-set gate. A sibling holding the same claim is a change nobody has answered yet, and holding this file until it is answered makes every file wait on the slowest one, which is the shape the per-file unit replaced.
81
+
82
+ A proposal outlives its own diff. The source moves under it, so an approved change stops matching while the defect it names survives in fresh wording. The anchor re-grep is the only thing that catches that.
83
+
84
+ ## After
85
+
86
+ - Strip the `diff` blocks
87
+ - Keep the files, their headings, their reasons, and the answers
88
+
89
+ What remains is the record of what changed and why, which is the half no commit message holds. The folder stays where it is, beside every earlier pass, so a later one reads what an earlier one settled instead of asking it again.
90
+
91
+ The folder is gitignored and unbacked. It carries decision state rather than generated data, which is why `src/records/backup.ts` names it in `BACKED_FOLDERS`, but nothing else about its contents is enforced.
92
+
93
+ ## Retrieval
94
+
95
+ Count the unread changes per file:
96
+
97
+ ```bash
98
+ grep -c '^- \*\*You:\*\*$' .claude/proposals/<slug>/*.md
99
+ ```
100
+
101
+ Report every answer given, against the change it sits under:
102
+
103
+ ```bash
104
+ awk '/^### /{h=FILENAME": "$0} /^- \*\*You:\*\*./{print h; print " "$0}' .claude/proposals/<slug>/*.md
105
+ ```
106
+
107
+ Both walk `###` headings, which is the mechanical reason an answer typed anywhere else is lost.
@@ -85,7 +85,7 @@ Review the diff and files for the same axes as `claude-review` (bugs, edge cases
85
85
 
86
86
  Then read the description's `## Testing` section, which is the one part of a pull request body this session is positioned to falsify. The branch author cannot see what a sibling branch drove the same day, and the arm list is what settles the claim rather than the diff.
87
87
 
88
- Test every unchecked box against the testing discipline in `${CLAUDE_SKILL_DIR}/../../standards/bundled/pr.md`, which reserves an unchecked box for a capability the agent lacks. Raise the box when it names no human at all, when the human it names is a live agent session, or when it names a person for a step the repository ships a harness for, `scripts/sandbox/run.sh` and `scripts/eval/run.sh` being the two. Cost alone is not an answer, since authorizing a spend is the operator's and performing the run is not. A refusal the author actually met is an answer, and it names which one.
88
+ Test every unchecked box against the testing discipline in `${CLAUDE_SKILL_DIR}/../../standards/pr.md`, which reserves an unchecked box for a capability the agent lacks. Raise the box when it names no human at all, when the human it names is a live agent session, or when it names a person for a step the repository ships a harness for, `scripts/sandbox/run.sh` and `scripts/eval/run.sh` being the two. Cost alone is not an answer, since authorizing a spend is the operator's and performing the run is not. A refusal the author actually met is an answer, and it names which one.
89
89
 
90
90
  Ask rather than grade. Whether a human is genuinely required is a reading the branch author may hold a reason this session cannot see, so the question carries no severity and enters no count. What it does carry is the heading and the dispatch, on the rule Step 4 states, because a question the author never receives corrects nothing and the author is the only party who can answer it. Answering it closes it, and the answer may be that the requirement holds.
91
91
 
@@ -9,7 +9,7 @@ argument-hint: <subject to learn, or the topic of a workspace to resume or promo
9
9
 
10
10
  Run a learning workspace on one subject across sessions. The workspace holds what the learner has been through, so a session weeks later resumes from the folder rather than from the conversation.
11
11
 
12
- The shape of the workspace is fixed by `${CLAUDE_SKILL_DIR}/../../standards/teach.md`. Read it before writing anything into the folder. The glossary answers to `${CLAUDE_SKILL_DIR}/references/glossary.md`, which travels with this skill rather than installing, because a promoted glossary keeps its shape at whatever path it lands on and no project folder covers all of them. The pedagogy sits in `${CLAUDE_SKILL_DIR}/references/pedagogy.md`, the lesson craft in `${CLAUDE_SKILL_DIR}/references/lesson-craft.md`, and the promotion routing in `${CLAUDE_SKILL_DIR}/references/promotion.md`.
12
+ The shape of the workspace is fixed by `${CLAUDE_SKILL_DIR}/../../standards/teach.md`. Read it before writing anything into the folder. The glossary answers to `${CLAUDE_SKILL_DIR}/../../standards/glossary.md`, whose shape governs a glossary wherever it lands, since a promoted glossary keeps its shape at whatever path it reaches and no project folder covers all of them. The pedagogy sits in `${CLAUDE_SKILL_DIR}/references/pedagogy.md`, the lesson craft in `${CLAUDE_SKILL_DIR}/references/lesson-craft.md`, and the promotion routing in `${CLAUDE_SKILL_DIR}/references/promotion.md`.
13
13
 
14
14
  ## Guards
15
15
 
@@ -43,7 +43,7 @@ Try each source in order. Stop at the first match.
43
43
 
44
44
  Validate the result: letters, digits, dots, underscores, dashes only, max 64 chars (`/` separators are also allowed). If the derived name violates the rule, sanitize by replacing invalid chars with `-` and truncating. Show the sanitized name in the preview before invoking.
45
45
 
46
- Resolve `<type>` here as well, since Step 3 previews it and Step 5 renames onto it. A name from a plan takes the type that plan's own work carries, read off its `## Summary` and `**Files to touch:**` lines. Every other case takes `feat`, which covers a name from a branch, a name from the user, and a plan whose lines settle nothing. Draw the value from the type vocabulary in `${CLAUDE_SKILL_DIR}/references/branch.md`.
46
+ Resolve `<type>` here as well, since Step 3 previews it and Step 5 renames onto it. A name from a plan takes the type that plan's own work carries, read off its `## Summary` and `**Files to touch:**` lines. Every other case takes `feat`, which covers a name from a branch, a name from the user, and a plan whose lines settle nothing. Draw the value from the type vocabulary in `${CLAUDE_SKILL_DIR}/../../standards/branch.md`.
47
47
 
48
48
  A wrong type is cheap. `git-branch` renames to conventional format later in the same chain and runs ahead of `git-pr`, so a `feat/` written over a fix is corrected before any pull request opens.
49
49
 
@@ -9,7 +9,7 @@ Creates one snippet file. Read these files in parallel:
9
9
 
10
10
  - `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: banned words, punctuation, and formatting for all generated text
11
11
  - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
12
- - `${CLAUDE_SKILL_DIR}/references/snippets.md`: authoring conventions, invocation channels, use patterns
12
+ - `${CLAUDE_SKILL_DIR}/../../standards/snippets.md`: authoring conventions, invocation channels, use patterns
13
13
 
14
14
  ## Guards
15
15
 
@@ -7,7 +7,7 @@ description: Generates and validates conventional branch names. Use for any bran
7
7
 
8
8
  Before generating a branch name, read:
9
9
 
10
- - `${CLAUDE_SKILL_DIR}/references/branch.md`: format, types, length limit, and constraints
10
+ - `${CLAUDE_SKILL_DIR}/../../standards/branch.md`: format, types, length limit, and constraints
11
11
 
12
12
  Follow it exactly.
13
13
 
@@ -7,7 +7,7 @@ description: Generates one conventional commit message from the staged changes a
7
7
 
8
8
  Before generating a commit message, read:
9
9
 
10
- - `${CLAUDE_SKILL_DIR}/references/commit.md`: format, types, scopes, and constraints
10
+ - `${CLAUDE_SKILL_DIR}/../../standards/commit.md`: format, types, scopes, and constraints
11
11
  - `${CLAUDE_SKILL_DIR}/../../standards/versioning.md`: phase label vs semver discipline
12
12
 
13
13
  Follow them exactly.
@@ -11,7 +11,7 @@ Format an issue from session context following the issue standard, then file it
11
11
 
12
12
  Read these in parallel:
13
13
 
14
- - `${CLAUDE_SKILL_DIR}/references/issue.md`: issue title, labels, body sections, and banned phrases
14
+ - `${CLAUDE_SKILL_DIR}/../../standards/issue.md`: issue title, labels, body sections, and banned phrases
15
15
  - `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: banned words, punctuation, and formatting for all generated text
16
16
  - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
17
17
 
@@ -39,7 +39,7 @@ After outputting the preview, execute the final command immediately. Claude Code
39
39
 
40
40
  ### Pre-publish scan
41
41
 
42
- Before running the final command, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the title and body. The title and body go straight to the remote with nothing checking them on the way, so this scan is the only gate. It covers the phase-label check as well as the characters, since both go to a reader who has no task board. It applies on top of the banned phrases in `${CLAUDE_SKILL_DIR}/references/issue.md`.
42
+ Before running the final command, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the title and body. The title and body go straight to the remote with nothing checking them on the way, so this scan is the only gate. It covers the phase-label check as well as the characters, since both go to a reader who has no task board. It applies on top of the banned phrases in `${CLAUDE_SKILL_DIR}/../../standards/issue.md`.
43
43
 
44
44
  ### Final command
45
45
 
@@ -9,8 +9,8 @@ description: Generates pull request titles and descriptions from git diffs. Use
9
9
 
10
10
  Read these files in parallel:
11
11
 
12
- - `${CLAUDE_SKILL_DIR}/references/branch.md`: branch format, valid types, and constraints
13
- - `${CLAUDE_SKILL_DIR}/references/pr.md`: structure, rules, and banned phrases
12
+ - `${CLAUDE_SKILL_DIR}/../../standards/branch.md`: branch format, valid types, and constraints
13
+ - `${CLAUDE_SKILL_DIR}/../../standards/pr.md`: structure, rules, and banned phrases
14
14
  - `${CLAUDE_SKILL_DIR}/references/labels.md`: label map format, matching, and the missing-label warning. Skip when the project has no `.claude/aitk/pr-labels.toml`.
15
15
  - `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: banned words, punctuation, and formatting for all generated text
16
16
  - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
@@ -47,7 +47,7 @@ Either case leaves both reads empty, which the no-commits guard below catches. S
47
47
 
48
48
  ## Guards
49
49
 
50
- - If branch name does not match `<type>/<description>` format (valid types are defined in `${CLAUDE_SKILL_DIR}/references/branch.md`), stop and output:
50
+ - If branch name does not match `<type>/<description>` format (valid types are defined in `${CLAUDE_SKILL_DIR}/../../standards/branch.md`), stop and output:
51
51
  `❌ Branch name does not follow conventions. Run /git-branch to rename first.`
52
52
  - If no commits ahead of main, stop and output:
53
53
  `❌ No commits ahead of main. Nothing to PR.`
@@ -64,13 +64,13 @@ After outputting the preview, execute the final command immediately. Claude Code
64
64
 
65
65
  ### Testing checkboxes
66
66
 
67
- Follow Testing discipline in `${CLAUDE_SKILL_DIR}/references/pr.md`. Run each check before writing its line, then tick the box and state the result the run reported. Never pre-check based on intent or past sessions.
67
+ Follow Testing discipline in `${CLAUDE_SKILL_DIR}/../../standards/pr.md`. Run each check before writing its line, then tick the box and state the result the run reported. Never pre-check based on intent or past sessions.
68
68
 
69
69
  Leave a box unchecked only for the human-only cases the reference defines, and name which human and why on the same line. A request for the reviewer is not a test result, so it belongs under `## For the reviewer` rather than in the Testing list.
70
70
 
71
71
  ### Pre-publish scan
72
72
 
73
- Before running the final command, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the PR title and body. The title and body go straight to the remote with nothing checking them on the way, so this scan is the only gate. It covers the phase-label check as well as the characters, since both go to a reader who has no task board. It applies on top of the banned phrases in `${CLAUDE_SKILL_DIR}/references/pr.md`.
73
+ Before running the final command, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the PR title and body. The title and body go straight to the remote with nothing checking them on the way, so this scan is the only gate. It covers the phase-label check as well as the characters, since both go to a reader who has no task board. It applies on top of the banned phrases in `${CLAUDE_SKILL_DIR}/../../standards/pr.md`.
74
74
 
75
75
  ### Resolving the pull request
76
76
 
@@ -7,8 +7,8 @@ description: Splits a mixed-commit branch into focused branches off main using c
7
7
 
8
8
  Before proposing a split, read in parallel:
9
9
 
10
- - `${CLAUDE_SKILL_DIR}/references/branch.md`: format, types, length limit, and constraints
11
- - `${CLAUDE_SKILL_DIR}/references/pr.md`: PR title format, body sections, and content rules
10
+ - `${CLAUDE_SKILL_DIR}/../../standards/branch.md`: format, types, length limit, and constraints
11
+ - `${CLAUDE_SKILL_DIR}/../../standards/pr.md`: PR title format, body sections, and content rules
12
12
 
13
13
  Follow both exactly.
14
14
 
@@ -7,7 +7,7 @@ description: Groups staged files by concern and generates one conventional commi
7
7
 
8
8
  Read these files in parallel:
9
9
 
10
- - `${CLAUDE_SKILL_DIR}/references/commit.md`: format, types, scopes, and constraints
10
+ - `${CLAUDE_SKILL_DIR}/../../standards/commit.md`: format, types, scopes, and constraints
11
11
  - `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: banned words, punctuation, and formatting for all generated text
12
12
  - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
13
13
 
@@ -52,8 +52,6 @@ Run `aitk tooling sync <stack> <target> --check` for the list resolved against a
52
52
  - `.vscode/extensions.json`
53
53
  - `.vscode/settings.json`
54
54
  - `commitlint.config.js`
55
- - `scripts/clean.sh`
56
- - `scripts/update.sh`
57
55
  - `scripts/verify.sh`
58
56
 
59
57
  ### python
@@ -22,11 +22,11 @@ aitk audits list --json
22
22
 
23
23
  ## What it runs
24
24
 
25
- Seventeen verbs, listed by `aitk audits list`. Each runs once in its fullest form, and the aggregate reads that verb's own record rather than imposing a shared envelope on it. Every one of those records already has consumers naming its keys, so a common shape would be a breaking change bought for tidiness.
25
+ Eighteen verbs, listed by `aitk audits list`. Each runs once in its fullest form, and the aggregate reads that verb's own record rather than imposing a shared envelope on it. Every one of those records already has consumers naming its keys, so a common shape would be a breaking change bought for tidiness.
26
26
 
27
27
  The verbs walk separate trees and share no state, so they run together. Measured on the authoring machine at twelve verbs, a run finished in 0.8 seconds of wall clock against 4.4 seconds of processor, which is under every other stage in `bun run check`. `aitk deps audit` is the one that changes that reading, since it reaches a network rather than a tree and its latency is the index's rather than this machine's.
28
28
 
29
- Fourteen of the seventeen read a tree on this disk, the one added by `restated.md` among them, since it reads three such trees against each other. The two added by `state-scoped-risk.md` read committed state rather than an arriving change, which is the gap every review surface here leaves by construction, and the one added by `label-coverage.md` reads a branch range against a map the project declares.
29
+ Fifteen of the eighteen read a tree on this disk, the one added by `restated.md` and the one added by `census.md` among them, since the first reads three such trees against each other and the second counts every file in one. The two added by `state-scoped-risk.md` read committed state rather than an arriving change, which is the gap every review surface here leaves by construction, and the one added by `label-coverage.md` reads a branch range against a map the project declares.
30
30
 
31
31
  Each is invoked as the CLI the caller is running rather than as a global `aitk`. A globally installed binary resolves to the main checkout no matter which worktree is executing, so the aggregate would measure a tree the branch never touched and report a pass over it.
32
32
 
@@ -57,11 +57,11 @@ The verdict is published as a field as well as an exit code. A reader branching
57
57
 
58
58
  A per-machine folder that is not on this disk reports as `absent` and moves neither the verdict nor the exit code. Every one of those folders is gitignored, so a fresh clone and every CI run carry none of them, and counting six expected absences as failures pins the verdict at `incomplete` forever. A signal that never changes is one nobody reads after the second time they see it.
59
59
 
60
- Which refusals count as an absence is declared per audit rather than inferred from the corpus alone. A per-machine corpus counts a missing folder. An upstream corpus counts every reason the advisory verb publishes, since each of the three means there is nothing resolved to measure. The secret scan overrides its tracked default for the three reasons that mean the project publishes nothing at all.
60
+ Which refusals count as an absence is declared per audit rather than inferred from the corpus alone. A per-machine corpus counts a missing folder. An upstream corpus counts every reason the advisory verb publishes, since each of the three means there is nothing resolved to measure. Several tracked audits override that default too, wherever the corpus not being there is the ordinary state of a target rather than a broken checkout: the secret scan for a project that publishes nothing, the skill corpora and the citation reach check for a project holding no skills tree, and the context audit for a project that adopted none of the folders it measures.
61
61
 
62
62
  Everything else stays `unmeasured`. That covers a tree git cannot list, which is a broken checkout, and a package declaring no `files` field, where a publish would pack the whole tree and the scan read none of it. Both are a corpus that exists and went unread, so softening either would report a pass over a shipped tree nobody measured.
63
63
 
64
- The override exists because the corpus answers the wrong question for one audit. What earns it is `private: true`, the one declaration that a package is never published, so a project carrying it reports an absent corpus rather than a broken one. Without that the aggregate would report `incomplete` in every such project on every run, which is the permanent signal this section opens by rejecting.
64
+ Each override exists because the corpus answers the wrong question for that audit. The secret scan earns its from `private: true`, the one declaration that a package is never published, so a project carrying it reports an absent corpus rather than a broken one. Without that the aggregate would report `incomplete` in every such project on every run, which is the permanent signal this section opens by rejecting.
65
65
 
66
66
  `upstream` is the third corpus value, carried by the advisory check alone. Its count moves when someone publishes rather than when someone edits here, so it is kept out of the retained baseline for the mirror image of the reason gitignored scratch is, and an offline run reports it absent rather than pinning the verdict at `incomplete` on every machine without a network.
67
67
 
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: Census
3
+ description: Tracked-plus-untracked file count, a breakdown by extension, and a line total that skips whatever reads as binary
4
+ ---
5
+
6
+ # Census
7
+
8
+ `aitk census [path]` reports how large a tree is: the tracked-plus-untracked file count, a breakdown by extension, and a line total. It reads `listRepositoryFiles`, the same corpus the citation check, the markdown corpus, and the secret scan already read, so this is not a fourth definition of what counts.
9
+
10
+ ```bash
11
+ aitk census
12
+ aitk census src --json
13
+ ```
14
+
15
+ | Option | Behavior |
16
+ | -------- | ---------------------------------------------------------- |
17
+ | `--json` | Add a machine-readable record on stdout, keeping the frame |
18
+
19
+ Grouping is by extension rather than by a named language category. A config file and a source file land in separate buckets and two source files sharing an extension land in one, and a file with no extension, such as `Dockerfile`, lands under `no-extension`.
20
+
21
+ Line counts are text-only. A file that reads as binary, and a file git lists that will not open, such as a symlink leaving the tree, are counted toward the file total and their extension's file count, and left out of every line count. The record's `skipped` field states that gap rather than leaving a reader to infer it from the difference between the file count and the summed extension line counts. It carries both causes as one number: on a healthy tree the two are indistinguishable, so a `skipped` count above what the tree's own binary files explain is itself the signal that something in the corpus will not open.
22
+
23
+ The command reports a snapshot rather than a delta. It registers in the audit catalog with an empty gating set, so `aitk audits run --record` is what turns two snapshots into the growth series a hand count used to approximate: 481 files on one date and 965 five weeks later, with nothing between them because nobody had counted again.
@@ -54,6 +54,7 @@ Full help: `aitk <command> --help`. Behavior notes for the install and sync verb
54
54
  | `aitk secrets scan` | Report credential-shaped values in the tree the package ships, keyed on issued values rather than on words (`--json`) |
55
55
  | `aitk deps audit` | Report published advisories against the resolved dependency set, refusing rather than reporting clean when the index is unreachable (`--json`) |
56
56
  | `aitk labels audit` | Report the labels a changed set earns from the pull request label map and the paths no row reaches (`--json`) |
57
+ | `aitk census [path]` | Report tracked file count, a breakdown by extension, and a line total that skips whatever reads as binary (`--json`) |
57
58
  | `aitk audits run` | Run every audit as one set, report per check under one verdict, and compare each count to the recorded baseline (`--json`, `--record`) |
58
59
  | `aitk audits list` | List every audit the set runs, with the corpus each reads and whether it gates (`--json`) |
59
60
  | `aitk capture [source]` | Render HTML capture sources to PNG, toolkit-only and absent from an installed package |
@@ -10,6 +10,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
10
10
 
11
11
  - [Audits](audits.md): Running every health check as one set, what the single verdict means, the exit code each outcome takes, the retained baseline and the delta it reports, and which corpora are kept out of the record
12
12
  - [Capture](capture.md): Rendering committed HTML sources to PNG, what the command asserts about fonts, and why it is toolkit-only
13
+ - [Census](census.md): Tracked-plus-untracked file count, a breakdown by extension, and a line total that skips whatever reads as binary
13
14
  - [Command catalog](commands.md): Every project-level command and every domain subcommand, plus the shape each domain exposes
14
15
  - [Comments](comments.md): Comment density by language and kind, the two structural exclusions, and how the degradation sweep finds its vocabulary
15
16
  - [Context audit checks](context-audit-checks.md): What each non-gating check reports, the unit each checkpoint is measured in, the architecture record's length gate and claim coverage, which folders each check reaches, and what moved to the attribute tier
@@ -23,7 +23,7 @@ aitk records validate intake --json
23
23
 
24
24
  It reads and never writes, and the reason splits by kind. A session record is per-machine scratch with no history behind it, so a repair that guessed wrong could not be undone. A standard installs into every target and is cited by bare filename, so a rename the verb performed would reach further than the file it moved, which is why a finding naming one says so.
25
25
 
26
- `standards` reads the authoring root at `standards/` where it exists and the installed copy at `.claude/standards/` otherwise. The authoring root wins because the installed tree is generated from it in the toolkit, where a fix written to the copy is discarded by the next regen. A project that consumed the corpus holds only the second, so one precedence serves both. The walk stays flat, matching install and the catalog, so `standards/bundled/` is out of range. Location decides that rather than subject, since a member there reaches its readers as a copy in each consuming skill and never as an installed file, which is the same reason install and sync skip the folder. What it costs is that a standard moved into the fan-out leaves the validator with nothing reporting the move.
26
+ `standards` reads the authoring root at `standards/` where it exists and the installed copy at `.claude/standards/` otherwise. The authoring root wins because the installed tree is generated from it in the toolkit, where a fix written to the copy is discarded by the next regen. A project that consumed the corpus holds only the second, so one precedence serves both. The walk stays flat, matching install and the catalog.
27
27
 
28
28
  Nothing fires it automatically. The five record folders are gitignored, so the standards-audit hook exits early on them and any check reading changed files from git never lists one. The corpus is tracked and still unreached, since the markdown audit reads content across the files git lists and rules on no filename. The verb runs at the moment a session claims the record is finished, which is the same placement `aitk tasks validate` takes over the board.
29
29
 
@@ -5,7 +5,7 @@ description: Listing learning workspaces and the ordinal a new one takes, openin
5
5
 
6
6
  # Teach
7
7
 
8
- Learning workspaces sit under `.claude/teach/<nn>-<topic>/`, and `standards/teach.md` fixes their layout, naming, and file formats, apart from the glossary, whose shape `standards/bundled/glossary.md` fixes and fans out into the `claude-teach` skill, so it travels with the file wherever a promotion lands it. Every verb here resolves that folder against the main worktree root rather than against the working directory, so a session standing in a linked worktree reaches the one workspace the learner has rather than opening a second.
8
+ Learning workspaces sit under `.claude/teach/<nn>-<topic>/`, and `standards/teach.md` fixes their layout, naming, and file formats, apart from the glossary, whose shape `standards/glossary.md` fixes, cited from the `claude-teach` skill, so it travels with the file wherever a promotion lands it. Every verb here resolves that folder against the main worktree root rather than against the working directory, so a session standing in a linked worktree reaches the one workspace the learner has rather than opening a second.
9
9
 
10
10
  That root resolution is also why the writing verbs exist at all. The file-editing tools refuse a main-root path from a linked worktree and offer a worktree copy instead, and a caller naming only the destination reports a success that did not happen. A whole-file create still goes out as a shell heredoc. Changing a line inside a file that already exists has no shell route, because the stream editors are banned, so `resource` and `glossary` are the route for the two files a running workspace edits.
11
11
 
@@ -214,12 +214,13 @@ This section is the corpus the coverage claim is measured against: every name `a
214
214
 
215
215
  ### Check the work before it leaves the branch
216
216
 
217
- | Skill | When to use |
218
- | ----------------------------- | --------------------------------------------------------------------- |
219
- | `aitk:claude-review` | On the local branch diff, before anything is pushed |
220
- | `aitk:claude-standards-audit` | When changed markdown has to answer to the authoring standards |
221
- | `aitk:claude-ux-audit` | To read UI source for missing states, edge cases, and inconsistencies |
222
- | `aitk:claude-ux-measure` | To start the interface and measure paint, processor, and layout cost |
217
+ | Skill | When to use |
218
+ | ------------------------------ | --------------------------------------------------------------------------------------- |
219
+ | `aitk:claude-review` | On the local branch diff, before anything is pushed |
220
+ | `aitk:claude-standards-audit` | When changed markdown has to answer to the authoring standards |
221
+ | `aitk:claude-markdown-propose` | When a markdown claim needs rewriting and the change should wait for an answer per file |
222
+ | `aitk:claude-ux-audit` | To read UI source for missing states, edge cases, and inconsistencies |
223
+ | `aitk:claude-ux-measure` | To start the interface and measure paint, processor, and layout cost |
223
224
 
224
225
  ### Ship it
225
226
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "3.9.0",
4
+ "version": "3.11.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -20,6 +20,5 @@ matches=$(grep -rnE "$BANNED_PATH_PATTERN" "$SKILLS_DIR" || true)
20
20
  echo "Shipped skills reference a repo-local path that does not exist in a target project:"
21
21
  echo "$matches" | sed "s|^$PROJECT_ROOT/||"
22
22
  echo
23
- echo "Reach supporting prose through an aitk docs command, a bundled reference, or inlined text."
24
- echo "A match inside a references/ folder is a generated copy. Fix the source under standards/bundled/."
23
+ echo "Reach supporting prose through an aitk docs command, a standard cited at the flat root, or inlined text."
25
24
  exit 1
@@ -267,11 +267,6 @@ main() {
267
267
  run_check "assert_hero_stamp" "The hero set disagrees with the stamp written when the image was captured. Run aitk capture assets/hero.html and commit all three files together."
268
268
  log_info "Hero clean"
269
269
 
270
- log_step "Skill references"
271
- run_check "bash $PROJECT_ROOT/scripts/core/regen-skill-references.sh" "Skill-reference regen failed"
272
- assert_no_drift "claude/skills/*/references" "Skill references drifted. Run bun run check and commit the updated reference files."
273
- log_info "Skill references clean"
274
-
275
270
  log_step "Tooling paths"
276
271
  run_check "bash $PROJECT_ROOT/scripts/core/regen-tooling-paths.sh" "Tooling-path regen failed"
277
272
  assert_no_drift "claude/skills/toolkit-cli/SKILL.md" "The overwrite contract drifted from what the stacks hold. Run bun run check and commit claude/skills/toolkit-cli/SKILL.md."