@erclx/aitk 3.43.2 → 3.45.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 (60) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/{toolkit-cli → aitk-cli}/REQUIREMENT.md +4 -4
  3. package/claude/skills/{toolkit-cli → aitk-cli}/SKILL.md +1 -1
  4. package/claude/skills/{toolkit-feedback → aitk-feedback-file}/REQUIREMENT.md +3 -3
  5. package/claude/skills/{toolkit-feedback → aitk-feedback-file}/SKILL.md +2 -2
  6. package/claude/skills/{toolkit-triage → aitk-feedback-triage}/REQUIREMENT.md +3 -3
  7. package/claude/skills/{toolkit-triage → aitk-feedback-triage}/SKILL.md +3 -3
  8. package/claude/skills/{toolkit-operator → aitk-operator}/REQUIREMENT.md +3 -3
  9. package/claude/skills/{toolkit-operator → aitk-operator}/SKILL.md +3 -3
  10. package/claude/skills/aitk-rollout/REQUIREMENT.md +59 -0
  11. package/claude/skills/aitk-rollout/SKILL.md +147 -0
  12. package/claude/skills/{claude-screencast → aitk-screencast}/REQUIREMENT.md +3 -3
  13. package/claude/skills/{claude-screencast → aitk-screencast}/SKILL.md +2 -2
  14. package/claude/skills/{claude-slides-draft → aitk-slides-draft}/REQUIREMENT.md +3 -3
  15. package/claude/skills/{claude-slides-draft → aitk-slides-draft}/SKILL.md +1 -1
  16. package/claude/skills/{cli-script → bash-cli-script}/REQUIREMENT.md +2 -2
  17. package/claude/skills/{cli-script → bash-cli-script}/SKILL.md +2 -2
  18. package/claude/skills/bash-script/REQUIREMENT.md +2 -2
  19. package/claude/skills/bash-script/SKILL.md +2 -2
  20. package/claude/skills/ci-workflow/REQUIREMENT.md +1 -1
  21. package/claude/skills/claude-memory-review/SKILL.md +2 -2
  22. package/claude/skills/claude-memory-review/references/receipt-format.md +1 -1
  23. package/claude/skills/claude-seed-sync/REQUIREMENT.md +1 -1
  24. package/claude/skills/claude-seed-sync/SKILL.md +1 -1
  25. package/claude/skills/git-issue/REQUIREMENT.md +2 -2
  26. package/claude/skills/git-issue/SKILL.md +1 -1
  27. package/claude/skills/{restate → restate-plainly}/REQUIREMENT.md +2 -2
  28. package/claude/skills/{restate → restate-plainly}/SKILL.md +2 -2
  29. package/claude/skills/setup-init/REQUIREMENT.md +1 -1
  30. package/claude/skills/setup-init/SKILL.md +1 -1
  31. package/claude/skills/write-human/REQUIREMENT.md +1 -1
  32. package/claude/skills/write-human/SKILL.md +1 -1
  33. package/docs/agents/demo.md +1 -1
  34. package/docs/agents/index.md +1 -0
  35. package/docs/agents/overview.md +2 -2
  36. package/docs/agents/scripting.md +1 -1
  37. package/docs/agents/sessions.md +11 -5
  38. package/docs/agents/targets.md +83 -0
  39. package/docs/ai-workflow.md +17 -16
  40. package/docs/target-projects.md +1 -1
  41. package/governance/rules/lang/120-bash.md +1 -1
  42. package/package.json +1 -1
  43. package/scripts/core/regen-tooling-paths.sh +1 -1
  44. package/scripts/core/verify.sh +1 -1
  45. package/src/claude/cases/authoring.ts +2 -2
  46. package/src/claude/cases/claude-workflow.ts +2 -2
  47. package/src/claude/cases/setup.ts +14 -6
  48. package/src/cli.ts +3 -0
  49. package/src/commands/demo.ts +1 -1
  50. package/src/commands/sessions.ts +24 -8
  51. package/src/commands/targets.ts +319 -0
  52. package/src/demo/beats.ts +1 -1
  53. package/src/sessions/claim.ts +7 -0
  54. package/src/sync/stamp.ts +9 -0
  55. package/src/targets/pulls.ts +250 -0
  56. package/src/targets/registry.ts +161 -0
  57. package/src/targets/resolve.ts +145 -0
  58. package/src/targets/sweep.ts +246 -0
  59. package/standards/issue.md +1 -1
  60. /package/claude/skills/{cli-script → bash-cli-script}/references/template.md +0 -0
@@ -16,7 +16,7 @@ Orchestrates the onboarding chain. Detects project type, resolves per-domain arg
16
16
 
17
17
  Three states reach this skill that the chain does not serve. Name the destination for each, so the refusal routes rather than ends. The first two stop the chain outright and the third runs it on a default the person may not want.
18
18
 
19
- - **An existing project.** Stop and hand off to `toolkit-operator`. It reads what the target already carries before it names a command, which this chain never does, so any per-domain install picked here is a guess against configs nobody read. The Scope bullet above names the same commands as the authoring alternative, and this is the destination a person takes.
19
+ - **An existing project.** Stop and hand off to `aitk-operator`. It reads what the target already carries before it names a command, which this chain never does, so any per-domain install picked here is a guess against configs nobody read. The Scope bullet above names the same commands as the authoring alternative, and this is the destination a person takes.
20
20
  - **An install wanting the `.claude/` folder alone.** Stop. Run `aitk claude init` for the seed docs, then invoke `setup-indexes` to bootstrap the `index.md` system over the project's own documentation folders. Neither needs the tooling sync this chain runs.
21
21
  - **A language the toolkit carries no stack for.** The chain still runs, on `base`, with the fallback marked in the preview. A project that wants none of what `base` carries declines there and takes `setup-gov` for the governance layer, which is language-neutral. Say so at the preview rather than resolving it here, since the fallback is a working default and only the person can say whether it fits.
22
22
 
@@ -41,6 +41,6 @@ Importing that catalog wholesale fails on a different measurement. External mate
41
41
 
42
42
  - The banned words, characters, and spellings, which `markdown.md` states for a reader and `aitk markdown audit` gates from package data
43
43
  - Markdown mechanics, being headings, lists, code spans, punctuation, and file references
44
- - Restating text that already exists in plainer words, which `restate` owns on a different trigger, since a restatement is asked for by name and this arrives on a glob match. The rules here still govern how that restatement reads, and that body cites this one rather than carrying a copy.
44
+ - Restating text that already exists in plainer words, which `restate-plainly` owns on a different trigger, since a restatement is asked for by name and this arrives on a glob match. The rules here still govern how that restatement reads, and that body cites this one rather than carrying a copy.
45
45
  - What voice a given surface declares, which belongs to the standard governing that surface
46
46
  - Measuring whether finished output followed these rules, which needs a check this skill does not carry
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: write-human
3
- description: Carries the voice, rhythm, sentence construction, and information density rules a banned-word list cannot express, plus the catalog of machine tells that survive a clean ban scan. Use when writing or revising prose a person will read, when a passage reads flat or uniform, or when asked to "make this read like a person", "fix the cadence", "this reads like AI wrote it", "vary the sentences", or "tighten this without gutting it". Do NOT use for banned words, characters, or spellings, which `markdown.md` states and `aitk markdown audit` gates, and do NOT use to restate text that already exists in plainer words, which is `restate`, whose body loads these rules from here.
3
+ description: Carries the voice, rhythm, sentence construction, and information density rules a banned-word list cannot express, plus the catalog of machine tells that survive a clean ban scan. Use when writing or revising prose a person will read, when a passage reads flat or uniform, or when asked to "make this read like a person", "fix the cadence", "this reads like AI wrote it", "vary the sentences", or "tighten this without gutting it". Do NOT use for banned words, characters, or spellings, which `markdown.md` states and `aitk markdown audit` gates, and do NOT use to restate text that already exists in plainer words, which is `restate-plainly`, whose body loads these rules from here.
4
4
  ---
5
5
 
6
6
  # Write human
@@ -17,7 +17,7 @@ aitk demo run demos/inline-edit.json --cursor ~/cursors/theme --out assets
17
17
 
18
18
  ## The draft and the plan are different files
19
19
 
20
- `claude-screencast` drafts beats for a person. A beat carries what is on screen, one verb, what to watch for, an emphasis, and a caption, and none of that names a selector, a URL, a wait condition, or a timing. Those four are what an executor needs and what would ruin the draft, since the format is pre-seeded so the operator edits down rather than fills blanks.
20
+ `aitk-screencast` drafts beats for a person. A beat carries what is on screen, one verb, what to watch for, an emphasis, and a caption, and none of that names a selector, a URL, a wait condition, or a timing. Those four are what an executor needs and what would ruin the draft, since the format is pre-seeded so the operator edits down rather than fills blanks.
21
21
 
22
22
  So `aitk demo compile` writes a second artifact rather than adding fields to a beat. It maps each beat's verb to a step, seeds the timing, marks which beat the still comes from, and leaves the target and the URL empty for a person to fill. The report names every field it could not supply.
23
23
 
@@ -36,6 +36,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
36
36
  - [Standard success criteria](standards-audit.md): Reading the corpus against the Success criterion gate, why the check scopes to arrival rather than the whole corpus, and the exit codes it sets
37
37
  - [State-scoped risk](state-scoped-risk.md): Reading committed state rather than an arriving change, the shipped-tree corpus the secret scan reads, what it keys on and how a deliberate value is exempted, the advisory check and its network failure mode, and why one gates while the other reports
38
38
  - [Superseded values](superseded.md): Reading where the tree still asserts a value a changed convention no longer produces, why the sweep keys on the value rather than the file, the exemption marker, the blind spot it cannot reach, and why it reports rather than gates
39
+ - [Targets](targets.md): The projects this toolkit installed into, the record the install writes against the sweep that backs it, what bounds each answer, and the cross-target pull request read
39
40
  - [Tasks](tasks.md): Selecting a shipped task by stem or pull request, recording a number and closing an outcome, the refusal reasons, the board and backlog checks validate runs, and why the board root defaults to the main worktree
40
41
  - [Teach](teach.md): Listing learning workspaces and the ordinal a new one takes, opening one with its required files, recording sources and glossary terms, resolving what the next lesson needs before it is written, the refusal reasons, and why every write here runs through a verb
41
42
  - [Test order](test-order.md): Reading where an implementation reached history ahead of its test, how a pair is decided, the three verdicts, the coverage the pairing cannot reach, and why the check reports rather than gates
@@ -7,7 +7,7 @@ description: What this folder covers, the invocation rules every command inherit
7
7
 
8
8
  CLI catalog and invocation rules for agents working in this repository.
9
9
 
10
- This folder is an index of what an agent can run and how to run it cleanly from a script. It does not cover domain behavior. Read `CLAUDE.md` for project behaviors and load the matching `.claude/skills/aitk-*` skill when working inside a domain.
10
+ This folder is an index of what an agent can run and how to run it cleanly from a script. It does not cover domain behavior. Read `CLAUDE.md` for project behaviors and load the matching `.claude/skills/internal-*` skill when working inside a domain.
11
11
 
12
12
  ## Invocation rules
13
13
 
@@ -22,5 +22,5 @@ See `CLAUDE.md` design principles. They apply to every command in this folder.
22
22
  ## Related
23
23
 
24
24
  - `CLAUDE.md`: project behaviors and design principles
25
- - `.claude/skills/aitk-*`: domain-scoped guidance for editing work
25
+ - `.claude/skills/internal-*`: domain-scoped guidance for editing work
26
26
  - `docs/index.md`: full docs directory
@@ -146,4 +146,4 @@ git hooks, the end-to-end harness, and the shell scripts under `scripts/`, so a
146
146
  headless run carrying neither `--check` nor `--write` reports what it would
147
147
  replace and exits 1 rather than applying it. Run `--check` first to read the
148
148
  list, then `--write` to apply it. `aitk tooling sync --help` names both, and the
149
- full per-stack path list sits in the `toolkit-cli` skill.
149
+ full per-stack path list sits in the `aitk-cli` skill.
@@ -13,12 +13,14 @@ description: Resolving live peer sessions to the worktree and branch each holds,
13
13
  aitk sessions list
14
14
  aitk sessions list --json
15
15
  aitk sessions list --branch feat/parser --json
16
+ aitk sessions list --branch chore/agents --repository ../caret --json
16
17
  ```
17
18
 
18
- | Option | Behavior |
19
- | ----------------- | -------------------------------------------- |
20
- | `--json` | Add a machine-readable record on stdout |
21
- | `--branch <name>` | Report the sessions holding this branch here |
19
+ | Option | Behavior |
20
+ | --------------------- | ----------------------------------------------------- |
21
+ | `--json` | Add a machine-readable record on stdout |
22
+ | `--branch <name>` | Report the sessions holding this branch |
23
+ | `--repository <path>` | Answer about this project rather than the working one |
22
24
 
23
25
  It reads and never writes. The question it answers is which session to address when work has to reach the one holding a given branch, which a session listing cannot answer on its own.
24
26
 
@@ -28,7 +30,11 @@ An exit code says nothing about a call made from a session, since a shell profil
28
30
 
29
31
  ## Scope and count
30
32
 
31
- `--branch` scopes the match to the repository the command runs in, and refuses outside one. A branch name identifies a branch inside a repository and nothing across a machine, so an unscoped match reaches a session working in a different project, and `main` collides on every machine running two of them.
33
+ `--branch` scopes the match to one repository, and refuses when none resolves. A branch name identifies a branch inside a repository and nothing across a machine, so an unscoped match reaches a session working in a different project, and `main` collides on every machine running two of them.
34
+
35
+ Which repository that is defaults to the one the command runs in, and `--repository <path>` names another. Every reading moves with it, the session match and the worktree and ref reads alike, because the answer is about that project rather than about where the caller stands. The roster underneath is machine-wide already, so the flag removes a filter rather than widening a search.
36
+
37
+ That is what a dispatcher reaching outside its own project needs. Without it a check run from the toolkit against a branch held by a live session in a consuming project answered unclaimed, and two sessions were sent onto branches other sessions were holding. One refused on the worktree lock and one cut a second worktree on the same branch, which would have put two sessions pushing to one ref.
32
38
 
33
39
  A bare run reports every repository and carries a `repository` field on each row, holding the shared git directory that a main checkout and all its linked worktrees agree on. That is what a caller filters on when it wants a scope of its own.
34
40
 
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: Targets
3
+ description: The projects this toolkit installed into, the record the install writes against the sweep that backs it, what bounds each answer, and the cross-target pull request read
4
+ ---
5
+
6
+ # Targets
7
+
8
+ ## List
9
+
10
+ `aitk targets list` reports the projects this toolkit has installed into, with where each answer came from.
11
+
12
+ ```bash
13
+ aitk targets list
14
+ aitk targets list --json
15
+ aitk targets list --sweep ~/repos --json
16
+ ```
17
+
18
+ | Option | Behavior |
19
+ | ----------------- | ------------------------------------------------------- |
20
+ | `--json` | Add a machine-readable record on stdout |
21
+ | `--sweep <path…>` | Also walk these roots for targets the record never held |
22
+ | `--depth <n>` | How deep below each swept root to walk, defaulting to 4 |
23
+
24
+ Exit codes: `0` the population was read, `1` refused. A refusal carries a `reason` of `bad-depth`, and an absent index reports as unknown rather than as no targets.
25
+
26
+ An exit code says nothing about a call made from a session, since a shell profile may wrap the binary in a function taking its status from a later command. Read the record's fields rather than the exit when a skill consumes this.
27
+
28
+ ## Where the answer comes from
29
+
30
+ Every sync that stamps a target records it in a machine-level index at `$XDG_STATE_HOME/aitk/targets.json`, falling back to `~/.local/state/aitk/targets.json`. A project installed into since that shipped is therefore known without anyone naming it, and each row carries `stampedAt` from the sync that last touched it.
31
+
32
+ `--sweep` walks the roots given and finds what the record never held, which is every target installed before the index existed. A row says which of the two found it, and a row the record knows keeps that source even when the sweep reaches it too.
33
+
34
+ The record is the primary source and the sweep is the fallback, because they fail in opposite directions. A record only knows an install that ran after it shipped. A walk only knows the paths someone thought to name, which is how a hand census of this population was wrong in both directions at once: it counted two folders that had never been targets, counted one clone of a target already counted, and missed the clone a repair had actually run in.
35
+
36
+ ## What bounds a sweep
37
+
38
+ A `--sweep` run carries a `bound` object naming the roots walked, the depth, the folders the walk stopped at on reaching the cap, the roots it could not read, and the directory symlinks it did not follow. Read it before treating a count as the population.
39
+
40
+ The bound a sweep can never state is the machine. It reads this one, so a target on another machine or under a path nobody named is outside every answer it gives. That is the same limit the hand census had, and the record above is what closes it going forward rather than the sweep.
41
+
42
+ `--depth` refuses anything that is not a whole number rather than falling back to the default. A value that is not one leaves every depth test false, so the walk runs to the bottom of its root while the bound claims a cap it never applied.
43
+
44
+ ## A project held in more than one clone
45
+
46
+ A target cloned twice is one target. The sweep reads each checkout's `origin`, trims it to a form an ssh URL and an https URL of one repository agree on, and reports a single row holding every path.
47
+
48
+ The row leads with the clone the record knows, because the record only names one a sync actually ran in. Every caller reading a single path takes the first, and picking that by sort order is the shape behind a repair that ran in one clone while a count was taken against another, leaving the target reported as untouched.
49
+
50
+ Nothing removes a row. A project deleted, moved, or that dropped the toolkit stays in the index, so a count drifts upward over time. It surfaces on use rather than silently, since the read below refuses a path it cannot open.
51
+
52
+ ## Pulls
53
+
54
+ `aitk targets pulls` reports, per target, every open pull request with its checks and the heading its newest review pass carries.
55
+
56
+ ```bash
57
+ aitk targets pulls
58
+ aitk targets pulls ../caret ../stackr --json
59
+ ```
60
+
61
+ Naming paths reads those and looks up nothing. Naming none reads every target `aitk targets list` reports. One clone per project is read, since two checkouts sharing an origin answer the same query and reading both spends the rate limit to print one answer twice.
62
+
63
+ Exit codes: `0` at least one target was read, `1` refused or every target refused.
64
+
65
+ | Field | Holds |
66
+ | ---------------- | ----------------------------------------------------------------------- |
67
+ | `checks` | `passing`, `failing`, `pending`, or `null` when GitHub reported none |
68
+ | `review` | `open`, `closed`, or `null` when no pass has landed |
69
+ | `reviewReadable` | `false` when the review query failed, leaving `review` covering nothing |
70
+
71
+ `checks` is `null` rather than `passing` when no check ran at all, which is not the same answer. A failure outranks a run still going, since a job that already failed cannot be cleared by one still in flight.
72
+
73
+ `review` reads the first line of the newest pass carrying `## Review` or `## Review closed`, which `claude-pr-review` owns and posts. A target leaves a wave on `closed` rather than on a worker's reply.
74
+
75
+ A target that could not be read carries a `reason` rather than an empty pull list. Reading a failed query as no open work is what reports a target as done having read nothing, which is the failure mode of the hand-written shell loop this replaces.
76
+
77
+ | Reason | Means |
78
+ | ----------------- | ------------------------------------------------------ |
79
+ | `not-a-directory` | the path is not a directory, so nothing was read there |
80
+ | `gh-unavailable` | `gh` is not on the path |
81
+ | `list-failed` | the open pull request list could not be read |
82
+
83
+ The reads run one target at a time. They share one GitHub API quota, and a wave firing a dozen at once meets the secondary rate limit rather than an answer.
@@ -185,7 +185,7 @@ This section is the corpus the coverage claim is measured against: every name `a
185
185
  | Skill | When to use |
186
186
  | ---------------------------- | --------------------------------------------------------------------------------------- |
187
187
  | `aitk:setup-init` | On a fresh scaffold, to detect the stack and run the whole install chain in one pass |
188
- | `aitk:toolkit-operator` | On a project that already exists, to read what it carries before an install is picked |
188
+ | `aitk:aitk-operator` | On a project that already exists, to read what it carries before an install is picked |
189
189
  | `aitk:setup-gov` | When the governance rules are wanted without the tooling chain |
190
190
  | `aitk:setup-indexes` | When a markdown-heavy folder needs an `index.md` a session can browse |
191
191
  | `aitk:setup-plugins` | On a new machine, to install the community and official plugins user-scoped |
@@ -266,32 +266,33 @@ This section is the corpus the coverage claim is measured against: every name `a
266
266
  | `aitk:migration-context` | When `docs/` holds agent-flavored files belonging in `.claude/context/` |
267
267
  | `aitk:migration-superseded` | When a drift report names a `.claude/` file a folder has replaced |
268
268
  | `aitk:migration-standards-drop` | When the project still holds an installed `.claude/standards/` tree |
269
- | `aitk:toolkit-feedback` | When something in the toolkit is broken, missing, or off |
270
- | `aitk:toolkit-triage` | In the toolkit repo, to work through the open feedback issues |
269
+ | `aitk:aitk-feedback-file` | When something in the toolkit is broken, missing, or off |
270
+ | `aitk:aitk-feedback-triage` | In the toolkit repo, to work through the open feedback issues |
271
+ | `aitk:aitk-rollout` | In the toolkit repo, to take one change out to every consuming project at once |
271
272
 
272
273
  ### Generate an artifact on demand
273
274
 
274
- | Skill | When to use |
275
- | -------------------------- | --------------------------------------------------------------------- |
276
- | `aitk:create-rule` | For a project-specific governance rule the toolkit does not ship |
277
- | `aitk:create-skill` | For a new `SKILL.md` |
278
- | `aitk:create-snippet` | For a reusable prompt |
279
- | `aitk:create-standard` | For a new authoring convention |
280
- | `aitk:bash-script` | For an interactive, human-facing shell tool |
281
- | `aitk:cli-script` | For a non-interactive automation, CI, or pipeline script |
282
- | `aitk:ci-workflow` | For a GitHub Actions workflow file |
283
- | `aitk:claude-slides-draft` | For a deck, drafted as `.claude/SLIDES.md` and rendered to PowerPoint |
284
- | `aitk:claude-screencast` | For a recording script with beats and defaults already seeded |
275
+ | Skill | When to use |
276
+ | ------------------------ | --------------------------------------------------------------------- |
277
+ | `aitk:create-rule` | For a project-specific governance rule the toolkit does not ship |
278
+ | `aitk:create-skill` | For a new `SKILL.md` |
279
+ | `aitk:create-snippet` | For a reusable prompt |
280
+ | `aitk:create-standard` | For a new authoring convention |
281
+ | `aitk:bash-script` | For an interactive, human-facing shell tool |
282
+ | `aitk:bash-cli-script` | For a non-interactive automation, CI, or pipeline script |
283
+ | `aitk:ci-workflow` | For a GitHub Actions workflow file |
284
+ | `aitk:aitk-slides-draft` | For a deck, drafted as `.claude/SLIDES.md` and rendered to PowerPoint |
285
+ | `aitk:aitk-screencast` | For a recording script with beats and defaults already seeded |
285
286
 
286
287
  ### Answer a question at any point
287
288
 
288
289
  | Skill | When to use |
289
290
  | -------------------------- | ------------------------------------------------------------------------------ |
290
- | `aitk:toolkit-cli` | Before a sync or install, to learn what it overwrites, merges, or leaves alone |
291
+ | `aitk:aitk-cli` | Before a sync or install, to learn what it overwrites, merges, or leaves alone |
291
292
  | `aitk:youtube-transcripts` | When a video transcript is wanted in the repo as context |
292
293
  | `aitk:claude-teach` | To learn a subject across sessions, in a workspace that holds the progress |
293
294
  | `aitk:write-human` | Before drafting or revising prose, for voice, rhythm, and density |
294
- | `aitk:restate` | When an answer or a document has to be read again in plain words |
295
+ | `aitk:restate-plainly` | When an answer or a document has to be read again in plain words |
295
296
 
296
297
  Every row answers a question rather than marking a point in a project's life, so a phase above would send a reader to the wrong group.
297
298
 
@@ -49,7 +49,7 @@ The chain is:
49
49
  - The agent reads `aitk tooling reference <stack>` (plus parents) as its audit context, follows it to generate eslint, vitest, playwright configs and the stack's setup script, and extends `.claude/context/ci.md` and `.claude/context/development.md` per the reference's extend sections <!-- audit-ignore-citations: .claude/context/development.md -->
50
50
  - `setup-verify` runs the installed `package.json` scripts (lint, typecheck, check, test, build) and reports pass or fail
51
51
 
52
- The chain serves a fresh scaffold and names a destination for the three states it does not. An existing project goes to `aitk:toolkit-operator`, which reads what the project already carries before naming a per-domain command. An install wanting the Claude layer without the tooling chain runs `aitk claude init` for the seed docs and then `aitk:setup-indexes` for the index system. A language the toolkit ships no stack for is the one of the three the chain still runs for, on `base`, with the fallback marked in the preview so it can be declined there.
52
+ The chain serves a fresh scaffold and names a destination for the three states it does not. An existing project goes to `aitk:aitk-operator`, which reads what the project already carries before naming a per-domain command. An install wanting the Claude layer without the tooling chain runs `aitk claude init` for the seed docs and then `aitk:setup-indexes` for the index system. A language the toolkit ships no stack for is the one of the three the chain still runs for, on `base`, with the fallback marked in the preview so it can be declined there.
53
53
 
54
54
  Keep the `## Scripts` table in `.claude/context/development.md` current as scripts are added. Base tooling seeds that entry with the commands it installs, and each stack reference extends the table. `project-commands` reads it to start the app or run a check on request, so a command missing from the table cannot be run that way. A project whose entry outgrew one file and split into `.claude/context/development/` keeps the table in `overview.md`, which is where the skill looks next. <!-- audit-ignore-citations: .claude/context/development.md -->
55
55
 
@@ -9,7 +9,7 @@ paths:
9
9
  ## Skill routing
10
10
 
11
11
  - Use `aitk:bash-script` for an interactive or human-facing script: prompts, a visual timeline UI, framed terminal output.
12
- - Use `aitk:cli-script` for a non-interactive script: automation, CI, cron, a pipeline helper, or anything run by an agent rather than watched by a person.
12
+ - Use `aitk:bash-cli-script` for a non-interactive script: automation, CI, cron, a pipeline helper, or anything run by an agent rather than watched by a person.
13
13
  - Load the matched skill's own reference templates rather than hand-rolling interactivity or logging patterns outside them.
14
14
  - Report it rather than proceeding silently when the matched skill does not resolve. Both ship with the plugin and this rule ships with the CLI, so a project that installed governance alone does not have them.
15
15
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "3.43.2",
4
+ "version": "3.45.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -15,7 +15,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
15
  PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
16
16
 
17
17
  TOOLING_DIR="$PROJECT_ROOT/tooling"
18
- CONTRACT="$PROJECT_ROOT/claude/skills/toolkit-cli/SKILL.md"
18
+ CONTRACT="$PROJECT_ROOT/claude/skills/aitk-cli/SKILL.md"
19
19
 
20
20
  BEGIN="<!-- generated:tooling-paths -->"
21
21
  END="<!-- /generated:tooling-paths -->"
@@ -298,7 +298,7 @@ main() {
298
298
 
299
299
  log_step "Tooling paths"
300
300
  run_check "bash $PROJECT_ROOT/scripts/core/regen-tooling-paths.sh" "Tooling-path regen failed"
301
- 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."
301
+ assert_no_drift "claude/skills/aitk-cli/SKILL.md" "The overwrite contract drifted from what the stacks hold. Run bun run check and commit claude/skills/aitk-cli/SKILL.md."
302
302
  log_info "Tooling paths clean"
303
303
 
304
304
  # The claude manifest is the only route a target's ignore set travels, and it
@@ -18,7 +18,7 @@ export const AUTHORING_CASES: readonly SkillCase[] = [
18
18
  {
19
19
  prompt:
20
20
  'Write me a headless automation script with no interactive prompts.',
21
- expect: 'cli-script',
21
+ expect: 'bash-cli-script',
22
22
  },
23
23
  {
24
24
  prompt: 'Scaffold a brand-new SKILL.md for this capability.',
@@ -39,7 +39,7 @@ export const AUTHORING_CASES: readonly SkillCase[] = [
39
39
  },
40
40
  {
41
41
  prompt: 'Say what that dense answer actually means in plain terms.',
42
- expect: 'restate',
42
+ expect: 'restate-plainly',
43
43
  },
44
44
  {
45
45
  prompt: 'This passage reads flat and robotic, give it some real cadence.',
@@ -81,7 +81,7 @@ export const CLAUDE_WORKFLOW_CASES: readonly SkillCase[] = [
81
81
  },
82
82
  {
83
83
  prompt: 'Draft me a script with beats for a screencast recording.',
84
- expect: 'claude-screencast',
84
+ expect: 'aitk-screencast',
85
85
  },
86
86
  {
87
87
  prompt:
@@ -90,7 +90,7 @@ export const CLAUDE_WORKFLOW_CASES: readonly SkillCase[] = [
90
90
  },
91
91
  {
92
92
  prompt: 'Turn this topic into a slide deck I can render.',
93
- expect: 'claude-slides-draft',
93
+ expect: 'aitk-slides-draft',
94
94
  },
95
95
  {
96
96
  prompt:
@@ -1,7 +1,7 @@
1
1
  import type { SkillCase } from '@/claude/skills-rank'
2
2
 
3
3
  /**
4
- * `setup-*`, `migration-*`, `toolkit-*`, and `create-rule`: scaffolding,
4
+ * `setup-*`, `migration-*`, `aitk-*`, and `create-rule`: scaffolding,
5
5
  * proposal-only migrations, and the toolkit's own reference and feedback
6
6
  * surfaces.
7
7
  */
@@ -53,20 +53,20 @@ export const SETUP_CASES: readonly SkillCase[] = [
53
53
  {
54
54
  prompt:
55
55
  "Before I run this sync, tell me exactly what it's going to overwrite.",
56
- expect: 'toolkit-cli',
56
+ expect: 'aitk-cli',
57
57
  },
58
58
  {
59
59
  prompt:
60
60
  'Something about the toolkit itself is broken, write it up and send it back to the maintainers.',
61
- expect: 'toolkit-feedback',
61
+ expect: 'aitk-feedback-file',
62
62
  },
63
63
  {
64
64
  prompt:
65
65
  "I don't know which specific toolkit skill I need, just handle it for me.",
66
- expect: 'toolkit-operator',
66
+ expect: 'aitk-operator',
67
67
  },
68
68
  // The performing skill wins a phrase naming its operation over the front
69
- // door's own routing framing, even though toolkit-operator's description
69
+ // door's own routing framing, even though aitk-operator's description
70
70
  // quotes a phrase near this one. See .claude/context/cli/audits.md.
71
71
  {
72
72
  prompt:
@@ -76,7 +76,15 @@ export const SETUP_CASES: readonly SkillCase[] = [
76
76
  {
77
77
  prompt:
78
78
  'Work through the open feedback issues on the toolkit repo one by one.',
79
- expect: 'toolkit-triage',
79
+ expect: 'aitk-feedback-triage',
80
+ },
81
+ // The outbound direction is what separates this from the front door above.
82
+ // aitk-operator runs inside one project the session already stands in, and
83
+ // this reaches every project the toolkit installed into from the toolkit.
84
+ {
85
+ prompt:
86
+ 'Take this change out to every project that installed the toolkit and get each one to a pull request.',
87
+ expect: 'aitk-rollout',
80
88
  },
81
89
  {
82
90
  prompt:
package/src/cli.ts CHANGED
@@ -33,6 +33,7 @@ import { register as secrets } from '@/commands/secrets'
33
33
  import { register as deps } from '@/commands/deps'
34
34
  import { register as labels } from '@/commands/labels'
35
35
  import { register as census } from '@/commands/census'
36
+ import { register as targets } from '@/commands/targets'
36
37
  import { register as upgrade } from '@/commands/upgrade'
37
38
  import { readInstalled, UNKNOWN_LABEL } from '@/version/installed'
38
39
  import { palette } from '@/ui'
@@ -72,6 +73,7 @@ function showHelp(): void {
72
73
  `${GREY}│${NC} markdown [cmd] ${GREY}# Report markdown against the attribute standards (audit)${NC}`,
73
74
  `${GREY}│${NC} records [cmd] ${GREY}# Session records under .claude/ (validate, size, push, pull)${NC}`,
74
75
  `${GREY}│${NC} sessions [cmd] ${GREY}# Resolve live sessions to worktree and branch (list)${NC}`,
76
+ `${GREY}│${NC} targets [cmd] ${GREY}# Report the projects this toolkit installed into (list, pulls)${NC}`,
75
77
  `${GREY}│${NC} worktrees [cmd] ${GREY}# Report which worktrees are reclaimable (list)${NC}`,
76
78
  `${GREY}│${NC} secrets [cmd] ${GREY}# Read the shipped tree for credential-shaped values (scan)${NC}`,
77
79
  `${GREY}│${NC} deps [cmd] ${GREY}# Read the resolved dependency set for advisories (audit)${NC}`,
@@ -170,6 +172,7 @@ context(program)
170
172
  markdown(program)
171
173
  records(program)
172
174
  sessions(program)
175
+ targets(program)
173
176
  worktrees(program)
174
177
  secrets(program)
175
178
  deps(program)
@@ -42,7 +42,7 @@ export function register(program: Command): void {
42
42
  demo
43
43
  .command('compile')
44
44
  .description('Turn a screencast draft into a plan a run can drive')
45
- .argument('<draft>', 'Screencast draft written by claude-screencast')
45
+ .argument('<draft>', 'Screencast draft written by aitk-screencast')
46
46
  .helpOption('-h, --help', 'Show this help message')
47
47
  .option('-o, --out <dir>', 'Directory the plan is written to', DEFAULT_OUT)
48
48
  .option('-s, --slug <slug>', 'Plan name, defaulting to the draft filename')
@@ -1,3 +1,4 @@
1
+ import { resolve } from 'node:path'
1
2
  import type { Command } from 'commander'
2
3
  import { checkClaim, type ClaimReport } from '@/sessions/claim'
3
4
  import {
@@ -19,6 +20,7 @@ import {
19
20
  interface ListCommandOptions {
20
21
  readonly json?: boolean
21
22
  readonly branch?: string
23
+ readonly repository?: string
22
24
  }
23
25
 
24
26
  const REASONS: Record<string, string> = {
@@ -46,6 +48,10 @@ export function register(program: Command): void {
46
48
  '--branch <name>',
47
49
  'Report only the sessions holding this branch in this repository',
48
50
  )
51
+ .option(
52
+ '--repository <path>',
53
+ 'Answer about this project rather than the working one',
54
+ )
49
55
  .addHelpText(
50
56
  'after',
51
57
  [
@@ -54,11 +60,18 @@ export function register(program: Command): void {
54
60
  ' 0 the roster was read',
55
61
  ' 1 refused, with the reason on stderr',
56
62
  '',
57
- '--branch scopes the match to the repository the command runs in, since',
58
- 'a branch name identifies a branch there and nothing across a machine.',
63
+ '--branch scopes the match to one repository, since a branch name',
64
+ 'identifies a branch there and nothing across a machine. That is the',
65
+ 'repository the command runs in unless --repository names another.',
59
66
  'A bare run reports every repository and carries the repository field,',
60
67
  'so a caller filtering by hand has something that identifies one.',
61
68
  '',
69
+ '--repository moves every reading to the project at that path, the',
70
+ 'session match and the worktree and ref reads alike. The roster is',
71
+ 'machine-wide already, so this is what lets a dispatcher in one project',
72
+ 'see a branch a live session holds in another rather than reading it as',
73
+ 'unclaimed and sending a second session onto it.',
74
+ '',
62
75
  'With --branch, the JSON also carries "worktree" (the path of any',
63
76
  'worktree already checked out to it, or null), "refs" (the refs that',
64
77
  'already name it, local head and origin remote-tracking alike), and',
@@ -94,6 +107,7 @@ export function register(program: Command): void {
94
107
  ' aitk sessions list',
95
108
  ' aitk sessions list --json',
96
109
  ' aitk sessions list --branch feat/parser --json',
110
+ ' aitk sessions list --branch chore/agents --repository ../caret --json',
97
111
  '',
98
112
  ].join('\n'),
99
113
  )
@@ -125,13 +139,18 @@ async function runList(opts: ListCommandOptions): Promise<number> {
125
139
  // A branch name identifies a branch inside one repository and nothing across
126
140
  // a machine, so an unscoped match reaches a session working in a different
127
141
  // project. `main` is the name that collides on every machine running two.
128
- const repository = opts.branch ? await repositoryOf(process.cwd()) : null
142
+ //
143
+ // Which repository that is is the caller's to name. The roster this filters
144
+ // is machine-wide already, so a dispatcher asking about another project was
145
+ // answered "unclaimed" about a branch a live session there was holding.
146
+ const at = opts.repository ? resolve(opts.repository) : process.cwd()
147
+ const repository = opts.branch ? await repositoryOf(at) : null
129
148
 
130
149
  if (opts.branch && repository === null) {
131
150
  intro('aitk sessions list')
132
151
  logStep('Refused')
133
152
  logWarn(
134
- '--branch scopes the match to the repository this command runs in, and no repository resolved here. Run it inside one, or read the whole roster and filter on the repository field.',
153
+ `--branch scopes the match to one repository, and none resolved at ${at}. Run it inside one, name another with --repository, or read the whole roster and filter on the repository field.`,
135
154
  )
136
155
  outro()
137
156
 
@@ -152,10 +171,7 @@ async function runList(opts: ListCommandOptions): Promise<number> {
152
171
  : report.sessions
153
172
 
154
173
  const claim = opts.branch
155
- ? await checkClaim(opts.branch, {
156
- cwd: process.cwd(),
157
- resolve: async () => report,
158
- })
174
+ ? await checkClaim(opts.branch, { cwd: at, resolve: async () => report })
159
175
  : null
160
176
 
161
177
  intro('aitk sessions list')