@erclx/aitk 3.33.1 → 3.34.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aitk",
3
3
  "description": "Automated governance, versioning, and discovery tools for Claude Code.",
4
- "version": "3.33.1",
4
+ "version": "3.34.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -68,7 +68,9 @@ The session also records nothing of what it learns. Both other callers of memory
68
68
  - Plan a row the re-test clears, since a cleared row carrying no plan is one the next pass looks at again
69
69
  - Split a task whose file set collides with every other by construction, rather than re-measuring a scoping defect that reads as a blocker
70
70
  - Check a candidate branch is unclaimed by an existing worktree or a live session before dispatching a background worker for it, since the measured failure this closes is a worker colliding with someone else's work already sitting in the row
71
- - Cap concurrent self-dispatched workers at three, counted by a session name no human-launched worker carries, since the evidence behind self-dispatch is one task shipped once
71
+ - Dispatch only a candidate whose file set is disjoint from every track in flight, compared at the file path rather than a folder above it, since a count knows nothing about what two workers write
72
+ - Hold a candidate whose sets are disjoint when a stated reason serializes it, and write that reason on the hold, since disjointness is necessary and not sufficient
73
+ - Name each self-dispatched worker with the `orchestrator-` prefix, since that is what separates one from an operator's own launch in a session listing
72
74
  - Report each self-dispatch and the row it fired against loudly enough to follow, since a person no longer watches the launch step happen
73
75
  - Stop dispatching once `## Run now` is empty or every row in it reads claimed, rather than waking again to fire on a board nobody is clearing
74
76
 
@@ -76,7 +78,7 @@ The session also records nothing of what it learns. Both other callers of memory
76
78
 
77
79
  - Implement a feature or edit any tracked file from this session, at any size, since the ban offers no proportionality exception
78
80
  - Merge. Recommend merge or changes and leave the gate to the human.
79
- - Spawn a worker with the Agent tool, since an in-process subagent shares this session's context and cannot be steered or reached independently. A dispatched `claude --bg` process is not this: it is a separate session with its own worktree and its own PR, gated by the collision check and the worker cap.
81
+ - Spawn a worker with the Agent tool, since an in-process subagent shares this session's context and cannot be steered or reached independently. A dispatched `claude --bg` process is not this: it is a separate session with its own worktree and its own PR, gated by the collision check and the file-set disjointness test.
80
82
  - Hand a worker anything but a plan, because scope lives there
81
83
  - Run a second orchestrator against the same board
82
84
  - Promote a task to fill the queue when nothing qualifies. A thin queue is a real answer.
@@ -93,7 +95,8 @@ The session also records nothing of what it learns. Both other callers of memory
93
95
  - This body dropped from a long session approaching a compaction: name the re-invocation and the runbook paths, since the routing lives in the body and a user-invoked skill routes nothing once it is gone
94
96
  - Blocker only an operator can clear: record the row as untestable this pass and name the action owed, rather than re-measuring what no session can move
95
97
  - Collision check refuses, with no session registry or no repository resolved: treat the candidate as unverified and fall back to the human-launch line, rather than reading a check that could not run as a clear one
96
- - Worker cap already at three: stop dispatching for the pass and leave the row ready, rather than queueing past it
98
+ - Candidate's file set overlaps a track in flight, or a stated reason serializes it: leave the row ready for the next pass, rather than dispatching onto a shared seam
99
+ - Operator states a cap for the session: honor it for that session alone, rather than treating it as a standing rule or writing the number into a file
97
100
 
98
101
  ## Out of scope
99
102
 
@@ -102,7 +102,7 @@ Write no shape for a correction. A correction is a sentence, and a format for ad
102
102
  1. 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. Every plan written from here also carries a constraint per track in flight, which the paragraph below this list states.
103
103
  2. Decide parallelism and merge order. Note which plans touch a shared wiring seam so their PRs merge in sequence, not at once.
104
104
  3. 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.
105
- 4. Hand off. Read `${CLAUDE_SKILL_DIR}/references/orchestrator-dispatch.md` and follow it: check the branch is unclaimed, check the worker cap, then dispatch a background worker with `claude --bg`. Fall back to the human-launch line it replaces when the check refuses, the cap is reached, or the row fails Parallelism against something already in flight.
105
+ 4. Hand off. Read `${CLAUDE_SKILL_DIR}/references/orchestrator-dispatch.md` and follow it: check the branch is unclaimed, check the row's file set against every track in flight, then dispatch a background worker with `claude --bg`. Fall back to the human-launch line it replaces when the check refuses, the sets overlap, or a stated reason serializes the row behind something already out.
106
106
  5. Review the PR. When a worker opens a PR, run `claude-pr-review` to post findings to it. This is the deep, independent pass. The worker's autoship self-review was only the green gate.
107
107
  - Learning that a PR moved is the mechanical half, so read `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` and start the poll it carries on the first dispatch rather than checking the board by hand. That runbook holds the routing, and a summary of it here is a second source that drifts from it.
108
108
  6. Dispatch the handback. A pass posting anything owed, a finding at any severity or a testing question, tells the session holding that branch to run `claude-address-review`, rather than waiting for a person to relay it. Re-review when the answer lands, then the human merges. Tell the trailing worker to rebase when its branch shares a seam with the merged one.
@@ -128,7 +128,7 @@ Stamp the block with the commit this session read the tree at, which the same se
128
128
  - Do not implement features in this session. Hand the plan to a worker.
129
129
  - Do not merge. Recommend merge or changes. The human merges.
130
130
  - Do not spawn a worker with the Agent tool. An in-process subagent shares this session's context and cannot be steered or reached independently, which breaks the property this boundary protects rather than the mechanism it names. The dispatch in `orchestrator-dispatch.md` is a separate `claude --bg` process with its own worktree and its own PR, so it preserves that property instead.
131
- - Dispatch a background worker only once the collision check in `orchestrator-dispatch.md` clears and the worker cap still has room. Colliding with an existing worktree or session, or exceeding the cap, is what the check and the cap exist to catch, not a judgment call this session makes case by case.
131
+ - Dispatch a background worker only once the collision check in `orchestrator-dispatch.md` clears and the row's file set is disjoint from every track in flight. Colliding with an existing worktree or session is what the check exists to catch rather than a judgment call this session makes case by case. No fixed count binds how many tracks run at once, and Parallelism below states what does.
132
132
  - Do not edit tracked files from this session, at any size. The boundary offers no proportionality exception and nothing enforces it.
133
133
  - Do not hand a worker anything but a plan, since scope lives there. A plan carries exact diffs only when they are already known, otherwise it states the scope and the open questions and lets the worker write the diff.
134
134
 
@@ -196,9 +196,16 @@ No fixed number caps worker tracks. Collision between file sets is what binds, s
196
196
  list the files a candidate touches against every track already in flight and open
197
197
  it only when the sets are disjoint. What thins as tracks multiply is the review
198
198
  attention each output gets, so add a track while you can still review every one
199
- properly and stop when you cannot.
199
+ properly and stop when you cannot. An operator can also cap this session's
200
+ workers by saying so, and a spoken cap binds for that session rather than
201
+ standing as a number in a file.
202
+
203
+ Serialize any track that touches a shared wiring seam with another in flight, and
204
+ serialize one whose sets are disjoint when a stated reason still puts it behind
205
+ another, since two tracks interact in ways no file-set comparison reads. One
206
+ building a skill and one auditing that catalog write nothing in common and the
207
+ audit still counts a denominator the other is moving.
200
208
 
201
- Serialize any track that touches a shared wiring seam with another in flight.
202
209
  Merge the branch with the smallest shared-file footprint first, and merge a
203
210
  branch touching `CLAUDE.md`, a Claude context entry, or a regenerated `index.md`
204
211
  last. Have every sibling rebase on the new `main` before the next merge. Two
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  title: Orchestrator dispatch runbook
3
- description: The collision check before a self-dispatch, the worker cap, the branch and model the launch names, and the loop's stopping condition
3
+ description: The collision check before a self-dispatch, the file-set disjointness gate, the branch and model the launch names, and the loop's stopping condition
4
4
  ---
5
5
 
6
- Run this at loop step 4, for a `## Run now` row whose plan is verified and whose file set has already cleared the Parallelism test against every track in flight, in place of handing the worktree to a human.
6
+ Run this at loop step 4, for a `## Run now` row whose plan is verified, in place of handing the worktree to a human. The disjointness gate below is where that row's file set is tested against every track in flight.
7
7
 
8
8
  ## Derive the candidate
9
9
 
@@ -16,7 +16,7 @@ This is the branch the worker takes, not a guess at one it will derive for itsel
16
16
  Run `aitk sessions list --branch <type>/<slug> --json` and read `claimed` off the record.
17
17
 
18
18
  - `claimed: true`: the row is not free. Report what holds it, `worktree` when it names a path, `sessions` when it carries a row, and `refs` when the branch already exists. Move to the next candidate rather than colliding.
19
- - `claimed: false`, `sessionsReadable: true`, and `refsReadable: true`: proceed to the cap check.
19
+ - `claimed: false`, `sessionsReadable: true`, and `refsReadable: true`: proceed to the disjointness gate.
20
20
  - `claimed: false` with either flag false, or the command refuses, or the record carries no `claimed` key (`reason` reads `no-registry` or `no-repository`): treat the candidate as unverified rather than clear. Report which reading could not be taken and fall back to the human-launch line below. Dispatching on a check that could not be read reproduces the exact collision this exists to prevent.
21
21
 
22
22
  Reading `claimed` off the record is what keeps this a check rather than a rule a session can talk itself out of. The field is already the composed answer across the worktree listing, the live session roster, and the refs that name the branch, so nothing here re-derives the OR.
@@ -31,11 +31,17 @@ A worker registers with `branch: main` and the main worktree as its `cwd` until
31
31
 
32
32
  Keep the branch of every row this pass has launched and treat a candidate matching one as claimed, without re-running the check. That closes the window for this dispatcher and only for it. A second dispatcher in another session reads git and the roster alone, sees none of this record, and can still take the same row. Say so when reporting, rather than implying the window is shut.
33
33
 
34
- ## Check the worker cap
34
+ ## Check the file sets are disjoint
35
35
 
36
- Run `aitk sessions list --json` with no `--branch`, then count entries whose `name` starts with `orchestrator-` and whose `repository` matches this run's own (`git rev-parse --path-format=absolute --git-common-dir`). An unscoped listing spans every repository on the machine, so the repository match is what keeps a busy sibling project from binding this one's cap. Every dispatch below names its session that way for exactly this count, so a worker the human launched by hand carries no such name and is never counted against it.
36
+ No count binds this. List the files the candidate's plan touches, from its `**Files to touch:**` lines, against the file set of every track already in flight, read off the Touches column of each row on the board. Dispatch when the sets are disjoint and hold the row otherwise.
37
37
 
38
- Three already out: report the cap and stop dispatching for this pass, leaving the row ready for the next one. The cap binds the self-dispatch path alone, since the evidence behind it is one task shipped once and the operator's own launches stay uncapped by count.
38
+ The board is not the whole set. A track a person launched by hand carries no row, so that column cannot see it, which is the ordinary shape whenever the operator is launching rather than dispatching. Read `aitk sessions list --json` for the branches in flight, and take the file set of any branch no row names from the plan that branch is building. A candidate cleared against the board alone is cleared against a partial reading.
39
+
40
+ Take the comparison at the file path rather than at a folder above it. `aitk tasks validate` compares path segments, and on 2026-08-28 it reported two rows as colliding on `src` where one writes `src/github.ts` and the other `src/markdown/structure.ts`. Most of the CLI sits under `src/`, so a folder-level reading fires on nearly every parallel pair and buries the one real collision that same run caught, `.claude/ARCHITECTURE.md` held by two rows. Read that verb's output as a candidate list and settle each pair by file.
41
+
42
+ Disjointness is necessary and not sufficient, so hold a candidate whose sets do not touch when a stated reason serializes it, and write the reason on the hold. One row creating a skill and another auditing that catalog and counting it write nothing in common, measured 2026-08-27, and dispatching both still leaves the audit counting a denominator that moves underneath it. Nothing verifies that a reason was written, so the rule holds only while the dispatcher applies it.
43
+
44
+ What binds past that is review attention rather than a count, and `## Parallelism` in the skill body states it along with the cap an operator can set for a session. No file here carries a number and this runbook does not either.
39
45
 
40
46
  ## Pick the model
41
47
 
@@ -49,7 +55,7 @@ Name `<model>` on the launch, and pick it against the task rather than copying w
49
55
  claude --bg --model <model> -n "orchestrator-<slug>" "Run /aitk:claude-worktree <type>/<slug>, then /aitk:claude-autoship <plan>"
50
56
  ```
51
57
 
52
- `--bg, --background` starts the session as a background agent and returns immediately, `-n, --name` sets the display name `aitk sessions list` reads back for the worker cap, and `--model` overrides the inheritance the section above measured.
58
+ `--bg, --background` starts the session as a background agent and returns immediately, `-n, --name` sets the display name that tells a self-dispatched worker from an operator's own launch in `aitk sessions list`, and `--model` overrides the inheritance the section above measured. Keep the `orchestrator-` prefix. It outlives the count it was introduced for, since the roster read still needs a way to separate the two kinds of launch.
53
59
 
54
60
  The worktree call comes first and carries the branch as its argument, which is tier 0 of `claude-worktree` Step 2 and the only tier a caller can reach. `claude-autoship` Step 0 then finds the session already in a linked worktree and continues, which is a path it already documents. The autoship call carries `<plan>`, the same file this runbook already read to derive the branch, so its Step 1 takes it as the caller-supplied plan rather than re-deriving one from the slug the worker's branch happens to carry.
55
61
 
@@ -59,7 +65,7 @@ Report the dispatch as loudly as the human-launch line it replaces: name the bra
59
65
 
60
66
  ## Fall back to the human
61
67
 
62
- Hand the row to the human-launch line in step 4 instead of dispatching when any of these hold, and name which one: the collision check refused, the cap is reached, or the row's file set failed the Parallelism test against something already out.
68
+ Hand the row to the human-launch line in step 4 instead of dispatching when any of these hold, and name which one: the collision check refused, the row's file set overlaps a track already out, or a stated reason holds the row behind one.
63
69
 
64
70
  ## Stop the loop
65
71
 
@@ -79,7 +79,9 @@ To run several worktrees as a coordinated flow rather than ad hoc, assert the or
79
79
 
80
80
  Execution order comes off `.claude/tasks/priority.md` and nothing sequences work into versions. Scope stays in `.claude/REQUIREMENTS.md` as a statement of what is wanted, and it reaches the board as discrete tasks the orchestrator orders by readiness.
81
81
 
82
- Run one orchestrator at a time. The board is gitignored, so a second session reads none of the first one's writes and the two collide on labels and archives. No fixed number caps the worker tracks underneath it. Collision between file sets is what binds, so a candidate opens only when its files are disjoint from every track in flight, and the ceiling in practice is how many outputs one session can still review properly.
82
+ Run one orchestrator at a time. The board is gitignored, so a second session reads none of the first one's writes and the two collide on labels and archives.
83
+
84
+ No fixed number caps the worker tracks underneath it. Collision between file sets is what binds, so a candidate opens only when its files are disjoint from every track in flight, compared at the file path rather than at a folder above it, and the ceiling in practice is how many outputs one session can still review properly. Disjointness is necessary and not sufficient, since two tracks interact in ways no file-set comparison reads, so a stated reason can still hold a disjoint candidate behind another. An operator caps a session's workers by saying so, and that cap binds for the session rather than standing as a number in a file.
83
85
 
84
86
  Before a handoff, the orchestrator checks the plan against the tree rather than reading it: grep each construct it names and count the sites, confirm every phase label it cites is still open, and open each file it describes. A plan goes stale from whatever merged after it was written, and reading cannot catch that.
85
87
 
@@ -37,7 +37,7 @@ and no later session recovers that vantage.
37
37
  One feature travels this path end to end.
38
38
 
39
39
  1. Orchestrator plans the next feature with `claude-feature`, writing a plan to `.claude/plans/`. Planning stays in the warm session because good planning is cross-feature. It needs the contract other features consume and the shared wiring seam. A cold session would re-derive or guess.
40
- 2. Orchestrator checks the branch is unclaimed and the worker cap has room, then dispatches a background worker with `claude --bg` against the plan, naming the branch and the model on the launch rather than leaving the worker to derive either. The branch travels as the argument to the worker's own worktree call, which is the one place the name is read rather than inferred. It falls back to naming the invocation for a human to run through `claude-worktree` and `claude-autoship` when the check refuses, the cap is reached, or the plan collides with a track already in flight. Either way, the worker enters its own worktree, builds, self-checks, opens a PR, and stops at the PR boundary.
40
+ 2. Orchestrator checks the branch is unclaimed and the plan's file set is disjoint from every track in flight, then dispatches a background worker with `claude --bg` against the plan, naming the branch and the model on the launch rather than leaving the worker to derive either. No count caps how many run at once. The branch travels as the argument to the worker's own worktree call, which is the one place the name is read rather than inferred. It falls back to naming the invocation for a human to run through `claude-worktree` and `claude-autoship` when the check refuses, the sets overlap, or a stated reason serializes the plan behind a track already in flight. Either way, the worker enters its own worktree, builds, self-checks, opens a PR, and stops at the PR boundary.
41
41
  3. Orchestrator reviews the PR with `claude-pr-review` and posts findings to it.
42
42
  4. Orchestrator tells the session holding that branch to run `claude-address-review` once the pass posted a finding at any severity, resolving the target then with `aitk sessions list --branch` and reporting the invocation for the human when no live session holds it. The worker addresses the findings, rebases onto `origin/main` when a sibling landed first and left the branch unable to merge, then pushes a follow-up. A pass carrying only minor findings dispatches too, since the grade runs low often enough that a floor at should-fix loses fixes a worker would have made. `claude-pr-review` states that threshold and the heading follows it, so an open heading is itself the signal to send.
43
43
  5. Orchestrator closes the review out with `claude-pr-review` again. The second pass reads only the commits the follow-up added, or the worker's response alone when the follow-up added none, and posts under `## Review` when it finds anything and under `## Review closed` when it finds nothing, so a reader learns from the heading whether work is still owed and takes the merge decision from the counts on the line under it. Repeat from step 4 until a pass closes the review.
@@ -147,9 +147,12 @@ before another is carried nowhere at all.
147
147
 
148
148
  ## Parallelism
149
149
 
150
- The binding constraint is the human and the shared files, not the board. Cap
151
- at two or three worker tracks and split them across the stack so they do not
152
- collide on the same files.
150
+ The binding constraint is the human and the shared files rather than the board.
151
+ No number caps worker tracks. Open one whenever its file set is disjoint from
152
+ every track already in flight, compared at the file path rather than at a folder
153
+ above it, and stop adding once you can no longer review every output properly.
154
+ Serialize a track sharing a wiring seam with another, and serialize one whose
155
+ sets are disjoint when a stated reason still puts it behind another.
153
156
 
154
157
  Unit checks run freely in many worktrees at once.
155
158
  A dev server, an end-to-end run, and a screenshot run alongside each other on a
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/aitk",
3
3
  "type": "module",
4
- "version": "3.33.1",
4
+ "version": "3.34.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {