@erclx/canon 5.41.0 → 5.42.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/api-design/references/adopted.md +34 -14
- package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
- package/claude/skills/auto-ship/SKILL.md +22 -2
- package/claude/skills/auto-ship/references/draft-mark.md +32 -6
- package/claude/skills/auto-ship/references/failure-recovery.md +15 -13
- package/claude/skills/auto-ship/references/tier-failures.md +31 -10
- package/claude/skills/auto-ship/references/ui-checklist.md +9 -4
- package/claude/skills/auto-ship/references/worktree-name.md +9 -3
- package/claude/skills/build-in-slices/references/adopted.md +35 -21
- package/claude/skills/canvas-board/references/canvas.md +17 -6
- package/claude/skills/canvas-board/references/design.md +26 -7
- package/claude/skills/code-craft/references/adopted.md +58 -20
- package/claude/skills/codebase-layout/references/adopted.md +49 -16
- package/claude/skills/codebase-layout/references/frontend.md +11 -4
- package/claude/skills/codebase-layout/references/tests.md +4 -2
- package/claude/skills/context-fold/references/classify.md +10 -15
- package/claude/skills/context-fold/references/completion-report.md +11 -9
- package/claude/skills/context-fold/references/context-refresh.md +26 -9
- package/claude/skills/context-fold/references/unusable-baseline.md +5 -3
- package/claude/skills/create-rule/REQUIREMENT.md +5 -0
- package/claude/skills/create-rule/SKILL.md +9 -1
- package/claude/skills/create-rule/references/checklist.md +26 -0
- package/claude/skills/create-rule/references/rule.md +98 -20
- package/claude/skills/create-skill/SKILL.md +1 -0
- package/claude/skills/create-skill/references/skill-disclosure.md +10 -2
- package/claude/skills/create-skill/references/skill-frontmatter.md +43 -0
- package/claude/skills/create-skill/references/skill-paths.md +7 -4
- package/claude/skills/create-skill/references/skill-practice.md +6 -3
- package/claude/skills/create-skill/references/skill-requirement.md +4 -2
- package/claude/skills/create-skill/references/skill.md +67 -44
- package/claude/skills/deploy-app/references/vercel.md +2 -1
- package/claude/skills/deprecation-migration/references/adopted.md +44 -25
- package/claude/skills/design-taste/references/adopted.md +9 -1
- package/claude/skills/design-taste/references/craft.md +3 -1
- package/claude/skills/design-taste/references/kinds.md +8 -7
- package/claude/skills/design-taste/references/preflight.md +12 -0
- package/claude/skills/design-taste/references/systems.md +7 -6
- package/claude/skills/design-taste/references/tells.md +24 -25
- package/claude/skills/design-taste/references/vocabulary.md +7 -5
- package/claude/skills/document-health/references/axes.md +54 -30
- package/claude/skills/draft-and-pick/references/live-arms.md +2 -2
- package/claude/skills/draft-doc/references/context.md +4 -3
- package/claude/skills/draft-doc/references/docs.md +6 -3
- package/claude/skills/draft-doc/references/readme/agent-facing.md +6 -0
- package/claude/skills/draft-doc/references/readme/application.md +8 -2
- package/claude/skills/draft-doc/references/readme/cli.md +5 -1
- package/claude/skills/draft-doc/references/readme/library.md +4 -0
- package/claude/skills/draft-doc/references/readme/plugin.md +9 -1
- package/claude/skills/draft-doc/references/readme.md +30 -13
- package/claude/skills/draft-doc/references/requirements.md +17 -4
- package/claude/skills/draft-doc/references/wiki-kind.md +20 -10
- package/claude/skills/draft-figure/references/architecture-set.md +7 -3
- package/claude/skills/draft-figure/references/figures.md +8 -6
- package/claude/skills/draft-figure/references/hand-drawn.md +3 -1
- package/claude/skills/draft-figure/references/mermaid-path.md +19 -9
- package/claude/skills/draft-figure/references/mermaid.md +10 -5
- package/claude/skills/draft-ready/references/ready.md +22 -15
- package/claude/skills/git-branch/references/branch.md +11 -1
- package/claude/skills/git-branch/references/slug.md +17 -5
- package/claude/skills/git-commit/references/commit.md +8 -0
- package/claude/skills/git-commit/references/versioning.md +23 -17
- package/claude/skills/git-followup/REQUIREMENT.md +1 -1
- package/claude/skills/git-followup/SKILL.md +5 -6
- package/claude/skills/git-issue/references/issue.md +29 -16
- package/claude/skills/git-pr/REQUIREMENT.md +1 -5
- package/claude/skills/git-pr/SKILL.md +11 -22
- package/claude/skills/git-pr/references/final-command.md +21 -8
- package/claude/skills/git-pr/references/labels.md +45 -28
- package/claude/skills/git-pr/references/pr.md +28 -9
- package/claude/skills/git-pr/references/publish.md +42 -28
- package/claude/skills/git-pr/references/task-number.md +20 -8
- package/claude/skills/git-ship/SKILL.md +1 -1
- package/claude/skills/plan-feature/references/plan-lifecycle.md +10 -3
- package/claude/skills/plan-feature/references/plan.md +57 -20
- package/claude/skills/plan-groundwork/references/groundwork-spikes.md +4 -1
- package/claude/skills/plan-groundwork/references/groundwork.md +14 -16
- package/claude/skills/plan-intake/references/intake.md +29 -24
- package/claude/skills/pr-evidence/REQUIREMENT.md +40 -0
- package/claude/skills/pr-evidence/SKILL.md +53 -0
- package/claude/skills/pr-evidence/references/evidence.md +150 -0
- package/claude/skills/review-address/references/post-review-findings.md +10 -3
- package/claude/skills/review-address/references/rebase-conflicts.md +15 -7
- package/claude/skills/review-address/references/rest-reads.md +3 -1
- package/claude/skills/review-craft/references/adopted.md +35 -18
- package/claude/skills/review-craft/references/security.md +42 -7
- package/claude/skills/review-craft/references/ui.md +23 -8
- package/claude/skills/review-pr/SKILL.md +6 -6
- package/claude/skills/review-pr/references/body-variants.md +29 -9
- package/claude/skills/review-pr/references/close-out.md +20 -5
- package/claude/skills/review-pr/references/key-changes.md +27 -3
- package/claude/skills/review-pr/references/post.md +83 -31
- package/claude/skills/review-pr/references/scope.md +54 -19
- package/claude/skills/review-ui/references/close-out.md +7 -5
- package/claude/skills/review-ui/references/driving.md +24 -4
- package/claude/skills/review-ui/references/post.md +43 -15
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +67 -17
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +80 -40
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +52 -15
- package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +48 -26
- package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +12 -13
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +72 -36
- package/claude/skills/role-orchestrator/references/orchestrator-output.md +12 -4
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +64 -24
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +80 -26
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +41 -18
- package/claude/skills/role-orchestrator/references/orchestrator-resume.md +19 -7
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +22 -12
- package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +15 -6
- package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +25 -7
- package/claude/skills/role-orchestrator/references/orchestrator-watch.md +34 -8
- package/claude/skills/role-orchestrator/scripts/poll.ts +16 -24
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +8 -0
- package/claude/skills/search-craft/references/adopted.md +18 -6
- package/claude/skills/session-map/references/session.md +26 -7
- package/claude/skills/session-worktree/references/main-root-writes.md +25 -8
- package/claude/skills/systematic-debugging/references/adopted.md +30 -16
- package/claude/skills/target-check/references/domains.md +39 -11
- package/claude/skills/target-setup/references/detect.md +80 -65
- package/claude/skills/target-setup/references/indexes.md +8 -6
- package/claude/skills/task-board/references/board.md +86 -30
- package/claude/skills/task-board/references/decline.md +29 -13
- package/claude/skills/task-board/references/tasks-decline.md +12 -5
- package/claude/skills/task-board/references/tasks.md +65 -33
- package/claude/skills/task-complete/references/archive.md +41 -17
- package/claude/skills/task-complete/references/receipt-sweep.md +23 -9
- package/claude/skills/task-complete/references/unusable-baseline.md +10 -3
- package/claude/skills/teach-workspace/references/glossary.md +6 -2
- package/claude/skills/teach-workspace/references/lesson-build.md +44 -16
- package/claude/skills/teach-workspace/references/lesson-craft.md +12 -7
- package/claude/skills/teach-workspace/references/pedagogy.md +6 -3
- package/claude/skills/teach-workspace/references/promotion-fold.md +17 -11
- package/claude/skills/teach-workspace/references/promotion.md +31 -8
- package/claude/skills/teach-workspace/references/revisit.md +8 -2
- package/claude/skills/teach-workspace/references/teach.md +17 -9
- package/claude/skills/test-craft/references/adopted.md +48 -14
- package/claude/skills/test-craft/references/component.md +7 -4
- package/claude/skills/test-craft/references/e2e.md +25 -7
- package/claude/skills/test-craft/references/unit.md +3 -1
- package/claude/skills/test-first/references/adopted.md +12 -4
- package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
- package/claude/skills/ui-checklist/SKILL.md +1 -1
- package/claude/skills/video-craft/references/adopted.md +62 -18
- package/claude/skills/write-human/references/adopted.md +21 -8
- package/docs/workflow/parallel-features.md +1 -1
- package/docs/workflow/skill-map.md +1 -0
- package/package.json +1 -1
- package/src/claude/cases/workflow.ts +5 -0
- package/src/commands/pr.ts +142 -28
- package/src/markdown/scope.ts +144 -0
- package/src/pr/lift.ts +6 -3
- package/src/pr/review-state.ts +182 -0
- package/claude/skills/git-pr/references/evidence.md +0 -124
|
@@ -7,7 +7,10 @@ description: The cloud build and review shapes, being the launch prompt that car
|
|
|
7
7
|
|
|
8
8
|
Run this once `orchestrator-dispatch.md` has cleared a row and picked cloud for it. The worker runs on a Claude Code cloud VM that clones the repository from GitHub, loads no plugin, and cannot see this machine's `.canon/`.
|
|
9
9
|
|
|
10
|
-
The shape needs a `SessionStart` hook in the repository that, on the VM alone, copies the plugin skills into `.claude/skills/` and puts `canon` on the path.
|
|
10
|
+
The shape needs a `SessionStart` hook in the repository that, on the VM alone, copies the plugin skills into `.claude/skills/` and puts `canon` on the path.
|
|
11
|
+
|
|
12
|
+
- A repository without one cannot take this shape, so fall back to a local worker there
|
|
13
|
+
- Where the hook exists, the prompt calls `/auto-ship` with no `canon:` prefix, since the copied skills list as project skills
|
|
11
14
|
|
|
12
15
|
## Contents
|
|
13
16
|
|
|
@@ -19,7 +22,9 @@ The shape needs a `SessionStart` hook in the repository that, on the VM alone, c
|
|
|
19
22
|
|
|
20
23
|
## Check the row is unclaimed
|
|
21
24
|
|
|
22
|
-
A cloud worker never appears in `canon sessions list` and never pushes the derived branch, since the cloud assigns it a `claude/` branch of its own
|
|
25
|
+
A cloud worker never appears in `canon sessions list` and never pushes the derived branch, since the cloud assigns it a `claude/` branch of its own, so the roster and the refs read clear on a row it is building.
|
|
26
|
+
|
|
27
|
+
Run the local check in `orchestrator-dispatch.md` anyway, since a local worker on the same row still collides, then read the two places a cloud worker does show:
|
|
23
28
|
|
|
24
29
|
```bash
|
|
25
30
|
prs=$(gh api 'repos/{owner}/{repo}/pulls?state=open&per_page=100' --jq '.[] | select(.head.ref | startswith("claude/")) | .number') || { echo 'unreadable: the open pull request list'; exit 1; }
|
|
@@ -37,7 +42,8 @@ Branch on the line it prints rather than on the exit, which a shell function wra
|
|
|
37
42
|
|
|
38
43
|
- `claimed: #<n>`: a cloud worker's pull request names the plan slug. Treat the row as claimed and report each number.
|
|
39
44
|
- `clear`, and this pass's launched record holds no cloud session for the row: the row is clear of cloud workers.
|
|
40
|
-
- `unreadable: <what>`:
|
|
45
|
+
- `unreadable: <what>`: nothing was checked, so treat the candidate as unverified and fall back to the human-launch line, as for a refused local check
|
|
46
|
+
- Never read `unreadable` as clear, since an empty answer from a failed read is the collision this check exists to catch
|
|
41
47
|
|
|
42
48
|
The launched record covers the minutes before the pull request opens, when nothing on GitHub names the row yet. It is this session's alone, so a second dispatcher sees only the pull request list, which is the window `orchestrator-dispatch.md` already states for local workers under `## Hold what this pass already launched`.
|
|
43
49
|
|
|
@@ -67,15 +73,26 @@ session=$(grep -A 2 'Created cloud session:' "$dir/create.typescript" | grep -o
|
|
|
67
73
|
printf 'session=%s\n' "$session"
|
|
68
74
|
```
|
|
69
75
|
|
|
70
|
-
Run it from the main worktree root, since the session targets whichever repository that checkout's `origin` names. That folder is already trusted, so the create screen shows no trust prompt.
|
|
76
|
+
Run it from the main worktree root, since the session targets whichever repository that checkout's `origin` names. That folder is already trusted, so the create screen shows no trust prompt.
|
|
77
|
+
|
|
78
|
+
- From an untrusted checkout, such as a fresh clone of another repository, the screen asks first, and piped keys answer it
|
|
79
|
+
- Replace `<(sleep 30)` with `<(sleep 4; printf '\033[B'; sleep 1; printf '\r'; sleep 30)` there
|
|
80
|
+
- Either way stdin stays open for the create, the measured shape, since an early end of input can reach the terminal before the screen settles
|
|
81
|
+
|
|
82
|
+
### The readout
|
|
71
83
|
|
|
72
|
-
The readout is the text `Created cloud session: <title>`, unanchored since a terminal capture can open a line with escape codes, followed by a `View:` address carrying the `session_...` id. Anything else is a failed create, including a run that exits zero.
|
|
84
|
+
The readout is the text `Created cloud session: <title>`, unanchored since a terminal capture can open a line with escape codes, followed by a `View:` address carrying the `session_...` id. Anything else is a failed create, including a run that exits zero.
|
|
73
85
|
|
|
74
|
-
|
|
86
|
+
- On a failed create, report the typescript's last lines and fall back to the human-launch line in `orchestrator-dispatch.md`
|
|
87
|
+
- The wrapper is a stopgap any change to the interactive create screen breaks, which is why the readout fails loudly instead of guessing
|
|
88
|
+
- Record `session` beside the row's branch in this pass's launched record, since that and the pull request list are the only readings that know it exists
|
|
89
|
+
- Report the dispatch as the local shape does, naming the row, the plan, the repository, and the session id in place of a session name
|
|
75
90
|
|
|
76
91
|
## Recognize the pull request
|
|
77
92
|
|
|
78
|
-
A cloud worker cannot message this session and never appears in the roster `watch.ts` reads, so its pull request and its `ANNOUNCE:` comment are the announcement. Start the poll in `orchestrator-poll.md` when the cloud dispatch goes out, rather than at
|
|
93
|
+
A cloud worker cannot message this session and never appears in the roster `watch.ts` reads, so its pull request and its `ANNOUNCE:` comment are the announcement. Start the poll in `orchestrator-poll.md` when the cloud dispatch goes out, rather than at its thirty-minute fallback.
|
|
94
|
+
|
|
95
|
+
A pull request on a `claude/` head is this row's when one of its commits carries a `Claude-Session:` trailer naming the session id the create recorded:
|
|
79
96
|
|
|
80
97
|
```bash
|
|
81
98
|
gh api 'repos/{owner}/{repo}/pulls/<number>/commits' --jq '.[].commit.message' | grep -c 'Claude-Session:.*<session>'
|
|
@@ -85,15 +102,31 @@ A count above zero matches the row. A count of zero is someone else's pull reque
|
|
|
85
102
|
|
|
86
103
|
## Dispatch a review to a cloud reviewer
|
|
87
104
|
|
|
88
|
-
Run this once `orchestrator-review-dispatch.md` has sent a code review to a dispatched reviewer and the operator picked cloud for it.
|
|
105
|
+
Run this once `orchestrator-review-dispatch.md` has sent a code review to a dispatched reviewer and the operator picked cloud for it. A UI review never takes this shape, because it drives a browser the VM does not have.
|
|
106
|
+
|
|
107
|
+
- The reviewer needs the same `SessionStart` hook as the build shape
|
|
108
|
+
- It needs a `canon` on the VM whose `pr` reads run on REST, since the proxy refuses GraphQL
|
|
109
|
+
|
|
110
|
+
### Confirm the REST reads
|
|
89
111
|
|
|
90
|
-
Confirm the VM's `canon` reads over REST before dispatching. In this repository the setup hook links the checkout's own CLI, so a pushed branch carries the reads.
|
|
112
|
+
Confirm the VM's `canon` reads over REST before dispatching. In this repository the setup hook links the checkout's own CLI, so a pushed branch carries the reads.
|
|
91
113
|
|
|
92
|
-
|
|
114
|
+
- Any other repository's VM installs `canon` from npm, so its `pr` reads run on REST only once a release carrying them is published
|
|
115
|
+
- Its copied skills carry the REST lookups only once that repository's skills are re-scaffolded from that release
|
|
116
|
+
- Read `npm view @erclx/canon version` against the first release whose changelog names the REST reads
|
|
117
|
+
- Run `grep -rnE 'gh pr (list|view|review|diff|comment)'` over the target's copied `review-pr` and expect no output
|
|
118
|
+
- A version short of that release, or a hit, dispatches a reviewer that fails on its first GraphQL call, so take the local shape instead
|
|
93
119
|
|
|
94
|
-
|
|
120
|
+
### Before the create
|
|
95
121
|
|
|
96
|
-
|
|
122
|
+
Check this pass's launched record for a cloud reviewer already holding the number, and run `canon pr review-state <number> --json` for a pass already posted. A cloud reviewer never appears in `canon sessions list`, so the local shape's live-session check reads clear on one.
|
|
123
|
+
|
|
124
|
+
The create targets whichever repository the checkout it runs from names as `origin`.
|
|
125
|
+
|
|
126
|
+
- For a pull request in this repository, write the prompt to `.canon/tmp/cloud-review-<number>/prompt.md` at the main worktree root and create there
|
|
127
|
+
- For another repository, run the create from its checkout and write the prompt under that checkout's own `.canon/tmp/cloud-review-<number>/`
|
|
128
|
+
- That checkout's `.gitignore` has to cover the folder before the create runs
|
|
129
|
+
- A fresh clone made for this is untrusted, so the create takes the trust-prompt key variant under `## The create`:
|
|
97
130
|
|
|
98
131
|
```plaintext
|
|
99
132
|
/role-reviewer
|
|
@@ -104,12 +137,29 @@ Your controller cannot receive a message from this session. The review you post
|
|
|
104
137
|
|
|
105
138
|
The cross-branch facts are the ones `### What the brief may carry` in `orchestrator-launch.md` allows a reviewer brief, and nothing of this session's own read. Neither skill carries the invocation flag, so no position-zero expansion is at stake and the bare names reach the copied project skills.
|
|
106
139
|
|
|
107
|
-
Create
|
|
140
|
+
### Create and record
|
|
141
|
+
|
|
142
|
+
Create the session with the wrapper under `## The create`, setting `dir` to that prompt's folder, and keep its readout rule, so no `session_` id means nothing was dispatched.
|
|
143
|
+
|
|
144
|
+
- Record the session id beside the number in this pass's launched record, and name the number, the repository, and the session id in the report
|
|
145
|
+
- `poll.ts` reads every open pull request's review state from this machine, so the posted `## Review` reaches the next poll like a local reviewer's
|
|
146
|
+
- Start the poll when the dispatch goes out rather than at its fallback
|
|
147
|
+
- A `QUESTION: review <number>` comment reaches the same poll as an unclassified reply, so answer it on the pull request
|
|
148
|
+
|
|
149
|
+
### Checking the transcript
|
|
150
|
+
|
|
151
|
+
The pull request is the record to act on, and the transcript is read back only to check for a refused call. Search the capture for `HTTP 403` and `graphql`, and report a hit as a finding naming a call still on GraphQL rather than reading the review as clean.
|
|
108
152
|
|
|
109
|
-
|
|
153
|
+
- Run `claude --teleport <session>` under `script` from a throwaway clone of the target outside this repository
|
|
154
|
+
- Answer its trust prompt with the same piped keys
|
|
155
|
+
- Set the terminal to 500 rows first, since only the screen tail is captured otherwise
|
|
110
156
|
|
|
111
|
-
|
|
157
|
+
### What a cloud reviewer cannot do
|
|
112
158
|
|
|
113
|
-
A cloud reviewer cannot be messaged after it posts, and it cannot message the worker either. `poll.ts` reports nothing when a code review posts on an unchanged head, so the poll's cloud-reviewer rule reads `canon pr review-state <number> --json` on every run for each pull request one holds
|
|
159
|
+
A cloud reviewer cannot be messaged after it posts, and it cannot message the worker either. `poll.ts` reports nothing when a code review posts on an unchanged head, so the poll's cloud-reviewer rule reads `canon pr review-state <number> --json` on every run for each pull request one holds.
|
|
114
160
|
|
|
115
|
-
|
|
161
|
+
- That read sends the `review-address` dispatch from this session when it shows an open pass
|
|
162
|
+
- A re-review after the worker's address pass is a fresh dispatch, local or cloud by the same pick
|
|
163
|
+
- It cannot lift the draft mark, since `canon pr lift` writes through the GraphQL mutation the proxy refuses, so leave the lift out of its prompt
|
|
164
|
+
- The same per-run read runs the verb from this session once the review reads closed at the head on a pull request still a draft
|
|
165
|
+
- A local reviewer whose run refused reports that in its close message, which reaches loop step 6 rather than the poll
|
|
@@ -20,55 +20,65 @@ Run this at loop step 4, for a `## Run now` row whose plan is verified, in place
|
|
|
20
20
|
|
|
21
21
|
## Derive the candidate
|
|
22
22
|
|
|
23
|
-
Run `canon tasks plan-branch <plan> --json` against the row's plan file and read `branch`, `type`, `slug`, and `conforms` off the record.
|
|
23
|
+
Run `canon tasks plan-branch <plan> --json` against the row's plan file and read `branch`, `type`, `slug`, and `conforms` off the record. Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero.
|
|
24
24
|
|
|
25
25
|
- `conforms: true`: take `branch` as the candidate, and take `type` and `slug` from the same record for the check below.
|
|
26
|
-
- `conforms: false`: the plan's
|
|
27
|
-
- `reason: archived`, `no-plan`, or `bad-input`: the row
|
|
28
|
-
- Anything else, including
|
|
26
|
+
- `conforms: false`: the plan's filename breaks a cap in `${CLAUDE_SKILL_DIR}/../git-branch/references/branch.md`. Report which, and hand the row to the human-launch line below.
|
|
27
|
+
- `reason: archived`, `no-plan`, or `bad-input`: the row cites no live plan, so repoint the row or fix the citation, since `auto-ship` Step 1 refuses the same file
|
|
28
|
+
- Anything else, including no `branch` key or a binary lacking `plan-branch`: treat the candidate as unverified, name the missing reading, and fall back to the human
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
### Why the verb decides
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Never shorten a non-conforming slug here, since a rename parts the branch from the plan filename that `session-worktree` tier 1 and `git-pr`'s plan lookup read back. Re-deriving by prose rebuilds the defect the verb closes, quietly.
|
|
33
33
|
|
|
34
|
-
The
|
|
34
|
+
- The worker calls the same verb on the same plan at `auto-ship` Step 0, so the checked branch and the taken branch are one string by construction
|
|
35
|
+
- Two readings of one plan part on the slug and the type alike, and a check against a branch nobody uses verifies nothing
|
|
36
|
+
- The type is fixed at `feat`, which is safe because `git-stage` and `git-pr` read types off the diff and no release reads the branch name
|
|
37
|
+
- The cost is a worktree listing where every dispatched branch reads `feat/`
|
|
35
38
|
|
|
36
39
|
## Check the plan waits on nobody
|
|
37
40
|
|
|
38
|
-
Run `canon tasks plan-answers <plan> --json` and read `launchable` off the record.
|
|
41
|
+
Run `canon tasks plan-answers <plan> --json` and read `launchable` off the record. Branch on `launchable` rather than on the exit code, which a wrapping shell function can flatten to zero and so read a held row as clear.
|
|
39
42
|
|
|
40
43
|
- `launchable: true`: the plan answers itself, so proceed to the branch check.
|
|
41
|
-
- `launchable: false`:
|
|
42
|
-
-
|
|
44
|
+
- `launchable: false`: report every entry in `open`, each with its question label and stated reason, and hand the row to the human-launch line below
|
|
45
|
+
- Never fill the slot on the operator's behalf, the one move the plan standard forbids outright
|
|
46
|
+
- `reason: archived`: the plan sits in `.canon/plans/archive/` and describes shipped work, so repoint the row, since `auto-ship` Step 1 refuses the same file
|
|
43
47
|
|
|
44
48
|
### Refusals and staging
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
A refusal or a staged plan holds the row as surely as an open question.
|
|
51
|
+
|
|
52
|
+
- Any other refusal, or no `launchable` key: treat the row as unverified, name what could not be read, and fall back, since a gate reading nothing is not running
|
|
53
|
+
- A plan still staging batches in one file with `**Batch N**` sub-headings reports an `open` entry labeled `Batch staging`, so the row waits on a split
|
|
48
54
|
- A `Fan-in` entry holds a fan-in set, per `batches.md` in `plan-feature`
|
|
49
|
-
-
|
|
55
|
+
- A `Stacked sibling` entry means the plan stacks on a live sibling it mostly shares files with, so the row waits on a fold or a `Judged apart from` line
|
|
56
|
+
|
|
57
|
+
### What the gate reads
|
|
50
58
|
|
|
51
|
-
|
|
59
|
+
This gate runs first because it is the cheapest reading, needing no roster and no ref, and the only one asking about the row itself. It reads the plan rather than a cell describing one, since a cell omitting a renamed path clears a check the tree would fail.
|
|
52
60
|
|
|
53
|
-
|
|
61
|
+
A blank `- Answer:` is not an unanswered question, since `${CLAUDE_SKILL_DIR}/../plan-feature/references/plan.md` fixes an empty slot as accepting the suggestion. A gate reading every blank slot as open would refuse every plan in the folder.
|
|
54
62
|
|
|
55
|
-
|
|
63
|
+
- The narrow case is `- Suggested: needs your call, <why>` over an empty slot, the form the standard writes where the answer turns on preference
|
|
64
|
+
- Two demonstrated paraphrases read the same, `needs operator's call` and `needs the operator's call`
|
|
56
65
|
|
|
57
|
-
|
|
66
|
+
The gate prevents a halt nobody is watching for. `role-worker` correctly stops a session on a question written as needing the operator's call, so a dispatch that never reads the plan lands a worker waiting for a person who does not know it. The dispatch is the defect, not the halt.
|
|
58
67
|
|
|
59
68
|
## Check the branch is unclaimed
|
|
60
69
|
|
|
61
|
-
Run `canon sessions list --branch <type>/<slug> --json` and read `claimed` off the record.
|
|
70
|
+
Run `canon sessions list --branch <type>/<slug> --json` and read `claimed` off the record. The field is already the composed answer across the worktree listing, the live roster, and the refs naming the branch, so nothing here re-derives the OR.
|
|
62
71
|
|
|
63
|
-
- `claimed: true`:
|
|
72
|
+
- `claimed: true`: report what holds it, `worktree` naming a path, `sessions` carrying a row, or `refs` when the branch exists, and move to the next candidate
|
|
64
73
|
- `claimed: false`, `sessionsReadable: true`, and `refsReadable: true`: proceed to the conflict check.
|
|
65
|
-
- `claimed: false` with either flag false,
|
|
74
|
+
- `claimed: false` with either flag false, a refusal, or no `claimed` key, such as `no-registry` or `no-repository`: treat it as unverified and fall back to the human
|
|
75
|
+
- Dispatching on a check that could not be read reproduces the exact collision this exists to prevent
|
|
66
76
|
|
|
67
|
-
|
|
77
|
+
### The refs reading
|
|
68
78
|
|
|
69
|
-
`refs`
|
|
79
|
+
`refs` catches a shipped row, since a branch behind a merged pull request has no worktree and no session. Without it the check answered clear until a worker refused and named the cost: a second pull request against a merged head, a row citing two numbers, and `canon tasks archive`'s `ambiguous` refusal.
|
|
70
80
|
|
|
71
|
-
|
|
81
|
+
The ref read cannot see a branch pushed from another machine since the last fetch. A `git ls-remote` per dispatch costs 0.438s against 0.001s, so the gap is recorded rather than closed.
|
|
72
82
|
|
|
73
83
|
### A cloud worker's claim
|
|
74
84
|
|
|
@@ -78,32 +88,55 @@ A cloud worker never appears in the roster and never pushes the derived branch,
|
|
|
78
88
|
|
|
79
89
|
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.
|
|
80
90
|
|
|
81
|
-
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
|
|
91
|
+
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 alone, since a second dispatcher reads only git and the roster, so say so when reporting.
|
|
82
92
|
|
|
83
93
|
## Check for a conflict with the tracks in flight
|
|
84
94
|
|
|
85
95
|
No count binds this, and a shared file does not either. Hold a candidate behind a track in flight when any of these five holds, naming the hold and the track, and dispatch it otherwise:
|
|
86
96
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
- **Dependency.** The row or plan cites the track as something it waits on or builds over, including a stacked slice on the other's branch.
|
|
98
|
+
- **Contract.** One plan changes a contract the other consumes, such as an exported signature, a verb's flags or record, a cited skill step, or a config key.
|
|
99
|
+
- **Relocation.** One plan moves, renames, splits, or deletes a path the other writes or reads, which a rebase cannot settle mechanically.
|
|
100
|
+
- **Sweep.** One plan rewrites a file or folder wholesale, such as a terminology pass or a `canon/context/` reflow, and the other writes inside it.
|
|
101
|
+
- **A stated reason.** A singleton resource, or tracks interacting where no file reading shows, as a row creating a skill does with one counting that catalog.
|
|
102
|
+
|
|
103
|
+
Read a contract off the changing plan's `**Risks:**`, and both sides of a rename before the colon of a `**Files to touch:**` entry, per `${CLAUDE_SKILL_DIR}/../plan-feature/references/plan.md`. Nothing verifies a stated reason, so it stands only while the dispatcher applies it.
|
|
104
|
+
|
|
105
|
+
### A shared file is not a hold
|
|
106
|
+
|
|
107
|
+
Dispatch both and name the shared paths, so the merge order and the second branch's rebase are planned rather than discovered. The branch merging second resolves after the first merges, never against a sibling still building.
|
|
108
|
+
|
|
109
|
+
- It resolves by running `review-address` in the session that built it, whose Step 5 rebases the branch once it no longer merges
|
|
110
|
+
- A hunk needing a decision the tree does not carry goes to the controller
|
|
111
|
+
- A branch no live session holds gets the review-address shape in `orchestrator-launch.md`
|
|
92
112
|
|
|
93
|
-
|
|
113
|
+
### The evidence
|
|
94
114
|
|
|
95
|
-
No practitioner source serializes on a shared file. Each builds in parallel and tests at integration, where the merge surfaces a textual conflict and the suite
|
|
115
|
+
No practitioner source serializes on a shared file. Each builds in parallel and tests at integration, where the merge surfaces a textual conflict and the suite over the merged result a semantic one.
|
|
96
116
|
|
|
97
|
-
|
|
117
|
+
- Fowler's [branching patterns](https://martinfowler.com/articles/branching-patterns.html) have the second integrator pull mainline in and check health "even if it's a clean merge"
|
|
118
|
+
- His [Semantic Conflict](https://martinfowler.com/bliki/SemanticConflict.html) names self-testing code as the first defense, and [DORA](https://dora.dev/capabilities/trunk-based-development/) keeps branches to a few hours
|
|
119
|
+
- GitHub's [merge queue](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue) tests each pull request against everything queued ahead of it
|
|
120
|
+
- A candidate has no commits to trial-merge, so `git merge-tree` runs at integration and this check reads what a plan declares
|
|
98
121
|
|
|
99
|
-
|
|
122
|
+
### Reading the tracks
|
|
123
|
+
|
|
124
|
+
Read `canon sessions list --json` for the branches in flight as well as the board, since a hand-launched track carries no row, and read the plan of any branch no row names.
|
|
125
|
+
|
|
126
|
+
- `canon tasks validate` and `canon tasks plan-reach` report the paths two rows share, a candidate list for the five holds and the paths a dispatch names
|
|
127
|
+
- A shared folder means a Touches cell claimed it bare, so narrow that cell rather than reading the folder as a sweep
|
|
128
|
+
- A declared set predicts rather than bounds, since `canon:context-fold`, `canon:docs-sync`, and the drift stages write past every plan
|
|
129
|
+
- Such a crossing changes what the second branch rebases over, not whether a row holds, and `canon tasks plan-reach` at `canon:git-ship` step 5 names it
|
|
130
|
+
|
|
131
|
+
What binds past the five holds is review attention, which `## Parallelism` in the skill body states.
|
|
100
132
|
|
|
101
133
|
## Pick the model
|
|
102
134
|
|
|
103
135
|
This section binds every launch shape that names `<model>`, the planner and both reviewers as well as the step 4 build, none of which pass through that step.
|
|
104
136
|
|
|
105
|
-
A `claude --bg` session inherits the launching session's model, so an orchestrator on the larger model spends it on every
|
|
137
|
+
A `claude --bg` session inherits the launching session's model, so an orchestrator on the larger model spends it on every launch. Name `<model>` on each with one test: `opus` where a wrong result is costly and nothing automatic would catch it, `sonnet` otherwise, never `haiku`.
|
|
106
138
|
|
|
139
|
+
- Read the role's worst failure and whether a test, gate, or review stops it, never the folder or the plan's length
|
|
107
140
|
- Planner: `opus` for a row that changes a contract others consume, spans modules, or needs slicing. `sonnet` for a narrow row, even one inside a hook or governance folder.
|
|
108
141
|
- Worker, and the review-address pass against the findings in hand: `opus` where the plan leaves a cross-module call tests will not settle. `sonnet` where it pins the fix, however long.
|
|
109
142
|
- Code reviewer: `opus` where a miss would ship unseen, a change to behavior no test or gate exercises that other surfaces read. `sonnet` otherwise, a one-line hook edit included.
|
|
@@ -117,18 +150,25 @@ A row qualifies for that pick when its plan carries no open question and touches
|
|
|
117
150
|
|
|
118
151
|
## Dispatch
|
|
119
152
|
|
|
120
|
-
Read `${CLAUDE_SKILL_DIR}/references/orchestrator-launch.md` once every check above clears, and launch from its build template
|
|
153
|
+
Read `${CLAUDE_SKILL_DIR}/references/orchestrator-launch.md` once every check above clears, and launch from its build template, which sits beside the review-address and planning shapes that skip these checks. A cloud row launches from `${CLAUDE_SKILL_DIR}/references/orchestrator-cloud-launch.md`, since the VM shares no plugin or board.
|
|
121
154
|
|
|
122
155
|
## Fall back to the human
|
|
123
156
|
|
|
124
|
-
Hand the row to the human-launch line in step 4 instead of dispatching when any of these hold, and name which one
|
|
157
|
+
Hand the row to the human-launch line in step 4 instead of dispatching when any of these hold, and name which one. A shared file alone is not listed.
|
|
158
|
+
|
|
159
|
+
- The plan still waits on the operator
|
|
160
|
+
- The plan-answer read could not be taken, or the collision check refused
|
|
161
|
+
- The row holds behind a track already out on a dependency, a contract, a relocation, a sweep, or a stated reason
|
|
162
|
+
|
|
163
|
+
The first is the one that reaches a person rather than the board. A row held on its branch or under the conflict check waits on the wave clearing, and one held on its plan waits on an answer only the operator can give, so hand it over with the question label and its stated reason attached.
|
|
125
164
|
|
|
126
|
-
The
|
|
165
|
+
### The command to hand over
|
|
127
166
|
|
|
128
|
-
Hand the person one command
|
|
167
|
+
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. `auto-ship` Step 0 already enters the worktree.
|
|
129
168
|
|
|
130
|
-
|
|
169
|
+
- A second command risks a client folding two into one message, dropping the second, per `### Position zero` in `orchestrator-launch.md`
|
|
170
|
+
- Suggest in one line that the operator rename their own session to the row's id, so a process listing shows what the session is for
|
|
131
171
|
|
|
132
172
|
## Stop the loop
|
|
133
173
|
|
|
134
|
-
Wrapped in `/loop`, re-run the check against `## Run now` on each wake
|
|
174
|
+
Wrapped in `/loop`, re-run the check against `## Run now` on each wake, and stop once the group is empty or every row reads `claimed: true`. Report that once, on the wake that finds it, rather than polling a board nobody is clearing, the reasoning `orchestrator-poll.md` carries for the review trigger.
|
|
@@ -7,34 +7,71 @@ Read this at loop step 6, once the poll reports a branch stale or conflicted, or
|
|
|
7
7
|
|
|
8
8
|
## Sending the handback
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
10
|
+
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.
|
|
11
|
+
|
|
12
|
+
- Resolve the target at sending with `canon sessions list --branch`, never from an earlier mapping, since names rotate as sessions end
|
|
13
|
+
- A mapping recorded earlier in a session has failed inside the hour. `orchestrator-poll.md` routes on the count and the confidence the verb answers with.
|
|
14
|
+
- Open the message with the worktree and branch the sender believes the reader holds, asking to be corrected, whenever that mapping is inferred
|
|
13
15
|
- Name the skill for the reader to run rather than writing an invocation, which arrives as text
|
|
14
|
-
|
|
16
|
+
|
|
17
|
+
### Reading the draft flag
|
|
18
|
+
|
|
19
|
+
Read the pull request's own draft flag rather than the state a worker reports, and report what the read returned and when rather than the state alone. `canon pr head --help` states why a reported field can lag and say nothing about it.
|
|
20
|
+
|
|
21
|
+
The flag settles the question only once the worker's chain has run its undo, and nothing marks that moment. A read taken between the pull request opening and that call sees a ready pull request about to become a draft, and once told an operator the opposite of what the worker had said.
|
|
15
22
|
|
|
16
23
|
## The rebase handback
|
|
17
24
|
|
|
18
|
-
A `STALE` or `CONFLICT` from the poll goes to the branch's own session the same way, with `review-address` as the skill to run, since its staleness test rebases a branch `main` moved under even when the merge is clean.
|
|
25
|
+
A `STALE` or `CONFLICT` from the poll goes to the branch's own session the same way, with `review-address` as the skill to run, since its staleness test rebases a branch `main` moved under even when the merge is clean.
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
- Name what merged under the branch, being the pull request that landed and the files the poll listed, so the worker reads those hunks first
|
|
28
|
+
- Say that a check failing after a clean rebase is a semantic conflict to fix on the branch
|
|
29
|
+
- Say that a hunk needing a decision the tree does not carry comes back as a message rather than as a guess
|
|
30
|
+
- A pull request carrying review findings as well earns one message naming both, since one `review-address` run answers them together
|
|
21
31
|
|
|
22
32
|
The worker that built the branch rebases it, not this session. It holds the plan behind each hunk, and a rebase made here would also write a branch this session does not own.
|
|
23
33
|
|
|
24
34
|
## Re-review and reachability
|
|
25
35
|
|
|
26
|
-
A dispatched reviewer sends the `review-address` dispatch to the worker itself, carrying its own sessionId, and the worker sends the re-review request straight back to it. Neither leg passes through this session, which sends either one only as
|
|
36
|
+
A dispatched reviewer sends the `review-address` dispatch to the worker itself, carrying its own sessionId, and the worker sends the re-review request straight back to it. Neither leg passes through this session, which sends either one only as a fallback.
|
|
37
|
+
|
|
38
|
+
### A cloud reviewer's pass
|
|
39
|
+
|
|
40
|
+
A cloud session can send no message, and the script reports no code review posting on an unchanged head. The poll's cloud-reviewer rule reads `canon pr review-state` for each pull request a cloud reviewer holds and routes the dispatch here.
|
|
41
|
+
|
|
42
|
+
### No worker resolved
|
|
43
|
+
|
|
44
|
+
A reviewer reports that `canon sessions list --branch` returned no session or an unconfirmed match. Route it the way the poll's dispatch rule routes the count.
|
|
45
|
+
|
|
46
|
+
- On zero, launch the review-address shape in `orchestrator-launch.md`, carrying the reviewer's sessionId so the new worker answers the reviewer directly
|
|
47
|
+
- On an unconfirmed match, pick from a session listing and ask to be corrected, since a session may well hold the branch
|
|
48
|
+
|
|
49
|
+
### No reviewer resolved
|
|
50
|
+
|
|
51
|
+
A worker reports that the reviewer's sessionId resolved to no live session, or sends a re-review request with no reviewer named in its dispatch. Launch a fresh reviewer through the reviewer shape in `orchestrator-reviewer-launch.md`, never a pass in place, rather than messaging a name that no longer answers.
|
|
52
|
+
|
|
53
|
+
A re-review this session sends goes to the reviewer that took the first pass. Find a live `reviewer-<project>-<number>` through `canon sessions list --json` by name and message it to re-run `review-pr`, launching a fresh one only when none is live.
|
|
54
|
+
|
|
55
|
+
### When no session is live
|
|
56
|
+
|
|
57
|
+
A session is reachable when it appears in a live listing, which reads what each session registered on disk rather than probing it. A message carries plain text and no authority.
|
|
58
|
+
|
|
59
|
+
- When no live session holds the branch, launch the review-address shape in `orchestrator-launch.md`, which enters the branch's own worktree
|
|
60
|
+
- Only where that launch cannot run, report the invocation for the human, naming the branch, the pull request, and the skill, then stop
|
|
61
|
+
- Retrying or waiting leaves the loop believing it is open while nothing acts on it
|
|
27
62
|
|
|
28
|
-
|
|
29
|
-
- A reviewer reporting that `canon sessions list --branch` returned no session or an unconfirmed match. Route it the way the poll's dispatch rule routes the count: on zero, launch the review-address shape in `orchestrator-launch.md`, carrying the reviewer's sessionId so the worker it launches answers the reviewer directly, and on an unconfirmed match, pick from a session listing and ask to be corrected, since a session may well hold the branch.
|
|
30
|
-
- A worker reporting that the reviewer's sessionId resolved to no live session, or a re-review request from a worker whose dispatch named no reviewer. Launch a fresh reviewer through the reviewer shape in `orchestrator-reviewer-launch.md`, never a pass in place, rather than messaging a name that no longer answers.
|
|
63
|
+
## The return leg
|
|
31
64
|
|
|
32
|
-
|
|
65
|
+
The channel runs both ways, and the return leg carries what the pull request cannot. A worker answering a finding by naming the plan question that already declined it changes the outcome in the moment, where a thread comment waits on its next reader.
|
|
33
66
|
|
|
34
|
-
|
|
67
|
+
- Read what a worker volunteers as part of the review rather than as an aside, and read a refusal the same way
|
|
68
|
+
- The corrections that landed on this session's model of the world arrived as a worker arguing back rather than complying
|
|
69
|
+
- What the worker owes on its own side is stated in `role-worker`, being the announcement, the block message, and the board ban. Do not restate it here.
|
|
35
70
|
|
|
36
|
-
|
|
71
|
+
### Placing a reply
|
|
37
72
|
|
|
38
|
-
What
|
|
73
|
+
What arrives does not become a record by being read, so place it by what it changes. Writing a tracked file to hold it is forbidden, which leaves the pull request and the board as the two surfaces this session writes.
|
|
39
74
|
|
|
40
|
-
|
|
75
|
+
- An answer settling a finding goes onto the pull request through the next pass, which withdraws or regrades it and names the fact behind it, per `review-pr`
|
|
76
|
+
- An answer changing what this session believes, such as a mapping correction or a constraint on a worker, settles no finding and reaches no thread
|
|
77
|
+
- Route that second kind the way `## Boundaries` in the skill body routes a change found while orchestrating, onto the task owning the surface it describes
|