@erclx/canon 5.10.0 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
- package/claude/skills/auto-ship/SKILL.md +5 -8
- package/claude/skills/auto-ship/references/failure-recovery.md +0 -1
- package/claude/skills/auto-ship/references/ui-checklist.md +21 -0
- package/claude/skills/git-pr/references/evidence.md +7 -7
- package/claude/skills/git-ship/REQUIREMENT.md +1 -1
- package/claude/skills/git-ship/SKILL.md +1 -1
- package/claude/skills/review-craft/references/ui.md +1 -2
- package/claude/skills/review-pr/SKILL.md +1 -1
- package/claude/skills/role-orchestrator/SKILL.md +2 -2
- package/claude/skills/ui-checklist/SKILL.md +1 -18
- package/docs/agents/gate.md +1 -1
- package/docs/agents/hooks.md +2 -0
- package/docs/agents/index.md +2 -2
- package/docs/agents/install-and-sync.md +2 -2
- package/docs/agents/pr-evidence.md +70 -22
- package/docs/agents/tasks-validate.md +3 -3
- package/docs/agents/worktrees.md +16 -1
- package/docs/target/migrations.md +1 -1
- package/docs/workflow/ai-workflow.md +2 -1
- package/docs/workflow/parallel-features.md +3 -3
- package/docs/workflow/skill-map.md +1 -1
- package/package.json +3 -4
- package/scripts/lib/sandbox-path.sh +1 -1
- package/src/commands/gate.ts +3 -2
- package/src/commands/pr.ts +93 -19
- package/src/commands/worktrees.ts +37 -0
- package/src/gate/sequencer.ts +0 -20
- package/src/gate/stages.ts +10 -3
- package/src/pr/evidence.ts +35 -0
- package/src/tasks/validate.ts +37 -27
- package/src/worktrees/bare-flag.ts +83 -0
- package/standards/tasks.md +1 -1
- package/tooling/base/configs/.husky/post-merge +30 -77
- package/tooling/base/configs/.husky/post-rewrite +3 -3
- package/tooling/base/reference.md +1 -1
- package/scripts/core/clean.sh +0 -36
- package/scripts/core/regen-agent-fixture.sh +0 -235
- package/scripts/core/regen-claude-copies.sh +0 -10
- package/scripts/core/regen-indexes.sh +0 -10
- package/scripts/core/repair-bare-flag.sh +0 -19
- package/scripts/core/snapshot.sh +0 -134
- package/scripts/core/update.sh +0 -35
- package/scripts/lib/worktree.sh +0 -20
|
@@ -21,6 +21,7 @@ Review is the step that varies most. It gets skipped on a diff that needed one,
|
|
|
21
21
|
- Own the review receipt's lifetime, since this chain writes it, cites it in its own closing block, and is the only body that can read whether the step keeping it is still using it
|
|
22
22
|
- Delegate the ship sequence to `git-ship` rather than restating it, and name only what this chain adds to it
|
|
23
23
|
- Open the pull request as a draft before the continuous integration watch begins, since a pull request marked after it is mergeable for the length of the run
|
|
24
|
+
- Continue past a produced UI checklist rather than stopping on it, and report its unchecked boxes in the closing block, since the draft mark already holds the merge and a stop there skipped review on the resumed path
|
|
24
25
|
- Prove the draft target's head is the current branch and its state is open before marking it, and stop with nothing marked on a mismatch, since the number is retyped between steps and a draft mark on a release pull request holds that release
|
|
25
26
|
- Name the recovery for the stop it took, since the value of stopping is that the user knows where to resume
|
|
26
27
|
|
|
@@ -6,7 +6,7 @@ disable-model-invocation: true
|
|
|
6
6
|
|
|
7
7
|
# Auto ship
|
|
8
8
|
|
|
9
|
-
Chain the post-plan pipeline in a single run. Every step has a stop condition. State is always recoverable on stop: code lives on the branch, review output on disk, plan still linked.
|
|
9
|
+
Chain the post-plan pipeline in a single run. Every step but the UI checklist has a stop condition. State is always recoverable on stop: code lives on the branch, review output on disk, plan still linked.
|
|
10
10
|
|
|
11
11
|
## Guards
|
|
12
12
|
|
|
@@ -95,11 +95,7 @@ Never read a missing subcommand as clean. Read `${CLAUDE_SKILL_DIR}/references/v
|
|
|
95
95
|
|
|
96
96
|
## Step 5: UI checklist (conditional)
|
|
97
97
|
|
|
98
|
-
If the diff touches UI files (JSX, TSX, Vue, Svelte, HTML, or CSS under `src/`), invoke `canon:ui-checklist
|
|
99
|
-
|
|
100
|
-
If `ui-checklist` produces a checklist, stop: `❌ UI requires visual verification. Checklist at .canon/tmp/handoff/ui-checklist/<slug>.md, which reaches the pull request once /git-ship runs. Verify manually, then run /git-ship.`
|
|
101
|
-
|
|
102
|
-
If there is nothing to verify visually and nothing shipping untested, continue.
|
|
98
|
+
If the diff touches UI files (JSX, TSX, Vue, Svelte, HTML, or CSS under `src/`), invoke `canon:ui-checklist`, then continue to Step 6 whatever it returns, in every run. The Step 8 draft mark holds the merge, so a stop here protects nothing. When it produces a checklist, read `${CLAUDE_SKILL_DIR}/references/ui-checklist.md` for the counts to hold before `git-pr` removes the file.
|
|
103
99
|
|
|
104
100
|
## Step 6: review
|
|
105
101
|
|
|
@@ -149,10 +145,11 @@ Emit the Output block on the wake after `git-ship`'s background CI watch exits o
|
|
|
149
145
|
|
|
150
146
|
## Output
|
|
151
147
|
|
|
152
|
-
Respond with up to
|
|
148
|
+
Respond with up to six lines:
|
|
153
149
|
|
|
154
150
|
```plaintext
|
|
155
151
|
✅ Autoshipped (<state>): <PR url>
|
|
152
|
+
🖼️ <N> visual boxes unchecked (<M> taste), owed on the evidence comment of <PR url> to the operator, or to the UI reviewer for the boxes a driver can run
|
|
156
153
|
<N minor findings kept in .canon/review/branch-<slug>.md>
|
|
157
154
|
<N facts routed to context entries>
|
|
158
155
|
<N memories captured in .canon/memory/>
|
|
@@ -161,7 +158,7 @@ Respond with up to five lines:
|
|
|
161
158
|
|
|
162
159
|
`<state>` is whatever the Step 8 read returned, being `draft` or `ready, unsupervised`, rather than the state the undo asked for.
|
|
163
160
|
|
|
164
|
-
|
|
161
|
+
Fill the second line from the counts Step 5 held, and omit it when no checklist was produced. Omit the third line if there were no minor findings, and the fourth if nothing routed. Omit the fifth if `memory-capture` wrote no memory file this session, and the sixth if it returned no review line. Pass that line through verbatim, since a dispatched worker's controller relays it to the operator.
|
|
165
162
|
|
|
166
163
|
This block replaces the one `git-ship` closes on rather than following it, since emitting both reports one run twice and buries the state under a `✅ Shipped` that does not name it.
|
|
167
164
|
|
|
@@ -20,7 +20,6 @@ Every stop point leaves recoverable state. The user resumes manually from the ap
|
|
|
20
20
|
| Empty changed-file list | Re-run once the plan produces tracked output. Ship gitignored output outside the chain, never by tracking it. |
|
|
21
21
|
| Branch collision on worktree entry | `session-worktree` Step 5 found `<slug>` already as a local branch. Resolve manually (rename or delete the stale branch), then re-run autoship. |
|
|
22
22
|
| Verify fails | Read logs, fix manually, run `/git-ship` |
|
|
23
|
-
| UI checklist | Verify visually, run `/git-ship` |
|
|
24
23
|
| Inherited review findings | Fix findings, run `/git-ship` |
|
|
25
24
|
| Self-introduced finding survived | Read the receipt for what the one repair pass left open, fix it, run `/git-ship` |
|
|
26
25
|
| git-ship fails | Inspect hook or remote error, run again |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: UI checklist counts
|
|
3
|
+
description: What auto-ship Step 5 holds when ui-checklist produces a checklist, so the closing block can name the unchecked visual boxes after git-pr has removed the file
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hold the checklist counts
|
|
7
|
+
|
|
8
|
+
Step 5 of `auto-ship`. The session reads this file when `ui-checklist` has produced a checklist.
|
|
9
|
+
|
|
10
|
+
The chain continues to Step 6 here in every run, dispatched or hand-run, since the skill cannot tell the two apart and the draft mark at Step 8 holds the merge either way. A stop here used to leave nothing committed, and resuming at `/git-ship` skipped the review at Step 6.
|
|
11
|
+
|
|
12
|
+
Count two things in `.canon/tmp/handoff/ui-checklist/<slug>.md` at the main worktree root:
|
|
13
|
+
|
|
14
|
+
- `<N>`, the `- [ ]` lines
|
|
15
|
+
- `<M>`, how many of those end in `(taste)`
|
|
16
|
+
|
|
17
|
+
Hold both until the Output block. `git-pr` removes the file once it posts the evidence comment, so a count taken after Step 8 reads nothing.
|
|
18
|
+
|
|
19
|
+
The Output block's second line takes both counts. When every box is a taste box, `<N>` and `<M>` match and the boxes are owed to the operator alone, since a driver reports a taste box as needing a person's eyes rather than passing it, so say the operator and drop the UI reviewer clause.
|
|
20
|
+
|
|
21
|
+
When `ui-checklist` reports nothing to verify visually, it writes no file, Step 5 holds no count, and the Output block carries no boxes line.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Rendered-surface evidence
|
|
3
|
-
description: How git-pr finds the UI checklist and the local server, posts the evidence comparison or the checklist alone, and adds the preview address, for a change that touches a rendered surface
|
|
3
|
+
description: How git-pr finds the UI checklist and the local server, posts the evidence comparison or the checklist alone as the fallback for a git refusal, and adds the preview address, for a change that touches a rendered surface
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Rendered-surface evidence
|
|
@@ -13,7 +13,7 @@ The rendered-surface step of `git-pr`, reached after the final command printed t
|
|
|
13
13
|
|
|
14
14
|
When it exists, scan it against `${CLAUDE_SKILL_DIR}/../../standards/publish.md` before either step posts it, the same as the pull request body in the skill's pre-publish scan.
|
|
15
15
|
|
|
16
|
-
Where it lands is decided by the evidence step below rather than here, since a checklist reads next to the screenshots it annotates and posting it on its own is the fallback for a
|
|
16
|
+
Where it lands is decided by the evidence step below rather than here, since a checklist reads next to the screenshots it annotates and posting it on its own is the fallback for a refused render.
|
|
17
17
|
|
|
18
18
|
## Find the local server
|
|
19
19
|
|
|
@@ -31,7 +31,7 @@ The verb reads the listening sockets on this machine, keeps those whose process
|
|
|
31
31
|
|
|
32
32
|
Pass `--local` to the evidence step only on an `ok` here. The binary answering `ok` is the one carrying the flag, so a binary lacking the verb never meets a flag it would reject.
|
|
33
33
|
|
|
34
|
-
With
|
|
34
|
+
With a checklist, a diff carrying no evidence image still renders `ok`, and a local link rides in the same comment above the checklist, so a reviewer gets both in one place. A local link with neither an evidence image nor a checklist still reports `no-evidence`, which keeps a branch that changed no rendered surface from getting a comment holding a link and nothing else.
|
|
35
35
|
|
|
36
36
|
A seeded workflow replaces the line with a note once the pull request closes, so the link does not outlive the branch it points at.
|
|
37
37
|
|
|
@@ -43,13 +43,13 @@ Run the verb once against the number the skill's final command printed. Pass `--
|
|
|
43
43
|
canon pr evidence <number> --checklist <main-root>/.canon/tmp/handoff/ui-checklist/<slug>.md --local <url> --json
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
One call answers both questions because a checklist
|
|
46
|
+
One call answers both questions because a checklist decides `no-evidence`. The verb renders `ok` on a diff carrying a checklist and no evidence image, with a marked body holding the checklist, so the checklist always lands in the one comment a later call finds and edits. Without a checklist, a diff carrying no evidence image reports `no-evidence`.
|
|
47
47
|
|
|
48
48
|
Pass `--checklist` only for a file that exists. The verb refuses as `unreadable-checklist` on a path it cannot read or one holding nothing, which is a caller bug rather than a transient failure, so stop and repair the path rather than posting a body with the checklist silently dropped.
|
|
49
49
|
|
|
50
50
|
Read `reason` on the record rather than the exit code.
|
|
51
51
|
|
|
52
|
-
- `no-evidence`: nothing changed under an `evidence/` segment
|
|
52
|
+
- `no-evidence`: nothing changed under an `evidence/` segment and no checklist was passed, so no body was rendered. Say nothing about the evidence and move on.
|
|
53
53
|
- `ok`: write `body` to `.canon/tmp/pr/evidence/body-<number>.md` at the main worktree root (resolved the way `session-worktree` does), then post or update the comment:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
@@ -68,7 +68,7 @@ Any other `reason` is one of the mirrored git refusals (`gh-missing`, `gh-failed
|
|
|
68
68
|
|
|
69
69
|
## Post the UI checklist alone
|
|
70
70
|
|
|
71
|
-
Run this step only when the evidence step above
|
|
71
|
+
Run this step only as the fallback, when the evidence step above reported one of the git refusals and a checklist file exists, since every other branch with a checklist rendered `ok` and carried it. The comment this posts carries no marker, so a later `canon pr evidence` call reports no `checklist` for it. Post it as its own comment on `<number>`:
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
74
|
gh pr comment <number> --body-file <main-root>/.canon/tmp/handoff/ui-checklist/<slug>.md
|
|
@@ -92,7 +92,7 @@ Deleting the file is what makes the later re-render safe. `git-followup` re-runs
|
|
|
92
92
|
|
|
93
93
|
## Post the preview address
|
|
94
94
|
|
|
95
|
-
Run this step only when the evidence step above returned `ok` or a checklist was posted
|
|
95
|
+
Run this step only when the evidence step above returned `ok` or a checklist was posted by the fallback. Either one means the pull request changes a rendered surface, and a reviewer holding a checklist with no screenshots needs the live page most. Otherwise skip it silently.
|
|
96
96
|
|
|
97
97
|
The evidence comment is already posted, so the reviewer has the screenshots while the deploy runs. Mint the preview against the same `<number>`:
|
|
98
98
|
|
|
@@ -9,7 +9,7 @@ description: What the ship chain is for, the gaps it closes, and why it does not
|
|
|
9
9
|
|
|
10
10
|
Without this skill, the post-feature sequence runs from memory. Doc sync gets skipped, so the pull request ships with planning docs describing the previous scope, or it runs after staging has already closed and its output never reaches a commit. Chaining by hand is also where a session narrates between steps, which turns one flow into a conversation and invites a decision at every boundary.
|
|
11
11
|
|
|
12
|
-
The sequence also reaches the remote on work nothing re-checked. This skill is the resume point `auto-ship` names at
|
|
12
|
+
The sequence also reaches the remote on work nothing re-checked. This skill is the resume point `auto-ship` names at three of its stop points, including the one a failed verify takes, so the fix the user makes by hand after that stop is pushed with no suite run against it. Every branch shipped so far passed that verify on its first attempt, which is why the path has produced no instance rather than being closed.
|
|
13
13
|
|
|
14
14
|
## Must
|
|
15
15
|
|
|
@@ -15,7 +15,7 @@ Run the verify commands `CLAUDE.md` names (lint, typecheck, tests) before the se
|
|
|
15
15
|
|
|
16
16
|
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.
|
|
17
17
|
|
|
18
|
-
Verify runs ahead of the sync skills so a stop leaves the tree exactly as the user left it. Re-running a suite the caller already ran costs one command, and the path it closes is the one that has no other guard: `auto-ship` verifies at its own Step 3 and then hands
|
|
18
|
+
Verify runs ahead of the sync skills so a stop leaves the tree exactly as the user left it. Re-running a suite the caller already ran costs one command, and the path it closes is the one that has no other guard: `auto-ship` verifies at its own Step 3 and then hands three of its stop points straight back here, so a fix made by hand after one of those stops otherwise reaches the remote with nothing re-run.
|
|
19
19
|
|
|
20
20
|
## Pre-check
|
|
21
21
|
|
|
@@ -45,7 +45,7 @@ Take the sha from the row, so the base and head sides are exactly what the comme
|
|
|
45
45
|
|
|
46
46
|
Open at most 12 images per pass, filled in this order:
|
|
47
47
|
|
|
48
|
-
1. Every image a ticked checklist box
|
|
48
|
+
1. Every image a ticked checklist box names
|
|
49
49
|
2. The head side of each state at its narrowest and widest captured width, in one theme
|
|
50
50
|
3. The base side, only for a state whose head image looks wrong or whose diff was meant to change appearance
|
|
51
51
|
|
|
@@ -65,7 +65,6 @@ The `## What to look at` block between the `pr-checklist` markers is the author'
|
|
|
65
65
|
|
|
66
66
|
- Test each ticked box against an opened image showing the state and width it names. Flag a box whose image contradicts it, quoting the box.
|
|
67
67
|
- A ticked box no image covers is untested rather than confirmed, and the finding says so.
|
|
68
|
-
- Read the `**Widths:**` block's `Seen at:` line against the widths the images carry.
|
|
69
68
|
- Test only the rows the current comment shows. A box ticked on an earlier head can describe images the comment no longer carries.
|
|
70
69
|
- Leave unchecked boxes to the procedure's own read of the description.
|
|
71
70
|
|
|
@@ -73,7 +73,7 @@ Read each test file the branch added or changed against the final filter in `can
|
|
|
73
73
|
|
|
74
74
|
Then read the description's `## Testing` section, which is the one part of a pull request body this session is positioned to falsify. The branch author cannot see what a sibling branch drove the same day, and the arm list is what settles the claim rather than the diff.
|
|
75
75
|
|
|
76
|
-
Test every unchecked box against the testing discipline in `${CLAUDE_SKILL_DIR}/../../standards/pr.md`, which reserves an unchecked box for a capability the agent lacks. Raise the box when it names no human at all, when the human it names is a live agent session, or when it names a person for a step the repository ships a harness for,
|
|
76
|
+
Test every unchecked box against the testing discipline in `${CLAUDE_SKILL_DIR}/../../standards/pr.md`, which reserves an unchecked box for a capability the agent lacks. Raise the box when it names no human at all, when the human it names is a live agent session, or when it names a person for a step the repository ships a harness for, such as `scripts/sandbox/run.sh`. Cost alone is not an answer, since authorizing a spend is the operator's and performing the run is not. A refusal the author actually met is an answer, and it names which one.
|
|
77
77
|
|
|
78
78
|
Test every ticked box too, bounded to one naming a file or a command. Confirm what it names still exists at `<headRefOid>`, `git show <headRefOid>:<path>` for a file or `git grep <command> <headRefOid>` for a command, rather than re-running what it claims. A box naming neither stays untested, since nothing here can confirm a claim carrying no artifact. A box ticked before a later commit removed or replaced what it names is a `should-fix` finding on the body itself, filed under a `**PR body**` block ahead of the file blocks, since what it corrupts is the merge record rather than a file in the diff.
|
|
79
79
|
|
|
@@ -63,7 +63,7 @@ Report the state of play in the invocation block, and open every later sweep rep
|
|
|
63
63
|
4. Hand off. Read `${CLAUDE_SKILL_DIR}/references/orchestrator-dispatch.md` and follow it: check the branch is unclaimed, check the row's file set against every track in flight, then dispatch a background worker with `claude --bg`. Fall back to the human-launch line it replaces when the check refuses, the sets overlap, or a stated reason serializes the row behind something already out.
|
|
64
64
|
5. Review the PR. When a worker opens a PR, its first pass runs through `review-pr` in a reviewer dispatched under `role-reviewer` when `### The review dispatch` below fires, and in this session otherwise. Either is the deep, independent pass. The worker's autoship self-review was only the green gate.
|
|
65
65
|
- Learning that a PR moved is the mechanical half, so read `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` and run the poll under the condition it states rather than checking the board by hand. That runbook holds the routing and the trigger, and a summary of it here is a second source that drifts from it.
|
|
66
|
-
6. Dispatch the handback. A pass posting anything owed, a finding at any severity or a testing question, tells the session holding that branch to run `review-address`, rather than waiting for a person to relay it. Re-review when the worker's own message says the address pass finished, per the channel `role-worker` states, rather than polling for an answer nothing else marks as landed, and send the re-review back to the dispatched reviewer when one took the first pass. Once a pass posts `## Review closed`,
|
|
66
|
+
6. Dispatch the handback. A pass posting anything owed, a finding at any severity or a testing question, tells the session holding that branch to run `review-address`, rather than waiting for a person to relay it. Re-review when the worker's own message says the address pass finished, per the channel `role-worker` states, rather than polling for an answer nothing else marks as landed, and send the re-review back to the dispatched reviewer when one took the first pass. Once a pass posts `## Review closed`, a UI close names the current head wherever the PR carries a checklist, and `--check` reports `settled`, lift the pull request's draft mark yourself, per Boundaries below. Then the human merges. Tell the trailing worker to rebase when its branch shares a seam with the merged one.
|
|
67
67
|
- Read `${CLAUDE_SKILL_DIR}/references/orchestrator-handback.md` on reaching this step. It 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.
|
|
68
68
|
|
|
69
69
|
A plan written here is written against a tree several branches are already changing, so it names the file set of every track in flight as a constraint, one set per track, read from the Touches column of that track's row. State for each set which of the two acts it forbids, per Constraints in `${CLAUDE_SKILL_DIR}/../../standards/plan.md`. A bare path list leaves the worker guessing, which is how a plan ends up forbidding the repair of a citation the change broke.
|
|
@@ -75,7 +75,7 @@ Stamp the block with the commit this session read the tree at, which the same se
|
|
|
75
75
|
- Run one orchestrator at a time. The board is gitignored, so a second session sees none of this one's writes: two task files land minutes apart under different labels for the same work, one session archives a task mid-sweep in the other, and each archives a plan the other had retargeted. An Owner column does not fix this, since neither session can read the other's rows.
|
|
76
76
|
- Do not implement features in this session. Hand the plan to a worker.
|
|
77
77
|
- Do not merge. Recommend merge or changes. The human merges.
|
|
78
|
-
- Lift a pull request's draft mark once its review closes, whether this session or a reviewer it dispatched closed it, acting directly on the pull request rather than dispatching a worker
|
|
78
|
+
- Lift a pull request's draft mark once its review closes, whether this session or a reviewer it dispatched closed it, acting directly on the pull request rather than dispatching a worker. Hold it on any `canon pr evidence <number> --check --json` reason but `settled`, reporting that reason, and where that record carries a `checklist`, until a UI close names the current head. `role-worker` and `role-reviewer` state the mirroring refusal: neither can verify who is asking or whether review actually closed, so the act stays with this session.
|
|
79
79
|
- Do not spawn a worker with the Agent tool. An in-process subagent shares this session's context and cannot be steered or reached independently, which breaks the property this boundary protects rather than the mechanism it names. The launch in `orchestrator-launch.md` is a separate `claude --bg` process with its own worktree and its own PR, so it preserves that property instead.
|
|
80
80
|
- Dispatch a background worker only once the collision check in `orchestrator-dispatch.md` clears and the row's file set is disjoint from every track in flight. Colliding with an existing worktree or session is what the check exists to catch rather than a judgment call this session makes case by case. No fixed count binds how many tracks run at once, and Parallelism below states what does.
|
|
81
81
|
- Do not edit tracked files from this session, at any size. The boundary offers no proportionality exception and nothing enforces it.
|
|
@@ -34,30 +34,13 @@ Group visual items by feature area. Use `- [ ]` checkbox syntax, and write each
|
|
|
34
34
|
Write each box so a session driving the running app can run it without guessing:
|
|
35
35
|
|
|
36
36
|
- **Route.** Name where the box is driven, as a path or the control that reaches it. A box naming no route is driven from the address the driver opens, so a single-page app with no routing needs no invented path. Write "from the page the app opens on" when a state is reached by a sequence rather than a URL.
|
|
37
|
-
- **Width.** Name the width a box is driven at only when the change can make it differ by width,
|
|
37
|
+
- **Width.** Name the width a box is driven at only when the change can make it differ by width, such as layout, spacing, or anything responsive. A box about copy, color, or a state that renders the same everywhere leaves the width off rather than inventing one.
|
|
38
38
|
- **Verb.** Open on an action a driver performs, such as "scroll to", "click", "resize to", or "tab to". Never open on "read" or "look at", which name no action.
|
|
39
39
|
- **Taste.** End the line with `(taste)` when the result is a judgment of look or feel rather than a fact a driver can observe. A driver reports such a box as needing a person's eyes instead of passing it.
|
|
40
40
|
- **Setup.** A box needing a state the page does not open in states the setup inline. When a hosted preview cannot reach that state, such as a stopped service or a seeded record, end the line with `(local only)` instead.
|
|
41
41
|
|
|
42
42
|
The checkbox stays `- [ ]` followed by the action and the result, since the evidence comment carries ticked boxes forward by that shape.
|
|
43
43
|
|
|
44
|
-
## The widths block
|
|
45
|
-
|
|
46
|
-
A screenshot shows one width, so a reviewer cannot tell from the picture alone whether any other width was looked at. When a change touches layout, spacing, or anything responsive, put this block above the visual items, since it frames what the screenshots beside it can support:
|
|
47
|
-
|
|
48
|
-
```markdown
|
|
49
|
-
**Widths:**
|
|
50
|
-
|
|
51
|
-
Seen at: <the widths the reviewer looked at>
|
|
52
|
-
Not seen at: <the widths nobody looked at, or "none">
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Leave both lines for the reviewer to complete. This session cannot verify a width, so the block asks what was seen and never asserts coverage. Fix no width list in the block, since which widths matter belongs to the project.
|
|
56
|
-
|
|
57
|
-
Keep the `Not seen at:` line even when the answer is "none", so an omission reads as a claim rather than a gap.
|
|
58
|
-
|
|
59
|
-
Omit the block when the change cannot differ by width, such as copy, color, or a state that renders the same everywhere, the way the missing-test heading is omitted below.
|
|
60
|
-
|
|
61
44
|
## The missing-test list
|
|
62
45
|
|
|
63
46
|
Name every automatable change this branch ships with no test, one per line, with the layer `test-craft` would place it at. Do not write the test and do not read the project's test config to write one against.
|
package/docs/agents/gate.md
CHANGED
|
@@ -5,7 +5,7 @@ description: Running the gate this repository verifies a branch with, what the s
|
|
|
5
5
|
|
|
6
6
|
# Merge gate
|
|
7
7
|
|
|
8
|
-
`canon gate run` runs every stage that guards a branch here, in order, stopping at the first stage that finds a fact. `bun run check` and `bun run check:ci` resolve to it, and `
|
|
8
|
+
`canon gate run` runs every stage that guards a branch here, in order, stopping at the first stage that finds a fact. `bun run check` and `bun run check:ci` resolve to it, and the `update` package script runs `bun run check` after a dependency update.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
canon gate run
|
package/docs/agents/hooks.md
CHANGED
|
@@ -16,6 +16,8 @@ canon hooks post-merge --root "$root"
|
|
|
16
16
|
| --------------- | ---------------------------------------------------------------------------------------------------- |
|
|
17
17
|
| `--root <path>` | Main worktree root holding the board and the records, resolved from `git worktree list` when omitted |
|
|
18
18
|
|
|
19
|
+
The base stack ships the same call as its `.husky/post-merge`, behind the same board guard and upgrade bootstrap, so a target that syncs it runs these five steps.
|
|
20
|
+
|
|
19
21
|
Exit codes: `0` on every path, since a hook failing aborts nothing useful. Lines go to stderr, and stdout stays empty. An ordinary merge prints nothing.
|
|
20
22
|
|
|
21
23
|
## The steps
|
package/docs/agents/index.md
CHANGED
|
@@ -35,7 +35,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
35
35
|
- [Migrate](migrate.md): What each canon migrate verb moves and rewrites, what it refuses, the markers that keep an old spelling, and the idempotence check a second run gives
|
|
36
36
|
- [Output shape](output-shape.md): Two framed shapes every command renders into, how JSON and --names modes keep stdout clean, and the exit discipline that lets piped output drain
|
|
37
37
|
- [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
|
|
38
|
-
- [The pull request evidence comparison](pr-evidence.md): What canon pr evidence compares, the marker that lets it edit its own comment rather than duplicate it, the refusal reasons it names, and why the comparison anchors at the merge base rather than the previous push
|
|
38
|
+
- [The pull request evidence comparison](pr-evidence.md): What canon pr evidence compares, the marker that lets it edit its own comment rather than duplicate it, the refusal reasons it names, what the --check read reports as owed, and why the comparison anchors at the merge base rather than the previous push
|
|
39
39
|
- [The pull request local preview](pr-local.md): How canon pr local finds the server a worktree is running, why a server in another worktree is never reported, the refusal reasons it names, and how a close workflow removes the link with --remove
|
|
40
40
|
- [The pull request preview deploy](pr-preview.md): How canon pr preview finds a fenced Cloudflare Pages deploy, dispatches it on a pull request's branch, reads the alias the run prints, the refusal reasons it names, and why an unfenced deploy is refused before anything runs
|
|
41
41
|
- [Head-sensitive pull request reads](pr-reads.md): Resolving a branch tip from the remote rather than from the pull request object, reading what a review pass covered off its own marker rather than off GitHub's submission stamps, why an empty run list is not a pass, the refusal reasons each verb names, and what the remote read costs
|
|
@@ -64,4 +64,4 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
64
64
|
- [Teach authoring](teach-authoring.md): Resolving what the next lesson needs before it is written, rendering a lesson body's blocks to HTML, and rewriting the root listing, a contents page, and each lesson's chrome and quiz stepper from its marker regions
|
|
65
65
|
- [Teach](teach.md): Listing learning workspaces with what their records schedule next, opening one with its required files, recording sources and glossary terms, viewing one with its chrome refreshed, where the lesson authoring verbs are described, the refusal reasons, and why every write here runs through a verb
|
|
66
66
|
- [Test order](test-order.md): Reading where an implementation reached history ahead of its test, how a pair is decided, the three verdicts, the coverage the pairing cannot reach, and why the check reports rather than gates
|
|
67
|
-
- [Worktrees](worktrees.md): Reporting which worktrees are reclaimable, removing the ones that are, the record a hook reads back, why the reading keys on the pull request rather than on git ancestry, the refusals it names, and the two removal shapes
|
|
67
|
+
- [Worktrees](worktrees.md): Reporting which worktrees are reclaimable, removing the ones that are, the hidden verb that clears a stranded bare flag, the record a hook reads back, why the reading keys on the pull request rather than on git ancestry, the refusals it names, and the two removal shapes
|
|
@@ -139,8 +139,8 @@ since a target has no rule source of its own that ships nowhere.
|
|
|
139
139
|
|
|
140
140
|
It takes `--root <path>` and defaults to the toolkit root, prints nothing on success, and
|
|
141
141
|
reports the reason on stderr with exit 1 when the record names a stack or rule
|
|
142
|
-
that does not resolve.
|
|
143
|
-
|
|
142
|
+
that does not resolve. The Consumed copies stage of `bun run check` calls it and
|
|
143
|
+
asserts the result is committed.
|
|
144
144
|
|
|
145
145
|
## Whole-project sync
|
|
146
146
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: The pull request evidence comparison
|
|
3
|
-
description: What canon pr evidence compares, the marker that lets it edit its own comment rather than duplicate it, the refusal reasons it names, and why the comparison anchors at the merge base rather than the previous push
|
|
3
|
+
description: What canon pr evidence compares, the marker that lets it edit its own comment rather than duplicate it, the refusal reasons it names, what the --check read reports as owed, and why the comparison anchors at the merge base rather than the previous push
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# The pull request evidence comparison
|
|
@@ -46,18 +46,19 @@ image or marks the case new.
|
|
|
46
46
|
|
|
47
47
|
`reason` on the record is what a caller branches on, not the exit code:
|
|
48
48
|
|
|
49
|
-
| Reason | What it means
|
|
50
|
-
| ---------------------- |
|
|
51
|
-
| `ok` | A body was rendered. `commentId` is set when a marked comment already exists.
|
|
52
|
-
| `no-evidence` |
|
|
53
|
-
| `unreadable-checklist` | `--checklist` named a path that could not be read, or one holding nothing.
|
|
54
|
-
| `gh-missing` | `gh` is not on the path, so no pull request could be resolved.
|
|
55
|
-
| `gh-failed` | `gh` could not answer for this repository or branch, or read its comments.
|
|
56
|
-
| `no-branch` | The pull request carries no head branch name.
|
|
57
|
-
| `no-object-head` | The pull request object reported no head commit.
|
|
58
|
-
| `no-base` | GitHub reported no merge base for the pull request.
|
|
59
|
-
| `unreadable-changes` | GitHub could not list what the pull request changed.
|
|
60
|
-
| `would-empty` | The render holds no cases and the marked comment holds some. No body.
|
|
49
|
+
| Reason | What it means |
|
|
50
|
+
| ---------------------- | --------------------------------------------------------------------------------------- |
|
|
51
|
+
| `ok` | A body was rendered. `commentId` is set when a marked comment already exists. |
|
|
52
|
+
| `no-evidence` | No `evidence/` segment in the diff and no `--checklist` or `--preview`. A silent no-op. |
|
|
53
|
+
| `unreadable-checklist` | `--checklist` named a path that could not be read, or one holding nothing. |
|
|
54
|
+
| `gh-missing` | `gh` is not on the path, so no pull request could be resolved. |
|
|
55
|
+
| `gh-failed` | `gh` could not answer for this repository or branch, or read its comments. |
|
|
56
|
+
| `no-branch` | The pull request carries no head branch name. |
|
|
57
|
+
| `no-object-head` | The pull request object reported no head commit. |
|
|
58
|
+
| `no-base` | GitHub reported no merge base for the pull request. |
|
|
59
|
+
| `unreadable-changes` | GitHub could not list what the pull request changed. |
|
|
60
|
+
| `would-empty` | The render holds no cases and the marked comment holds some. No body. |
|
|
61
|
+
| `check-writes` | `--check` was passed with `--preview`, `--local`, or `--checklist`. |
|
|
61
62
|
|
|
62
63
|
`no-evidence` is not a refusal a caller reports. A project on a stack that
|
|
63
64
|
carries no evidence path, such as `base` or `python`, hits this reason on
|
|
@@ -75,8 +76,9 @@ shows a reviewer, each field present only when that comment holds it:
|
|
|
75
76
|
|
|
76
77
|
These come from the comment already posted, never from the flags the call
|
|
77
78
|
passed, so a skill driving a review reads which address and which checklist a
|
|
78
|
-
reviewer has without parsing the comment itself. A checklist posted
|
|
79
|
-
|
|
79
|
+
reviewer has without parsing the comment itself. A checklist posted raw, which
|
|
80
|
+
only the fallback for a refused render does now, carries no marker, so the
|
|
81
|
+
record reports none of the three for it. Reading
|
|
80
82
|
them means the thread is read before the `no-evidence` answer too, so an
|
|
81
83
|
unreadable thread refuses as `gh-failed` on both reasons rather than
|
|
82
84
|
reporting the fields absent.
|
|
@@ -155,11 +157,11 @@ already holds, the same way the preview address is carried. That is what keeps
|
|
|
155
157
|
already ticked, since `git-pr` deletes the handoff once the first post reports
|
|
156
158
|
success and no later call has a file to pass.
|
|
157
159
|
|
|
158
|
-
The option
|
|
159
|
-
|
|
160
|
-
checklist
|
|
161
|
-
|
|
162
|
-
that cannot be read, or one holding nothing, refuses as
|
|
160
|
+
The option decides `no-evidence` on its own. A branch with a checklist and no
|
|
161
|
+
changed evidence image renders `ok` with a marked body holding the checklist,
|
|
162
|
+
so the checklist always lands in the one comment a later call finds and edits.
|
|
163
|
+
The raw post survives only as the caller's fallback when the render is refused.
|
|
164
|
+
A path that cannot be read, or one holding nothing, refuses as
|
|
163
165
|
`unreadable-checklist` rather than rendering without it: the caller deletes the
|
|
164
166
|
handoff once a post succeeds, so a silently dropped checklist is the only copy
|
|
165
167
|
gone.
|
|
@@ -174,11 +176,57 @@ the local address the marked comment already holds, the same as the other two.
|
|
|
174
176
|
|
|
175
177
|
The option does not turn `no-evidence` into `ok` on its own. A branch with a
|
|
176
178
|
dev server running and no rendered change would otherwise get a comment holding
|
|
177
|
-
a link and nothing else. Together with `--checklist`
|
|
178
|
-
|
|
179
|
+
a link and nothing else. Together with `--checklist` the link and the
|
|
180
|
+
checklist land in one comment.
|
|
179
181
|
`canon docs pr-local` covers where the address comes from and how the line is
|
|
180
182
|
removed at close.
|
|
181
183
|
|
|
184
|
+
## What a pull request is still owed
|
|
185
|
+
|
|
186
|
+
`--check` reads the same changed set and the same thread, renders no body, and
|
|
187
|
+
reports which steps of the ship chain that run after the pull request opens
|
|
188
|
+
never landed on it. It reads the pull request rather than any session's account
|
|
189
|
+
of what it ran, so a session that stopped after opening the pull request leaves
|
|
190
|
+
a branch the check can tell apart from one that needed neither step.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
canon pr evidence 1341 --check --json
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
| Reason | What it means |
|
|
197
|
+
| --------- | ------------------------------------------------------------------ |
|
|
198
|
+
| `settled` | Nothing is owed. `owed` is empty. |
|
|
199
|
+
| `owed` | `owed` lists `evidence`, `preview`, or both, always in that order. |
|
|
200
|
+
|
|
201
|
+
- `evidence` is owed when the changed set carries an evidence image and no
|
|
202
|
+
comment carries the marker.
|
|
203
|
+
- `preview` is owed when the pull request has a marked comment or an evidence
|
|
204
|
+
change, a deploy workflow resolves in the checkout the verb runs from, and
|
|
205
|
+
the marked comment's first line is no `**Preview:**` line. A
|
|
206
|
+
`**Local preview:**` line does not satisfy it. A project deploying nothing is
|
|
207
|
+
never owed a preview.
|
|
208
|
+
|
|
209
|
+
The record carries `owed`, `commentId` when a marked comment exists, and the
|
|
210
|
+
same `preview`, `local`, and `checklist` fields the other reasons carry, so a
|
|
211
|
+
caller reads one shape. It never carries `body`, so a writer branching on `ok`
|
|
212
|
+
and posting `body` cannot act on a check record. Passing `--preview`, `--local`,
|
|
213
|
+
or `--checklist` with it refuses as `check-writes` before any `gh` call, since
|
|
214
|
+
those ask a read to write.
|
|
215
|
+
|
|
216
|
+
The thread cannot separate a skipped preview step from a failed one. A pull
|
|
217
|
+
request whose deploy run failed or timed out reads as owing a preview, and the
|
|
218
|
+
session that ran it holds the cause. A checklist-only branch posts a marked
|
|
219
|
+
comment, so it reads as owing a preview once that comment exists and a deploy
|
|
220
|
+
workflow resolves. The deploy
|
|
221
|
+
workflow is read from the checkout rather than the pull request's head, so a
|
|
222
|
+
pull request that adds or removes its own deploy workflow reads against trunk's.
|
|
223
|
+
|
|
224
|
+
An unreadable thread refuses as `gh-failed` rather than reporting `settled` off
|
|
225
|
+
a thread it never read. The check skips the merge base read, which only the
|
|
226
|
+
render needs, so it never refuses `no-base`. The orchestrator's draft lift is
|
|
227
|
+
the caller, and lifts only on `settled`, so a refusal holds it the same as
|
|
228
|
+
`owed` does.
|
|
229
|
+
|
|
182
230
|
## What a collapsed comment still leaves to GitHub
|
|
183
231
|
|
|
184
232
|
GitHub already draws its own before-and-after comparison on the Files Changed
|
|
@@ -17,7 +17,7 @@ Seven checks run. Collisions reaches one half of the `## Run now` test the board
|
|
|
17
17
|
| Check | What it reports |
|
|
18
18
|
| ---------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
19
19
|
| Shape | A row whose cell count disagrees with its table's header, or one stranded behind a table a blank line already closed |
|
|
20
|
-
| Plan | A row whose plan citation disagrees with its group or its task file, or a task whose `Plan:` line
|
|
20
|
+
| Plan | A row whose plan citation disagrees with its group or its task file, or a task whose `Plan:` line lists one plan twice |
|
|
21
21
|
| Mapping | A row or backlog line naming no task file |
|
|
22
22
|
| Grouping | A task carrying a row in more than one readiness group, or on both surfaces |
|
|
23
23
|
| Ordering | A `## Needs a plan` row whose stated position disagrees with where it actually sits, or which states no position at all |
|
|
@@ -26,11 +26,11 @@ Seven checks run. Collisions reaches one half of the `## Run now` test the board
|
|
|
26
26
|
|
|
27
27
|
Shape runs before any other check reads a row, since a row failing it carries no dependable fields for the rest to check. A blank or prose line closes the table above it, so the walk treats the next pipe line as a fresh header candidate rather than as a continuation. That candidate counts as a header only when the line behind it is a separator carrying the same cell count, and one that fails is `row-untabled`, stranded behind a table that already closed. Cell count still has to match the header on every row that clears that test, and a row whose count disagrees is `row-misshapen`, the shape a dropped pipe or a merged column produces.
|
|
28
28
|
|
|
29
|
-
The Plan check reads the row and the task file both, because the two are written by different hands and only the task's own `Plan:` line reaches the archive. A row carrying a plan whose task states none is `plan-uncited`, and a pair
|
|
29
|
+
The Plan check reads the row and the task file both, because the two are written by different hands and only the task's own `Plan:` line reaches the archive. A row carrying a plan whose task states none is `plan-uncited`, and a pair where the row's plan is none of the task's links is `plan-mismatched`. Both sides resolve against the board and against the project root before they compare, so a row writing `../plans/x.md` and a task writing `.canon/plans/x.md` name one file rather than two.
|
|
30
30
|
|
|
31
31
|
The other two groups have no Plan column, so the same check reads the task file's own `Plan:` line against what the group name claims. A `## Needs a plan` row whose task cites a plan that sits live on disk is `plan-parked`, since the group says no such plan exists and the row is either misplaced or its plan is stale and belongs in the archive. An `## Up next` row whose task cites no live plan is `plan-absent`, since that group says one is written. A plan already archived, or a cited path with no file behind it, reads as not live on both sides. A row whose task file is gone is left to `task-unresolved`. An `## Up next` row with nothing left to build, waiting on an act only a person can take, reports `plan-absent` once its plan archives while the task stays live. That report is expected, since the check reads the task file and not the `Waiting on` prose, so a row in that state moves to `## Needs a plan` or closes.
|
|
32
32
|
|
|
33
|
-
A
|
|
33
|
+
A `Plan:` line linking several distinct plans is the shape a sliced task carries, so the checks read the whole line rather than reporting it. A `## Run now` row passes when its plan is any one of the links, and a parked row is judged on whether any link is live: `## Up next` needs one, and `## Needs a plan` reports `plan-parked` when one is. The check adds no sliced marker, so an unsliced task given a second link by hand reads as sliced. `plan-several` now means a line listing one plan twice, compared by the file each link resolves to, so `../plans/x.md` beside `.canon/plans/x.md` counts. It is reported in every group and replaces the `plan-uncited` or `plan-absent` report the line would otherwise draw. The message lists the links, and the fix is to drop the repeat.
|
|
34
34
|
|
|
35
35
|
Mapping spans two surfaces, because a task sits on `priority.md` when it would plausibly be planned soon and on `backlog.md` otherwise. A row or a backlog line naming no task file is `task-unresolved`, and a file both surfaces name is `row-duplicated` for the reason a task in two groups is: it claims two things about itself and only one can hold. A task file neither surface names is `unplaced` rather than a finding, since that is the normal state between a session filing it and a live orchestrator placing it on the board. One check across both is what lets a task move between them without the move reading as a dropped file.
|
|
36
36
|
|
package/docs/agents/worktrees.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Worktrees
|
|
3
|
-
description: Reporting which worktrees are reclaimable, removing the ones that are, the record a hook reads back, why the reading keys on the pull request rather than on git ancestry, the refusals it names, and the two removal shapes
|
|
3
|
+
description: Reporting which worktrees are reclaimable, removing the ones that are, the hidden verb that clears a stranded bare flag, the record a hook reads back, why the reading keys on the pull request rather than on git ancestry, the refusals it names, and the two removal shapes
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Worktrees
|
|
@@ -24,6 +24,21 @@ Exit codes: `0` every worktree was read, `1` refused. The refusal carries a `rea
|
|
|
24
24
|
|
|
25
25
|
An exit code says nothing about a call made from a session, since a shell profile may wrap the binary in a function taking its status from a later command. Read the record's `reason` rather than the exit when a skill consumes this.
|
|
26
26
|
|
|
27
|
+
## Repair the bare flag
|
|
28
|
+
|
|
29
|
+
`canon worktrees repair-bare-flag` clears a `core.bare` flag that Claude Code's worktree entry left set in the shared config. It is hidden, so no help listing shows it, because its one caller is a hook rather than a person.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
canon worktrees repair-bare-flag --root <path> --json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| Option | Behavior |
|
|
36
|
+
| --------------- | ------------------------------------- |
|
|
37
|
+
| `--root <path>` | Repository to repair, default the cwd |
|
|
38
|
+
| `--json` | Print the record on stdout |
|
|
39
|
+
|
|
40
|
+
`--json` writes `{repaired, reason, message}` on stdout, once, whether or not anything was written. `reason` is `flag-unset`, `common-dir-unreadable`, `genuinely-bare`, or `write-failed` when `repaired` is false. `message` carries text when the flag is repaired and when the write failed, and is null on the three quiet skips. A `write-failed` record means the flag is still set, which a lock file or a read-only config causes. A repository whose common dir is not named `.git` keeps its flag. The exit code is always `0`, so a hook never fails a tool call. Without `--json`, a record carrying a message prints it on stderr and any other prints nothing.
|
|
41
|
+
|
|
27
42
|
## Reclaim
|
|
28
43
|
|
|
29
44
|
`canon worktrees reclaim` removes every worktree the reading above called reclaimable, and the branch behind each one.
|
|
@@ -62,7 +62,7 @@ The first line reports the plan and the second applies it, relocating each rule
|
|
|
62
62
|
|
|
63
63
|
Twenty-five plugin skills dropped their `claude-` prefix for two-word names, so `canon:claude-docs` answers as `canon:context-fold` and `canon:claude-tasks` as `canon:task-board`. A project that installed governance or tooling before that release holds files naming the old ones, and the plugin answers to none of them. A later release renamed `docs-fold` to `context-fold`, since the skill folds a session into the context entries and the task board rather than into `docs/`, and the same sweep carries a project across that rename too. <!-- canon-keep-retired -->
|
|
64
64
|
|
|
65
|
-
Two of those files run rather than sit there. `.husky/post-merge`
|
|
65
|
+
Two of those files run rather than sit there. `.husky/post-merge` runs the `canon hooks post-merge` verb, so a stale copy of the hook calls a binary that may lack it, and `.claude/hooks/pr-create-log.sh` hands a session a message naming a skill, so a stale copy tells someone to invoke something that no longer exists. A rule under `.claude/rules/canon/core/` names skills too, though a rule is read rather than run.
|
|
66
66
|
|
|
67
67
|
Resync what the toolkit owns, then sweep what the project wrote:
|
|
68
68
|
|
|
@@ -87,7 +87,8 @@ When features are independent, run them in parallel, one worktree and one sessio
|
|
|
87
87
|
For features on a mature stack, chain the post-plan pipeline in one session. Approve the plan, invoke `canon:auto-ship`, and the skill runs implement → verify → review → ship sequentially.
|
|
88
88
|
|
|
89
89
|
- Use when the plan is tight and the stack has real verify commands and test coverage
|
|
90
|
-
- Autoship stops on: verify failure after one fix attempt,
|
|
90
|
+
- Autoship stops on: verify failure after one fix attempt, an inherited review finding above minor, no diff baseline resolving against `main`, an empty changed-file list, or hook failure
|
|
91
|
+
- A produced UI checklist does not stop it. The checklist rides to the draft pull request's evidence comment, and the closing block names how many visual boxes are still unchecked and who owes them
|
|
91
92
|
- Every stop leaves recoverable state. Fix and resume with `/git-ship`
|
|
92
93
|
- Skip autoship for auth, migrations, security-sensitive changes, or work where the plan itself is uncertain
|
|
93
94
|
|
|
@@ -70,8 +70,8 @@ Past that shape, it checks what a surviving row claims against what the tree hol
|
|
|
70
70
|
|
|
71
71
|
Archiving a task carries its plan with it, in the same act. The merge is what settles a plan, and the hook below reaches the archive with nobody watching, so a second call after it would be a second failure point leaving the task archived and the plan live. A task whose plan a sibling still cites archives on its own and leaves the plan live, since moving it on the first task to close strands every other pointer at a path that has gone.
|
|
72
72
|
|
|
73
|
-
Nothing chained that archive until the `post-merge` git hook landed. Every earlier step fires from `canon:auto-ship` or `canon:git-ship`, both of which finish while the pull request is still open, so a task archived there would close for work that may be abandoned. The board is gitignored, which rules out reading it from anywhere but the machine that pulled. The hook
|
|
73
|
+
Nothing chained that archive until the `post-merge` git hook landed. Every earlier step fires from `canon:auto-ship` or `canon:git-ship`, both of which finish while the pull request is still open, so a task archived there would close for work that may be abandoned. The board is gitignored, which rules out reading it from anywhere but the machine that pulled. The hook archives the task a merged pull request closed, through the same verb the base stack ships to every target, and does nothing on a project with no board.
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
The archive gates on a pull request number the merge carried and a closed task, because outcomes are marked on the branch and a task can read all `[x]` while its pull request is still open, so `canon:task-board` still confirms the work reached `main` when a person archives by hand. A companion `post-rewrite` hook carries the same steps for anyone pulling with rebase, which fires that event instead of `post-merge`.
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
The hook archives through `canon tasks archive`, which carries the refusals above, so a task whose pull request has not merged stays where it is. Both hooks ship with the `base` tooling stack, so a target project running this workflow gets the same trigger, and `CANON_SKIP_RECLAIM`, `CANON_SKIP_UPGRADE`, and `CANON_SKIP_PLUGIN_UPDATE` turn off the three steps that act on the machine.
|
|
@@ -8,7 +8,7 @@ category: Workflow
|
|
|
8
8
|
|
|
9
9
|
Groups run in the order a project meets them, so a reader at a known point scans to that group and reads across. The set reconciles the scenarios in [AI workflow](ai-workflow.md) with the lifecycle [target projects](../target/projects.md) describes, rather than inventing a third vocabulary beside those two, so a group name matches neither source exactly and every moment either one names has a group. Each row says when to reach for the skill. What it does is the skill's own description.
|
|
10
10
|
|
|
11
|
-
This page is the corpus the coverage claim is measured against: every name `canon claude skills list --names` reports takes exactly one row here. A skill serving two moments sits at the earlier one, and a mention on any other page is prose rather than routing.
|
|
11
|
+
This page is the corpus the coverage claim is measured against: every name `canon claude skills list --names` reports takes exactly one row here. A skill serving two moments sits at the earlier one, and a mention on any other page is prose rather than routing. The landing page's skills field renders from this page, so its build refuses a skill with no row and a row naming no skill.
|
|
12
12
|
|
|
13
13
|
## Set up a project
|
|
14
14
|
|