@erclx/canon 5.77.0 → 5.79.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.
Files changed (125) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/app-drive/REQUIREMENT.md +12 -0
  4. package/claude/skills/app-drive/SKILL.md +44 -8
  5. package/claude/skills/app-drive/references/config.md +18 -8
  6. package/claude/skills/app-drive/references/drive-record.md +4 -0
  7. package/claude/skills/auto-ship/REQUIREMENT.md +1 -1
  8. package/claude/skills/auto-ship/SKILL.md +5 -4
  9. package/claude/skills/auto-ship/references/draft-mark.md +33 -15
  10. package/claude/skills/auto-ship/references/failure-recovery.md +4 -2
  11. package/claude/skills/auto-ship/references/ui-checklist.md +9 -1
  12. package/claude/skills/code-craft/REQUIREMENT.md +1 -1
  13. package/claude/skills/code-craft/SKILL.md +7 -0
  14. package/claude/skills/code-craft/references/adopted.md +8 -0
  15. package/claude/skills/git-followup/SKILL.md +1 -0
  16. package/claude/skills/git-pr/REQUIREMENT.md +2 -0
  17. package/claude/skills/git-pr/SKILL.md +2 -0
  18. package/claude/skills/git-pr/references/final-command.md +34 -2
  19. package/claude/skills/git-pr/references/pr.md +1 -1
  20. package/claude/skills/git-ship/REQUIREMENT.md +2 -2
  21. package/claude/skills/git-ship/SKILL.md +16 -11
  22. package/claude/skills/git-ship/references/ci-watch.md +28 -4
  23. package/claude/skills/markdown-craft/references/markdown.md +4 -4
  24. package/claude/skills/plan-feature/references/plan.md +2 -0
  25. package/claude/skills/pr-evidence/SKILL.md +6 -1
  26. package/claude/skills/pr-evidence/references/evidence.md +1 -0
  27. package/claude/skills/pr-evidence/references/reel.md +9 -1
  28. package/claude/skills/review-address/SKILL.md +2 -1
  29. package/claude/skills/review-craft/references/ui.md +13 -1
  30. package/claude/skills/review-pr/references/body-variants.md +2 -0
  31. package/claude/skills/review-pr/references/close-out.md +2 -0
  32. package/claude/skills/review-pr/references/key-changes.md +2 -1
  33. package/claude/skills/review-pr/references/post.md +1 -0
  34. package/claude/skills/review-ui/REQUIREMENT.md +1 -0
  35. package/claude/skills/review-ui/SKILL.md +2 -2
  36. package/claude/skills/review-ui/references/driving.md +32 -4
  37. package/claude/skills/review-ui/references/post.md +6 -2
  38. package/claude/skills/role-orchestrator/REQUIREMENT.md +1 -1
  39. package/claude/skills/role-orchestrator/SKILL.md +4 -4
  40. package/claude/skills/role-orchestrator/references/orchestrator-hand-launch.md +2 -0
  41. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
  42. package/claude/skills/role-orchestrator/references/orchestrator-limit-stops.md +47 -0
  43. package/claude/skills/role-orchestrator/references/orchestrator-output.md +24 -1
  44. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +3 -2
  45. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +35 -4
  46. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +1 -1
  47. package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +3 -1
  48. package/claude/skills/role-worker/SKILL.md +2 -1
  49. package/claude/skills/task-board/SKILL.md +1 -0
  50. package/claude/skills/task-board/references/tasks.md +1 -0
  51. package/claude/skills/test-craft/SKILL.md +1 -0
  52. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  53. package/claude/skills/ui-checklist/SKILL.md +2 -1
  54. package/claude/skills/ui-craft/references/capture.md +16 -0
  55. package/claude/skills/ui-film/REQUIREMENT.md +2 -2
  56. package/claude/skills/ui-film/SKILL.md +6 -1
  57. package/claude/skills/ui-film/references/compose-craft.md +68 -11
  58. package/claude/skills/ui-film/references/config.md +2 -2
  59. package/claude/skills/ui-film/references/handoff.md +1 -1
  60. package/claude/skills/ui-film/references/harness.md +71 -0
  61. package/claude/skills/ui-film/references/take-craft.md +42 -17
  62. package/docs/workflow/ai-workflow.md +1 -1
  63. package/docs/workflow/operating-model.md +6 -5
  64. package/docs/workflow/parallel-features.md +2 -1
  65. package/docs/workflow/visual-design-workflow.md +2 -1
  66. package/governance/ledger/skills/code-craft/SKILL.md +9 -0
  67. package/governance/ledger/skills/test-craft/SKILL.md +1 -0
  68. package/governance/ledger/skills/ui-craft/capture.md +18 -5
  69. package/package.json +4 -3
  70. package/src/commands/pr.ts +255 -46
  71. package/src/commands/sessions.ts +88 -6
  72. package/src/commands/take.ts +12 -1
  73. package/src/commands/tasks.ts +41 -2
  74. package/src/design/components.ts +5 -107
  75. package/src/design/favicon.ts +21 -17
  76. package/src/design/render.ts +9 -27
  77. package/src/design/template.ts +42 -0
  78. package/src/design/templates/favicon.svg +17 -0
  79. package/src/design/templates/hand-drawn-figure.css +54 -0
  80. package/src/design/templates/preview.html +27 -0
  81. package/src/design/templates/scrollbar.css +29 -0
  82. package/src/design/templates/status.css +24 -0
  83. package/src/gate/embedded.ts +400 -0
  84. package/src/gate/stages.ts +8 -0
  85. package/src/git/files.ts +5 -2
  86. package/src/indexes/frontmatter.ts +27 -6
  87. package/src/indexes/render.ts +21 -3
  88. package/src/markdown/colons.ts +14 -4
  89. package/src/markdown/heading-case.ts +9 -2
  90. package/src/pr/bijection.ts +8 -0
  91. package/src/pr/evidence.ts +81 -13
  92. package/src/pr/frames.ts +1 -6
  93. package/src/pr/health.ts +63 -15
  94. package/src/pr/lift.ts +77 -9
  95. package/src/pr/links.ts +160 -0
  96. package/src/pr/local.ts +17 -4
  97. package/src/pr/paths.ts +20 -2
  98. package/src/pr/rest.ts +2 -0
  99. package/src/pr/review-scope.ts +28 -0
  100. package/src/pr/review-state.ts +5 -5
  101. package/src/pr/waiver.ts +45 -0
  102. package/src/sessions/stop.ts +145 -0
  103. package/src/sessions/transfer/bundle.ts +1 -1
  104. package/src/take/camera.ts +337 -208
  105. package/src/take/encode.ts +16 -42
  106. package/src/take/film.ts +7 -1
  107. package/src/take/frame-clock.ts +46 -0
  108. package/src/take/log.ts +43 -2
  109. package/src/take/perform.ts +85 -13
  110. package/src/take/plan.ts +26 -5
  111. package/src/take/reel.ts +30 -5
  112. package/src/take/screencast.ts +223 -13
  113. package/src/take/stepper.ts +24 -4
  114. package/src/tasks/holders.ts +198 -0
  115. package/src/tasks/validate.ts +148 -0
  116. package/src/commands/fixtures/gh.sh +0 -64
  117. package/src/take/fixtures/busy.html +0 -107
  118. package/src/take/fixtures/fade.html +0 -49
  119. package/src/take/fixtures/fetch.html +0 -38
  120. package/src/take/fixtures/input.html +0 -138
  121. package/src/take/zoom/NOTICE.md +0 -45
  122. package/src/take/zoom/math-utils.ts +0 -69
  123. package/src/take/zoom/region-utils.ts +0 -55
  124. package/src/take/zoom/spring.ts +0 -133
  125. /package/src/sessions/{transfer/transcript.ts → transcript.ts} +0 -0
@@ -13,7 +13,7 @@ Do not output any text between steps and do not wait for user input. Tool permis
13
13
 
14
14
  ## Verify
15
15
 
16
- Run the verify commands `CLAUDE.md` names (lint, typecheck, tests) before the sequence starts. On a failure, stop: `❌ Verify failed. Fix the reported errors and run /git-ship again.` Make no fix attempt, since this skill is the resume point and the user is already making the fix.
16
+ Run the verify commands `CLAUDE.md` names (lint, typecheck, tests) before the sequence starts. On a failure, stop: `❌ Verify failed. Fix the reported errors and run /git-ship again with the same arguments.` Make no fix attempt, since this skill is the resume point and the user is already making the fix.
17
17
 
18
18
  When `CLAUDE.md` names no verify command, say so on one line and continue. A project with no suite is not a project with a failing one.
19
19
 
@@ -36,10 +36,10 @@ Run `git diff --cached --name-only 2>/dev/null` to check for staged files. If ou
36
36
  5. Run `canon tasks plan-reach <plan> --json`, naming this branch's plan by path or slug, and report both lists per `### Reading the reach` below. This step never stops the sequence.
37
37
  6. Invoke `canon:git-stage` to commit by concern, only when `git diff --cached --name-only` prints a path. When it prints nothing, the work already reached history in slices, so continue.
38
38
  7. Invoke `canon:git-branch` to rename branch to match conventional format
39
- 8. Invoke `canon:git-pr` to push branch and open pull request
39
+ 8. Invoke `canon:git-pr` to push branch and open pull request, passing `--draft` only when this skill's own arguments carry that exact token
40
40
  9. After the PR opens, watch CI in the background, so the session stays reachable while CI runs. Read `### Watching CI` below for the commands and the wake.
41
41
 
42
- A caller wrapping this sequence may act between step 8 and step 9, the one gap the order leaves open, since the pull request exists and nothing has read its checks. `auto-ship` marks the pull request draft there. A caller needing a step anywhere else is asking for a change to this body.
42
+ A caller wrapping this sequence may act between step 8 and step 9, the one gap the order leaves open, since the pull request exists and nothing has read its checks. `auto-ship` backs up its draft there, having passed `--draft` so the pull request opens as one. A caller needing a step anywhere else is asking for a change to this body.
43
43
 
44
44
  ### Reading the reach
45
45
 
@@ -62,21 +62,26 @@ The verb ships with the CLI and this body with the plugin, so an older binary me
62
62
  Run `canon pr checks <number> --json` once in the foreground. When no record comes back at all, the CLI predates the verb, so read `${CLAUDE_SKILL_DIR}/references/ci-watch.md` for the fallback watch. Otherwise start this loop through the Bash tool with `run_in_background` and a 60-minute timeout:
63
63
 
64
64
  ```bash
65
- until canon pr checks <number> --json | jq -e '.state != "pending" or .conflicted == true' >/dev/null; do sleep 30; done; canon pr checks <number> --json
65
+ until canon pr checks <number> --json | jq -e '.conflicted == true or (.state | IN("passing", "failing")) or (.reason | IN("no-remote-branch", "ambiguous-pull", "no-branch"))' >/dev/null; do sleep 30; done; canon pr checks <number> --json
66
66
  ```
67
67
 
68
+ The loop exits on a terminal state, a conflict, or one of the three permanent refusals, and polls through anything else. One failed GitHub call such as `gh-failed` never ends the watch while CI runs.
69
+
70
+ - A record carrying neither field, or an empty line from a crashed binary, waits for the next read too
71
+ - A refusal that never clears waits out the timeout rather than stopping at once
72
+
68
73
  Emit `⏳ Watching CI on #<number> in the background` and end the turn, printing nothing more while the watch runs. The wake resumes this step rather than restarting at step 1, and a wake landing inside another skill, such as a `review-address` pass, goes to whichever step is waiting on CI.
69
74
 
70
75
  ### Reading the wake
71
76
 
72
- Branch on the final record's fields rather than on the exit. Do not auto-fix any reading, and the watch line and a stop report are the two exceptions to the no-text-between-steps rule.
77
+ Branch on the final record's fields rather than on the exit. Do not auto-fix any reading except by the one cancelled-run rerun `ci-watch.md` states. The watch line and a stop report are the two exceptions to the no-text-between-steps rule.
73
78
 
74
- | Record | Route |
75
- | --------------------------------------- | ------------------------------------------------------------------------------------- |
76
- | `state: passing` | Settle the evidence thread below, then continue to After completion on `settled` |
77
- | `state: failing` | Stop the sequence and report the failing check with its URL |
78
- | `conflicted: true` | Stop and report the branch conflicts with its base, since no run will start. Rebase. |
79
- | A `reason` and no `state`, or a timeout | Read `${CLAUDE_SKILL_DIR}/references/ci-watch.md` for the refused and unsettled reads |
79
+ | Record | Route |
80
+ | --------------------------------------- | ----------------------------------------------------------------------------------------------------- |
81
+ | `state: passing` | Settle the evidence thread below, then continue to After completion on `settled` |
82
+ | `state: failing` | Read the cancelled-run section of `${CLAUDE_SKILL_DIR}/references/ci-watch.md`, which reruns or stops |
83
+ | `conflicted: true` | Stop and report the branch conflicts with its base, since no run will start. Rebase. |
84
+ | A `reason` and no `state`, or a timeout | Read `${CLAUDE_SKILL_DIR}/references/ci-watch.md` for the refused and unsettled reads |
80
85
 
81
86
  ### Settling the evidence thread
82
87
 
@@ -5,7 +5,7 @@ description: What the git-ship CI watch does when the installed CLI predates the
5
5
 
6
6
  # CI watch fallback and refusals
7
7
 
8
- Applies to step 9 of `git-ship` once the watch wakes on anything but a `state` of `passing` or `failing` or a `conflicted: true` record, and to a target whose CLI carries no `canon pr checks`.
8
+ Applies to step 9 of `git-ship` once the watch wakes on anything but a `state` of `passing` or `failing` or a `conflicted: true` record, to a `failing` record whose failed runs were all cancelled, and to a target whose CLI carries no `canon pr checks`.
9
9
 
10
10
  ## The fallback watch
11
11
 
@@ -23,9 +23,33 @@ Empty output stops rather than waits, since `no checks reported on the '<branch>
23
23
 
24
24
  ## Refused and unsettled reads
25
25
 
26
- Neither of these is a pass, and neither emits `✅ Shipped`.
26
+ None of these is a pass, and none emits `✅ Shipped`. A `reason` and no `state` means the read was refused, and the watch sorts refusals into two kinds.
27
27
 
28
- - A `reason` and no `state` means the read was refused, such as `no-remote-branch` for a branch deleted on the remote. Stop and report that `reason`.
29
- - A watch that hit its timeout and printed no final record is CI unsettled after 60 minutes, so report it that way
28
+ | Kind | Reasons | What the watch did |
29
+ | --------- | ------------------------------------------------------------ | ---------------------------------------------------------------- |
30
+ | Permanent | `no-remote-branch`, `ambiguous-pull`, `no-branch` | Exited on the first one, since no amount of waiting changes them |
31
+ | Transient | Every other reason, such as `gh-failed` or `runs-unreadable` | Kept polling, since the next read can clear |
32
+
33
+ The set lives in the watch command rather than in the verb, so a refusal `canon pr checks` adds later defaults to transient and waits, which is the safe side.
34
+
35
+ - A permanent refusal ends the sequence. Stop and report that `reason`, such as `no-remote-branch` for a branch deleted on the remote.
36
+ - A transient refusal in the final record came from the read after the loop, since the loop never exits on one. Read `canon pr checks <number> --json` once more and route on that.
37
+ - A second refusal on that read stops the sequence with its `reason`
38
+ - A watch that hit its timeout and printed no final record is CI unsettled after 60 minutes, so report it that way. A transient refusal that never cleared ends here too.
30
39
 
31
40
  Do not auto-fix any of these. A stop report is one of the two exceptions to the no-text-between-steps rule.
41
+
42
+ ## A failing record with only cancelled runs
43
+
44
+ A run cancelled by a runner or a superseded workflow reads as `failing`, and a reviewer reads it as a real failure. This section decides whether a `failing` wake reruns or stops, and the rerun is the one exception to the no-auto-fix rule.
45
+
46
+ List the failed check runs on the record's `tip`, keeping the newest run per check name as `canon pr checks` does, and print each run id when every one of them was cancelled. The read goes through REST, since `gh pr checks` runs on GraphQL and a cloud session's proxy refuses it:
47
+
48
+ ```bash
49
+ gh api "repos/{owner}/{repo}/commits/<tip>/check-runs?per_page=100" --jq '[.check_runs | group_by(.name)[] | max_by(.id) | select(.conclusion | IN("failure", "timed_out", "cancelled", "action_required", "startup_failure"))] | if length > 0 and all(.conclusion == "cancelled") then [.[].details_url | capture("/runs/(?<id>[0-9]+)").id] | unique | .[] else empty end'
50
+ ```
51
+
52
+ - A non-zero exit means the read was refused, so stop and report the refusal rather than reading it as a real failure
53
+ - An empty print on a zero exit means at least one check really failed, so stop and report it with its URL
54
+ - Otherwise run `gh run rerun <id> --failed` once per printed id, then start the watch again from `### Watching CI`
55
+ - Rerun once per ship. A second `failing` wake on the same cancelled runs stops and reports them as cancelled, naming each URL.
@@ -41,7 +41,7 @@ Does not govern:
41
41
  ## Headings
42
42
 
43
43
  - H1 for document title, H2 for main sections, H3 for subsections, and no H4
44
- - Use sentence case for every heading. The audit reports a heading or a frontmatter `title` with a capitalized word after the first.
44
+ - Use sentence case for every heading. The audit reports a heading or `title` with a capital after the first word, past any task phase label.
45
45
  - Proper nouns and product names keep their casing, whatever the audit reports
46
46
  - Shape a record as H2 per section and H3 per item a reader looks up by name. Use a table only for a fixed-shape set.
47
47
 
@@ -133,7 +133,7 @@ A bullet's punctuation follows its sentence count, and a list opens unannounced.
133
133
  ## Punctuation
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
- - 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.
136
+ - Do not use a colon to join two clauses in a sentence. A colon follows a label of three words or fewer, or ends a line introducing a list.
137
137
  - The check misses a clause colon in a list of colon items, but it is wrong.
138
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.
139
139
 
@@ -173,8 +173,8 @@ When frontmatter carries a `title` or `description` used for catalog display:
173
173
  ## Links and file references
174
174
 
175
175
  - Use descriptive anchor text for links. Avoid `click here` or `read more`.
176
- - Wrap file references in backticks by default. Never repeat the path verbatim as a link label.
177
- - Use a labeled markdown link (`[label](path)`) only on rendered-for-human surfaces (`README.md`, `docs/`) and in an index file, whose rows exist to be followed
176
+ - Wrap file references in backticks by default. Never repeat the path verbatim as a link label, bar a Key changes code span.
177
+ - Use a labeled markdown link (`[label](path)`) only on human-read surfaces (`README.md`, `docs/`), an index file, and a pull request body's Key changes
178
178
  - A relative link resolves against the filesystem over the corpus the ban scan reads, and one carrying a placeholder in angle brackets, such as `<slug>`, is an exempt illustration
179
179
 
180
180
  ## Examples
@@ -218,6 +218,8 @@ Every outcome reaches the review with its proof named.
218
218
 
219
219
  - Name, for each outcome, the test or the command that proves it, as one bullet leading with the outcome and ending on the command in backticks.
220
220
  - Write a command a later session can run as given, from the project root. A description of what would be checked leaves the executing session to invent the check.
221
+ - Write each command as one command, with no pipe, `&&`, `;`, or command substitution.
222
+ - A permission mode can refuse a compound form, and a substituted check no longer matches the plan, so reach a filter through a verb's own argument or flag, or name a test that holds it.
221
223
  - Name the visual check where no test reaches, and say it is visual, so a reader can tell a proof from a look.
222
224
 
223
225
  ### Risks
@@ -52,7 +52,12 @@ The no-local-preview and no-reel lines also land on the evidence comment, throug
52
52
 
53
53
  ### The uncaptured line
54
54
 
55
- Collect `📸 <N> painted paths changed with no evidence capture. Recapture and push.` when the evidence record lists `uncaptured` paths, with `<N>` its count. The line never stops the run, since no step here can take a capture, and the review raises the same paths as a finding until a recapture lands.
55
+ Collect `📸 <N> painted paths changed with no evidence capture. Recapture and push.` when the evidence record lists `uncaptured` paths, with `<N>` its count. It never stops the run. No step here can take a capture, so the gap reaches the thread and the lift by other routes:
56
+
57
+ - The evidence call writes an `**Uncaptured:**` line naming each path on the marked comment, posting it even on a head with no other news
58
+ - The line drops on the first render after a capture lands or a reel filmed at the head renders beside it
59
+ - `canon pr lift` refuses `painted-uncaptured` until a capture, a reel at the head, or a waiver in the newest review pass covers every listed path
60
+ - A worker never writes the waiver, since a review is the one surface a worker never posts
56
61
 
57
62
  ### The no-local-preview line
58
63
 
@@ -150,6 +150,7 @@ rmdir <main-root>/.canon/tmp/handoff/ui-checklist 2>/dev/null || true
150
150
 
151
151
  - The `rmdir` is a no-op while another branch's pending checklist sits in the folder, so this step never deletes a handoff not its own
152
152
  - `git-followup` re-runs `canon pr evidence` with no `--checklist`, and the verb carries the checklist forward out of the comment it edits
153
+ - Drop a carried checklist with `canon pr evidence <number> --no-checklist --json` and post its `ok` body, never a hand edit, which the next render undoes
153
154
  - A tick survives a render at the head its stamp names and is cleared by one at a newer head, so the next UI pass earns it again
154
155
 
155
156
  ## Post the preview address
@@ -36,7 +36,7 @@ Film where motion is the claim. Filter the boxes first, then spend the three bea
36
36
 
37
37
  A box is filmable when it asks the reviewer to click, fill, or scroll something and its result is a visible change.
38
38
 
39
- - Skip a box ending in `(taste)`, since no driver judges it
39
+ - Skip a box whose trailing markers hold `(taste)`, in any order, since no driver judges it
40
40
  - Skip a box that asks only to look at a state the page opens on, since a screenshot already shows it
41
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
42
 
@@ -80,6 +80,14 @@ Branch on the record's `reason`, never on the exit code.
80
80
  | `over-cap` | Drop `beat` and each beat after it, then film once more. Skip as `over-cap` if `beat` is first or it refuses again |
81
81
  | Any other value | Skip under that `reason`, such as `target-missing` with its `beat` |
82
82
 
83
+ ### A skip for a state the fixture lacks
84
+
85
+ A skip whose cause is a state the drive fixture lacks, such as `target-missing` on a control only that state renders, is work the building session owes.
86
+
87
+ - Film a beat from a box carrying `(needs fixture)` only if the state answers, and otherwise skip it as owed
88
+ - Report the owed skip on the evidence comment's `--reel-skip` line and in the closing report, naming the state, the selector, or the setup step the beat needed
89
+ - Never report it as a plain skip, since the next pull request meets the same fixture and skips again
90
+
83
91
  ## Check each still
84
92
 
85
93
  Open each beat's `still.jpg`, the closing frame the record names in its `still` field, and confirm it shows the state the beat's box describes. This check replaces the operator's approval, so it runs on every reel.
@@ -138,7 +138,8 @@ gh api -X POST 'repos/{owner}/{repo}/issues/<number>/comments' -F body=@.canon/t
138
138
 
139
139
  After the push, read Watching CI in `${CLAUDE_SKILL_DIR}/../git-ship/SKILL.md` without invoking that skill, start its background watch, end the turn on its line, and run the rest of this step and Step 8 on the wake. Reuse a watch already running on this PR, since it reads the new tip.
140
140
 
141
- - On the wake, stop on `conflicted` naming a rebase, on a `reason` naming it, and on a timeout reporting CI unsettled
141
+ - On the wake, stop on `conflicted` naming a rebase, and on a timeout reporting CI unsettled
142
+ - Route a `reason` through the refused reads in `${CLAUDE_SKILL_DIR}/../git-ship/references/ci-watch.md`, which re-read a transient one once and stop on a permanent one naming it
142
143
  - If any check fails, skip the edit and report the failing check so it can be fixed first
143
144
 
144
145
  When every finding is addressed and the state is `passing`, append the closing confirmation to the reply file Step 6 posted, so the thread carries one terminal state rather than a second comment. A rebase-only run appends the line `${CLAUDE_SKILL_DIR}/references/rebase-only.md` gives instead.
@@ -36,12 +36,24 @@ canon pr evidence <number> --check --json
36
36
 
37
37
  Read the record's `uncaptured` field, never the exit code.
38
38
 
39
- - It lists paths: the project keeps captures and this change skipped them. File a finding against the pull request naming each path.
39
+ - It lists paths: the project keeps captures and this change skipped them. File a should-fix naming each path, since `canon pr lift` refuses `painted-uncaptured` until each one is covered.
40
40
  - An empty list beside a changed `evidence/` image means the capture exists and the comment fails to show it. File that as a finding too.
41
41
  - An empty list with no changed `evidence/` image means the painting file sits outside the painted set, such as a token file. Raise a question naming the path.
42
42
  - It is absent: the base keeps no capture, or its tree went unread. Raise a question with no severity, since a project with no capture harness would otherwise take the flag on every styling change.
43
43
  - The record refuses: it decides nothing, so take the tree test under the last section instead
44
44
 
45
+ ### Waiving a capture
46
+
47
+ A worker may state why a listed path needs no capture, such as a change to keyboard focus order that no reachable state shows. Accept the exemption only when the diff bears it out, and leave the should-fix standing otherwise.
48
+
49
+ - Write the waiver line in this pass's body, in the form `${CLAUDE_SKILL_DIR}/../review-pr/references/post.md` gives, one line per path
50
+ - Keep it outside any code fence, since the lift skips a fenced line as a quoted sample
51
+ - Copy the path from the record, since the lift matches it only as `uncaptured` spells it
52
+ - Write the reason after the colon, since a line with none waives nothing
53
+ - Restate it in every later pass, a close-out included, since the lift reads only the newest marked pass of each family and never a reply
54
+
55
+ ### A recapture of the design
56
+
45
57
  A recapture under `canon/design/` redraws the accepted design rather than the built app, so it never stands in for an evidence capture. The verb leaves those paths out of `uncaptured`, and a pass clears a painted change on the evidence comment alone, however many design references beside it were redrawn.
46
58
 
47
59
  Stop reading this reference once the flag is raised, since there is nothing to open. Otherwise continue with the comment in hand.
@@ -63,6 +63,8 @@ A pass carrying nothing at all takes `## Review closed` and a short body, with t
63
63
  - A prior finding this pass withdrew leaves the count, and its line names the fact that settled it rather than a fix, per the withdrawal rule below
64
64
  - A closing remark that fits no prior finding, such as a ticked Testing box, takes one line of its own after them
65
65
 
66
+ Each capture waiver this pass still accepts takes its `- **Waived capture:**` line last, unfenced. The lift reads waivers from the newest pass alone, so a close-out that drops one withdraws it.
67
+
66
68
  ### Only minors
67
69
 
68
70
  A pass carrying only minors is an ordinary finding-carrying pass, so it takes the open heading and the full shape, since neither short line reports the minors. A pass carrying only Testing questions or only an unanswered reviewer request takes the same route. Keep whichever scope sentence the pass owes on the summary line:
@@ -19,6 +19,8 @@ gh api --paginate 'repos/{owner}/{repo}/pulls/<number>/reviews?per_page=100' --j
19
19
 
20
20
  Write the replacement body to `<body-file>`, the name `post.md` already derived at the top of Step 4. Keep the heading and the footer, and name what this pass covered on the scope line in place of what the old one covered.
21
21
 
22
+ Carry every `- **Waived capture:**` line the standing close-out holds into the replacement when this pass still accepts it. The lift reads waivers from the newest pass alone, so a rewrite that drops one withdraws it and the lift refuses `painted-uncaptured` again.
23
+
22
24
  - Derive that name the same way whichever path reached here, since the guard reads `<prior-heading>` alone and a repeated head resolves the third segment as usual
23
25
  - The folder then gains a record of every covered head rather than losing the one the standing comment named
24
26
 
@@ -16,11 +16,12 @@ Branch on the record rather than on the exit code, which a shell function wrappi
16
16
  | Field | Reading |
17
17
  | ------------ | -------------------------------------------------------------------------------------- |
18
18
  | `unmet` | a `should-fix` finding under the `**PR body**` block the stale box takes, one per path |
19
+ | `mislinked` | a `should-fix` finding under the same block, one per link, since it opens another file |
19
20
  | `unnamed` | read for yourself and raise nothing off the count |
20
21
  | `unresolved` | reported nowhere, since it was judged in neither direction |
21
22
  | `incidental` | reported nowhere, since it owes no bullet |
22
23
 
23
- Each `unmet` finding quotes the `preview` bullet and the `head`.
24
+ Each `unmet` finding quotes the `preview` bullet and the `head`. The exit is 2 for a `mislinked` entry too, so a body exiting 2 with `unmet` empty is not clean.
24
25
 
25
26
  ### Before filing an unmet path
26
27
 
@@ -65,6 +65,7 @@ X critical, Y should-fix, Z minor. Reviewed against project docs and the board.
65
65
  - Fix: the change
66
66
  - **minor** ([lines 30-34](<repo-url>/blob/<headRefOid>/path/to/file.ext#L30-L34)): what breaks, in one sentence.
67
67
  - Fix: the change
68
+ - **Waived capture:** `src/client/board/overlay.tsx`: keyboard focus order only, no visible change in any reachable state
68
69
 
69
70
  <details>
70
71
  <summary>Review focus, N checked</summary>
@@ -16,6 +16,7 @@ A model asked to drive a checklist also drifts. It judges a taste box the operat
16
16
  - Every checklist box is driven in the running app and gets one verdict, pass or fail with the value quoted, needs eyes for a taste box, or not driven with the reason
17
17
  - The checklist and address come from the evidence record rather than the diff, and only a build of the head the verdict names is driven
18
18
  - An unreachable address reports not driven rather than fail, a box no commit can settle leaves the review closed, and a pass that drove no box never reads as closed
19
+ - A box not driven for a state the drive fixture lacks is the exception, since the building session can add that state, so it opens the review. A state no fixture file can hold stays closed.
19
20
  - The review posts as its own pull request review under `## UI review` while anything is owed and `## UI review closed` once nothing is, ending on a marker naming the head it drove
20
21
  - The pass drives a pinned browser under its own named session and sweeps only console errors, overflow, and the focus, details, and axe probes, opening on an axe finding the CLI marks as gating
21
22
 
@@ -84,7 +84,7 @@ Take the first rung that answers, testing each with `curl -s -o /dev/null -w '%{
84
84
  2. The `local` address off the record.
85
85
  3. An address the launch names.
86
86
 
87
- When the hosted rung answers, read `${CLAUDE_SKILL_DIR}/references/hosted-preview.md` to check it was built from the head before driving. A pass on the local rung or a launch-named address skips it.
87
+ When the hosted rung answers, read `${CLAUDE_SKILL_DIR}/references/hosted-preview.md` to check it was built from the head before driving. A pass on the local rung or a launch-named address skips that check, and every rung then takes the config's `access` per `## The access join` in `${CLAUDE_SKILL_DIR}/references/driving.md`.
88
88
 
89
89
  ### Unverified and unanswered addresses
90
90
 
@@ -112,7 +112,7 @@ Read `${CLAUDE_SKILL_DIR}/references/driving.md` on reaching this step for how a
112
112
  - Make each box its own item on the session's task list, and tick it as its verdict lands. Skip it on a host that offers no list tool.
113
113
  - Give every box exactly one verdict, in checklist order, since skipping a box silently reads the same as passing it
114
114
  - Drive a box the pass could not place on a route or a width from the opened address at 1440 wide, and name the guess in the verdict
115
- - Never judge a box ending in `(taste)`. Drive to the state, capture both themes, and mark it needs eyes.
115
+ - Never judge a box whose trailing markers hold `(taste)`, in any order. Drive to the state, capture both themes, and mark it needs eyes.
116
116
  - Drive a ticked box the same as an unchecked one, at any head, since a tick is a claim this pass exists to check
117
117
 
118
118
  ### Push a frame
@@ -1,25 +1,36 @@
1
1
  ---
2
2
  title: Drive each box
3
- description: Step 5 of review-ui, which maps a checklist line to browser calls, reads each value off the page, and gives the box one of four verdicts with the evidence that verdict carries
3
+ description: The access join Step 3 of review-ui makes, then Step 5, which maps a checklist line to browser calls, reads each value off the page, and gives the box one of four verdicts with the evidence that verdict carries
4
4
  ---
5
5
 
6
6
  # Drive each box
7
7
 
8
8
  Step 5 of `review-ui`. The browser is open at the address Step 3 picked, under the session Step 4 named. Every call below goes through `canon browser -s=<project>-<number>`, shortened here to `pw`.
9
9
 
10
+ ## The access join
11
+
12
+ Step 3 reads this section once a rung answers. Read `access` from `canon/config/app-drive.toml` at the main worktree root, since a page needing a write link, a signed-in route, or a demo token shows its start state only behind it. An absent file or key opens the rung as it stands.
13
+
14
+ - Join a value starting with `/` to the rung, and take a full address as it stands. Step 4 opens the joined address alone.
15
+ - Every later route joins to the bare rung, never the joined address, since an `access` holding a query would swallow the path
16
+ - Test the rung bare in Step 3, so the `curl` spends no single-use link before the drive
17
+ - Take no `access` value from the launch brief, since the config is the one source
18
+ - Never print the joined address in a post, a frame, or a message, since `access` may carry a token. Name the rung and say the config's `access` was joined.
19
+
10
20
  ## Reading a line
11
21
 
12
22
  A box written to the drivable format reads:
13
23
 
14
24
  ```plaintext
15
- - [ ] <route>[, <width>]: <verb> <target> → <expected result>[ (taste)][ (local only)]
25
+ - [ ] <route>[, <width>]: <verb> <target> → <expected result>[ (taste)][ (local only)][ (needs fixture)]
16
26
  ```
17
27
 
18
- - **Route.** A path goes through `pw goto <address><path>`. A control name, or "from the page the app opens on", is reached by clicking from the opened address.
28
+ - **Route.** A path goes through `pw goto <rung><path>`, the rung before the access join. A control name, or "from the page the app opens on", is reached by clicking from the opened address.
19
29
  - **Width.** `pw resize <width> 900` before acting. A box naming no width is driven at 1440.
20
30
  - **Verb.** The action the driver performs: `click`, `fill`, `press`, `hover`, a scroll through `eval` of `scrollIntoView`, or a resize.
21
31
  - **`(taste)`.** The result is a judgment of look or feel. Capture, never judge.
22
32
  - **`(local only)`.** The state needs something a hosted preview cannot reach. On a hosted address the box is not driven, naming the marker as the reason.
33
+ - **`(needs fixture)`.** The drive fixture lacks the state. Drive the box if the state now answers, and otherwise it is not driven for a cause on the branch, as the verdicts below state.
23
34
 
24
35
  A box written before that format may carry no route, no width, and a verb such as "read" or "look at". Drive it anyway: take the opened address as the route and 1440 as the width, turn the verb into the nearest action, and name each guess in the verdict's evidence.
25
36
 
@@ -51,13 +62,30 @@ Each box takes exactly one, keyed here by the state it answers.
51
62
  - The evidence is the value read, quoted, such as `scrollWidth 436 against clientWidth 320`.
52
63
  - **pass or fail, frame.** The result has a stated criterion only an image settles.
53
64
  - The evidence is the matching evidence stem or the pushed frame's link, inline under the failed box's heading, and what the frame shows, in words.
54
- - **needs eyes.** The box ends in `(taste)`.
65
+ - **needs eyes.** The box's trailing markers hold `(taste)`, in any order.
55
66
  - The evidence is the dark and the light shot as a pair, each the matching evidence stem or a pushed frame's link, and what the frames showed, with nothing about whether it looks right.
56
67
  - **not driven.** The state could not be reached.
57
68
  - The evidence is the reason, such as an unreachable address, a `(local only)` box on a hosted preview, or a target the snapshot does not hold.
58
69
 
59
70
  A fail names what was expected beside what was read. A not driven never reads as a fail, since it says the pass could not look rather than that the page is wrong. Its reason says whether the cause sits on the page or off it, since only a cause on the page opens the heading Step 7 picks.
60
71
 
72
+ ### A state the fixture lacks
73
+
74
+ A box the pass could not drive because the drive fixture holds no such state is a cause on the branch, never a skip. The building session owes the state, and no other session can add it.
75
+
76
+ - Name the cause as a missing fixture state, with the state to add and the selector or setup step the box needs
77
+ - Count it as not driven, and never as a fail, since the page may be right
78
+ - An address that did not answer stays a cause off the branch, and a `(local only)` box on a hosted address does too
79
+ - A state no fixture file can hold is the exit, such as one a project with no `canon/config/app-drive.toml` cannot reach inline. Name it a cause off the branch, so the review stays closed.
80
+
81
+ ### A refused address
82
+
83
+ A permission rule or a classifier that denies the call opening or driving an address leaves the box not driven, for a cause off the branch. Name the refusal as the host worded it and the call it denied.
84
+
85
+ - Never retry through another route, being a second address, a different browser call, or a direct fetch, since the refusal is a decision about this pass rather than a fault to work around
86
+ - A refused opening call drives no box, so the pass posts open with the refusal as its cause line, per `${CLAUDE_SKILL_DIR}/references/post.md`
87
+ - Name the address by its rung and never print the joined `access`, which may carry a token
88
+
61
89
  ### Which image a verdict carries
62
90
 
63
91
  A pass or fail resting on a frame carries one image at most, and never one the worker's evidence already shows. A needs-eyes box carries the pair, dark and light, since a taste call is made by comparing them.
@@ -11,7 +11,10 @@ Step 7 of `review-ui`.
11
11
 
12
12
  The heading reports whether the branch owes anything, the way the code review's does.
13
13
 
14
- - `## UI review` when a box failed, the sweep raised a finding Step 6 names, the worktree check read `changed`, a box was not driven for a cause on the page, or the pass drove no box at all.
14
+ - `## UI review` when a box failed, the sweep raised a finding Step 6 names, the worktree check read `changed`, a box was not driven for a cause the branch holds, or the pass drove no box at all.
15
+
16
+ A missing fixture state opens the heading because a commit settles it, being the state the building session adds. That pass reaches `review-address` like a failed box, with the state to add named in the box's Not driven entry. A state no fixture file can hold, which `driving.md` names, is a cause off the branch and leaves the review closed.
17
+
15
18
  - `## UI review closed` otherwise.
16
19
 
17
20
  A needs-eyes box leaves the review closed, and so does a box not driven for a cause off the page, such as an address that did not answer or a `(local only)` box on a hosted preview, as long as something else was driven.
@@ -95,7 +98,7 @@ The post takes the length limits alone, with a box's reason under 350 characters
95
98
  The body opens on its count line, in that order, so the operator reads what they owe before anything else. The second line carries the address, the head, and the renderer, and says the address was driven unverified when it came from the local rung or the launch.
96
99
 
97
100
  - Drop each section holding no box, along with its heading. The order is fixed as Failed, Changed in the worktree, Needs your eyes, Not driven, then the folded blocks.
98
- - A box takes exactly one section by its verdict, so a box that fails and also ends in `(taste)` appears once, under Failed
101
+ - A box takes exactly one section by its verdict, so a box that fails and also carries `(taste)` appears once, under Failed
99
102
  - Quote page text in backticks as content, never as the pass's own words
100
103
 
101
104
  ### A loopback address
@@ -104,6 +107,7 @@ A loopback address has `localhost`, `127.0.0.1`, `0.0.0.0`, or `[::1]` as its ho
104
107
 
105
108
  - The cause line of a pass that drove no box, and every Not driven entry, name a loopback address it tried as a local preview with its port, such as `a local preview on port 4211`
106
109
  - A hosted address posts as written, since it outlives the session, and the close drops it from the evidence comment
110
+ - `<address>` is always the rung before the access join, followed by `behind the config's access` when one was joined, per `## The access join` in `${CLAUDE_SKILL_DIR}/references/driving.md`
107
111
  - The evidence comment carries the local link while the pull request is open, for an operator on the same machine
108
112
  - `canon pr local --remove` masks a loopback address left on a review's `Driven at` line when the pull request closes
109
113
 
@@ -9,7 +9,7 @@ description: What the one warm control session owns, why it plans and dispatches
9
9
 
10
10
  Without this skill, the control session builds or merges, and the cross-feature picture goes with it. Plans go out unread against each other and a moved tree, the queue empties or fills with whatever is oldest, a parked row's blocker is never re-tested, and a second orchestrator writes a board neither can read.
11
11
 
12
- The channel fails at every hand-off. A finding or a reply stays in a thread nobody re-reads, a dispatch launches a branch other than the one the check cleared, a wave's cost grows unweighed, a report buries the human's decision, and a compaction loses the way back in.
12
+ The channel fails at every hand-off. A finding or a reply stays in a thread nobody re-reads, a dispatch launches a branch other than the one the check cleared, a wave's cost grows unweighed, a report buries the human's decision, a compaction loses the way back in, and a wave a usage limit stopped reads as finished.
13
13
 
14
14
  ## Must
15
15
 
@@ -42,7 +42,7 @@ The human asks for each side of a compaction, and this skill reads the runbook.
42
42
 
43
43
  - On a request to write the handoff, follow `${CLAUDE_SKILL_DIR}/references/orchestrator-handoff.md`. It sends the generic half to `canon:session-map` and adds decisions taken under delegated authority.
44
44
  - That map follows `${CLAUDE_SKILL_DIR}/../session-map/references/session.md`. Write nothing to the handoff that the board, a task file, or a groundwork folder already carries.
45
- - Hand launch: `${CLAUDE_SKILL_DIR}/references/orchestrator-hand-launch.md`
45
+ - Hand launch: `${CLAUDE_SKILL_DIR}/references/orchestrator-hand-launch.md`. Limit stops, on request or on this session's first turn after: `${CLAUDE_SKILL_DIR}/references/orchestrator-limit-stops.md`.
46
46
  - A lesson about how to work goes to the owning task's Findings, as a bold-labeled line per `${CLAUDE_SKILL_DIR}/../task-board/references/tasks.md`
47
47
  - On a request to resume after a compaction, read `${CLAUDE_SKILL_DIR}/references/orchestrator-resume.md`, which reads that file back with the board and the groundwork behind the live work
48
48
 
@@ -56,7 +56,7 @@ A board that is not moving is a third such moment. On a request to re-test the p
56
56
 
57
57
  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, when the handoff matters, is when a long session is likeliest to have dropped it.
58
58
 
59
- 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`, so a person who knows their plugin root can follow one without this skill loaded.
59
+ Re-invoke `/canon:role-orchestrator` first whenever the session has run long or the ask goes unanswered. The runbooks sit under `references/`, so a person who knows their plugin root can follow one without this skill loaded.
60
60
 
61
61
  ## Output
62
62
 
@@ -101,9 +101,9 @@ Learning that a PR moved is the mechanical half. Read `${CLAUDE_SKILL_DIR}/refer
101
101
  A pass posting anything owed reaches the session holding the branch from the reviewer directly, and the re-review request goes straight back to that reviewer, per `role-reviewer` and `role-worker`. Read `${CLAUDE_SKILL_DIR}/references/orchestrator-handback.md` on reaching this step.
102
102
 
103
103
  - This session sends either leg only where a cloud reviewer posted the pass or one side reports the other unreachable
104
- - Each reviewer runs `canon pr lift` on its close. The verb lifts the draft once both reviews read closed at the head, the evidence settled, the head current, and CI passed.
104
+ - Each reviewer's close runs `canon pr lift`, lifting the draft once both reviews close at the head, the evidence settles, the head is fresh, and CI passes
105
105
  - Run it yourself when a close message reports a refusal other than the other review being open, or when a cloud reviewer's close posts, per Boundaries below
106
- - Then the human merges. After each merge, tell each trailing worker whose files the merged diff touches to run `review-address`, which rebases it where needed.
106
+ - Then the human merges from a line naming its proof, per `${CLAUDE_SKILL_DIR}/references/orchestrator-output.md`. Tell each trailing worker the merged diff touches to run `review-address`.
107
107
 
108
108
  The handback runbook holds how the message is addressed and worded, what to do when no live session holds the branch, and where a worker's reply goes.
109
109
 
@@ -24,6 +24,8 @@ The `Controller:` line replaces the background template's message clauses, which
24
24
 
25
25
  The first wave carries the worker. The wave after its pull request opens carries the reviewer alone.
26
26
 
27
+ Once the operator confirms a worker launched, run `canon tasks promote <stem>`, the same call a background launch makes. Nothing else moves a hand-launched row out of `## Up next`.
28
+
27
29
  ````markdown
28
30
  # Dispatch prompts
29
31
 
@@ -18,7 +18,7 @@ Read the threshold off `review-pr`, which states it once and governs the heading
18
18
 
19
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
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.
21
+ A chain's create drafts at once, so its pull request reads draft from the first read. Before a lift or a person readies it, a ready read means the create missed and the fallback mark has yet to run or has failed, so report it as that rather than as a settled state.
22
22
 
23
23
  ## The rebase handback
24
24
 
@@ -0,0 +1,47 @@
1
+ ---
2
+ title: Orchestrator limit stops runbook
3
+ description: Finding the sessions a usage limit stopped through the roster, and resuming each from its own record with one fixed message
4
+ ---
5
+
6
+ A usage limit stops every session on the account at once, and each one then reads `idle`, `shell`, or `waiting` as though it had finished. Run this pass on the operator's ask, or on this session's own first turn after a limit stop, once the limit has lifted.
7
+
8
+ ## Finding the rows
9
+
10
+ Read the roster and keep what this session can reach.
11
+
12
+ ```bash
13
+ canon sessions list --stopped --json
14
+ ```
15
+
16
+ - Keep this repository's rows and report the rest to the operator, since `session-relay` refuses a send across repositories
17
+ - Report `stopsUnread` when it is above zero, since those rows may be stopped and nothing will message them
18
+ - Report `foreignDead` when it is above zero, since this reader could not check those sessions at all
19
+ - Find each row's task with `grep -l <sessionId> .canon/tasks/*.md` at the main worktree root, since `canon tasks session` writes the id there
20
+ - Report a refusal of the flag as an older CLI behind the plugin, never as an empty list
21
+
22
+ ### What the watch cannot tell you
23
+
24
+ `orchestrator-watch.md` reads a worker gone idle as finished, so a limit-stopped worker reports that way there. Its `WORKER-STOPPED` line means a long `waiting` row and says nothing about a limit, so read the `stopped` field in full on every row this pass decides.
25
+
26
+ ## Sending
27
+
28
+ Each row takes the same message with its own record filled in.
29
+
30
+ ```plaintext
31
+ The usage limit lifted. Re-read <record> and continue. Re-run any command whose result you never read.
32
+ ```
33
+
34
+ The last sentence covers a session stopped between starting a command and reading what came back, such as a reviewer stopped mid-lift.
35
+
36
+ Fill `<record>` by the row's role, read off its name. A row with a task and a feature branch whose name states no role is a hand-launched worker.
37
+
38
+ | Row | `<record>` |
39
+ | -------- | ---------------------------------------------------------------------------------- |
40
+ | Worker | The plan its task links |
41
+ | Reviewer | The pull request its name carries, through `canon pr review-state <number> --json` |
42
+ | Planner | Its task |
43
+ | No task | Its branch, and list the row to the operator |
44
+
45
+ Send each row the message once through `canon:session-relay`, then run the roster read again.
46
+
47
+ Never send a row the message twice in one pass. A row still reading stopped on the second read either has not drained the message or stopped again, and a new stop can carry the same reset text as the one before. Report it with its reset to the operator and hold the rest of the wave.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Orchestrator output formats
3
- description: The invocation block with its four sections, the three-slot shape every later report opens with, and the rule against a shape for a correction
3
+ description: The invocation block with its four sections, the three-slot shape every later report opens with, the proof a merge line names, and the rule against a shape for a correction
4
4
  ---
5
5
 
6
6
  Read this on invocation, before reporting the state of play, and again before any later report.
@@ -70,4 +70,27 @@ Keep the detail below the block and keep it skippable. A decision reached at the
70
70
  - A rename leaves the launch name matching nothing, so read the current name off `canon sessions list --json` when the line is written
71
71
  - `claude rm` takes the id alone, so that line carries the id
72
72
 
73
+ ## The merge line
74
+
75
+ A pull request recommended for merge names the proof its evidence comment carries, beside the merge command, since a lift's `ok` says the gates held and nothing about what anyone could look at.
76
+
77
+ ```plaintext
78
+ PR #<n> <title> proof: <screenshots|reel|screenshots and reel|waived|none>
79
+ → canon pr merge <n>
80
+ ```
81
+
82
+ Read the slot off `canon pr evidence <number> --json` at the moment the line is written, branching on the record rather than the exit code.
83
+
84
+ - `screenshots` when the record carries `states`, and `reel` when it carries `reel`
85
+ - `waived` when neither is carried and `canon pr lift <number> --check --json` names every listed path under `waived`, quoting no token from the reason
86
+ - `none` otherwise, and a pull request with no painted path takes no slot at all
87
+
88
+ ### An unproven painted pull request
89
+
90
+ A painted pull request whose slot reads `none` is unproven. Report it as unproven, never as ready, whatever the lift returned, and put the missing proof to the operator as a decision.
91
+
92
+ - Painted means the record carries a `checklist`, or the check record lists `uncaptured` paths
93
+ - A project whose base keeps no captures reads `uncaptured` absent, so a checklist with no stills and no reel is still unproven there
94
+ - Send the branch's session back to run `pr-evidence` under the proof check in `orchestrator-review-dispatch.md`, rather than recommending the merge
95
+
73
96
  Write no shape for a correction. A correction is a sentence, and a format for admitting error invites ceremony where plainness is the whole value.
@@ -47,8 +47,9 @@ bun <POLL_SCRIPT> --wait 1200
47
47
  Act on what the poll printed when it exited, then start it again.
48
48
 
49
49
  - A release pull request, whatever state follows it: report it and stop. Its sweep carries no findings, so no pass is owed. Test this before any rule below, since a release pull request is reported OPENED like any other and would otherwise match that rule first.
50
+ - MOVED, before the rule below: run the review dispatch runbook's proof check on the new head. A head first carrying an uncaptured path, or owing evidence, goes back to its worker and holds the re-review. One first carrying a `drivable` box with no UI reviewer launched takes one now.
50
51
  - MOVED or RESPONSE on a pull request already reviewed: when a live local reviewer holds it, report it and stop, since the worker asks that reviewer for the re-review directly. When none does, which a cloud reviewer always leaves, launch a fresh reviewer under the review dispatch runbook of the canon:role-orchestrator skill. Never run the canon:review-pr skill here. Re-reviews read prior..head and gain nothing from waiting.
51
- - OPENED, or a pull request with no prior review pass: launch its reviewer under the review dispatch runbook of the canon:role-orchestrator skill, and its UI reviewer beside it when the evidence record carries a checklist. Never run the first pass here. A draft counts, since every pull request here opens as one and skipping drafts skips everything.
52
+ - OPENED, or a pull request with no prior review pass: once that runbook's proof check reads proof, launch its reviewer under the review dispatch runbook of the canon:role-orchestrator skill, and its UI reviewer beside it when the evidence record counts a `drivable` box. Never run the first pass here. A draft counts, since every pull request here opens as one and skipping drafts skips everything.
52
53
  - SEEN: report it and stop. A pass already covers that head, whether it arrived out of band or before the poll first saw the pull request, so no review follows.
53
54
  - STALLED: read the last pass and report what it carried. The pass has sat open for hours with nothing following it, so a worker mid-task is already ruled out and the dispatch either never went out or the session holding it is gone. Confirm and re-send it under the dispatch rule below, whatever grades the pass carried. Do not re-run a review to correct the heading, since a pass on an unchanged head with no response behind it stops by design.
54
55
  - CONFLICT or STALE: send the session holding that branch the rebase handback in the canon:role-orchestrator skill's handback runbook, resolving it the way the handback rule below does. The branch owner rebases, not this session. The poll prints one of the two for a pull request, never both, so it earns one message. The canon pr lift verb refuses on either standing itself, since the green run tested a main that no longer exists, so nothing here lifts the mark.
@@ -80,7 +81,7 @@ The eight headings the script knows are written by `review-pr`, `review-address`
80
81
  - The reply family matches by a filter in `poll.ts`, so a project posting it under different headings edits that
81
82
  - The review and UI families match inside `canon pr review-state`, which the script and `review-pr` both read, so renaming one changes the verb
82
83
  - The `UI-` states report the newest UI pass on its transition, and `UI-STALE` fires beside the `MOVED` of a push that left its marker behind
83
- - A first sighting reports no `UI-` state at no cost to the mark, since `canon pr lift` reads the UI review itself and holds the mark on a `canon pr evidence` checklist until a UI close names the head
84
+ - A first sighting reports no `UI-` state at no cost to the mark, since `canon pr lift` reads the UI review itself and holds the mark on a drivable checklist until a UI close names the head
84
85
 
85
86
  ### UNMATCHED and RESPONSE
86
87