@erclx/aitk 0.40.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/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/claude-orchestrate/REQUIREMENT.md +12 -0
- package/claude/skills/claude-orchestrate/SKILL.md +35 -2
- package/docs/agents/context-audit-checks.md +2 -0
- package/package.json +1 -1
- package/snippets/claude/orchestrator-handoff.md +37 -0
- package/src/commands/context.ts +3 -0
- package/src/context/audit.ts +31 -1
- package/standards/context.md +1 -0
|
@@ -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
|
|
@@ -19,6 +19,8 @@ It reports rather than gates, the closer call because a missing section reads mo
|
|
|
19
19
|
|
|
20
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
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
|
+
|
|
22
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.
|
|
23
25
|
|
|
24
26
|
## Bullet weight and tables
|
package/package.json
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Write the pre-compact handoff as orchestrator. Do this before a compaction, because a compaction keeps conclusions and drops the reasoning that produced them, and no other file in the repository carries that reasoning.
|
|
2
|
+
|
|
3
|
+
1. Resolve the main worktree root with `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd`. Write `.claude/tasks/session.md` under it.
|
|
4
|
+
2. Write only what a compaction destroys and no other file already carries. The board holds the ordering and what each task waits on, a task file holds its own findings, and a groundwork folder holds its track.
|
|
5
|
+
3. Use this shape:
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
---
|
|
9
|
+
title: Session map
|
|
10
|
+
description: <what the board cannot show, and the date it was written>
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Session map
|
|
14
|
+
|
|
15
|
+
<one line marking the file throwaway and naming the board as the real source>
|
|
16
|
+
|
|
17
|
+
## State
|
|
18
|
+
|
|
19
|
+
<what is clean, what is running, what is open, and any untracked file that needs committing>
|
|
20
|
+
|
|
21
|
+
## Decisions taken under delegated authority
|
|
22
|
+
|
|
23
|
+
<each decision and why it went that way, so nobody re-proposes it>
|
|
24
|
+
|
|
25
|
+
## Mistakes worth not repeating
|
|
26
|
+
|
|
27
|
+
<what went wrong and the rule it yields>
|
|
28
|
+
|
|
29
|
+
## Standing cautions
|
|
30
|
+
|
|
31
|
+
<commands that lie, tools that measure the wrong tree, and anything unbacked>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
4. Cite a commit, a task, or a file and line for every claim, so the next session can tell a read from a recall.
|
|
35
|
+
5. Overwrite the previous handoff rather than appending to it. A stale entry read as current is worse than no handoff.
|
|
36
|
+
|
|
37
|
+
Add a section only for content that fits none of the four and would otherwise be lost. Do not restate the board, and do not summarize the work that shipped, because git already carries it.
|
package/src/commands/context.ts
CHANGED
|
@@ -408,6 +408,9 @@ function reportDepth(entries: readonly EntryReport[]): void {
|
|
|
408
408
|
logInfo(
|
|
409
409
|
`Fenced blocks are excluded, and so are peer lists averaging under ${PEER_BULLET_CHECKPOINT} characters a bullet.`,
|
|
410
410
|
)
|
|
411
|
+
logInfo(
|
|
412
|
+
'A run that is entirely table rows is excluded too, since a heading inside a table splits the table rather than the run.',
|
|
413
|
+
)
|
|
411
414
|
|
|
412
415
|
const over = entries
|
|
413
416
|
.filter((entry) => entry.longestRun > RUN_CHECKPOINT)
|
package/src/context/audit.ts
CHANGED
|
@@ -231,6 +231,36 @@ function isScannablePeerList(run: readonly BodyLine[]): boolean {
|
|
|
231
231
|
return characters / items < PEER_BULLET_CHECKPOINT
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Reports whether a run is a table, the second shape the checkpoint cannot fix.
|
|
236
|
+
*
|
|
237
|
+
* The peer list above is exempt because it is already navigable. A table is
|
|
238
|
+
* exempt for the other reason: the remedy does not exist. A heading dropped
|
|
239
|
+
* inside one splits the table into two tables rather than breaking the run, so
|
|
240
|
+
* a catalog renders as an unbroken stretch by construction and no edit short of
|
|
241
|
+
* rewriting it as a list clears the report.
|
|
242
|
+
*
|
|
243
|
+
* Every non-blank line has to be a row. A run holding a table between
|
|
244
|
+
* paragraphs is genuinely mixed, and a heading breaks it at a seam either side,
|
|
245
|
+
* so testing whether the run holds a table would hide the case the checkpoint
|
|
246
|
+
* exists for.
|
|
247
|
+
*
|
|
248
|
+
* A delimiter is required rather than assumed, matching the table scan below. A
|
|
249
|
+
* stack of lines opening with a pipe and no delimiter renders as paragraph text
|
|
250
|
+
* and would otherwise earn the exemption on its punctuation.
|
|
251
|
+
*/
|
|
252
|
+
function isTableRun(run: readonly BodyLine[]): boolean {
|
|
253
|
+
let separators = 0
|
|
254
|
+
|
|
255
|
+
for (const line of run) {
|
|
256
|
+
if (line.text.trim() === '') continue
|
|
257
|
+
if (!TABLE_ROW.test(line.text)) return false
|
|
258
|
+
if (TABLE_SEPARATOR.test(line.text)) separators++
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return separators > 0
|
|
262
|
+
}
|
|
263
|
+
|
|
234
264
|
/**
|
|
235
265
|
* Height a source line occupies once wrapped.
|
|
236
266
|
*
|
|
@@ -272,7 +302,7 @@ function longestRun(lines: readonly BodyLine[]): {
|
|
|
272
302
|
// two headings rather than a stretch a reader travels, so it never counts.
|
|
273
303
|
const first = run.find((line) => line.text.trim() !== '')
|
|
274
304
|
|
|
275
|
-
if (first && !isScannablePeerList(run)) {
|
|
305
|
+
if (first && !isScannablePeerList(run) && !isTableRun(run)) {
|
|
276
306
|
const height = run.reduce(
|
|
277
307
|
(sum, line) => sum + renderedHeight(line.text),
|
|
278
308
|
0,
|
package/standards/context.md
CHANGED
|
@@ -104,6 +104,7 @@ Only the `development` entry carries this section. It is not a general-purpose h
|
|
|
104
104
|
- Past roughly 40 rendered lines with no heading of any level breaking them, add a subheading at the seam. Measure the longest such run rather than everything under one `##`, and exclude fenced code blocks. The number is a checkpoint like the 150 above, not a cap.
|
|
105
105
|
- Both checkpoints count rendered lines, so wrap each source line at 80 columns and sum the heights. Source lines undercount an entry authored one line per bullet, where a block of fifteen paragraph-bullets occupies fifteen lines and renders past sixty. Counting the two checkpoints in different units would put a file measured one way beside a run measured another.
|
|
106
106
|
- Exempt a block whose lines are all list items at one level averaging under roughly 130 characters. A flat list of short peers is already navigable, and a subheading dropped into it splits a set that belongs together. Bullet count says nothing on its own, since a catalog of one-liners and a stack of paragraphs reach the same count and read nothing alike, so weight is what decides. Mixing prose with the list, or nesting levels inside it, ends the exemption at any weight.
|
|
107
|
+
- Exempt a block whose lines are all table rows, at any length. The peer list above is exempt because it is already navigable, and a table because the remedy does not exist: a subheading dropped inside one splits the table rather than the run, so no edit short of rewriting it as a list clears the checkpoint. Prose either side of the table ends the exemption, since that block has a seam and a heading breaks it there.
|
|
107
108
|
- Past roughly 400 characters in one top-level bullet, counting the lines that continue it and excluding any bullet nested under it, check whether the incident that motivated the decision sits beside the decision itself. Keep the current design and the alternative that lost, and move the incident to the change that introduced it, the issue that tracked it, or the research record behind it. The number is a checkpoint like the two above, and a bullet reading well past it means the number is wrong rather than the rule.
|
|
108
109
|
- Collapse a stack of bullets narrating one subsystem into a single `###` subsection carrying one narrative. Splitting a heavy bullet into three light ones satisfies the checkpoint above and leaves the reader no better off, and subdividing a block does not lighten the bullets inside it, so the two rules answer different defects.
|
|
109
110
|
- Never cut a `## Decisions` or `## Gotchas` entry to shorten a file. Cut a `## Layout` or `## CLI` section instead.
|