@erclx/aitk 0.39.0 → 0.41.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.
package/README.md CHANGED
@@ -65,7 +65,7 @@ Scaffolding your first project? Start with target projects, then the AI workflow
65
65
  - [Operating model](docs/operating-model.md): orchestrator and worker roles for building across parallel sessions
66
66
  - [Visual design workflow](docs/visual-design-workflow.md): tiered guide for design and wireframe authoring
67
67
  - [Target projects](docs/target-projects.md): scaffold, add a domain later, sync upstream drift
68
- - [Agents](docs/agents.md): CLI flags, exit codes, and JSON output shapes
68
+ - [Agents](docs/agents/index.md): CLI flags, exit codes, and JSON output shapes
69
69
  - [Docs index](docs/index.md): every reference doc in this repo
70
70
 
71
71
  ## Development
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aitk",
3
3
  "description": "Automated governance, versioning, and discovery tools for Claude Code.",
4
- "version": "0.39.0",
4
+ "version": "0.41.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -36,7 +36,7 @@ Read these from the project root on both paths, skipping any that do not exist:
36
36
 
37
37
  Read a standard from `${CLAUDE_SKILL_DIR}/../../standards/` instead when the project does not have it.
38
38
 
39
- On the source path, also read the UI surfaces matched in Step 1 plus `docs/agents.md` and `docs/index.md` for output shape or framing rules already documented.
39
+ On the source path, also read the UI surfaces matched in Step 1 plus `docs/agents/output-shape.md` and `docs/index.md` for output shape or framing rules already documented.
40
40
 
41
41
  On the greenfield path, also read `.claude/ARCHITECTURE.md` for platform, tech stack, and surface type. Do not scan `src/`, stylesheets, or UI modules. Step 1 already established they hold nothing.
42
42
 
@@ -7,13 +7,14 @@ description: What feature planning is for, the gaps it closes, and why it stops
7
7
 
8
8
  ## Gap
9
9
 
10
- Without this skill, implementation starts before anyone knows what it touches. A session reads no project context and rediscovers a settled constraint halfway through, the file list emerges as the work goes rather than before it, and the ambiguities that needed a decision get resolved silently in whichever direction the first edit happened to go.
10
+ Without this skill, implementation starts before anyone knows what it touches. A session reads no project context and rediscovers a settled constraint halfway through, the file list emerges as the work goes rather than before it, and the ambiguities that needed a decision get resolved silently in whichever direction the first edit happened to go. A constraint naming a surface to leave alone forbids two different acts at once, so the executing session picks one and the branch either grows an excluded concern or ships a reference to a file the change deleted.
11
11
 
12
12
  ## Must
13
13
 
14
14
  - Read the project's own Claude setup before scanning source, so the plan inherits decisions already made instead of reopening them
15
15
  - Name every file the work touches with the reason it is touched
16
16
  - Surface each unresolved ambiguity as a numbered question carrying a suggested answer and an empty answer slot, so the plan is decision-ready in one pass
17
+ - State which act a constraint forbids when it names a surface to leave alone, since conforming that surface and retargeting a pointer into it are different acts and only one is out of scope
17
18
  - Scale the output to the work. A two-file change with nothing to decide should not produce a plan file.
18
19
  - Stop at the plan and wait to be told to continue
19
20
 
@@ -38,13 +38,21 @@ Measure against the tree rather than recall. Grep for each construct the plan wi
38
38
  Construct the plan with these sections:
39
39
 
40
40
  - **Summary:** three to five one-line bullets covering the goal, the main deliverables, and the key trade-off or decision. Aimed at humans scanning the plan, not agents executing it. Full mode only.
41
- - **Constraints:** durable rules the work must respect (patterns to reuse, surfaces not to touch, platform limits). Optional. Include when an orchestrator or prior context supplies them, omit the section otherwise.
41
+ - **Constraints:** durable rules the work must respect (patterns to reuse, surfaces not to touch, platform limits). Optional. Include when an orchestrator or prior context supplies them, omit the section otherwise. A constraint naming a surface to leave alone carries the distinction under Constraints below.
42
42
  - **Files to touch:** each file with a one-line reason
43
43
  - **Risks:** conflicts, coupling, or tricky spots. When the plan establishes a resource with more than one consumer, list the consumers and mark each read or write, because a policy stated over that resource has to hold for the writers and not just the consumer that prompted it. If none, use `None identified.`
44
44
  - **Questions:** numbered list of things to resolve before starting. Each carries a `- Suggested:` line and an `- Answer:` slot (see Suggestions below). If none, use `None identified.`
45
45
 
46
46
  Prefer `None identified.` over low-signal fillers. A small feature should produce a short plan, not a padded one. Small mode skips the summary since the plan is already short enough to scan in full.
47
47
 
48
+ ### Constraints
49
+
50
+ A constraint naming a surface to leave alone forbids two different acts. Name which one, since a constraint carrying only the surface leaves the executing session to guess.
51
+
52
+ - Forbid conforming the surface to whatever shape the change introduces. This is the act a scope constraint means, and it keeps the branch from growing a second concern.
53
+ - Never forbid retargeting a pointer the change breaks. A rename, a split, or a deletion that leaves a citation behind ships a dangling reference, so fixing it is required work rather than scope creep.
54
+ - Decide both acts for every surface the constraint names. Carving the distinction out for one file and leaving its siblings under the bare wording is how a plan ships one correct call beside one broken reference.
55
+
48
56
  ### Suggestions
49
57
 
50
58
  Attach a `- Suggested:` line to every question, then an empty `- Answer:` slot below it. A blank answer means accept the suggestion at execution time. This makes the plan decision-ready in one pass, with no separate decision-help round.
@@ -11,6 +11,10 @@ Without this skill, the session holding the cross-feature picture starts buildin
11
11
 
12
12
  The queue fails in both directions. It empties and a free worker waits, or it fills with whatever is oldest rather than with what establishes a mechanism. A plan handed over unverified is the quiet one, since it goes stale from whatever merged after it was written, and a worker that trusts its account of the tree builds against a shape that no longer exists. A second orchestrator makes all of this unrecoverable, because the board is gitignored and neither session can read the other's writes.
13
13
 
14
+ The session also writes surfaces it is told only how to read. Refilling the queue promotes and demotes rows in the priority file with no stated method, so a session invents one, and an inline rewrite exits clean when it matches nothing and leaves the board wrong with nothing reporting it. A row carrying prose where a plan pointer belongs costs a worker dispatch, because the ship chain refuses at its guard after the worktree is already open. A plan archived from a worker's own branch strands the pointer the board still carries, and the row reads as correct until someone follows it.
15
+
16
+ Output drifts everywhere the contract stops. The specified shape covers invocation alone, so a sweep report, a board report, and an analysis each end in a decision the human owns and each buries it under the evidence they would have skipped. A compaction is the same failure one step earlier, since the file that survives it has a stated reader and no stated writer, and the session improvises what to save and loses the reasoning the board never held.
17
+
14
18
  ## Must
15
19
 
16
20
  - Read the priority file for execution order, since the index sorts by filename and states no order
@@ -20,6 +24,11 @@ The queue fails in both directions. It empties and a free worker waits, or it fi
20
24
  - Place every finding a merged pull request produced against the surface that owns it
21
25
  - Date the roadmap line from that file's last commit, so an old sequence reads as old
22
26
  - Keep one planned, non-conflicting task in reserve beyond what is running
27
+ - Write the priority file with an editing tool that errors on a non-match, since the board is where a silent failure costs a dispatch
28
+ - Carry a plan pointer in the Plan column and a file set in the Touches column, so a row's readiness and disjointness claims stay checkable
29
+ - Re-resolve the board's plan pointers after any archive, since the archiving skill rewrites the task file and knows nothing about the board
30
+ - Lead a sweep report, a board report, and an analysis with the state, the open decisions, and the next action, keeping the evidence below them
31
+ - Write the pre-compact handoff with what no other file carries, and name the snippet that reads it back
23
32
 
24
33
  ## Must not
25
34
 
@@ -29,6 +38,9 @@ The queue fails in both directions. It empties and a free worker waits, or it fi
29
38
  - Hand a worker anything but a plan, because scope lives there
30
39
  - Run a second orchestrator against the same board
31
40
  - Promote a task to fill the queue when nothing qualifies. A thin queue is a real answer.
41
+ - Rewrite the board with a shell stream editor or an inline string replace, both of which exit clean when they match nothing
42
+ - Restate the board, a task file, or a groundwork folder in the pre-compact handoff, which is the padding that makes a handoff stop being read
43
+ - Specify a shape for a correction, since a format for admitting error invites ceremony where plainness is the whole value
32
44
 
33
45
  ## Guards
34
46
 
@@ -35,6 +35,10 @@ Then output the state of play so the human knows what to launch, review, and mer
35
35
 
36
36
  The roadmap is optional and this skill does not require it. It carries why a sequence is what it is, changes only when strategy changes, and is absent in a project whose scope has already shipped. Report what it says and name it as the source. Never assert an active version the file does not state, and say nothing about one when the file is missing.
37
37
 
38
+ A compaction is a moment this skill cannot detect, so both sides of it are snippets the human fires. Before one, `@.claude/snippets/claude/orchestrator-handoff.md` writes `.claude/tasks/session.md` with the state of play, the decisions taken under delegated authority, the mistakes worth not repeating, and the standing cautions. After one, `@.claude/snippets/claude/orchestrator-resume.md` reads that file back with the board and the groundwork behind the live work. Write nothing to the handoff that the board, a task file, or a groundwork folder already carries.
39
+
40
+ Name `${CLAUDE_SKILL_DIR}/../../snippets/claude/<name>.md` as the fallback for any orchestrator snippet the project copy lacks. Snippets install by named bundle rather than wholesale, so a project that installed one bundle has the `.claude/snippets/` directory and none of these files, and the plugin ships the whole snippets folder beside `skills/`.
41
+
38
42
  ## Output
39
43
 
40
44
  ```plaintext
@@ -68,10 +72,27 @@ Omit the `Roadmap` line when `.claude/ROADMAP.md` is absent. Quote the `Now` row
68
72
 
69
73
  That command returns nothing for a roadmap that exists but has never been committed, which is the state `claude-roadmap` leaves behind when it writes the file and declines to stage it. Write `uncommitted` as the date in that case. A blank there would read as a formatting slip rather than as the newest possible sequence.
70
74
 
75
+ ### Every later turn
76
+
77
+ The block above covers invocation alone. A sweep report, a board report, and an analysis each end in something the human decides, so each opens with the same three slots and puts its evidence underneath:
78
+
79
+ ```plaintext
80
+ State: <what changed since they last looked>
81
+
82
+ Decisions:
83
+ 1. <one line each, or "none open">
84
+
85
+ Next: <the single most useful action>
86
+ ```
87
+
88
+ Keep the detail below the block and keep it skippable. A decision reached at the bottom of three paragraphs has been buried, which is the failure this shape exists to prevent. Reuse the vocabulary above rather than inventing a second one, and keep a file set on the row claiming it so the reader can check a disjointness claim instead of taking it.
89
+
90
+ Write no shape for a correction. A correction is a sentence, and a format for admitting error invites ceremony where plainness is the whole value.
91
+
71
92
  ## The loop
72
93
 
73
94
  1. Own the roadmap while a scope exists to sequence. Capture a needed draft or resequence of `.claude/ROADMAP.md` in the plan or a task file, naming the MVP list in `.claude/REQUIREMENTS.md` as the source, so a worker runs `claude-roadmap` in its branch and the tracked edit ships in a PR rather than dirtying main. Stop owning it once that list has shipped, since later work then arrives as discrete items rather than as versions.
74
- 2. Plan the next feature. Run `claude-feature` here, with the cross-feature context, to write a plan to `.claude/plans/`. Planning stays in this warm session so the plan front-loads reasoning a cold worker would otherwise re-derive.
95
+ 2. Plan the next feature. Run `claude-feature` here, with the cross-feature context, to write a plan to `.claude/plans/`. Planning stays in this warm session so the plan front-loads reasoning a cold worker would otherwise re-derive. A constraint supplied from here that names a surface to leave alone states which of two acts it forbids, and the rule governing that is Step 3 of `claude-feature` under Constraints.
75
96
  3. Decide parallelism and merge order. Note which plans touch a shared wiring seam so their PRs merge in sequence, not at once.
76
97
  4. Verify the plan against the tree. Reading it is not enough, since a plan goes stale from whatever merged after it was written. Grep for each construct it names and count the sites against the count it claims. Check that every phase label it cites is still open. Open each file it describes rather than trusting its account of the contents. Correct the plan before handing it over.
77
98
  5. Hand off. The human opens a worker worktree with `claude-worktree` and runs `claude-autoship` against the plan. The orchestrator does not spawn workers.
@@ -89,7 +110,7 @@ That command returns nothing for a roadmap that exists but has never been commit
89
110
 
90
111
  ## Refilling the ready queue
91
112
 
92
- Keep enough planned, non-conflicting tasks available that a free worker never waits, and place the findings the last merge produced before promoting anything new. Run this after every merge and whenever the ready list thins.
113
+ Keep enough planned, non-conflicting tasks available that a free worker never waits, and place the findings the last merge produced before promoting anything new. Run this after every merge and whenever the ready list thins. `@.claude/snippets/claude/orchestrator-sweep.md` fires this procedure after a batch of merges and adds the plan re-verification that a merge invalidates.
93
114
 
94
115
  1. Run `gh pr list --state open` and `git log --oneline -8`. Report any pull request whose review has not been posted and stop for that one first.
95
116
  2. For each pull request merged since the last sweep, place every finding it produced. Route a finding that changes a rule to the standard or rule that states it, one that changes another task to that task's Findings, and one that overturns a groundwork lean to that folder marked answered. Never leave a finding in a pull request thread alone.
@@ -107,10 +128,22 @@ Serialized: <task> behind <task>, both write <file>
107
128
  Ready now: <tasks with plans, and what each waits on>
108
129
  ```
109
130
 
131
+ That block is the detail. Lead the reply with the three slots under Every later turn above, so the human reads what they own before the evidence for it.
132
+
110
133
  Treat a task that edits `.claude/context/` entries wholesale as conflicting with every other task, because the root instruction file requires each task to update its own domain entry as it lands.
111
134
 
112
135
  Do not promote a task to fill the queue when nothing qualifies. A thin queue is a real answer and it beats a plan nobody needed.
113
136
 
137
+ ### Writing the board
138
+
139
+ Promoting, demoting, and archiving a row all write `.claude/tasks/priority.md`, and this session is the only writer apart from `aitk tasks archive`.
140
+
141
+ - Edit the file with the file-editing tool. A shell stream editor and an inline string replace both exit clean on a non-match, so a promotion that matched nothing leaves the board wrong with nothing reporting it, and the file-editing tool errors instead.
142
+ - Put a pointer in the Plan column, never prose. `## Run now` claims a written plan covers every open outcome, and `claude-autoship` refuses at its guard when it follows the column and finds no plan, which spends a worker dispatch to learn what the row should have said.
143
+ - Name the file set in the Touches column. The disjointness call in step 6 is only checkable later when the sets are written down rather than reasoned once and discarded.
144
+ - Re-resolve every Plan pointer after anything archives a plan. `claude-docs` moves a plan to `.claude/.tmp/plans-archive/` and rewrites the citation in the task file alone, so a row for a task still on the board keeps pointing into `.claude/plans/` at a file that has moved. Workers running the ship chain on their own branches archive plans this board still cites, and the board reads as correct until a pointer is followed.
145
+ - Read the file back after writing it, since the row that lands is the row a worker acts on.
146
+
114
147
  ## Parallelism
115
148
 
116
149
  No fixed number caps worker tracks. Collision between file sets is what binds, so
@@ -145,4 +145,4 @@ Replace bracketed values with the values from this run. Drop the "Folders bootst
145
145
  ## Reference
146
146
 
147
147
  - `.claude/context/indexes.md`: system rationale, frontmatter contract, when to adopt
148
- - `docs/agents.md`: `aitk indexes regen` flags, exit codes, JSON shape
148
+ - `docs/agents/indexes.md`: `aitk indexes regen` flags, exit codes, JSON shape
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Capture
3
+ description: Rendering committed HTML sources to PNG, what the command asserts about fonts, and why it is toolkit-only
4
+ ---
5
+
6
+ # Capture
7
+
8
+ `aitk capture [source]` renders HTML capture sources to PNG, which is how a committed documentation image regenerates from its committed source. The source defaults to `assets/`, where a directory expands to every `.html` directly inside it, so adding a capture means dropping a file beside the first one and running the same bare command.
9
+
10
+ ```bash
11
+ aitk capture
12
+ aitk capture assets/install.html
13
+ aitk capture assets --out .claude/review/captures
14
+ ```
15
+
16
+ `assets/` now holds two sources, so a bare `aitk capture` rebuilds both. `install.html` is hand-authored and its text came from a real run. `hero.html` is generated by `scripts/core/regen-hero.sh` from the CLI catalogs and must not be edited by hand, since `bun run check` regenerates it and fails on the difference. Only the HTML is asserted for drift. The PNG is a chromium render whose bytes move with the browser version, so rebuild it with `aitk capture assets/hero.html` when the check reports the HTML changed.
17
+
18
+ | Option | Behavior |
19
+ | ------------------ | ------------------------------------------------- |
20
+ | `--out <dir>` | Write every PNG here instead of beside its source |
21
+ | `--selector <sel>` | Element to capture (default: `.window`) |
22
+
23
+ ## What the command asserts
24
+
25
+ Each source renders at `deviceScaleFactor` 2 with a transparent background, and the success line reports the pixel dimensions the element wrapped to. Size is reported and never asserted. The height of a terminal frame is whatever its text wrapped to at a fixed width, so pinning that number would harden an accident.
26
+
27
+ What is asserted is the font. The command reads the first family the captured element declares and fails when the browser did not resolve it, because a fallback face rewraps the block and silently changes the output. Sources therefore name a real font rather than relying on `monospace`. A source that cannot render reports its own line and exits 1 without dropping the rest of the batch.
28
+
29
+ The browser binary installs separately from the package. A fresh clone runs `bunx playwright install chromium` once, and a run that cannot launch one reports the engine's own remediation inside the frame and exits 1 rather than escaping as a stack trace.
30
+
31
+ The command is toolkit-only. Its render module holds every browser reference in the toolkit and `files` in `package.json` excludes it, so an installed `aitk` carries the command, reports it as absent on one line, and exits 1. Every other command is unaffected, which is the reason the browser import sits behind a dynamic import rather than at a command's top level.
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: Command catalog
3
+ description: Every project-level command and every domain subcommand, plus the shape each domain exposes
4
+ ---
5
+
6
+ # Command catalog
7
+
8
+ Full help: `aitk <command> --help`. Behavior notes for the install and sync verbs live in `install-and-sync.md`.
9
+
10
+ ## Project-level
11
+
12
+ | Command | Purpose |
13
+ | ------------------------ | ---------------------------------------------------------------------------------------------- |
14
+ | `aitk init [path]` | Bootstrap a project with selected toolkit domains |
15
+ | `aitk sync [path]` | Sync all installed domains in a target project |
16
+ | `aitk sync --check` | Report toolkit drift without writing (`--json`, `--exit-code`) |
17
+ | `aitk sandbox [cat:cmd]` | Run sandbox scenarios (interactive or routed), toolkit-only like the tree it reads |
18
+ | `aitk sandbox reset` | Reset sandbox to baseline |
19
+ | `aitk sandbox clean` | Wipe the sandbox |
20
+ | `aitk sandbox check` | Score a provisioned sandbox against a scenario expectation (`--json` for the verdict) |
21
+ | `aitk sandbox coverage` | Report which scenarios declare expectations (`--json`, `--strict`, `--skills`) |
22
+ | `aitk indexes regen` | Regenerate `index.md` files from sibling frontmatter |
23
+ | `aitk docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name) |
24
+ | `aitk design render` | Render `.claude/DESIGN.md` tokens to HTML and CSS |
25
+ | `aitk slides render` | Render a `.claude/SLIDES.md` source into a PowerPoint deck |
26
+ | `aitk slides list` | List the available slide layouts (`--json` for the catalog) |
27
+ | `aitk feedback` | Write toolkit feedback from stdin to `.claude/review/`, or open a GitHub issue with `--github` |
28
+ | `aitk transcripts <url>` | Fetch a YouTube transcript with metadata frontmatter (needs `yt-dlp`) |
29
+ | `aitk tasks archive` | Move a shipped task off the board, clear its ordering row, and regenerate the index |
30
+ | `aitk comments scan` | Measure comment density by language and comment kind, with a trend recomputed from git |
31
+ | `aitk context audit` | Report required sections, length, depth, bullet weight, cited paths, provenance, and drift |
32
+ | `aitk capture [source]` | Render HTML capture sources to PNG, toolkit-only and absent from an installed package |
33
+
34
+ ## Domain commands
35
+
36
+ Each domain exposes a consistent shape where applicable: `list`, `install`, `sync`, `create`.
37
+
38
+ | Domain | Subcommands |
39
+ | ----------- | ---------------------------------------------------------------------- |
40
+ | `tooling` | `list`, `sync`, `ref`, `create`, `verify`, `inject`, `prune-gitignore` |
41
+ | `snippets` | `list`, `install`, `sync`, `create` |
42
+ | `standards` | `list`, `install`, `sync` |
43
+ | `gov` | `list`, `install`, `sync`, `build` |
44
+ | `claude` | `init`, `sync`, `seeds list`, `skills list`, `setup [dest]` |
45
+ | `wiki` | `init` |
46
+ | `design` | `render` |
47
+ | `slides` | `render`, `list` |
48
+ | `tasks` | `archive` |
49
+ | `comments` | `scan` |
50
+ | `context` | `audit` |
51
+
52
+ Common patterns:
53
+
54
+ - `list --json` → machine-readable catalog on stdout.
55
+ - `install <name> <path>` → install a specific entry into a target project.
56
+ - `sync <path>` → reapply all installed entries in a target project.
57
+ - `create [name]` → scaffold a new authoring entry in this repo.
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Comments
3
+ description: Comment density by language and kind, the two structural exclusions, and how the degradation sweep finds its vocabulary
4
+ ---
5
+
6
+ # Comments
7
+
8
+ `aitk comments scan [path]` reports comment density for a tree, split by language and by comment kind. It is the only command that parses the target's own source, so its scope stays deliberately narrow: TypeScript and bash, line-oriented, no AST.
9
+
10
+ ```bash
11
+ aitk comments scan
12
+ aitk comments scan src --json
13
+ aitk comments scan --since v0.5.0
14
+ ```
15
+
16
+ | Option | Behavior |
17
+ | -------------------- | --------------------------------------------------------------- |
18
+ | `--json` | Add a machine-readable record on stdout, keeping the frame |
19
+ | `--since <rev>` | Report the trend from this revision instead of a snapshot alone |
20
+ | `--languages <list>` | Comma-separated subset of `ts,sh` (default: both) |
21
+
22
+ A line counts as a comment when its first non-whitespace token opens one, which is what keeps a URL in a string literal from reading as a `//` comment without a parser. Density is `commentLines / lines`, reported and never graded. The command produces the number and a rule produces the judgment.
23
+
24
+ Two exclusions are structural rather than tuning. Heredoc bodies are dropped from both the numerator and the denominator, because a scenario script carrying markdown inside one has `#` opening a heading rather than a comment, which inflated a measured 112 comment lines to 427. Fixture trees are pruned by path segment for the same reason. The line-1 shebang is not a comment, since every script has one and counting it puts a floor under density that reports the file count.
25
+
26
+ `--since` recomputes each point from git via `ls-tree` and `cat-file --batch`, checking nothing out. No ledger is written or read. Six points spread evenly across the window by default, and the boundary revision is always included so the series keeps the reading it is measured against. This works only because density is a pure function of a tree. Which author or session wrote a comment is not recoverable from git and does not belong here.
27
+
28
+ ## Degradation sweep
29
+
30
+ The degradation sweep reads its vocabulary from whichever rule publishes a `## Degradation vocabulary` heading, preferring `.claude/rules/` over `governance/rules/`, so one definition serves the toolkit and every target. Discovery anchors on the heading rather than a filename, because a renumbered rule would otherwise empty the vocabulary while the sweep still reported clean. With no such rule the sweep reports **skipped** rather than zero hits, since finding nothing and looking for nothing mean opposite things.
31
+
32
+ `090-code-comments` is the rule that publishes the list, and it ships on the `base` stack. A project that installs or syncs governance for the first time after that rule landed gets a sweep that previously reported skipped, so hits appear where the command used to stay quiet. Edit the backticked terms in the installed copy to change what that project sweeps for. The sweep matches comment text, so a comment naming a term as an example is a hit, and a hit is a prompt to read the line rather than a verdict on it.
@@ -0,0 +1,42 @@
1
+ ---
2
+ title: Context audit checks
3
+ description: What each non-gating check reports, the unit each checkpoint is measured in, and which folders each check reaches
4
+ ---
5
+
6
+ # Context audit checks
7
+
8
+ What each finding from `aitk context audit` means. The command surface, its flags, and the one gating check are in `context-audit.md`.
9
+
10
+ ## Required sections
11
+
12
+ The required-section check reports what does not declare `## Overview` and `## Layout`, the two sections `.claude/standards/context.md` marks required. The list is held in code beside the numeric checkpoints rather than parsed out of the standard, so it fails on a defect rather than on a rewrite of the wording around it. A heading at any level counts, because a domain that split into a folder carries its overview in a sibling named `overview.md` where the section is the `#` title and an `##` beneath it would repeat the filename. Matching exactly is what keeps `## Layout catalog` from satisfying `Layout`.
13
+
14
+ Which unit answers depends on the folder. Entries of the folder named under `.claude/` are one domain each, so each answers for itself and a finding names the entry. Entries of a folder a domain split into describe that one domain between them, so any sibling answers and a finding names the folder. Holding a split folder to the rule per file would report every child beside its `overview.md`, and rolling the named folder up would let one conforming entry stand in for every other domain sitting next to it.
15
+
16
+ It reports rather than gates, the closer call because a missing section reads more like a fact than the other judgments. What settles it is that the standard sanctions omitting `## Layout` from a domain owning no paths in the repo, and no measure separates that from an entry that forgot it. A domain covering only external tools is that case, and it reports on every run. The JSON record carries the findings as `missingSections` and the list as `checkpoints.requiredSections`.
17
+
18
+ ## Length and depth
19
+
20
+ Length and depth quote their checkpoints from `.claude/standards/context.md`: roughly 150 rendered lines for an entry, roughly 40 for a run no heading breaks. Depth measures the longest such run rather than everything under one `##`, skips fenced blocks so a markdown example does not read as three headings, and exempts a run whose lines are all list items at one indent averaging under 130 characters. The weight condition is what separates a scannable catalog of one-liners from a stack of paragraph-bullets, which reach the same count and read nothing alike.
21
+
22
+ Depth exempts a second shape, and the two are excused for opposite reasons. A peer list is already navigable, so a subheading dropped into it splits a set that belongs together. A table is exempt because the remedy does not exist: a heading placed inside one splits the table rather than the run, so a catalog renders as an unbroken stretch by construction and no edit short of rewriting it as a list clears the report. The test is whether the run is a table rather than whether it holds one, so a table with prose either side still reports and a heading breaks it at the seam. A run of piped lines carrying no delimiter row is not a table and reports like any other prose. The table finding above is unaffected, so a catalog silenced here still reports as a candidate for a bullet list, which is the measure whose remedy does exist.
23
+
24
+ Both checks count rendered lines rather than source lines, wrapping each line at 80 columns and summing the heights. Entries here are authored one line per bullet, so a block of fifteen paragraph-bullets occupies fifteen source lines and renders past sixty, which source counting cannot see. Measuring one checkpoint in each unit would put an entry length beside a run length that mean different things. Their exclusions still differ: the file measure counts fenced blocks and frontmatter, while the run measure skips a fence so an example cannot break the run around it. A reference-heavy entry therefore ranks by its examples, which the length legend states on every run. Runs count blank lines, which the standard leaves open, so a hand reader who drops them lands a line or two lower. Both sections state the width on every run, since a number in rendered lines cannot be reproduced without it.
25
+
26
+ ## Bullet weight and tables
27
+
28
+ The bullet check reports a top-level bullet past roughly 400 characters, which is where a bullet stops carrying a decision alone and starts carrying the incident that motivated it beside the decision. Continuation lines fold into the bullet they belong to, so a heavy bullet cannot fall under the checkpoint by wrapping across two source lines, while a nested item is left out because the parent's own text is what the checkpoint asks about. Findings group by entry and narrow to `.claude/context/` for the reasons the provenance ones do both. Unlike the peer-list threshold above it, this corpus has no gap behind the number: bullet weight decays smoothly from a median near 170, so the number is a judgment where that one was a measurement, and a bullet reading well past it means the number is wrong rather than the rule.
29
+
30
+ The table check reports a catalog that grows a row per shipped thing, not a table count. A fixed comparison table never reflows, so its size costs nothing. A table qualifies at six or more body rows whose first column mostly carries a path, command, or link, which is what separates a catalog from a comparison without reading the prose.
31
+
32
+ ## Provenance
33
+
34
+ The provenance check reports the markers narrating how a domain reached its shape rather than describing what it is: a date, a change number, or a release label. The standard admits a rejected alternative and the reasoning that killed it while refusing the provenance attached to it, so a marker names a line to read rather than a line to delete. Findings group by entry and sort left to right within a line, since what a reader acts on is which file to open. Fenced blocks are excluded, which keeps a pinned version in an install command from reading as a claim the entry makes. Frontmatter is excluded with them, since the content checks read the body alone, and that is what keeps a diagram entry's dated `verified` stamp a record of its last check rather than a marker to settle. Length is the exception, counting the whole file, so a reader applying the 150-rendered-line checkpoint against the body alone lands a few lines under what the tool reports.
35
+
36
+ ## Which folders each check reaches
37
+
38
+ The provenance, bullet-weight, and required-section checks cover `.claude/context/` alone, while length, depth, and the table finding reach every audited folder. The rule is stated in `.claude/standards/context.md`, which opens its scope by handing diagrams and wireframes to `diagrams.md` and `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder, and what decides it is whether the remedy is actionable rather than what the check measures. Subdividing a run and splitting a file mean something in any entry, so length and depth generalize. Moving an incident out of a bullet and keeping the decision means nothing in a folder whose entries declare no decisions, which is why bullet weight narrows despite measuring a distance like the two that do not. Required sections narrow for a plainer reason: the names are the context standard's own, and neither sibling standard states a required section at all. The scoping key is the folder an entry was audited under, so `--folder` still reaches a folder the default list does not carry, and a domain split into `context/<sub-area>/` is governed as `context`. Every run states the reach, including a run where no audited folder is the governed one. The JSON record carries it as `checkpoints.provenanceFolder` and a per-folder `governsContent`.
39
+
40
+ ## Index drift
41
+
42
+ Index drift compares an index against its siblings in both directions. An entry the index does not link is invisible to a session choosing what to open, and a linked name resolving to nothing sends one to a path that opens nothing.
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: Context audit
3
+ description: Running the audit, its flags and folder scope, the exit codes, and the citation gate that is the only failing one
4
+ ---
5
+
6
+ # Context audit
7
+
8
+ `aitk context audit [path]` reports the structural state of the folders following the index-plus-entry contract, meaning a generated `index.md` beside entries carrying frontmatter. It reads and reports. Fixing what it finds is separate work. What each finding means is in `context-audit-checks.md`.
9
+
10
+ ```bash
11
+ aitk context audit
12
+ aitk context audit --json
13
+ aitk context audit --citations-only
14
+ aitk context audit --folder context,diagrams
15
+ aitk context audit --folder docs
16
+ ```
17
+
18
+ | Option | Behavior |
19
+ | ------------------ | -------------------------------------------------------------------- |
20
+ | `--json` | Add a machine-readable record on stdout, keeping the frame |
21
+ | `--folder <list>` | Comma-separated folder names (default: the three below) |
22
+ | `--citations-only` | Run the gating citation check alone, printing nothing when it passes |
23
+
24
+ ## Folder scope
25
+
26
+ Scope defaults to `context`, `diagrams`, and `wireframes`, and a folder the project does not carry is skipped rather than reported. A domain that outgrew one file and split into `<domain>/` is audited as its own folder, so a split entry measures at the same grain as a flat one.
27
+
28
+ A name passed to `--folder` resolves under `.claude/` first and at the project root second, which is what puts `docs/` and any later corpus in reach of the same engine. The root base is reached only by a name the caller passes, so the default list still resolves under `.claude/` alone and a project holding a root `wireframes/` is not audited against a standard it never adopted. The scope line prints the resolved path, so a project carrying both spellings reads which one was taken. The JSON record carries the base per folder as `folders[].base`.
29
+
30
+ A run where no requested name resolves refuses, whichever list it read. Naming the absent ones narrows to `--folder`, since a project carrying one of the three default folders is the ordinary case and a name it never asked for is not a typo. The JSON record carries those names as `unresolvedFolders`.
31
+
32
+ ## Exit codes
33
+
34
+ Exit codes are `0` for a clean run, `1` for a refusal, and `2` for an unresolved citation. Only the citation check sets a failing code. Required-section, length, depth, bullet weight, table, provenance, and index findings print and return `0`, because each is a judgment and failing a push on one would make the check something to route around.
35
+
36
+ ## The citation gate
37
+
38
+ The citation check resolves every path into an audited folder that appears anywhere in the repository, and it is the half wired into `bun run check`. A stale reference has a silent failure mode: the session opens nothing and carries on.
39
+
40
+ Three exclusions keep it from firing on prose about paths. Fenced blocks are skipped in markdown, which covers a standard displaying a path as an example. Fixture and harness trees are skipped by location, covering sandbox scenarios that describe their own scratch tree, the eval harness naming its target project, and `*.test.ts`. A path into a folder the project does not carry is skipped, so a skill directing a reader to `.claude/wireframes/index.md` stays valid in a project that has wireframes and silent in one that does not.
41
+
42
+ What remains is a sentence naming a hypothetical entry to show the shape of a name, which no syntax separates from a real reference. Append `<!-- audit-ignore-citations -->` to that source line. The marker suppresses citation checking for its own line only.
43
+
44
+ The pattern spells the `.claude/` prefix, so a folder resolved at the project root is measured by every other check and contributes nothing here. Widening it to a bare `docs/x.md` would match prose that references nothing, which is a separate decision from where entries come from. A run whose folders all resolved at the root says the check is out of scope rather than reporting that zero paths resolved, and the same run under `--citations-only` refuses, because a gate exiting clean on a scope it could not build is the failure the gate exists to catch.
@@ -0,0 +1,17 @@
1
+ ---
2
+ title: Docs
3
+ description: How aitk docs resolves the toolkit's own reference surface from an install root, and how a split domain is named
4
+ ---
5
+
6
+ # Docs
7
+
8
+ `aitk docs` emits the toolkit's own reference docs so an agent in a target project can orient without the toolkit source checked out. The CLI resolves `docs/` and `.claude/context/` from its install root, and which of the two it finds depends on how the CLI was installed. A registry install carries `docs/` alone, since `.claude/` is not published. A clone or a linked worktree carries both.
9
+
10
+ - `aitk docs list [--json]` lists the downstream catalog: the consumer-facing `docs/` surface plus per-domain narrative from `.claude/context/` when that root is present. Toolkit-internal context entries (`ci`, `development`, `extensions`, `sandbox`) are dropped. From a registry install the context section is absent rather than empty.
11
+ - `aitk docs <topic>` prints one doc to stdout, resolved by exact name from `docs/` first, then `.claude/context/`. Any doc the install carries is reachable by name, including the toolkit-internal topics the list omits.
12
+
13
+ A domain too large for one file splits into `<domain>/` with a generated `index.md`, and both verbs name it by the folder. `aitk docs <domain>` prints that index, which is the catalog routing to the sub-area files, and the listing describes it from the index's `subtitle` where a sibling file supplies `description`. A sibling file wins over a folder of the same name. A folder carrying no `index.md` is absent from both, since a catalog is what makes the sub-areas reachable.
14
+
15
+ Data prints to stdout and the frame to stderr, so `aitk docs <topic> > out.md` captures clean markdown. With no topic and no verb, `aitk docs` runs `list`. An unknown topic names the available topics on stderr and exits 1.
16
+
17
+ Only a `---` block opening on the first line counts as frontmatter, so a document body carrying horizontal rules emits whole.
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: Agents
3
+ subtitle: CLI catalog and invocation rules for agents, split by command domain. Start with overview.
4
+ category: Agent surface
5
+ ---
6
+
7
+ # Agents
8
+
9
+ CLI catalog and invocation rules for agents, split by command domain. Start with overview.
10
+
11
+ - [Capture](capture.md): Rendering committed HTML sources to PNG, what the command asserts about fonts, and why it is toolkit-only
12
+ - [Command catalog](commands.md): Every project-level command and every domain subcommand, plus the shape each domain exposes
13
+ - [Comments](comments.md): Comment density by language and kind, the two structural exclusions, and how the degradation sweep finds its vocabulary
14
+ - [Context audit checks](context-audit-checks.md): What each non-gating check reports, the unit each checkpoint is measured in, and which folders each check reaches
15
+ - [Context audit](context-audit.md): Running the audit, its flags and folder scope, the exit codes, and the citation gate that is the only failing one
16
+ - [Docs](docs.md): How aitk docs resolves the toolkit's own reference surface from an install root, and how a split domain is named
17
+ - [Indexes](indexes.md): Flags, exit codes, and JSON shape for aitk indexes regen, plus when it auto-stages what it rewrote
18
+ - [Install and sync](install-and-sync.md): What each install and sync verb writes, refuses, or leaves alone, and how drift is attributed in a target project
19
+ - [Output shape](output-shape.md): The two framed shapes every command renders into, and how JSON and --names modes keep stdout clean
20
+ - [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
21
+ - [Sandbox](sandbox.md): Scenario routing, the expectation scoring surface, and the coverage census over scenarios and skills
22
+ - [Scripting](scripting.md): The runtime catalogs that replace hardcoded names, what each carries, and a headless invocation per domain
23
+ - [Tasks](tasks.md): Selecting a shipped task by stem or pull request, the refusal reasons, and why the board root defaults to the main worktree
@@ -0,0 +1,29 @@
1
+ ---
2
+ title: Indexes
3
+ description: Flags, exit codes, and JSON shape for aitk indexes regen, plus when it auto-stages what it rewrote
4
+ ---
5
+
6
+ # Indexes
7
+
8
+ `aitk indexes regen` rewrites `index.md` files from sibling frontmatter. With no positional paths, it walks the current directory. With paths, each resolves by walking up to the nearest indexed ancestor, bounded by `--root`. Duplicates dedupe. The whole-repo walk prunes `.git`, `node_modules`, and anything `.gitignore` covers via `git check-ignore`.
9
+
10
+ A positional path is not filtered that way, because the walk-up resolves on the filesystem and never consults git. That is the only way to regenerate an index inside a gitignored folder, and it is how `.claude/tasks/` stays current.
11
+
12
+ | Option | Behavior |
13
+ | --------------- | ---------------------------------------------------------------- |
14
+ | `--dry-run` | Report which indexes would change without writing |
15
+ | `--json` | Emit a machine-readable record per index on stdout |
16
+ | `--root <path>` | Walk-up boundary when positional paths are passed (default: CWD) |
17
+ | `--no-stage` | Skip the auto `git add` on modified indexes |
18
+
19
+ Exit codes: `0` clean, `1` frontmatter error or missing index, `2` drift found in `--dry-run`.
20
+
21
+ When positional paths are passed inside a git repo, modified `index.md` files are staged so lint-staged and Claude `PostToolUse` hooks commit the regenerated catalog. Whole-repo walks never auto-stage, and neither does a path git ignores, since staging one always fails and the warning would fire on every edit.
22
+
23
+ Skills can parse drift without branching on exit code:
24
+
25
+ ```bash
26
+ aitk indexes regen --dry-run --json | jq '.results[] | select(.action == "would-write")'
27
+ ```
28
+
29
+ For the system rationale, frontmatter contract, when to adopt, and bootstrap path, see `.claude/context/indexes.md`.
@@ -0,0 +1,109 @@
1
+ ---
2
+ title: Install and sync
3
+ description: What each install and sync verb writes, refuses, or leaves alone, and how drift is attributed in a target project
4
+ ---
5
+
6
+ # Install and sync
7
+
8
+ The behavior notes behind the verbs listed in `commands.md`. Each one records what the verb writes, what it refuses, and what it deliberately leaves alone.
9
+
10
+ ## Domain sync
11
+
12
+ `aitk gov sync` updates only rules already present under `.claude/rules/` and
13
+ never adds new ones. A rule the toolkit does not ship is left alone, which is
14
+ how project-authored rules survive. It also removes a stale `.claude/GOV.md`
15
+ from the retired build. Use `aitk gov install` to add rules.
16
+
17
+ `aitk standards sync` matches by filename against `.claude/standards/` and
18
+ regenerates that folder's `index.md` on every completed run. It is the one sync
19
+ that refuses under `AITK_NON_INTERACTIVE=1` when drift exists, logging a warning
20
+ and exiting 0 without writing, because standards are seeds a project edits. Run
21
+ it interactively, or use the `claude-seed-sync` skill for a per-section audit
22
+ that preserves customizations.
23
+
24
+ `aitk snippets sync` behaves the same way against `.claude/snippets/`. It
25
+ matches by path relative to that directory, so a snippet the toolkit no longer
26
+ ships, or one authored directly in the target, is reported and skipped rather
27
+ than deleted. It is not preset-aware, so a project that installed `essentials`
28
+ does not grow new snippets on a sync. Use `aitk snippets install` to add them.
29
+
30
+ ## Install guards
31
+
32
+ `aitk gov install` and `aitk snippets install` require their first argument
33
+ under `AITK_NON_INTERACTIVE=1`. Both used to fall back to an interactive picker
34
+ that resolved to its first option headlessly, so `aitk gov install` with no
35
+ stack installed whichever stack sorted first and `aitk snippets install` with no
36
+ category installed every category. Each now reports the valid names on stderr
37
+ and exits 1. Every documented agent path already passes the argument, including
38
+ `aitk init`. The confirm-then-apply prompt after it still resolves to `Yes`
39
+ headlessly, so a call that names its stack or category is unchanged.
40
+
41
+ `aitk gov install` also refuses the toolkit root as a target, matching
42
+ `aitk snippets install`. Both resolve the target before anything else, so a path
43
+ that does not exist fails rather than being scaffolded.
44
+
45
+ ## Governance regen
46
+
47
+ `aitk gov regen` is the one governance verb that runs against the toolkit root,
48
+ because the `.claude/rules/` it writes there is produced output rather than an
49
+ operator's working copy. It reads the stack recorded in `internal/governance.toml`,
50
+ installs it alongside anything under `internal/rules/`, and clears the
51
+ destination first so a rule the record stopped naming disappears. It takes
52
+ `--root <path>` and defaults to the toolkit root, prints nothing on success, and
53
+ reports the reason on stderr with exit 1 when the record names a stack or rule
54
+ that does not resolve. `scripts/core/regen-claude-copies.sh` calls it, and the
55
+ Consumed copies stage of `bun run check` asserts the result is committed.
56
+
57
+ ## Whole-project sync
58
+
59
+ `aitk sync` runs every installed domain sync, then offers to commit the result
60
+ and open a pull request. Under `AITK_NON_INTERACTIVE=1` it applies the domain
61
+ syncs and then refuses the git workflow, reporting the branch and commit it
62
+ would have created and exiting 0. Nothing is staged, committed, or pushed
63
+ headlessly. Run it interactively to reach the commit and pull request options.
64
+ It also refuses a target whose working tree is dirty, so commit or stash first.
65
+
66
+ ## Drift reporting
67
+
68
+ `aitk sync --check` reports drift and writes nothing, so it needs no clean tree
69
+ and is safe to run at any time. Each file is classified as `stale` when it still
70
+ matches what the toolkit installed, `customized` when the project edited it,
71
+ `stranded` when it sits at a path the toolkit no longer installs to, `orphaned`
72
+ when the project authored it, or `drifted` when no stamp covers it. Use `--json`
73
+ for the machine-readable report and `--exit-code` to fail a CI job. Orphaned
74
+ files are excluded from that exit code, since a project-authored rule never
75
+ converges. Attribution reads `.claude/aitk.json`, which every install and sync
76
+ writes.
77
+
78
+ A target installed before stamping shipped has no such file, and the report
79
+ falls back to the toolkit's own git history. Installed content matching any
80
+ version that history ever published proves the file is untouched, so it reports
81
+ `stale` naming the commit it came from, and content matching no published
82
+ version stays `drifted`. A toolkit reached outside a git clone, which is what a
83
+ registry install is, cannot run that fallback and reports
84
+ `historyUnavailable` alongside the unattributed files.
85
+
86
+ Each domain carries its own toolkit anchor in that file, so syncing one domain
87
+ never advances the revision another measures from, and each reports the upstream
88
+ commits touching its own source path. The `covers` field names the domains a
89
+ target has actually stamped, so a domain that was never stamped is legible
90
+ rather than reading as a clean one.
91
+
92
+ ## Bootstrap
93
+
94
+ `aitk init` installs up to six core domains and reports each one independently. A
95
+ domain that fails does not abort the run, so the command finishes the rest and
96
+ exits 1 naming the failures. Passing any flag skips the confirmation prompt,
97
+ which is what makes it scriptable. `--stack` defaults to `base`, and the default
98
+ does not read as a passed flag, so a bare `aitk init` installs governance and
99
+ still prompts. `--skip` takes `wiki`, `standards`, and `governance`, and warns
100
+ without aborting on any other value.
101
+
102
+ ## Unguarded tooling primitives
103
+
104
+ `aitk tooling inject` and `aitk tooling prune-gitignore` are the unguarded
105
+ primitives beneath `sync`. They apply one stack with no scan and no prompt, and
106
+ they deliberately skip the check that rejects `claude`, which is how `aitk
107
+ claude` drives its own stack through them. Use `sync` unless you are scripting
108
+ provisioning. Both frame their own output, so pass `--nested` when calling from
109
+ inside an already-open frame.