@erclx/canon 5.70.0 → 5.72.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/CHANGELOG.md +24 -0
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
- package/claude/skills/canon-feedback/SKILL.md +27 -2
- package/claude/skills/canon-feedback/references/template.md +22 -0
- package/claude/skills/git-pr/references/task-number.md +13 -0
- package/claude/skills/markdown-craft/references/markdown.md +1 -0
- package/claude/skills/plan-intake-answer/REQUIREMENT.md +4 -3
- package/claude/skills/plan-intake-answer/SKILL.md +35 -2
- package/claude/skills/review-ui/SKILL.md +1 -1
- package/claude/skills/review-ui/references/tick.md +17 -5
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +1 -0
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +6 -20
- package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +10 -0
- package/claude/skills/role-orchestrator/references/orchestrator-talk-launch.md +30 -0
- package/claude/skills/role-orchestrator/scripts/poll.ts +1 -1
- package/claude/skills/role-reviewer/SKILL.md +4 -0
- package/claude/skills/task-board/references/tasks-record-lines.md +40 -0
- package/claude/skills/task-board/references/tasks.md +4 -8
- package/claude/skills/ui-film/references/pr-clip.md +26 -2
- package/package.json +1 -1
- package/src/commands/feedback.ts +83 -3
- package/src/commands/markdown.ts +6 -1
- package/src/commands/pr.ts +66 -21
- package/src/commands/tasks.ts +133 -0
- package/src/feedback/body.ts +50 -0
- package/src/feedback/github-format.ts +77 -0
- package/src/feedback/github.ts +51 -12
- package/src/markdown/colons.ts +102 -16
- package/src/pr/carry.ts +64 -0
- package/src/pr/evidence.ts +1 -1
- package/src/pr/lift.ts +29 -12
- package/src/pr/review-state.ts +2 -0
- package/src/tasks/archive.ts +54 -1
- package/src/tasks/record.ts +118 -0
- package/src/tasks/validate.ts +37 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.72.0](https://github.com/erclx/canon/compare/v5.71.0...v5.72.0) (2026-10-27)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **feedback:** post a checked follow-up on an open feedback issue ([#2805](https://github.com/erclx/canon/issues/2805)) ([b014d5e](https://github.com/erclx/canon/commit/b014d5ed5a5501b0902aa4adf794dd50d715d7aa))
|
|
9
|
+
* **feedback:** read each issue's comments in triage ([#2802](https://github.com/erclx/canon/issues/2802)) ([ab2c761](https://github.com/erclx/canon/commit/ab2c7616c094ba43f4045c48f9fdbbe7bfb5b976))
|
|
10
|
+
* **intake:** offer to close an issue when its item is declined ([#2807](https://github.com/erclx/canon/issues/2807)) ([95df7da](https://github.com/erclx/canon/commit/95df7da6e6769b240e2565e24b12dc35f9233993))
|
|
11
|
+
* **pr:** carry a UI close only across pushes no box can observe ([#2804](https://github.com/erclx/canon/issues/2804)) ([c5102ea](https://github.com/erclx/canon/commit/c5102eaf5e6367b7335b8b66650ad03ca06dad41))
|
|
12
|
+
* **ui-film:** film one beat per group and skip negative boxes ([#2806](https://github.com/erclx/canon/issues/2806)) ([fb24ed3](https://github.com/erclx/canon/commit/fb24ed36c23e1e3bcb5c34b3d89c2321707873cd))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **pr:** drive rendered markdown outside doc folders in carry rule ([#2808](https://github.com/erclx/canon/issues/2808)) ([c1f1582](https://github.com/erclx/canon/commit/c1f1582b284eb25ed359915223e52182af073d97))
|
|
18
|
+
|
|
19
|
+
## [5.71.0](https://github.com/erclx/canon/compare/v5.70.0...v5.71.0) (2026-10-27)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* **markdown:** read colon lists as labels ([#2797](https://github.com/erclx/canon/issues/2797)) ([f733a5f](https://github.com/erclx/canon/commit/f733a5f8d74e63cf5e257557a4d227b3478ca04a))
|
|
25
|
+
* **tasks:** name the sessions behind a task on a Sessions line ([#2799](https://github.com/erclx/canon/issues/2799)) ([acf80c4](https://github.com/erclx/canon/commit/acf80c4ce9d2c1adbc3e1ea2dfde433a08d46b4e))
|
|
26
|
+
|
|
3
27
|
## [5.70.0](https://github.com/erclx/canon/compare/v5.69.0...v5.70.0) (2026-10-27)
|
|
4
28
|
|
|
5
29
|
|
|
@@ -14,7 +14,7 @@ Asked to report, a session also starts diagnosing, which spends the context the
|
|
|
14
14
|
## Must
|
|
15
15
|
|
|
16
16
|
- Build the report from what the session already holds, name the surface and its type, and write the stated fallback for a field it cannot fill
|
|
17
|
-
- Carry the whole request in the issue body
|
|
17
|
+
- Carry the whole request in the issue body, and what came after filing in a follow-up the CLI checks for links and for whether the fix still holds, never a hand-written comment
|
|
18
18
|
- Open a GitHub issue on the toolkit repository through the CLI and print the returned URL on its own line
|
|
19
19
|
- Surface the block and the reason when the issue call fails or the CLI is absent, so the report still exists
|
|
20
20
|
- Hold a report the operator marks sensitive, since the issue is public
|
|
@@ -17,6 +17,19 @@ Format a `## Toolkit feedback` block from the current session, then open it as a
|
|
|
17
17
|
|
|
18
18
|
## Step 1: build the block
|
|
19
19
|
|
|
20
|
+
### A follow-up or a new issue
|
|
21
|
+
|
|
22
|
+
Pick the form before filling any field, from what the session already holds.
|
|
23
|
+
|
|
24
|
+
- A follow-up, when the session cites an open feedback issue and the new case sits on its surface, such as a fix landing elsewhere, a second instance, or a finding that overturns the proposed fix
|
|
25
|
+
- A new issue, when no feedback issue is cited or the case sits on a different surface
|
|
26
|
+
|
|
27
|
+
For a follow-up, fill the `## Toolkit feedback follow-up` block in `${CLAUDE_SKILL_DIR}/references/template.md` and go to Step 2. For a new issue, build the report below.
|
|
28
|
+
|
|
29
|
+
A follow-up carries `### Observed`, `### Changes the fix`, and `### Links`, and the CLI refuses one missing any of them. `### Changes the fix` opens with yes or no, since a yes tells triage the body's fix no longer stands. `### Links` holds at least one URL or issue reference such as `frameboard#156`, never a bare name.
|
|
30
|
+
|
|
31
|
+
### The report fields
|
|
32
|
+
|
|
20
33
|
From the conversation so far, identify:
|
|
21
34
|
|
|
22
35
|
- Target project name or kind, never its path, which names one machine's folder and nothing triage routes on. Name a private project by kind, such as `a Next.js app`, since reports leave the machine.
|
|
@@ -56,7 +69,7 @@ Keep Observed and Expected to one or two lines each, so the report scans. Length
|
|
|
56
69
|
|
|
57
70
|
A GitHub issue form renders a submitted field as `### <label>`, so one shape reaches the toolkit whichever route a report takes, and the CLI parses both with one parser. The retired `**Surface:**` form is refused, so a block carrying it has to be rewritten.
|
|
58
71
|
|
|
59
|
-
The issue body is the request. Put everything the toolkit needs to act on it there, since a comment is easy to miss and a body and a comment that differ leave triage choosing. A comment carries only what happens after filing
|
|
72
|
+
The issue body is the request. Put everything the toolkit needs to act on it there, since a comment is easy to miss and a body and a comment that differ leave triage choosing. A comment carries only what happens after filing, and goes out as a follow-up through `canon feedback --on`, never a hand-written `gh issue comment`.
|
|
60
73
|
|
|
61
74
|
## Step 2: ship to the toolkit
|
|
62
75
|
|
|
@@ -78,14 +91,25 @@ cat <<'EOF' | canon feedback
|
|
|
78
91
|
EOF
|
|
79
92
|
```
|
|
80
93
|
|
|
94
|
+
A follow-up pipes the same way with the issue number, and the CLI refuses a closed issue or one without the `feedback` label before posting anything:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cat <<'EOF' | canon feedback --on <issue>
|
|
98
|
+
## Toolkit feedback follow-up
|
|
99
|
+
|
|
100
|
+
...
|
|
101
|
+
EOF
|
|
102
|
+
```
|
|
103
|
+
|
|
81
104
|
The CLI opens a GitHub issue on the toolkit repo, labeled `feedback` and each domain label the surface type names, such as `skills` for a plugin skill, and prints the issue URL for this skill to report on its own line. It needs `gh` authenticated, and `git-issue` is not the route, since it files on the current repository.
|
|
82
105
|
|
|
83
106
|
### Reading the outcome
|
|
84
107
|
|
|
85
108
|
Read the outcome off stdout, never off the exit code, since a shell wrapper can flatten it. Stdout takes one of three shapes:
|
|
86
109
|
|
|
87
|
-
- A line opening with `https://` is the filed issue. Report the URL.
|
|
110
|
+
- A line opening with `https://` is the filed issue, or the posted comment for a follow-up. Report the URL.
|
|
88
111
|
- A block opening with `## Toolkit feedback` is a failed call. Show it in chat with the stderr reason and `📋 Paste this into an issue at https://github.com/erclx/canon/issues/new`.
|
|
112
|
+
- The same block on a follow-up is a failed comment. Show it the same way, pointing the paste line at the issue's own URL.
|
|
89
113
|
- Empty stdout is a refusal. Step 3 says how to repair it from stderr.
|
|
90
114
|
|
|
91
115
|
If `canon` is not on PATH, fall back: print the block in chat and tell the user `📋 Copy the block above into a toolkit-repo session.`
|
|
@@ -95,4 +119,5 @@ If `canon` is not on PATH, fall back: print the block in chat and tell the user
|
|
|
95
119
|
A report that was not filed reads one of two ways on stdout, and stderr carries the reason in both:
|
|
96
120
|
|
|
97
121
|
- Empty stdout, with a named missing field on stderr. Add that heading with a real value or its stated fallback, then re-run. Do not report the defect as filed.
|
|
122
|
+
- Empty stdout on a follow-up naming a field, an unreadable number, a closed issue, or a missing label. Repair the field or number, or file a new issue for a closed or unlabeled one.
|
|
98
123
|
- The block on stdout, with `gh` absent or its call failed on stderr, which names which, since the two repairs differ. Show the block in chat with the reason and the paste line from Step 2.
|
|
@@ -51,3 +51,25 @@ Step 1 of `canon-feedback`. The session reads this file on reaching the point wh
|
|
|
51
51
|
|
|
52
52
|
<one link per line>
|
|
53
53
|
```
|
|
54
|
+
|
|
55
|
+
## Follow-up block
|
|
56
|
+
|
|
57
|
+
Step 1 fills this block instead of the report when the new case sits on an open feedback issue's surface, and Step 2 pipes it to `canon feedback --on <issue>`.
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
## Toolkit feedback follow-up
|
|
61
|
+
|
|
62
|
+
### Observed
|
|
63
|
+
|
|
64
|
+
<one or two lines on what happened after filing>
|
|
65
|
+
|
|
66
|
+
### Changes the fix
|
|
67
|
+
|
|
68
|
+
<yes or no, then one line on what replaces the proposed fix when yes>
|
|
69
|
+
|
|
70
|
+
### Links
|
|
71
|
+
|
|
72
|
+
<one URL or issue reference per line, such as frameboard#156>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Keep Observed to one or two lines, as in the report. The CLI checks the fields and their openings but not their length, so the density is this template's rule alone.
|
|
@@ -29,6 +29,19 @@ The verb resolves the board at the main worktree root in-process, the root `sess
|
|
|
29
29
|
- A line already reading as a list of `#NNN` entries takes the new number appended, reported as `appended`, so a task shipped in slices keeps every pull request
|
|
30
30
|
- The same write drops this branch from the `Pending branch:` line `canon tasks outcome` wrote, which lets the merge-time archive close the task
|
|
31
31
|
|
|
32
|
+
## Record the session
|
|
33
|
+
|
|
34
|
+
Beside the number, name this session on the same task's `Sessions:` line. It is the one record that covers a hand-launched worker, which no dispatcher saw start. Read the id from the roster's own row for the caller, then hand it to the verb under the same plan:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
id=$(canon sessions list --self --json | jq -r '.sessions[0].sessionId // empty')
|
|
38
|
+
[ -n "$id" ] && canon tasks session "$id" --plan feature-<slug> --json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- A dispatched worker is already listed, since its dispatcher recorded it at launch, and the verb reports `unchanged` rather than writing it twice
|
|
42
|
+
- An empty `id` means the roster could not name the caller, so skip the write and report that no session was recorded
|
|
43
|
+
- Skip the same three refusals as the number below, and report `bad-input` or `no-name`, since either is a defect in this call
|
|
44
|
+
|
|
32
45
|
## Refusals
|
|
33
46
|
|
|
34
47
|
Skip silently when the record is `ok: false` and `reason` is `no-board`, `no-match`, or `ambiguous`, meaning no board, no task naming the plan, or more than one. A guessed write would compound each, since a wrong match archives the wrong task unattended once the branch merges. Report any other refusal rather than swallowing it.
|
|
@@ -134,6 +134,7 @@ A bullet's punctuation follows its sentence count, and a list opens unannounced.
|
|
|
134
134
|
|
|
135
135
|
- Do not use em dashes (`—`) or semicolons (`;`). Rewrite or restructure the sentence to avoid them. A colon or a comma standing where the dash was is the same sentence, so split it or rewrite it.
|
|
136
136
|
- Do not use a colon to join two clauses in the middle of a sentence. A colon belongs after a label or at the end of a line introducing a list.
|
|
137
|
+
- The check misses a clause colon in a list of colon items, but it is wrong.
|
|
137
138
|
- Do not use parenthetical asides in prose (`the config (which is optional) controls...`). Split into its own sentence or drop it. Parentheses in rule definitions for grouping examples are fine.
|
|
138
139
|
|
|
139
140
|
## Language
|
|
@@ -15,15 +15,16 @@ The write fails where no prose rule catches it. A worker's file-editing tools re
|
|
|
15
15
|
|
|
16
16
|
- Offer every item with an empty slot, batched by cluster in the folder's numbering and capped at four items, so a stop leaves whole clusters unread
|
|
17
17
|
- Open each question with a lead-in an operator who has not opened the file can follow, then rank the item's own suggestion first and give every option its cost
|
|
18
|
-
- Land each selection through a verb that resolves the root in-process and rewrites the whole line, one cluster per call
|
|
19
|
-
- Pass the cluster and the label exactly as the heading spells them, letter suffix included
|
|
18
|
+
- Land each selection through a verb that resolves the root in-process and rewrites the whole line, one cluster per call, with the label as the heading spells it
|
|
20
19
|
- Report what stays unread by count after each cluster, and stop when there is no folder or no unread item
|
|
20
|
+
- Offer to close the issue an item headed `(#NNN)` names once its answer begins `decline`, with the drafted comment shown first, so closing takes one word
|
|
21
21
|
|
|
22
22
|
## Must not
|
|
23
23
|
|
|
24
24
|
- Fill a slot the operator did not answer, or infer an answer from the conversation having happened
|
|
25
25
|
- Overwrite a slot already carrying an answer
|
|
26
|
-
- Write anywhere but an item's answer slot, the index included
|
|
26
|
+
- Write anywhere but an item's answer slot, the index included, bar one exception, which is closing a declined item's issue on GitHub after a yes given for that issue in the turn its draft was shown
|
|
27
|
+
- Close an issue when the operator says no to the offer, gives no answer, or when the only yes came from another issue
|
|
27
28
|
|
|
28
29
|
## Out of scope
|
|
29
30
|
|
|
@@ -21,7 +21,7 @@ Read `${CLAUDE_SKILL_DIR}/../plan-intake/references/intake.md` before writing an
|
|
|
21
21
|
- If the named folder has no unread item, stop: `❌ Every item in <slug> carries an answer. Nothing to ask.`
|
|
22
22
|
- Never fill a slot the operator did not answer. An abandoned batch leaves every unreached item unread, which is what the empty slot already means.
|
|
23
23
|
- Never infer an answer from the conversation having happened. A selection reaches the file through the verb or not at all.
|
|
24
|
-
- Do not promote an item, edit a verdict, or write outside the answer slots. Promoting runs through `task-board` after the answers land.
|
|
24
|
+
- Do not promote an item, edit a verdict, or write outside the answer slots, bar the close Step 5 offers on an explicit yes. Promoting runs through `task-board` after the answers land.
|
|
25
25
|
|
|
26
26
|
## Step 1: pick the folder
|
|
27
27
|
|
|
@@ -72,7 +72,37 @@ canon intake answer <slug> --cluster <file> --set <label>=<answer> --set <label>
|
|
|
72
72
|
|
|
73
73
|
The verb refuses the whole batch when any item in it already carries an answer, since a filled slot is a decision already made. On that refusal, drop the named item and send the rest.
|
|
74
74
|
|
|
75
|
-
## Step 5:
|
|
75
|
+
## Step 5: offer to close declined issues
|
|
76
|
+
|
|
77
|
+
Run this after Step 4 lands a cluster, over the items that batch just answered. Closing is a public write, so each close waits on a yes given for that issue.
|
|
78
|
+
|
|
79
|
+
An item qualifies when both hold:
|
|
80
|
+
|
|
81
|
+
- The answer's first word is `decline`. Whatever follows it, as in `decline, but ask frameboard first`, stays on the item and still qualifies.
|
|
82
|
+
- The title ends in `(#NNN)`. Read that trailing number alone, so a title naming two issues, or a number sitting in prose, gets no offer.
|
|
83
|
+
|
|
84
|
+
Skip the whole step and say why when `gh auth status` fails or `gh` is absent. The answers already landed stay.
|
|
85
|
+
|
|
86
|
+
For each qualifying item:
|
|
87
|
+
|
|
88
|
+
1. Run `gh issue view <NNN> --json state --jq .state`. When it reads `CLOSED`, name the issue as already closed and offer nothing.
|
|
89
|
+
2. Draft the comment as one or two sentences condensed from the item's `problem` and `fix`, giving the reason and a pointer to what covers it.
|
|
90
|
+
3. Run the scan in `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md` against the draft, since nothing else checks text on its way to the remote.
|
|
91
|
+
4. Show the draft and ask for a yes or no on that issue in the same turn, through the question surface Step 3 used.
|
|
92
|
+
5. On a yes, close with the draft passed through a quoted heredoc. On a no, or no answer, leave the issue open.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
gh issue close <NNN> --reason "not planned" --comment "$(cat <<'EOF'
|
|
96
|
+
<comment>
|
|
97
|
+
EOF
|
|
98
|
+
)"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The quoted heredoc matters because `problem` and `fix` carry file paths in code spans. Inside a double-quoted argument the shell would run each backtick pair as a command and post a comment with the paths missing.
|
|
102
|
+
|
|
103
|
+
Never carry a yes from one issue or one turn to another.
|
|
104
|
+
|
|
105
|
+
## Step 6: continue or stop
|
|
76
106
|
|
|
77
107
|
After each cluster, state how many clusters still carry unread items and continue to the next. Stop when the operator says to stop, and report what is left rather than pressing on.
|
|
78
108
|
|
|
@@ -85,10 +115,13 @@ Report per cluster as it lands, then close with the folder's state:
|
|
|
85
115
|
```plaintext
|
|
86
116
|
✅ <N> answered in <file>
|
|
87
117
|
<label>. <answer>
|
|
118
|
+
🔒 Closed #<NNN>, or left open: #<NNN>
|
|
88
119
|
|
|
89
120
|
📋 <N> cluster(s) still carrying unread items in <slug>
|
|
90
121
|
```
|
|
91
122
|
|
|
123
|
+
Omit the 🔒 line for a cluster that offered no close.
|
|
124
|
+
|
|
92
125
|
Close the run with the path so the reader can open what changed:
|
|
93
126
|
|
|
94
127
|
```plaintext
|
|
@@ -26,7 +26,7 @@ A pass stops rather than repeat a verdict that already covers the head.
|
|
|
26
26
|
- An open verdict at the head stops the same way, unless a `## Review response` or `## Post-review findings` comment is newer, the launch names an address, or it drove no box, as `post.md` defines
|
|
27
27
|
- The hosted preview was not built from the head: stop and post nothing, naming `built`, `tip`, and `canon pr preview <number> --json` for the dispatcher
|
|
28
28
|
- Post, then run `canon pr lift <number>` on a close. Never merge or ready the PR by hand, and edit the evidence comment only through `canon pr tick`.
|
|
29
|
-
- A push after a close owes a re-drive
|
|
29
|
+
- A push after a close owes a re-drive unless every path it changed is inert, the list `references/tick.md` gives, since the lift carries the close across those alone.
|
|
30
30
|
|
|
31
31
|
## Step 1: resolve the pull request
|
|
32
32
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Tick the passed boxes
|
|
3
|
-
description: Step 8 of review-ui, which ticks each box that passed through canon pr tick once the verdict has posted, and reports a stale head instead of retrying
|
|
3
|
+
description: Step 8 of review-ui, which ticks each box that passed through canon pr tick once the verdict has posted, and reports an owed re-drive or a stale head instead of retrying
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Tick the passed boxes
|
|
@@ -15,14 +15,26 @@ canon pr tick <number> --boxes <n,...> --head <head> --json
|
|
|
15
15
|
|
|
16
16
|
Number the boxes off the `boxes` field Step 2 kept. Leave a box that failed, needs eyes, or was not driven empty.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## When the tip moved
|
|
19
|
+
|
|
20
|
+
A push that landed while this pass drove carries the ticks to the tip when it changed only paths no box observes. The record then reads `ticked` with the head it came from in `carriedFrom`.
|
|
21
|
+
|
|
22
|
+
- Tests, stories, snapshots, evidence captures, and `canon/design/` carry.
|
|
23
|
+
- Markdown carries only in the root and under `canon/`, `.claude/`, `.github/`, and `docs/`.
|
|
24
|
+
- Markdown anywhere else, such as a page a stack renders, is driven.
|
|
25
|
+
|
|
26
|
+
The verb refuses a taste box and a head the tip moved past in any other way, writing nothing in either case. Branch on the record's `reason`.
|
|
19
27
|
|
|
20
28
|
- `count-mismatch`: nothing was written. With `ticked` below `passed`, re-run once with every passed box. With it above, a box ticked earlier has failed, so report it on `Ticks:` for the operator.
|
|
21
|
-
- `
|
|
29
|
+
- `redrive-owed`: a push since `<head>` changed a path a box can observe. Report `driven`, `head`, and `drivenPaths` on the `Ticks:` line of Step 10, and never retry at the tip.
|
|
30
|
+
- `stale-head`: the driven head was rewritten away, by a force-push or a rebase, or the gap could not be read. Report it on the `Ticks:` line and never retry at the new tip.
|
|
22
31
|
- `body-refused`: the comment is ticked and the body is not. Retry the same call once, then report the partial result on the `Ticks:` line rather than claiming both.
|
|
23
32
|
- Any other refusal: report the `reason` on the `Ticks:` line and tick nothing further.
|
|
24
|
-
- A binary whose `canon pr` lacks `tick` predates the verb. Report that on the `Ticks:` line and tick nothing.
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
A binary whose `canon pr` lacks `tick` predates the verb. Report that on the `Ticks:` line and tick nothing.
|
|
35
|
+
|
|
36
|
+
## What a tick reports
|
|
37
|
+
|
|
38
|
+
The record's `countCheck` reads `matched` when the verdict's passed count agreed with the ticks, and `unchecked` when the verdict covered neither the tip nor the head a carry came from, or carried no count line. Report an `unchecked` on the `Ticks:` line.
|
|
27
39
|
|
|
28
40
|
The same call also writes the one UI pass line in the body's `## Testing`, such as `UI pass, 17 of 17 boxes passed at <sha>, 1 taste box left to the operator`, so the operator sees the result without opening the evidence comment. Never edit that line by hand.
|
|
@@ -86,6 +86,7 @@ The readout is the text `Created cloud session: <title>`, unanchored since a ter
|
|
|
86
86
|
- On a failed create, report the typescript's last lines and fall back to the human-launch line in `orchestrator-dispatch.md`
|
|
87
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
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
|
+
- Name it on the row's task with `canon tasks session "$session" <task> --name cloud-<project>-<slug> --json`, since a cloud worker has no board and the roster never lists it
|
|
89
90
|
- 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
|
|
90
91
|
|
|
91
92
|
## Recognize the pull request
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Orchestrator launch runbook
|
|
3
|
-
description: The launch every dispatch kind shares, being the build, cloud build, review-address, planning
|
|
3
|
+
description: The launch every dispatch kind shares, being the build, cloud build, review-address, and planning templates with a pointer to the talk variant, the session name and controller id each carries, why the command sits at position zero, and what the brief may carry
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Run this once `orchestrator-dispatch.md` has cleared a row, or from its planning or review-address shape below when that runbook's checks do not bind. The model each template names comes from `## Pick the model` in that runbook.
|
|
@@ -79,6 +79,10 @@ The prompt carries pointers and standing context, and stops there. The branch an
|
|
|
79
79
|
|
|
80
80
|
Report the dispatch as loudly as the human-launch line it replaces, naming the branch, the model, the task, and the session name, so a person reading the transcript can follow what fired without watching it happen.
|
|
81
81
|
|
|
82
|
+
### Record the worker on its task
|
|
83
|
+
|
|
84
|
+
Once a build or review-address launch returns, run `canon tasks session <worker-id> <task> --json` with the sessionId the launch output carries. On `no-name`, the worker already exited, so rerun with `--name` and the name passed to `-n`.
|
|
85
|
+
|
|
82
86
|
## Dispatch to a cloud worker
|
|
83
87
|
|
|
84
88
|
Read `${CLAUDE_SKILL_DIR}/references/orchestrator-cloud-launch.md` when `orchestrator-dispatch.md` picked cloud for the row. It holds the prompt that carries the plan as text and announces over GitHub, the create under `script`, and the readout that refuses to record a missing session id.
|
|
@@ -137,25 +141,7 @@ Hold all planning of a row any talk session has said by message it is planning,
|
|
|
137
141
|
|
|
138
142
|
## Dispatch a talk session
|
|
139
143
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
claude --bg --model <model> -n "planner-<project>-<slug>-talk" "Run /canon:role-planner, then /canon:plan-feature <task>. This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
|
|
144
|
-
claude --bg --model <model> -n "worker-<project>-<slug>-talk" "/canon:auto-ship <plan>
|
|
145
|
-
This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
The ellipsis stands for the rest of the cold template's message clauses, unchanged. The build variant keeps `/canon:auto-ship <plan>` at position zero with nothing before it, per the rule above.
|
|
149
|
-
|
|
150
|
-
- Keep the role prefix and add the suffix, since `orchestrator-handoff.md` separates dispatched sessions by `worker-` and `planner-` and a new prefix reads as a hand launch
|
|
151
|
-
- A talk session is retired only on the operator's word, stated once in `orchestrator-handoff.md`, so do not restate it in a launch report
|
|
152
|
-
- Reviewers get no talk shape, since a reviewer's pass holds no operator dialogue
|
|
153
|
-
|
|
154
|
-
### Recording the talk session
|
|
155
|
-
|
|
156
|
-
Read the session's `sessionId` off the launch output, carry it in this session's own context, and write it into the map's `## Talk sessions held open` at the next handoff. The client can rename a session and drop the suffix, so the id is the durable marker and the suffix is only for display.
|
|
157
|
-
|
|
158
|
-
The map exists only once the handoff writes it, so this session's own launches, read with the prior map, are what the first wind-down reads talk sessions from.
|
|
144
|
+
Read `${CLAUDE_SKILL_DIR}/references/orchestrator-talk-launch.md` when the operator will talk with a planner or worker rather than leave it to report back. It states the `-talk` name suffix, the one sentence the brief adds, and where the session's id is kept for the handoff.
|
|
159
145
|
|
|
160
146
|
## Hand launch
|
|
161
147
|
|
|
@@ -21,6 +21,16 @@ claude --bg --model <model> -n "reviewer-<project>-<number>" "Run /canon:role-re
|
|
|
21
21
|
- Append the cross-branch facts after the controller clause, per `### What the brief may carry` in `orchestrator-launch.md`
|
|
22
22
|
- Check `canon sessions list --json` for a live `reviewer-<project>-<number>` before launching, and message it instead when one holds the pull request
|
|
23
23
|
|
|
24
|
+
### Record the reviewer on the task
|
|
25
|
+
|
|
26
|
+
A reviewer writes no task file, so this session names it on the task the pull request closes, through the sessionId the launch output carries:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
canon tasks session <reviewer-id> <task> --json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Record the UI reviewer below the same way after its launch. A `no-name` refusal means the reviewer exited before the read, so rerun with `--name` and the name the launch passed to `-n`.
|
|
33
|
+
|
|
24
34
|
### The channel clauses
|
|
25
35
|
|
|
26
36
|
The channel clauses restate what `role-reviewer` holds, so a reviewer whose plugin cache predates that body still sends the dispatch itself. The worker reads the reviewer's sessionId off that message and sends its re-review request back to it, since a reviewer holds the trunk branch and no branch lookup finds it.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Orchestrator talk launch
|
|
3
|
+
description: The talk variant of the planning and build launches, being the name suffix, the one added brief sentence, and where the talk session's id is recorded for the handoff
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run this when the operator wants to talk with a planner or worker rather than leave it to report back. The rules every launch shares stay in `orchestrator-launch.md`.
|
|
7
|
+
|
|
8
|
+
# Talk launch
|
|
9
|
+
|
|
10
|
+
## The launch
|
|
11
|
+
|
|
12
|
+
A planner or worker the operator will talk with takes the same launch as its cold shape in `orchestrator-launch.md`, with a `-talk` suffix on its name and one sentence added to its brief. A cold session works alone and reports back, and a talk session stays open after its plan or pull request lands so the operator can keep shaping the row.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
claude --bg --model <model> -n "planner-<project>-<slug>-talk" "Run /canon:role-planner, then /canon:plan-feature <task>. This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
|
|
16
|
+
claude --bg --model <model> -n "worker-<project>-<slug>-talk" "/canon:auto-ship <plan>
|
|
17
|
+
This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The ellipsis stands for the rest of the cold template's message clauses, unchanged. The build variant keeps `/canon:auto-ship <plan>` at position zero with nothing before it, per `### Position zero` in `orchestrator-launch.md`.
|
|
21
|
+
|
|
22
|
+
- Keep the role prefix and add the suffix, since `orchestrator-handoff.md` separates dispatched sessions by `worker-` and `planner-` and a new prefix reads as a hand launch
|
|
23
|
+
- A talk session is retired only on the operator's word, stated once in `orchestrator-handoff.md`, so do not restate it in a launch report
|
|
24
|
+
- Reviewers get no talk shape, since a reviewer's pass holds no operator dialogue
|
|
25
|
+
|
|
26
|
+
## Recording the talk session
|
|
27
|
+
|
|
28
|
+
Read the session's `sessionId` off the launch output, carry it in this session's own context, and write it into the map's `## Talk sessions held open` at the next handoff. The client can rename a session and drop the suffix, so the id is the durable marker and the suffix is only for display.
|
|
29
|
+
|
|
30
|
+
The map exists only once the handoff writes it, so this session's own launches, read with the prior map, are what the first wind-down reads talk sessions from.
|
|
@@ -200,7 +200,7 @@ export const scopeFallback = (payload: Payload, now: number): Scope => {
|
|
|
200
200
|
|
|
201
201
|
/**
|
|
202
202
|
* Reads the UI family off the verb's record, so the poll and the lift agree on
|
|
203
|
-
* which head a close covers, a close carried across
|
|
203
|
+
* which head a close covers, a close carried across inert pushes included.
|
|
204
204
|
* A record carrying no `ui` object is a refusal or a CLI predating the field,
|
|
205
205
|
* and reads as unread, which leaves the baseline's value standing.
|
|
206
206
|
*/
|
|
@@ -74,6 +74,10 @@ Run `canon pr lift <number> --json` after posting `## Review closed` or `## UI r
|
|
|
74
74
|
|
|
75
75
|
Skip that message when the reason names the other review as open or missing, since the other reviewer's close runs the verb again.
|
|
76
76
|
|
|
77
|
+
### A re-drive owed
|
|
78
|
+
|
|
79
|
+
Message the controller when `canon pr tick` refuses `redrive-owed`, naming the driven commit, the tip in `head`, and the `drivenPaths`. A push the boxes can observe landed after the pass drove, so the next UI pass is a dispatch only the controller orders.
|
|
80
|
+
|
|
77
81
|
### Every other message
|
|
78
82
|
|
|
79
83
|
The rest of the channel is what this session never sends.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Task record lines reference
|
|
3
|
+
description: The lines a verb writes on a task below its origin lines, being the Pull request line that lets a merge close its task, the Pending branch marker that holds that merge back, and the Sessions line naming who worked it
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task record lines reference
|
|
7
|
+
|
|
8
|
+
Applies to the lines a task carries under its origin lines that no session writes by hand. Each one has a `canon tasks` verb as its writer, and this file fixes what each line means and who calls that verb.
|
|
9
|
+
|
|
10
|
+
This is an attribute standard. It governs lines inside a task file rather than a file of its own, so it carries no template.
|
|
11
|
+
|
|
12
|
+
## Scope
|
|
13
|
+
|
|
14
|
+
Governs the `Pull request:`, `Pending branch:`, and `Sessions:` lines.
|
|
15
|
+
|
|
16
|
+
Does not govern:
|
|
17
|
+
|
|
18
|
+
- The task file's layout, filename, format, origin lines, and archiving: `tasks.md`
|
|
19
|
+
- The `Declined:` line: `tasks-decline.md`
|
|
20
|
+
|
|
21
|
+
## The `Pull request:` line
|
|
22
|
+
|
|
23
|
+
`Pull request:` lists every pull request that shipped part of the task as bare numbers, oldest first and comma-separated, as in `Pull request: #NNN, #NNN`. It is not an origin, so a task without one is well-formed, and `git-pr` appends to it when a pull request opens.
|
|
24
|
+
|
|
25
|
+
The line lets a merge close its own task. `canon tasks archive --pull-request <n>` finds the task by any listed number and archives it only on the last.
|
|
26
|
+
|
|
27
|
+
- One pull request, one task. Two tasks naming the same number refuse to archive rather than both moving.
|
|
28
|
+
- `Pending branch: <branch>` holds that merge back while a branch that ticked an outcome waits on its own number
|
|
29
|
+
- `canon tasks outcome` writes that line, skipping it when the branch's pull request is already listed, and `canon tasks pull-request` clears it
|
|
30
|
+
|
|
31
|
+
## The `Sessions:` line
|
|
32
|
+
|
|
33
|
+
`Sessions:` names each session that built or reviewed the task, by roster name and full sessionId, as in `Sessions: <name> (<sessionId>), <name> (<sessionId>)`. A retro or a regression hunt reaches each transcript through `canon sessions export <sessionId>`, which takes the full id alone. It is not an origin either.
|
|
34
|
+
|
|
35
|
+
- `canon tasks session <sessionId> <task>` writes it, or `--plan <slug>` in place of the stem, so it is never hand-edited
|
|
36
|
+
- The verb reads the name off the live roster. A session that already exited takes `--name`, and so does a cloud session's `session_` id, since the roster never lists one.
|
|
37
|
+
- The id is the key. A repeat call for a listed id keeps the name first recorded, so two callers recording one worker write it once.
|
|
38
|
+
- The dispatcher records each worker and reviewer it launches, and `git-pr` records the session opening the pull request, which covers a hand launch
|
|
39
|
+
|
|
40
|
+
The line sits below the origin, `Pull request:`, and `Pending branch:` lines. `canon tasks validate` reports a line that does not parse as name and id pairs as `sessions-misshapen`.
|
|
@@ -29,6 +29,7 @@ Governs the task files under `.canon/tasks/`: folder layout, filenames, frontmat
|
|
|
29
29
|
Does not govern:
|
|
30
30
|
|
|
31
31
|
- **`tasks-decline.md`**: the declined folder, the `Declined:` line, and what declining does to a plan and a board row
|
|
32
|
+
- **`tasks-record-lines.md`**: the `Pull request:`, `Pending branch:`, and `Sessions:` lines a verb writes below the origin lines
|
|
32
33
|
- **`board.md`**: execution order, readiness groups, the backlog, and the generated index beside the tasks
|
|
33
34
|
- **`plan.md`**: the plan file a task cites, its sections, and its answer contract
|
|
34
35
|
- **`versioning.md`**: phase-label format and which surfaces a label may appear on
|
|
@@ -112,6 +113,7 @@ Groundwork: [<slug>](../groundwork/<slug>/)
|
|
|
112
113
|
Intake: [<slug>](../intake/<slug>/)
|
|
113
114
|
Issue: #NNN
|
|
114
115
|
Pull request: #NNN
|
|
116
|
+
Sessions: <name> (<sessionId>)
|
|
115
117
|
|
|
116
118
|
Why this task exists and what it depends on.
|
|
117
119
|
|
|
@@ -165,15 +167,9 @@ Three rules cover the line itself:
|
|
|
165
167
|
- Use `Intake:` rather than `Groundwork:` for an intake pass, so the line records which kind of pass produced the task
|
|
166
168
|
- `Intake:` names the folder rather than an item, and item numbers belong in the task's `## Findings`
|
|
167
169
|
|
|
168
|
-
### The
|
|
170
|
+
### The lines a verb writes
|
|
169
171
|
|
|
170
|
-
`Pull request:`
|
|
171
|
-
|
|
172
|
-
The line lets a merge close its own task. `canon tasks archive --pull-request <n>` finds the task by any listed number and archives it only on the last.
|
|
173
|
-
|
|
174
|
-
- One pull request, one task. Two tasks naming the same number refuse to archive rather than both moving.
|
|
175
|
-
- `Pending branch: <branch>` holds that merge back while a branch that ticked an outcome waits on its own number
|
|
176
|
-
- `canon tasks outcome` writes that line, skipping it when the branch's pull request is already listed, and `canon tasks pull-request` clears it
|
|
172
|
+
`Pull request:` and `Sessions:` are not origins, so a task without them is well-formed. A verb writes each, and `${CLAUDE_SKILL_DIR}/references/tasks-record-lines.md` fixes what they mean and who calls the verb.
|
|
177
173
|
|
|
178
174
|
## What goes in
|
|
179
175
|
|
|
@@ -30,13 +30,37 @@ The mode holds only while the caller names it. An ordinary run that finds a pull
|
|
|
30
30
|
|
|
31
31
|
## Choose the beats
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Film where motion is the claim. Filter the boxes first, then spend the three beats so each feature area shows its change once before any area shows two.
|
|
34
|
+
|
|
35
|
+
### Filter the boxes
|
|
36
|
+
|
|
37
|
+
A box is filmable when it asks the reviewer to click, fill, or scroll something and its result is a visible change.
|
|
34
38
|
|
|
35
39
|
- Skip a box ending in `(taste)`, since no driver judges it
|
|
36
40
|
- Skip a box that asks only to look at a state the page opens on, since a screenshot already shows it
|
|
41
|
+
- Skip a negative box, one asserting that something does not happen, such as "no drop line draws", since footage of nothing shows nothing
|
|
42
|
+
|
|
43
|
+
Read the box's text for the negative. A box asserting an unchanged result, such as "the board goes to all projects as before", is not negative, since the action still produces a visible change. Rank it behind a box in the same group that names new behavior.
|
|
44
|
+
|
|
45
|
+
### Order the beats
|
|
46
|
+
|
|
47
|
+
A group is the bold feature-area label above at most five boxes, as `ui-checklist` defines it.
|
|
48
|
+
|
|
49
|
+
1. Take one beat per group in checklist order, from the highest-ranked filmable box of each group, up to three beats.
|
|
50
|
+
2. When beats remain after every group has one, take a second pass in checklist order over the boxes left, highest-ranked first within each group, up to three beats in all.
|
|
51
|
+
|
|
52
|
+
A checklist with one group gives up to three beats from it. A checklist with four groups gives three beats, one from each of the first three.
|
|
53
|
+
|
|
54
|
+
### Plan the beats
|
|
55
|
+
|
|
56
|
+
Write one plan entry for each beat chosen, then skip when none was.
|
|
57
|
+
|
|
37
58
|
- Name each beat after its box's text, cut to the action
|
|
38
59
|
- Write the plan per `${CLAUDE_SKILL_DIR}/references/take-craft.md`, finding each target on the served page rather than guessing it
|
|
39
|
-
- With no box
|
|
60
|
+
- With no interactive box, skip as `no-interactive-box` and film nothing
|
|
61
|
+
- With interactive boxes that the filter removed, whether negative, static, or marked `(taste)`, skip as `no-visible-change` and film nothing
|
|
62
|
+
|
|
63
|
+
The negative test is a judgment over the box's text. A misread box costs a weaker reel and never a wrong pass, since the still check below guards the footage and the UI reviewer drives every box regardless.
|
|
40
64
|
|
|
41
65
|
Keep the whole reel at or under 12 seconds. Each beat opens and closes on a 0.6 s hold, so give each action's `wait` only what its result needs to settle.
|
|
42
66
|
|