@erclx/canon 4.67.0 → 4.69.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-autoship → auto-ship}/REQUIREMENT.md +3 -3
- package/claude/skills/{claude-autoship → auto-ship}/SKILL.md +36 -36
- package/claude/skills/canon-cli/REQUIREMENT.md +2 -2
- package/claude/skills/canon-cli/SKILL.md +2 -2
- package/claude/skills/canon-feedback-triage/REQUIREMENT.md +1 -1
- package/claude/skills/canon-feedback-triage/SKILL.md +3 -3
- package/claude/skills/canon-operator/REQUIREMENT.md +1 -1
- package/claude/skills/canon-operator/SKILL.md +4 -4
- package/claude/skills/canon-rollout/REQUIREMENT.md +6 -6
- package/claude/skills/canon-rollout/SKILL.md +7 -7
- package/claude/skills/{claude-design-extract → design-extract}/REQUIREMENT.md +4 -4
- package/claude/skills/{claude-design-extract → design-extract}/SKILL.md +1 -1
- package/claude/skills/{claude-docs → docs-fold}/REQUIREMENT.md +3 -3
- package/claude/skills/{claude-docs → docs-fold}/SKILL.md +14 -14
- package/claude/skills/{claude-docs → docs-fold}/references/anchor-sweep.md +1 -1
- package/claude/skills/{claude-docs → docs-fold}/references/wireframe-sweep.md +1 -1
- package/claude/skills/docs-sync/REQUIREMENT.md +3 -3
- package/claude/skills/docs-sync/SKILL.md +1 -1
- package/claude/skills/draft-and-pick/REQUIREMENT.md +4 -4
- package/claude/skills/draft-and-pick/SKILL.md +6 -6
- package/claude/skills/draft-context/REQUIREMENT.md +2 -2
- package/claude/skills/draft-context/SKILL.md +3 -3
- package/claude/skills/{claude-diagram → draft-diagram}/REQUIREMENT.md +4 -4
- package/claude/skills/{claude-diagram → draft-diagram}/SKILL.md +3 -3
- package/claude/skills/draft-docs/REQUIREMENT.md +1 -1
- package/claude/skills/draft-wireframes/REQUIREMENT.md +1 -1
- package/claude/skills/draft-wireframes/SKILL.md +2 -2
- package/claude/skills/git-followup/REQUIREMENT.md +1 -1
- package/claude/skills/git-followup/SKILL.md +1 -1
- package/claude/skills/git-pr/SKILL.md +3 -3
- package/claude/skills/git-ship/REQUIREMENT.md +2 -2
- package/claude/skills/git-ship/SKILL.md +8 -8
- package/claude/skills/git-worktree/REQUIREMENT.md +2 -2
- package/claude/skills/git-worktree/SKILL.md +3 -3
- package/claude/skills/identity/REQUIREMENT.md +2 -2
- package/claude/skills/identity/SKILL.md +3 -3
- package/claude/skills/{claude-markdown-propose → markdown-propose}/REQUIREMENT.md +8 -8
- package/claude/skills/{claude-markdown-propose → markdown-propose}/SKILL.md +5 -5
- package/claude/skills/{claude-markdown-propose → markdown-propose}/references/format.md +1 -1
- package/claude/skills/{claude-memory-capture → memory-capture}/REQUIREMENT.md +5 -5
- package/claude/skills/{claude-memory-capture → memory-capture}/SKILL.md +13 -13
- package/claude/skills/{claude-memory-review → memory-review}/REQUIREMENT.md +4 -4
- package/claude/skills/{claude-memory-review → memory-review}/SKILL.md +10 -10
- package/claude/skills/migration-context/SKILL.md +1 -1
- package/claude/skills/migration-standards-drop/REQUIREMENT.md +1 -1
- package/claude/skills/migration-superseded/REQUIREMENT.md +1 -1
- package/claude/skills/{claude-feature → plan-feature}/REQUIREMENT.md +4 -4
- package/claude/skills/{claude-feature → plan-feature}/SKILL.md +4 -4
- package/claude/skills/{claude-groundwork → plan-groundwork}/REQUIREMENT.md +5 -5
- package/claude/skills/{claude-groundwork → plan-groundwork}/SKILL.md +8 -8
- package/claude/skills/{claude-intake → plan-intake}/REQUIREMENT.md +6 -6
- package/claude/skills/{claude-intake → plan-intake}/SKILL.md +10 -10
- package/claude/skills/{claude-intake-answer → plan-intake-answer}/REQUIREMENT.md +4 -4
- package/claude/skills/{claude-intake-answer → plan-intake-answer}/SKILL.md +5 -5
- package/claude/skills/{claude-address-review → review-address}/REQUIREMENT.md +5 -5
- package/claude/skills/{claude-address-review → review-address}/SKILL.md +6 -6
- package/claude/skills/{claude-address-review → review-address}/references/rebase-conflicts.md +1 -1
- package/claude/skills/{claude-review → review-branch}/REQUIREMENT.md +4 -4
- package/claude/skills/{claude-review → review-branch}/SKILL.md +4 -4
- package/claude/skills/{claude-pr-review → review-pr}/REQUIREMENT.md +5 -5
- package/claude/skills/{claude-pr-review → review-pr}/SKILL.md +11 -11
- package/claude/skills/{claude-orchestrate → role-orchestrator}/REQUIREMENT.md +5 -5
- package/claude/skills/{claude-orchestrate → role-orchestrator}/SKILL.md +20 -20
- package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-dispatch.md +30 -30
- package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-handoff.md +2 -2
- package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-parked.md +8 -8
- package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-poll.md +8 -8
- package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-resume.md +1 -1
- package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-sweep.md +1 -1
- package/claude/skills/{claude-orchestrate → role-orchestrator}/scripts/poll.sh +6 -6
- package/claude/skills/{claude-planner → role-planner}/REQUIREMENT.md +12 -12
- package/claude/skills/{claude-planner → role-planner}/SKILL.md +4 -4
- package/claude/skills/{claude-worker → role-worker}/REQUIREMENT.md +8 -8
- package/claude/skills/{claude-worker → role-worker}/SKILL.md +6 -6
- package/claude/skills/{claude-seed-sync → seed-sync}/REQUIREMENT.md +2 -2
- package/claude/skills/{claude-seed-sync → seed-sync}/SKILL.md +3 -3
- package/claude/skills/session-map/REQUIREMENT.md +2 -2
- package/claude/skills/session-map/SKILL.md +2 -2
- package/claude/skills/session-resume/REQUIREMENT.md +2 -2
- package/claude/skills/session-resume/SKILL.md +2 -2
- package/claude/skills/{claude-worktree → session-worktree}/REQUIREMENT.md +3 -3
- package/claude/skills/{claude-worktree → session-worktree}/SKILL.md +6 -6
- package/claude/skills/setup-plugins/references/plugin-catalog.md +1 -1
- package/claude/skills/{claude-standards-audit → standards-audit}/REQUIREMENT.md +2 -2
- package/claude/skills/{claude-standards-audit → standards-audit}/SKILL.md +2 -2
- package/claude/skills/systematic-debugging/REQUIREMENT.md +1 -1
- package/claude/skills/{claude-tasks → task-board}/REQUIREMENT.md +3 -3
- package/claude/skills/{claude-tasks → task-board}/SKILL.md +7 -7
- package/claude/skills/{claude-teach → teach-workspace}/REQUIREMENT.md +2 -2
- package/claude/skills/{claude-teach → teach-workspace}/SKILL.md +4 -4
- package/claude/skills/test-first/REQUIREMENT.md +2 -2
- package/claude/skills/{claude-ui-test → ui-test}/REQUIREMENT.md +3 -3
- package/claude/skills/{claude-ui-test → ui-test}/SKILL.md +3 -3
- package/claude/skills/{claude-ux-audit → ux-audit}/REQUIREMENT.md +6 -6
- package/claude/skills/{claude-ux-audit → ux-audit}/SKILL.md +5 -5
- package/claude/skills/{claude-ux-measure → ux-measure}/REQUIREMENT.md +5 -5
- package/claude/skills/{claude-ux-measure → ux-measure}/SKILL.md +5 -5
- package/docs/agents/commands.md +1 -0
- package/docs/agents/install-and-sync.md +1 -1
- package/docs/agents/key-changes.md +3 -3
- package/docs/agents/markdown-audit.md +1 -1
- package/docs/agents/restated.md +1 -1
- package/docs/agents/review-classification.md +1 -1
- package/docs/agents/sandbox.md +13 -10
- package/docs/agents/sessions.md +1 -1
- package/docs/agents/state-scoped-risk.md +1 -1
- package/docs/agents/targets.md +1 -1
- package/docs/agents/tasks.md +4 -4
- package/docs/agents/teach.md +1 -1
- package/docs/target-projects.md +10 -10
- package/docs/workflow/ai-workflow.md +84 -84
- package/docs/workflow/operating-model.md +17 -17
- package/docs/workflow/visual-design-workflow.md +6 -6
- package/governance/rules/core/045-memory.md +1 -1
- package/governance/rules/core/085-worktrees.md +1 -1
- package/package.json +1 -1
- package/scripts/core/regen-agent-fixture.sh +1 -1
- package/scripts/core/regen-hero.sh +7 -7
- package/scripts/lib/sandbox-dispatch.sh +8 -0
- package/snippets/claude/decision-memo.md +1 -1
- package/src/autoship/paths.ts +1 -1
- package/src/claude/cases/all.ts +2 -2
- package/src/claude/cases/{claude-workflow.ts → workflow.ts} +33 -33
- package/src/claude/plugin-update.ts +48 -0
- package/src/commands/claude.ts +281 -1
- package/src/commands/feedback.ts +15 -5
- package/src/commands/gate.ts +3 -1
- package/src/commands/sandbox.ts +13 -4
- package/src/commands/sync.ts +3 -3
- package/src/design/components.ts +12 -0
- package/src/design/tokens.ts +1 -1
- package/src/gate/measures.ts +47 -1
- package/src/gov/restated.ts +2 -2
- package/src/markdown/structure.ts +1 -1
- package/src/migrate/rename.ts +4 -3
- package/src/pr/bijection.ts +1 -1
- package/src/pr/paths.ts +2 -2
- package/src/sandbox/expect.ts +26 -1
- package/src/shipped/references.ts +1 -1
- package/src/sync/seeds-report.ts +1 -1
- package/src/targets/pulls.ts +2 -2
- package/src/tasks/answers.ts +1 -1
- package/src/tasks/archive.ts +4 -4
- package/src/tasks/record.ts +2 -2
- package/src/tasks/validate.ts +1 -1
- package/src/teach/nav.ts +97 -3
- package/standards/glossary.md +8 -0
- package/standards/groundwork.md +1 -1
- package/standards/snippets.md +1 -1
- package/standards/tasks.md +3 -3
- package/standards/teach.md +2 -2
- package/tooling/base/configs/.husky/post-merge +3 -3
- package/tooling/claude/reference.md +5 -5
- package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +2 -2
- /package/claude/skills/{claude-memory-review → memory-review}/references/receipt-format.md +0 -0
- /package/claude/skills/{claude-orchestrate → role-orchestrator}/scripts/watch.sh +0 -0
- /package/claude/skills/{claude-teach → teach-workspace}/references/lesson-craft.md +0 -0
- /package/claude/skills/{claude-teach → teach-workspace}/references/pedagogy.md +0 -0
- /package/claude/skills/{claude-teach → teach-workspace}/references/promotion.md +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Reviews an open pull request from an independent session and posts findings as a review comment on the PR. Posts a first pass against the whole change and every later pass against only the commits added since, under `## Review` while any finding is open and `## Review closed` once a pass carries none. Reads project docs and the task board for cross-feature context a self-review lacks. Use when asked to "review the PR", "review this feature's PR", "post a PR review", "re-review the PR", "close out the review", "confirm the findings are fixed", or acting as the orchestrator reviewing a worker's PR. Do NOT use to review local uncommitted changes. That is `
|
|
2
|
+
name: review-pr
|
|
3
|
+
description: Reviews an open pull request from an independent session and posts findings as a review comment on the PR. Posts a first pass against the whole change and every later pass against only the commits added since, under `## Review` while any finding is open and `## Review closed` once a pass carries none. Reads project docs and the task board for cross-feature context a self-review lacks. Use when asked to "review the PR", "review this feature's PR", "post a PR review", "re-review the PR", "close out the review", "confirm the findings are fixed", or acting as the orchestrator reviewing a worker's PR. Do NOT use to review local uncommitted changes. That is `review-branch`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Review PR
|
|
7
7
|
|
|
8
|
-
This is the orchestrator's independent review, distinct from `
|
|
9
|
-
`
|
|
8
|
+
This is the orchestrator's independent review, distinct from `review-branch`.
|
|
9
|
+
`review-branch` reviews local changes for the session that wrote them and writes
|
|
10
10
|
to disk. This one reviews an open PR the session did not write and posts the
|
|
11
11
|
findings to the PR, so the vantage is independent and the output is durable.
|
|
12
12
|
|
|
@@ -24,7 +24,7 @@ reader scanning the thread finds the current verdict where the last one sat.
|
|
|
24
24
|
|
|
25
25
|
## Guards
|
|
26
26
|
|
|
27
|
-
- If no open PR resolves for the target branch via `gh pr view`, stop: `❌ No open PR to review. Open one first, or use /
|
|
27
|
+
- If no open PR resolves for the target branch via `gh pr view`, stop: `❌ No open PR to review. Open one first, or use /review-branch for local changes.`
|
|
28
28
|
- Review and post. Do not merge. Merging is the human's gate.
|
|
29
29
|
|
|
30
30
|
## Step 1: resolve the PR and read context
|
|
@@ -36,7 +36,7 @@ Read these in parallel from the project root, skipping any that do not exist:
|
|
|
36
36
|
- `CLAUDE.md`: project type, conventions, and commands
|
|
37
37
|
- `.claude/REQUIREMENTS.md`: feature scope and non-goals
|
|
38
38
|
- `.claude/ARCHITECTURE.md`: technical design decisions
|
|
39
|
-
- `.canon/tasks/priority.md`: where this feature sits on the board and what each neighboring row waits on. Resolve this one at the main worktree root the way `
|
|
39
|
+
- `.canon/tasks/priority.md`: where this feature sits on the board and what each neighboring row waits on. Resolve this one at the main worktree root the way `session-worktree` does, since the board is gitignored and a linked worktree holds no copy of it
|
|
40
40
|
- `.canon/plans/feature-<slug>.md` for the branch, when present: the intent the PR should satisfy
|
|
41
41
|
|
|
42
42
|
Coding standards from `.claude/rules/` are auto-loaded by Claude Code.
|
|
@@ -105,7 +105,7 @@ Read each changed file in scope. Skip deleted files. Run reads in parallel.
|
|
|
105
105
|
|
|
106
106
|
## Step 3: review
|
|
107
107
|
|
|
108
|
-
Review the diff and files for the same axes as `
|
|
108
|
+
Review the diff and files for the same axes as `review-branch` (bugs, edge cases, error handling, logic flaws, security, rule violations, checkout assumptions in a shipped file), then add the three lenses a self-review structurally cannot apply:
|
|
109
109
|
|
|
110
110
|
- Integration: does this fit the board's order, the shared wiring seam, and any sibling PR in flight?
|
|
111
111
|
- Contract: does a contract downstream features depend on land correctly, and should the plan itself be questioned?
|
|
@@ -141,7 +141,7 @@ Use severity: `critical` (blocks merge), `should-fix` (fix before merge), `minor
|
|
|
141
141
|
|
|
142
142
|
## Step 4: post to the PR
|
|
143
143
|
|
|
144
|
-
Write the comment to `.canon/tmp/pr-review/body-<number>-<short-sha>.md` at the main worktree root, not the current worktree, which the rest of this step calls `<body-file>`. Resolve that root the way `
|
|
144
|
+
Write the comment to `.canon/tmp/pr-review/body-<number>-<short-sha>.md` at the main worktree root, not the current worktree, which the rest of this step calls `<body-file>`. Resolve that root the way `session-worktree` does, and send the write as a plain single `Bash` command carrying a heredoc from a linked worktree, since `Edit` and `Write` refuse a main-root path there. The PR number stops two sessions reviewing different pull requests from overwriting each other between the write and the post, and the head commit stops a second pass overwriting the first one's body, leaving the folder a record of which commit each review covered.
|
|
145
145
|
|
|
146
146
|
Derive both segments from Step 1. Never pick a suffix by hand, and never reuse a name the folder already holds.
|
|
147
147
|
|
|
@@ -204,7 +204,7 @@ An unanswered bullet is owed the same way an unanswered Testing box is, so a pas
|
|
|
204
204
|
- Confirm the 401 and 403 split reads correctly for the public API. Confirmed — `AuthService.authenticate()` returns 401 for an expired token and 403 for a missing scope, and both paths are covered under `## Testing`.
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
The threshold is stated here and nowhere else, and every other surface acting on it cites this skill rather than restating the grades. One rule governs both the heading and the dispatch: a pass carrying anything owed takes `## Review` and owes a dispatch to the session holding the branch, and a pass carrying nothing at all takes `## Review closed` and owes none. Owed covers a finding at any severity, a Testing question, and a reviewer request nobody has answered alike, which is what keeps the two halves from separating. Sending that dispatch is `
|
|
207
|
+
The threshold is stated here and nowhere else, and every other surface acting on it cites this skill rather than restating the grades. One rule governs both the heading and the dispatch: a pass carrying anything owed takes `## Review` and owes a dispatch to the session holding the branch, and a pass carrying nothing at all takes `## Review closed` and owes none. Owed covers a finding at any severity, a Testing question, and a reviewer request nobody has answered alike, which is what keeps the two halves from separating. Sending that dispatch is `role-orchestrator`'s step rather than this one, which posts and stops. Post the open heading whether it is the first pass or the fourth. A pull request thread then reads as `## Review`, the worker's answer under `## Review response` from `review-address`, another `## Review` while anything stays open, and `## Review closed` when nothing does.
|
|
208
208
|
|
|
209
209
|
Keying either half on the grade was measured wrong: across 8 findings on one archived pass, 3 were posted as minor and 2 of those were defects a worker fixed rather than recorded, so a floor at should-fix loses real fixes to a grade that runs low. Splitting the two halves so the dispatch fired lower than the heading was the other candidate, and it left a thread reading closed while work was owed on it. The Testing question was first written to sit outside both, which is that same split reached from the other side, and it left the one party who could answer the question with no route to it.
|
|
210
210
|
|
|
@@ -214,7 +214,7 @@ A minor the dispatched worker declines is what needs a surface that survives the
|
|
|
214
214
|
|
|
215
215
|
Read the state off the most recent review comment rather than off the presence of a closed one. A close-out does not close the pull request, so a commit pushed after it gets its own pass, and that pass reopens the review under `## Review` when it raises a finding of any grade.
|
|
216
216
|
|
|
217
|
-
Both of this skill's headings anchor as a section distinct from human threads, and neither invents beyond what the whole set already states. That set is five headings across two families, stated here once so `
|
|
217
|
+
Both of this skill's headings anchor as a section distinct from human threads, and neither invents beyond what the whole set already states. That set is five headings across two families, stated here once so `role-orchestrator`'s poll and every reply-posting skill cite it rather than carry a copy. The review family, `## Review` and `## Review closed`, belongs to this skill alone, and the reply family, `## Review response`, `## Rebase`, and `## Post-review findings`, belongs to `review-address`.
|
|
218
218
|
|
|
219
219
|
The first reply heading answers a finding this skill posted, the second reports a stale branch resolved without one, and the third carries a finding a worker produces after a close-out rather than in answer to one already on the thread, since a finding produced late is still a finding. A comment posted under a heading outside these five reaches the poll as unclassified rather than as silence, so an invented sixth heading is a gap the next run reports instead of one it repeats. Do not append the PR number, which GitHub already renders above the comment.
|
|
220
220
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: role-orchestrator
|
|
3
3
|
description: What the one warm control session owns, why it plans and reviews without building or merging, and the collision rule that binds parallelism
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Role orchestrator requirement
|
|
7
7
|
|
|
8
8
|
## Gap
|
|
9
9
|
|
|
@@ -116,8 +116,8 @@ The session also records nothing of what it learns. Both other callers of memory
|
|
|
116
116
|
|
|
117
117
|
## Out of scope
|
|
118
118
|
|
|
119
|
-
- Writing the plan itself, which `
|
|
120
|
-
- Reviewing a worker's pull request, which `
|
|
119
|
+
- Writing the plan itself, which `plan-feature` owns and this session runs rather than reimplements
|
|
120
|
+
- Reviewing a worker's pull request, which `review-pr` owns
|
|
121
121
|
- Entering the worktree a build runs in, which the worker opens for itself whether a human launched it or this session dispatched it
|
|
122
|
-
- The worker's half of the channel and the boundaries a building session holds, which `
|
|
122
|
+
- The worker's half of the channel and the boundaries a building session holds, which `role-worker` states where that session reads them
|
|
123
123
|
- The operating model this enacts, which the toolkit's own docs hold
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: role-orchestrator
|
|
3
3
|
description: Asserts the orchestrator role for the current session, holds the build loop and the queue-refill sweep, and dispatches to the feature, review, and worktree skills. Use when asked to "be the orchestrator", "run the orchestrator", "orchestrate this project", or to set up the control session for parallel feature builds. Do NOT build features or merge PRs in this session.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# Role orchestrator
|
|
8
8
|
|
|
9
9
|
This session is the orchestrator: the one warm session that holds the
|
|
10
10
|
cross-feature picture. It plans and reviews.
|
|
@@ -23,7 +23,7 @@ session's review are different passes, and how a feature is sized.
|
|
|
23
23
|
|
|
24
24
|
## On invocation
|
|
25
25
|
|
|
26
|
-
Read the board in parallel, resolving the paths at the main worktree root the way `
|
|
26
|
+
Read the board in parallel, resolving the paths at the main worktree root the way `session-worktree` does:
|
|
27
27
|
|
|
28
28
|
- `.canon/tasks/priority.md`: execution order and what each task is waiting on
|
|
29
29
|
- `.canon/tasks/backlog.md`: what is not being scheduled, when the file exists
|
|
@@ -49,7 +49,7 @@ The review trigger takes the same shape. `references/orchestrator-poll.md` holds
|
|
|
49
49
|
|
|
50
50
|
A board that is not moving is a third such moment. On a request to re-test the parked rows, read `${CLAUDE_SKILL_DIR}/references/orchestrator-parked.md` and follow it. It re-tests every `## Up next` and `## Needs a plan` blocker against the current tree, walks `backlog.md` on the same pass, writes what each test showed into the row, and plans what it clears. Its trigger is the inverse of the refill sweep's below, which fires on a merge and asks what to promote next rather than whether a row already parked is still parked for a reason.
|
|
51
51
|
|
|
52
|
-
That routing lives in this body and this skill is user-invoked, so a session that has dropped the body routes nothing and the request lands as ordinary conversation. Approaching a compaction is when a long session is likeliest to have dropped it, which is the same moment the handoff exists for. Re-invoke `/canon:
|
|
52
|
+
That routing lives in this body and this skill is user-invoked, so a session that has dropped the body routes nothing and the request lands as ordinary conversation. Approaching a compaction is when a long session is likeliest to have dropped it, which is the same moment the handoff exists for. Re-invoke `/canon:role-orchestrator` first whenever the session has run long or the ask goes unanswered. The three runbooks sit at `references/orchestrator-handoff.md`, `references/orchestrator-resume.md`, and `references/orchestrator-parked.md` inside this skill's own folder, so a person who knows their plugin root opens any one of them directly and follows it without this skill loaded at all.
|
|
53
53
|
|
|
54
54
|
## Output
|
|
55
55
|
|
|
@@ -60,11 +60,11 @@ Ready to build (hand each to its own worker):
|
|
|
60
60
|
|
|
61
61
|
<feature>
|
|
62
62
|
plan: .canon/plans/feature-<slug>.md
|
|
63
|
-
→ /
|
|
63
|
+
→ /auto-ship
|
|
64
64
|
|
|
65
65
|
<feature>
|
|
66
66
|
no plan yet. A handoff without a plan has no scope
|
|
67
|
-
→ /
|
|
67
|
+
→ /plan-feature here first
|
|
68
68
|
|
|
69
69
|
In flight (this session's workers, building now):
|
|
70
70
|
|
|
@@ -74,7 +74,7 @@ In flight (this session's workers, building now):
|
|
|
74
74
|
In review (your turn):
|
|
75
75
|
|
|
76
76
|
PR #<n> <title>
|
|
77
|
-
→ /
|
|
77
|
+
→ /review-pr
|
|
78
78
|
|
|
79
79
|
Merge order: #<a> before #<b> (shared seam: <files>).
|
|
80
80
|
|
|
@@ -108,14 +108,14 @@ Write no shape for a correction. A correction is a sentence, and a format for ad
|
|
|
108
108
|
|
|
109
109
|
## The loop
|
|
110
110
|
|
|
111
|
-
1. Plan the next feature. The cross-feature call stays in this warm session, being which rows collide, what merges before what, and whether a row should run at all. Per-row planning runs either way: `
|
|
111
|
+
1. Plan the next feature. The cross-feature call stays in this warm session, being which rows collide, what merges before what, and whether a row should run at all. Per-row planning runs either way: `plan-feature` here with that context, or a cold planner dispatched under `role-planner` through the planning shape in `${CLAUDE_SKILL_DIR}/references/orchestrator-dispatch.md`. Every plan written from here also carries a constraint per track in flight, which the paragraph below this list states.
|
|
112
112
|
2. Decide parallelism and merge order. Note which plans touch a shared wiring seam so their PRs merge in sequence, not at once.
|
|
113
113
|
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.
|
|
114
114
|
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.
|
|
115
|
-
5. Review the PR. When a worker opens a PR, run `
|
|
115
|
+
5. Review the PR. When a worker opens a PR, run `review-pr` to post findings to it. This is the deep, independent pass. The worker's autoship self-review was only the green gate.
|
|
116
116
|
- Learning that a PR moved is the mechanical half, so read `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` and run the poll under the condition it states rather than checking the board by hand. That runbook holds the routing and the trigger, and a summary of it here is a second source that drifts from it.
|
|
117
|
-
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 `
|
|
118
|
-
- Read the threshold off `
|
|
117
|
+
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 `review-address`, rather than waiting for a person to relay it. Re-review when the worker's own message says the address pass finished, per the channel `role-worker` states, rather than polling for an answer nothing else marks as landed. Then the human merges. Tell the trailing worker to rebase when its branch shares a seam with the merged one.
|
|
118
|
+
- Read the threshold off `review-pr`, which states it once and governs the heading with it, so an open heading and an owed dispatch answer the same question and either one is enough to send
|
|
119
119
|
- Resolve the target at the moment of sending with `canon sessions list --branch`, never from a mapping written down earlier, since names rotate as sessions end and one recorded earlier in a session has failed inside the hour. The runbook read at step 5 routes on the count and the confidence it answers with
|
|
120
120
|
- Open the message with the worktree and branch the sender believes the reader holds, asking to be corrected, whenever that mapping is inferred rather than confirmed
|
|
121
121
|
- Name the skill for the reader to run rather than writing an invocation, which arrives as text
|
|
@@ -125,9 +125,9 @@ A session is reachable when it appears in a live listing, which reads what each
|
|
|
125
125
|
|
|
126
126
|
The channel runs both ways and the return leg carries what the pull request cannot. A worker answering a posted finding by naming the plan question that had already declined it changes the outcome in the moment, where a thread comment waits on whoever reads it next. Read what a worker volunteers as part of the review rather than as an aside, and read a refusal the same way, since the corrections that landed on this session's model of the world arrived as a worker arguing back rather than complying.
|
|
127
127
|
|
|
128
|
-
What the worker owes on its own side is stated in the `
|
|
128
|
+
What the worker owes on its own side is stated in the `role-worker` skill that session loads, being the pull-request announcement, the message a block goes out as before it becomes a prompt, and the ban on writing the board. Do not restate any of it here. This half held the only written copy of a channel that runs both ways, which put every obligation on the side that does not perform it.
|
|
129
129
|
|
|
130
|
-
What arrives there does not become a record by being read, so place it by what it changes. An answer that settles a finding goes onto the pull request through the next pass, which withdraws or regrades that finding and names the fact behind it, per `
|
|
130
|
+
What arrives there does not become a record by being read, so place it by what it changes. An answer that settles a finding goes onto the pull request through the next pass, which withdraws or regrades that finding and names the fact behind it, per `review-pr`. An answer that changes what this session believes about the world instead, which is a mapping correction or a constraint on what a worker can do, settles no finding and reaches no thread, so route it the way Boundaries below routes a change found while orchestrating, which lands it on the task owning the surface it describes. Writing a tracked file to hold either is forbidden here, which leaves the pull request and the board as the two surfaces this session writes.
|
|
131
131
|
|
|
132
132
|
Step 1 splits a rule that used to hold every plan in this session, and the evidence narrows it rather than retiring it. Two trials on 2026-08-31 put a cold planner on four rows, and it reported ten things the task files got wrong, corrected this session's own premise twice, and overturned one row's closing conclusion. What that measures is finding quality. The rule's own claim is that a warm plan front-loads reasoning a cold worker would otherwise re-derive, which is a statement about a plan's downstream value, and no plan from either trial has been built. So the per-row measurement goes cold on the evidence and the cross-feature call stays here on the boundary the same trials confirmed, which is that a planner reading the board sees blockers and file sets and can write a confident merge order off a partial picture.
|
|
133
133
|
|
|
@@ -145,9 +145,9 @@ Stamp the block with the commit this session read the tree at, which the same se
|
|
|
145
145
|
- Do not edit tracked files from this session, at any size. The boundary offers no proportionality exception and nothing enforces it.
|
|
146
146
|
- 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.
|
|
147
147
|
|
|
148
|
-
The tracked-file boundary collides with `CLAUDE.md`, which says to handle a small edit immediately without a task entry, and this rule wins wherever the two meet. A session that writes a change cannot review it independently afterwards and no later session recovers that vantage, which is the separation `
|
|
148
|
+
The tracked-file boundary collides with `CLAUDE.md`, which says to handle a small edit immediately without a task entry, and this rule wins wherever the two meet. A session that writes a change cannot review it independently afterwards and no later session recovers that vantage, which is the separation `review-pr` exists to supply.
|
|
149
149
|
|
|
150
|
-
Record a change identified while orchestrating against the task that owns it, fold one no task owns into the next task touching the same surface, and file a task only when no such task exists or is expected. Run `
|
|
150
|
+
Record a change identified while orchestrating against the task that owns it, fold one no task owns into the next task touching the same surface, and file a task only when no such task exists or is expected. Run `review-branch` when the boundary is crossed anyway, since a branch-diff pass is not independent and is the only check a self-authored change can get.
|
|
151
151
|
|
|
152
152
|
Filing a row states the defect and the surface it was seen on, and stops there. The extent and the cause belong to whoever plans it, so a row names neither a count of how far the defect reaches nor the mechanism behind it. Say in a plain sentence in the task file that the count was not taken, where the row's shape invites one, rather than in a marker of any prescribed form. The board's own cell has no room for it, since `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` caps a `Waiting on` cell at two clauses.
|
|
153
153
|
|
|
@@ -170,14 +170,14 @@ It counts unclaimed plans against workers rather than reading the reserve in ste
|
|
|
170
170
|
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.
|
|
171
171
|
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.
|
|
172
172
|
3. Archive what closed.
|
|
173
|
-
- A task whose outcomes are all `[x]` runs `
|
|
173
|
+
- A task whose outcomes are all `[x]` runs `docs-fold` for the plan sweep, then `task-board` to archive
|
|
174
174
|
- A task whose outcomes describe standing policy rather than a deliverable never closes on its own, so hand it to a worker to encode the policy where it is enforced, then cut the outcomes with the reason recorded and archive once that branch merges. Encoding it from this session would write a tracked file, which Boundaries forbids.
|
|
175
175
|
4. Read `.canon/tasks/priority.md` and count entries under its `## Run now` heading that carry a written plan. Keep one in reserve beyond what is running.
|
|
176
176
|
5. Promote from the top of `## Needs a plan`, which is where the last sweep recorded what to plan next. Depart from that order when something has changed under it and say what changed, since a position nobody honors is the ordering going stale on the surface built to hold it. What sets the order in the first place is whether a task establishes functionality rather than how old it is, so prefer a task that adds or proves a mechanism over one that trims, tidies, or audits an existing surface.
|
|
177
177
|
- Re-take the demotion half of the board-or-backlog call while the file is open. A row that has stopped being near-term moves to `backlog.md`, one line removed from `priority.md` and written there, per the standard's test. The promotion half is `references/orchestrator-parked.md`'s to run as a full walk over every backlog row, so this step does not repeat it. A row that pass clears already sits at the bottom of `## Needs a plan` before this sweep reads the heading.
|
|
178
178
|
6. Before promoting a candidate, list the files it touches against every task already running, per Parallelism below. Name the overlap and serialize when the sets are not disjoint.
|
|
179
179
|
- A candidate held by something outside the tree stays where it is whatever those sets show. A collision is one of the reasons a task cannot start, so disjointness clears that reason alone and leaves an external condition standing.
|
|
180
|
-
7. Write a plan for each newly promoted task with `
|
|
180
|
+
7. Write a plan for each newly promoted task with `plan-feature`, carrying the in-flight constraint that The loop above states, then report:
|
|
181
181
|
|
|
182
182
|
```plaintext
|
|
183
183
|
Capture: owed since <the last handoff, or session start when none has run>
|
|
@@ -204,12 +204,12 @@ Promoting, demoting, and archiving a row all write `.canon/tasks/priority.md`, a
|
|
|
204
204
|
- 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.
|
|
205
205
|
- Write both halves of a move before reporting it. A row removed from one surface and not written to the other leaves a task file nothing names, and the folder is gitignored with no history to recover the row from. `canon tasks validate` reports that state, so run it after any move.
|
|
206
206
|
- Put the reason a row sits where it does in its Waiting on cell. Position is the ordering and the cell is where the ordering's rationale lives, so a row promoted with the cell left alone carries an order the next sweep cannot check.
|
|
207
|
-
- Put a pointer in the Plan column, never prose. `## Run now` claims a written plan covers every open outcome, and `
|
|
207
|
+
- Put a pointer in the Plan column, never prose. `## Run now` claims a written plan covers every open outcome, and `auto-ship` 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.
|
|
208
208
|
- 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.
|
|
209
209
|
- Re-resolve every Plan pointer after anything archives a plan
|
|
210
210
|
- Read the file back after writing it, since the row that lands is the row a worker acts on
|
|
211
211
|
|
|
212
|
-
A Plan pointer goes stale from a branch this board never sees. `
|
|
212
|
+
A Plan pointer goes stale from a branch this board never sees. `docs-fold` moves a plan to `.canon/plans/archive/` and rewrites the citation in the task file alone, so a row for a task still on the board keeps pointing into `.canon/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.
|
|
213
213
|
|
|
214
214
|
## Parallelism
|
|
215
215
|
|
|
@@ -275,7 +275,7 @@ lands. A re-review asks whether the prior findings landed and whether the fix
|
|
|
275
275
|
regressed anything, which is bounded to a delta and carries none of that reading,
|
|
276
276
|
so it is the half that leaves cleanly.
|
|
277
277
|
|
|
278
|
-
What it dispatches has no role skill yet. `
|
|
278
|
+
What it dispatches has no role skill yet. `role-worker` and `role-planner`
|
|
279
279
|
each state what their session may not do and no third body states a reviewer's,
|
|
280
280
|
so a dispatched re-review would hold its obligations in whatever launch string
|
|
281
281
|
this session types. That is the defect those two skills were written to close, so
|
package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-dispatch.md
RENAMED
|
@@ -10,13 +10,13 @@ Run this at loop step 4, for a `## Run now` row whose plan is verified, in place
|
|
|
10
10
|
Run `canon tasks plan-branch <plan> --json` against the row's plan file and read `branch`, `type`, `slug`, and `conforms` off the record.
|
|
11
11
|
|
|
12
12
|
- `conforms: true`: take `branch` as the candidate, and take `type` and `slug` from the same record for the check below.
|
|
13
|
-
- `conforms: false`: the plan's own filename breaks a cap in `${CLAUDE_SKILL_DIR}/../../standards/branch.md`. Report which, and hand the row to the human-launch line below rather than shortening the slug here. A rename parts the branch from the plan filename that `
|
|
14
|
-
- `reason: archived`, `no-plan`, or `bad-input`: the row does not cite a live plan. Repoint the row or fix the citation rather than dispatching, since `
|
|
13
|
+
- `conforms: false`: the plan's own filename breaks a cap in `${CLAUDE_SKILL_DIR}/../../standards/branch.md`. Report which, and hand the row to the human-launch line below rather than shortening the slug here. A rename parts the branch from the plan filename that `session-worktree` tier 1 and `git-pr`'s plan lookup both read back.
|
|
14
|
+
- `reason: archived`, `no-plan`, or `bad-input`: the row does not cite a live plan. Repoint the row or fix the citation rather than dispatching, since `auto-ship` Step 1 refuses the same file and the worker would meet that refusal after the launch spent.
|
|
15
15
|
- Anything else, including a record carrying no `branch` key and an installed binary carrying no `plan-branch` subcommand: treat the candidate as unverified rather than clear, name which reading could not be taken, and fall back to the human-launch line below. Re-deriving by prose here rebuilds the defect the verb closes, and does it quietly.
|
|
16
16
|
|
|
17
17
|
Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero.
|
|
18
18
|
|
|
19
|
-
The worker calls the same verb on the same plan at `
|
|
19
|
+
The worker calls the same verb on the same plan at `auto-ship` Step 0, so the branch this gate checks and the branch that session takes are one string by construction rather than two readings of one paragraph. They were two readings until 2026-09-06. One run checked `docs/remaining-skill-verdicts` against a worker that took `docs/skill-verdicts-decide`, another checked `fix/path-form-hook` against a worker that took `feat/path-form-hook`, and four dispatches on 2026-09-05 produced three strings for one plan. A check against a branch nobody uses verifies nothing.
|
|
20
20
|
|
|
21
21
|
The type the verb reports is fixed at `feat` whatever the row does, which is the half of the derivation that disagreed most. What makes that safe is that a branch type is cosmetic: `git-stage` reads a commit's type off the staged diff and `git-pr` reads a title off the diff, so nothing a release reads passes through the branch name. What it costs is a worktree listing where every dispatched branch reads `feat/`, which a person scanning one loses. Nothing renames it later, and this paragraph said `git-branch` did until 2026-09-06, when its conventions guard turned out to fire on a conforming `feat/` before reaching any type judgment.
|
|
22
22
|
|
|
@@ -26,7 +26,7 @@ Run `canon tasks plan-answers <plan> --json` and read `launchable` off the recor
|
|
|
26
26
|
|
|
27
27
|
- `launchable: true`: the plan answers itself, so proceed to the branch check.
|
|
28
28
|
- `launchable: false`: the row is not dispatchable. Report every entry in `open`, each carrying the question label and the reason its suggestion gave for needing a person, and hand the row to the human-launch line below. Never fill the slot on the operator's behalf, which is the one move the plan standard forbids outright.
|
|
29
|
-
- `reason: archived`: the row's plan sits in `.canon/plans/archive/` and describes work that already shipped. Repoint the row at a live plan rather than dispatching, since `
|
|
29
|
+
- `reason: archived`: the row's plan sits in `.canon/plans/archive/` and describes work that already shipped. Repoint the row at a live plan rather than dispatching, since `auto-ship` Step 1 refuses the same file and the worker would meet that refusal after the launch spent.
|
|
30
30
|
- The command refuses for any other reason, or the record carries no `launchable` key: treat the row as unverified rather than clear, name what could not be read, and fall back to the human. A gate that reads nothing and proceeds is the gate not running.
|
|
31
31
|
|
|
32
32
|
Branch on `launchable` rather than on the exit code, which a shell function wrapping `canon` can flatten to zero and so read a held row as a clear one.
|
|
@@ -37,7 +37,7 @@ It also reads the plan rather than a cell describing one, which is the input the
|
|
|
37
37
|
|
|
38
38
|
A blank `- Answer:` is not an unanswered question. `${CLAUDE_SKILL_DIR}/../../standards/plan.md` fixes an empty slot as accepting the `- Suggested:` line above it, which is what makes a plan decision-ready in one pass. The narrow case this reads is `- Suggested: needs your call, <why>` and its two demonstrated paraphrases, `needs operator's call` and `needs the operator's call`, over an empty slot, the form that same standard writes where the answer turns on preference rather than on a technical default. A gate reading every blank slot as open would refuse every plan in the folder.
|
|
39
39
|
|
|
40
|
-
What it prevents is a halt nobody is watching for. `
|
|
40
|
+
What it prevents is a halt nobody is watching for. `role-worker` instructs a session to stop on a question written as needing the operator's call, correctly and by its own body, so a dispatch that never reads the plan lands a worker in a wait for a person who does not know it is waiting. The worker's halt is not the defect, and the dispatch that made it necessary is.
|
|
41
41
|
|
|
42
42
|
## Check the branch is unclaimed
|
|
43
43
|
|
|
@@ -55,7 +55,7 @@ What the ref read cannot see is a branch pushed from another machine since the l
|
|
|
55
55
|
|
|
56
56
|
## Hold what this pass already launched
|
|
57
57
|
|
|
58
|
-
A worker registers with `branch: main` and the main worktree as its `cwd` until `
|
|
58
|
+
A worker registers with `branch: main` and the main worktree as its `cwd` until `auto-ship` Step 0 moves it, which took several seconds on both measured runs. Neither the roster nor the refs name the candidate during that window, so a second check inside it reads clear.
|
|
59
59
|
|
|
60
60
|
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.
|
|
61
61
|
|
|
@@ -82,7 +82,7 @@ Name `<model>` on the launch, and pick it against the task rather than copying w
|
|
|
82
82
|
## Dispatch
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
claude --bg --model <model> -n "worker-<project>-<slug>" "/canon:
|
|
85
|
+
claude --bg --model <model> -n "worker-<project>-<slug>" "/canon:auto-ship <plan>
|
|
86
86
|
Your controller is the session whose sessionId is <dispatcher-id>. Resolve its current name from that id through canon sessions list --json, which carries sessionId per row, at the moment you send, and never resolve an addressee by name prefix. Message it when the pull request opens, carrying the number, the branch, the head sha, the CI state, and every point you departed from the plan on, and message it again if you stop on a question."
|
|
87
87
|
```
|
|
88
88
|
|
|
@@ -90,7 +90,7 @@ Your controller is the session whose sessionId is <dispatcher-id>. Resolve its c
|
|
|
90
90
|
|
|
91
91
|
The prefix reads `worker-` because that is the role it marks. It read `orchestrator-` until 2026-08-31, and no controlling session ever carried it, so a worker filtering the roster for that string found a sibling or itself on every row. Nothing matches the prefix programmatically, which is what kept the rename down to three strings.
|
|
92
92
|
|
|
93
|
-
`<project>` is the basename of the main worktree root, not of wherever the dispatcher happens to be running. Resolve the main root first, the way `
|
|
93
|
+
`<project>` is the basename of the main worktree root, not of wherever the dispatcher happens to be running. Resolve the main root first, the way `session-worktree` Step 1 does, since a bare `git rev-parse --show-toplevel` inside a linked worktree returns the worktree path rather than the project's.
|
|
94
94
|
|
|
95
95
|
`claude agents` lists every session on the machine with no path column and no per-project filter, so `<project>` in the name is the only thing left telling two fleets apart, and a session named off the worktree path instead would carry the branch folder rather than the project. Two projects each dispatching a bare `worker-page-driver` used to read as one row in that view.
|
|
96
96
|
|
|
@@ -100,11 +100,11 @@ Where the installed CLI answers `--self` with an unknown option, that flag is ne
|
|
|
100
100
|
|
|
101
101
|
The worker resolves that id back to a name through `canon sessions list --json`, which carries `sessionId` per row, rather than through the agent listing, which prints a name and a short ref and no id at all. A worker reaching for the listing first therefore finds no lookup and can conclude there is none. That failure is silent in both directions: the session has nothing useful to do with the message it owes and goes idle holding it, and nothing on this side reports the quiet, so the loss surfaces as a missing worktree or a pull request that never opens rather than as anything watching for it.
|
|
102
102
|
|
|
103
|
-
The template carries no worktree call. `
|
|
103
|
+
The template carries no worktree call. `auto-ship` Step 0 invokes `canon:role-worker` and then `canon:session-worktree` itself, and neither carries the flag, so both are reachable through the `Skill` tool regardless of where a call to them would sit in a prompt. 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.
|
|
104
104
|
|
|
105
|
-
The template names no branch, and it does not need to. `
|
|
105
|
+
The template names no branch, and it does not need to. `auto-ship` Step 0 runs `canon tasks plan-branch <plan>` on the same file this runbook derived the candidate from, and hands the `<type>/<slug>` it reports to `session-worktree` as its tier 0 argument, so the two sides agree by calling one derivation rather than by a string copied between them.
|
|
106
106
|
|
|
107
|
-
That retires the inference four workers took before the verb existed, which was to derive the name from `<plan>` by their own reading of it. Nothing has to reach `
|
|
107
|
+
That retires the inference four workers took before the verb existed, which was to derive the name from `<plan>` by their own reading of it. Nothing has to reach `session-worktree`'s ladder now, which mattered because a worker launched onto `main` cannot match tier 1, a board carrying more than one plan puts tier 2 out of reach, and tier 3 tells it to ask a person who is not there. What still travels on judgment is the fallback: a worker whose installed binary carries no `plan-branch` derives by prose, which is where both live disagreements came from.
|
|
108
108
|
|
|
109
109
|
### Expansion needs position zero and a clean delimiter, not leading order alone
|
|
110
110
|
|
|
@@ -112,17 +112,17 @@ The client expands a slash command at position zero of a launch prompt as a
|
|
|
112
112
|
user invocation, which is the route `disable-model-invocation: true` permits
|
|
113
113
|
and gates. Everything that reaches the session as prose instead falls to the
|
|
114
114
|
model, which invokes it through the `Skill` tool, and that route answers a
|
|
115
|
-
flagged skill inconsistently. `
|
|
115
|
+
flagged skill inconsistently. `auto-ship` has carried the flag since early in its life, and seven other
|
|
116
116
|
shipped skills carry it too.
|
|
117
117
|
|
|
118
118
|
Three launches on 2026-08-31 and 2026-09-02 bound what makes a command take
|
|
119
119
|
that route. Observation A is the first refused worker, launched as `Run
|
|
120
|
-
/canon:
|
|
121
|
-
nothing. Observation B is a re-dispatch launched as `/canon:
|
|
120
|
+
/canon:session-worktree ..., then /canon:auto-ship ...`, which expanded
|
|
121
|
+
nothing. Observation B is a re-dispatch launched as `/canon:auto-ship
|
|
122
122
|
<plan>` with a space before the path, which expanded and shipped.
|
|
123
123
|
|
|
124
|
-
Observation C is a planning dispatch launched as `/canon:
|
|
125
|
-
/canon:
|
|
124
|
+
Observation C is a planning dispatch launched as `/canon:role-planner, then
|
|
125
|
+
/canon:plan-feature <task>` with a comma glued to the command name at
|
|
126
126
|
position zero, which expanded nothing and reached both bodies through the
|
|
127
127
|
`Skill` tool instead. A rules out leading order alone, C rules out position
|
|
128
128
|
zero on its own, and the only visible difference between B and C is the
|
|
@@ -137,7 +137,7 @@ by a space and its argument, with nothing before it.
|
|
|
137
137
|
|
|
138
138
|
Four sessions made the same tool call against the same plugin cache on
|
|
139
139
|
2026-08-31. Two were answered with the body and shipped, and two were refused
|
|
140
|
-
with `Skill canon:
|
|
140
|
+
with `Skill canon:auto-ship cannot be used with Skill tool due to
|
|
141
141
|
disable-model-invocation`. Prefixing separated nothing, since three of the
|
|
142
142
|
four carried the namespace and those three landed on both answers, so nothing
|
|
143
143
|
a dispatcher writes predicts which answer a launch through the tool gets.
|
|
@@ -157,8 +157,8 @@ onto the same branch with the build template above, which already leads with
|
|
|
157
157
|
the one command that needs the expansion route.
|
|
158
158
|
|
|
159
159
|
The review shape and the planning shape below depend on no expansion at all.
|
|
160
|
-
None of `
|
|
161
|
-
`
|
|
160
|
+
None of `role-worker`, `review-address`, `role-planner`, or
|
|
161
|
+
`plan-feature` carries the flag, so both correctly keep their leading word
|
|
162
162
|
regardless of the delimiter or the position it sits at.
|
|
163
163
|
|
|
164
164
|
The same collapse reaches a human relay rather than a `claude --bg` string. A
|
|
@@ -185,8 +185,8 @@ Report the dispatch as loudly as the human-launch line it replaces: name the bra
|
|
|
185
185
|
|
|
186
186
|
## Dispatch to address a review
|
|
187
187
|
|
|
188
|
-
`
|
|
189
|
-
alone reaches no `
|
|
188
|
+
`review-address` is a single pass, not a chain, so a launch naming it
|
|
189
|
+
alone reaches no `role-worker` and takes no role, which owes no message
|
|
190
190
|
either. A replacement session was launched that way once, onto the branch a
|
|
191
191
|
review had already posted findings against, and it answered by posting a
|
|
192
192
|
thread reply and telling its controller nothing. Reach the role directly on
|
|
@@ -208,14 +208,14 @@ directly with `Bash`, `Read`, and `Edit` instead of retrying the tool, which
|
|
|
208
208
|
is the route two workers already took today on two different branches.
|
|
209
209
|
|
|
210
210
|
```bash
|
|
211
|
-
claude --bg --model <model> -n "worker-<project>-<slug>" "Enter the worktree for <branch> at .claude/worktrees/<slug>/, creating it from that branch if the folder is gone. Run /canon:
|
|
211
|
+
claude --bg --model <model> -n "worker-<project>-<slug>" "Enter the worktree for <branch> at .claude/worktrees/<slug>/, creating it from that branch if the folder is gone. Run /canon:role-worker, then /canon:review-address. Your controller is the session whose sessionId is <dispatcher-id>. Resolve its current name from that id through canon sessions list --json, which carries sessionId per row, at the moment you send, and never resolve an addressee by name prefix. Message it when the address pass finishes, carrying what was addressed and the PR's CI state, and message it again if you stop on a question."
|
|
212
212
|
```
|
|
213
213
|
|
|
214
214
|
`<dispatcher-id>`, `<model>`, and `<project>` resolve the same way the build
|
|
215
215
|
shape resolves them above.
|
|
216
216
|
|
|
217
217
|
Take this shape wherever a review needs answering and no live session already
|
|
218
|
-
holds the branch. Where one does, message it to run `
|
|
218
|
+
holds the branch. Where one does, message it to run `review-address`
|
|
219
219
|
instead, per the loop's own step 6, since a session already there needs no
|
|
220
220
|
second one dispatched onto the same branch.
|
|
221
221
|
|
|
@@ -227,22 +227,22 @@ nothing the check can see.
|
|
|
227
227
|
|
|
228
228
|
## Dispatch to plan a row
|
|
229
229
|
|
|
230
|
-
`
|
|
231
|
-
reaches no `
|
|
230
|
+
`plan-feature` is a procedure rather than a role, so a launch naming it alone
|
|
231
|
+
reaches no `role-planner` and takes no role, which owes no message either.
|
|
232
232
|
Both trials on 2026-08-31 ran on prose the controller retyped into each launch,
|
|
233
233
|
which held every obligation those sessions took and is where the first one's
|
|
234
234
|
in-flight read went wrong. Reach the role directly on this launch, the way the
|
|
235
|
-
build shape above reaches `
|
|
235
|
+
build shape above reaches `role-worker`.
|
|
236
236
|
|
|
237
237
|
No branch and no worktree exist here and none is created. A planner writes one
|
|
238
238
|
gitignored file at the main worktree root, so this shape names the row's task
|
|
239
239
|
file rather than a branch and opens with the role instead of a worktree call.
|
|
240
240
|
That write meets the isolation guard the same way a linked worktree's
|
|
241
241
|
main-root write does, with no worktree here to redirect it to, so
|
|
242
|
-
`
|
|
242
|
+
`role-planner` sends it as a `Bash` heredoc rather than through `Write`.
|
|
243
243
|
|
|
244
244
|
```bash
|
|
245
|
-
claude --bg --model <model> -n "planner-<project>-<slug>" "Run /canon:
|
|
245
|
+
claude --bg --model <model> -n "planner-<project>-<slug>" "Run /canon:role-planner, then /canon:plan-feature <task>. Your controller is the session whose sessionId is <dispatcher-id>. Resolve its current name from that id through canon sessions list --json, which carries sessionId per row, at the moment you send, and never resolve an addressee by name prefix. Message it when the plan lands, carrying the path and what the task file got wrong, and message it again if you stop on a question."
|
|
246
246
|
```
|
|
247
247
|
|
|
248
248
|
`<task>` is the row's task file path and `<slug>` the slug its plan will take,
|
|
@@ -261,7 +261,7 @@ over a plan nobody has written yet.
|
|
|
261
261
|
|
|
262
262
|
What a planning dispatch owes instead is the reverse reading, because the plan
|
|
263
263
|
it produces carries a constraint per track in flight and a row planned during a
|
|
264
|
-
wave is planned against a tree that wave is changing. `
|
|
264
|
+
wave is planned against a tree that wave is changing. `role-planner` composes
|
|
265
265
|
the session roster with the pull request list for that read rather than reading
|
|
266
266
|
pull requests alone, which is why the brief carries no branch list for it: the
|
|
267
267
|
planner takes this reading itself either way.
|
|
@@ -278,7 +278,7 @@ Hand the row to the human-launch line in step 4 instead of dispatching when any
|
|
|
278
278
|
|
|
279
279
|
The first of those five is the one that reaches a person rather than the board. A row held for a collision or for a serialize reason waits on the wave clearing, where a row held on its plan waits on an answer only the operator can give, so hand that one over with the question label and its stated reason attached rather than as a name and a refusal.
|
|
280
280
|
|
|
281
|
-
Hand the person one command: `/canon:
|
|
281
|
+
Hand the person one command: `/canon:auto-ship <plan>`, naming the row, the plan path, and the branch together, with no worktree call ahead of it. A leading worktree call adds nothing beyond what `auto-ship` Step 0 already reaches for itself, by the same judgment the template above calls a residual risk rather than a settled contract. A second command also risks a client folding two commands into one message, which reads everything after the first command's name as its own argument and drops the second: that happened in four dispatches out of four before the fix became one message carrying the autoship call alone.
|
|
282
282
|
|
|
283
283
|
Suggest, as one line to the operator, that they rename their own session to the row's id, so a process listing shows what the session is for without a cross-reference to the board.
|
|
284
284
|
|
package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-handoff.md
RENAMED
|
@@ -41,12 +41,12 @@ Write the pre-compaction handoff as orchestrator. Invoke `canon:session-map` for
|
|
|
41
41
|
|
|
42
42
|
Settle all three steps below before the door writes, so one write carries the core and the extension together. The door reports the map as written and knows nothing of this role, so its success line ends the generic half rather than this runbook, and a session that stops there ships a map missing both of the things this section adds to it.
|
|
43
43
|
|
|
44
|
-
1. Tell the door this session does not commit, which is the caveat its capture step takes and passes to `canon:
|
|
44
|
+
1. Tell the door this session does not commit, which is the caveat its capture step takes and passes to `canon:memory-capture`.
|
|
45
45
|
2. Add `## Decisions taken under delegated authority` directly after `## State`, holding each decision and why it went that way, so nobody re-proposes it. It sits there rather than after the core because a decision is read against the state it was taken in.
|
|
46
46
|
3. Close the file with the block below, resolving `${CLAUDE_SKILL_DIR}/references/orchestrator-resume.md` and `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` to absolute paths as you write it and pasting each in place of `<RESUME_RUNBOOK>` and `<POLL_RUNBOOK>`:
|
|
47
47
|
|
|
48
48
|
```markdown
|
|
49
|
-
Resume by loading the orchestrator skill and asking it to resume after a compaction. This repository spells that `/canon:
|
|
49
|
+
Resume by loading the orchestrator skill and asking it to resume after a compaction. This repository spells that `/canon:role-orchestrator` followed by the request. Following <RESUME_RUNBOOK> reaches the same place with no skill loaded at all.
|
|
50
50
|
|
|
51
51
|
That resume reads the board and stops. It restarts nothing, so the review poll is a second thing owed here, and <POLL_RUNBOOK> holds the prompt and the condition. Do not reach for `session-resume`, which reads tracked work and reports the newest map without restarting this loop.
|
|
52
52
|
```
|
package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-parked.md
RENAMED
|
@@ -15,7 +15,7 @@ The sweep's own question stays distinct from this one. It asks which parked row
|
|
|
15
15
|
|
|
16
16
|
## Scope
|
|
17
17
|
|
|
18
|
-
Every row under `## Up next` and `## Needs a plan` in `.canon/tasks/priority.md`. A `## Run now` row carries no blocker by definition, so the pass skips it. On the idle trigger, also every row in `.canon/tasks/backlog.md` when the file exists, per the trigger split above. Resolve the board, the backlog, and each task file at the main worktree root, the way `
|
|
18
|
+
Every row under `## Up next` and `## Needs a plan` in `.canon/tasks/priority.md`. A `## Run now` row carries no blocker by definition, so the pass skips it. On the idle trigger, also every row in `.canon/tasks/backlog.md` when the file exists, per the trigger split above. Resolve the board, the backlog, and each task file at the main worktree root, the way `session-worktree` does.
|
|
19
19
|
|
|
20
20
|
Take the board rows in board order and finish one before opening the next. Clearing a row changes what the next row collides with, so a pass that measures every row first and writes afterwards writes against a board it has already invalidated. On the idle trigger, walk the backlog after the board, in the file's own filename order, since `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` fixes that file as unordered and nothing about a row's position there means anything to preserve mid-pass.
|
|
21
21
|
|
|
@@ -29,9 +29,9 @@ The blocker cell states what the row waits on, and each kind is tested different
|
|
|
29
29
|
- Waiting on a plan: nothing external holds the row, so the pass writes the plan rather than testing anything. See The plan half below.
|
|
30
30
|
- Waiting on an operator action, such as a run that happens from a shell: record it as untestable this pass and name what the operator has to do. A session cannot clear it, and re-measuring it every pass is waste.
|
|
31
31
|
|
|
32
|
-
Every measurement this pass takes is a blocker re-test on a row already filed, and it decides whether that row can start rather than how big it is. Sizing a row is the filing boundary `
|
|
32
|
+
Every measurement this pass takes is a blocker re-test on a row already filed, and it decides whether that row can start rather than how big it is. Sizing a row is the filing boundary `role-orchestrator` states under `## Boundaries`, which leaves the extent and the cause to whoever plans the row.
|
|
33
33
|
|
|
34
|
-
Write the result into the row. A re-test reported in chat is lost at the next compaction and the next pass measures the same thing again. Rewrite a blocker cell whose test no longer holds, move the row to the group its new state puts it in, and record the measurement in that task's `## Findings` with the date it was taken. `### Writing the board` in `
|
|
34
|
+
Write the result into the row. A re-test reported in chat is lost at the next compaction and the next pass measures the same thing again. Rewrite a blocker cell whose test no longer holds, move the row to the group its new state puts it in, and record the measurement in that task's `## Findings` with the date it was taken. `### Writing the board` in `role-orchestrator` owns the method, and `canon tasks validate` runs once the board is rewritten and before the report.
|
|
35
35
|
|
|
36
36
|
## Re-testing a backlog row
|
|
37
37
|
|
|
@@ -39,7 +39,7 @@ A backlog row carries no blocker cell, since `${CLAUDE_SKILL_DIR}/../../standard
|
|
|
39
39
|
|
|
40
40
|
Clearing a row answers yes to that question. It is not a count of how long the row has waited: `## Two results that are not a re-test` below refuses age as evidence for a board row, and it refuses it here on the same ground, since a row untouched for weeks is not more clearable than one added yesterday.
|
|
41
41
|
|
|
42
|
-
A row this test clears moves out of `backlog.md` and onto the bottom of `## Needs a plan`, carrying a `Waiting on` cell that states what changed and ends with the word `last`. `canon tasks validate`'s ordering check reads `last` as the ordinal bottom placement already claims, and a cell stating only what changed matches neither that check's ordinal reading nor its rank reading, which raises the finding this pass would then have written against its own row. The next refill sweep's promotion step still orders the row against the rest of that heading the way it orders every other row there, per step 5 under `## Refilling the ready queue` in `
|
|
42
|
+
A row this test clears moves out of `backlog.md` and onto the bottom of `## Needs a plan`, carrying a `Waiting on` cell that states what changed and ends with the word `last`. `canon tasks validate`'s ordering check reads `last` as the ordinal bottom placement already claims, and a cell stating only what changed matches neither that check's ordinal reading nor its rank reading, which raises the finding this pass would then have written against its own row. The next refill sweep's promotion step still orders the row against the rest of that heading the way it orders every other row there, per step 5 under `## Refilling the ready queue` in `role-orchestrator`.
|
|
43
43
|
|
|
44
44
|
## Two ways a re-test goes wrong
|
|
45
45
|
|
|
@@ -55,15 +55,15 @@ The second is measuring against the wrong tree. A command that ships to targets
|
|
|
55
55
|
|
|
56
56
|
Plan what the pass clears, and plan any `## Needs a plan` row whose only blocker is the missing plan. The window is the argument: this pass runs while workers build and the session is otherwise idle, which is when planning costs the critical path nothing, and a row cleared with no plan is a row the next pass looks at again.
|
|
57
57
|
|
|
58
|
-
Run `
|
|
58
|
+
Run `plan-feature` for each, carrying the constraint per in-flight track that `## The loop` in `role-orchestrator` requires. Verify each plan against the tree the way that step does, since a plan written now is written against a tree several branches are already changing.
|
|
59
59
|
|
|
60
60
|
Stop where `## Parallelism` stops rather than planning every row the pass cleared. A plan whose file set collides with every track in flight is one nobody can dispatch.
|
|
61
61
|
|
|
62
|
-
Do not restate the refill procedure. `
|
|
62
|
+
Do not restate the refill procedure. `role-orchestrator` owns it under `## Refilling the ready queue` and `orchestrator-sweep.md` wraps it for a batch of merges, so this pass promotes through that method rather than a second one.
|
|
63
63
|
|
|
64
64
|
## Two results that are not a re-test
|
|
65
65
|
|
|
66
|
-
Age is not evidence. A row untouched for weeks invites promotion, and the waiting is not an argument for it. `
|
|
66
|
+
Age is not evidence. A row untouched for weeks invites promotion, and the waiting is not an argument for it. `role-orchestrator` refuses to promote a task to fill the queue and this pass inherits that refusal, so a row whose blocker still holds stays where it is. Reporting it as still parked, against a measurement taken this pass, is a result.
|
|
67
67
|
|
|
68
68
|
A scoping defect can wear a blocker. A task whose file set collides with every other task by construction is oversized rather than blocked, and planning it again produces the same plan nobody can dispatch. Split it into tasks with disjoint file sets, so the board stops carrying a row that re-measures the same way every pass.
|
|
69
69
|
|
|
@@ -81,4 +81,4 @@ Still backlogged: <row>, <what was checked> found unchanged
|
|
|
81
81
|
|
|
82
82
|
Omit any row with nothing in it. Name what was measured rather than the verdict alone, since a re-test the reader cannot check is the same claim the row already carried.
|
|
83
83
|
|
|
84
|
-
Lead the reply with the three slots under `### Every later turn` in `
|
|
84
|
+
Lead the reply with the three slots under `### Every later turn` in `role-orchestrator`, so the human reads what they own before the evidence for it.
|