@erclx/canon 5.11.0 → 5.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/REQUIREMENT.md +1 -1
- package/claude/skills/api-design/SKILL.md +1 -1
- package/claude/skills/api-design/references/adopted.md +1 -1
- package/claude/skills/auto-ship/REQUIREMENT.md +2 -0
- package/claude/skills/auto-ship/SKILL.md +7 -10
- 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/build-in-slices/REQUIREMENT.md +45 -0
- package/claude/skills/build-in-slices/SKILL.md +94 -0
- package/claude/skills/build-in-slices/references/adopted.md +41 -0
- package/claude/skills/code-craft/REQUIREMENT.md +48 -0
- package/claude/skills/code-craft/SKILL.md +107 -0
- package/claude/skills/code-craft/references/adopted.md +52 -0
- package/claude/skills/codebase-layout/REQUIREMENT.md +1 -1
- package/claude/skills/git-pr/references/evidence.md +7 -7
- package/claude/skills/git-ship/REQUIREMENT.md +2 -1
- package/claude/skills/git-ship/SKILL.md +2 -2
- package/claude/skills/review-craft/REQUIREMENT.md +3 -0
- package/claude/skills/review-craft/SKILL.md +1 -1
- package/claude/skills/review-craft/references/adopted.md +8 -0
- package/claude/skills/review-craft/references/security.md +5 -0
- package/claude/skills/review-craft/references/ui.md +1 -2
- package/claude/skills/review-pr/SKILL.md +1 -1
- package/claude/skills/review-ui/REQUIREMENT.md +1 -0
- package/claude/skills/review-ui/SKILL.md +11 -0
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +4 -0
- package/claude/skills/test-first/REQUIREMENT.md +3 -0
- package/claude/skills/test-first/SKILL.md +2 -1
- 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/install-and-sync.md +2 -2
- package/docs/agents/pr-evidence.md +26 -25
- package/docs/agents/pr-preview.md +40 -12
- package/docs/agents/tasks-validate.md +3 -3
- 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 +2 -0
- package/governance/rules/code/000-code.md +5 -1
- package/package.json +3 -4
- package/scripts/lib/sandbox-path.sh +1 -1
- package/src/claude/cases/misc.ts +10 -0
- package/src/claude/skills-audit.ts +2 -0
- package/src/commands/pr.ts +123 -21
- package/src/commands/tooling.ts +39 -16
- package/src/gate/stages.ts +10 -2
- package/src/pr/preview.ts +66 -0
- package/src/tasks/validate.ts +37 -27
- package/src/tooling/manifest.ts +16 -0
- package/src/tooling/verify-stack.ts +249 -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/tooling/base/seeds/.cspell/tech-stack.txt +2 -0
- package/tooling/go/manifest.toml +3 -0
- package/tooling/go/reference.md +1 -0
- package/tooling/php/manifest.toml +3 -0
- package/tooling/php/reference.md +1 -0
- package/tooling/python/manifest.toml +3 -0
- package/tooling/python/reference.md +1 -1
- package/tooling/python/seeds/.cspell/tech-stack.txt +0 -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/snapshot.sh +0 -134
- package/scripts/core/update.sh +0 -35
- package/scripts/tooling/verify.sh +0 -184
|
@@ -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
|
|
|
@@ -17,6 +17,7 @@ The sequence also reaches the remote on work nothing re-checked. This skill is t
|
|
|
17
17
|
- Say so and continue when the project names no verify command, since silence there reads as a suite that passed
|
|
18
18
|
- Invoke each step through the Skill tool in the stated order and continue without waiting
|
|
19
19
|
- Stage after the sync skills write, so what they produced reaches a commit
|
|
20
|
+
- Reach the pull request on a branch whose work is already committed and whose sync steps wrote nothing, since `git-stage` stops on an empty index and a session building in slices leaves one
|
|
20
21
|
- Emit no text between steps. The sequence is the unit and prose inside it reopens settled decisions.
|
|
21
22
|
- Name the one point a wrapping caller may act at, so a chain built on this one is not left to pick a gap of its own
|
|
22
23
|
- Name the condition under which the closing block is not emitted, since a caller that closes on its own block leaves two instructions about the last line and nothing deciding between them
|
|
@@ -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
|
|
|
@@ -28,7 +28,7 @@ Run `git diff --cached --name-only 2>/dev/null` to check for staged files. If ou
|
|
|
28
28
|
3. Invoke `canon:docs-sync` to sync public docs against changes since main
|
|
29
29
|
4. Run `git add -A` to stage any files the sync skills wrote
|
|
30
30
|
5. Run `canon tasks plan-reach <plan> --json` and report both lists it carries. Name the plan this branch built under, by path or by slug. Read `claimed` first and say who holds each path, since that is the half a reader acts on, then say how many of the changed paths `undeclared` names. Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero. This step reports and never stops the sequence.
|
|
31
|
-
6. Invoke `canon:git-stage` to group staged changes and commit by concern
|
|
31
|
+
6. Invoke `canon:git-stage` to group staged changes and 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 to step 7.
|
|
32
32
|
7. Invoke `canon:git-branch` to rename branch to match conventional format
|
|
33
33
|
8. Invoke `canon:git-pr` to push branch and open pull request
|
|
34
34
|
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.
|
|
@@ -13,6 +13,8 @@ The miss is measured. On a seeded branch that deleted a dirty-tree guard while t
|
|
|
13
13
|
|
|
14
14
|
Rendered output is the larger hole. `git-pr` posts an `## Evidence` comment through `canon pr evidence`, carrying base and head screenshots and a checklist a reviewer ticks. The pull request review named that heading only in its heading set, and no step opened an image. On a seeded pull request whose narrow head screenshot shows the navigation running off the edge while a ticked box claims it collapses, the review filed the finding off the stylesheet diff and said it had not rendered the page. On a styling change with no screenshot at all, on a project whose trunk keeps them, it did not mention the absence.
|
|
15
15
|
|
|
16
|
+
A dependency upgrade is not a measured miss. On 2026-10-02 a seeded branch bumped one dependency across a major version beside a second, with a lockfile adding a transitive package that carried an install script, and the body without a dependency reference reported it. The run that measured it passed every assertion, including a graded finding naming the upgrade, so the case is a floor and no reference exists for it. An earlier run matched only a loose pattern and left no report to read, so it counts for nothing. The security reference still had no threat-model step and no class for a delete or clean on a derived path, both groundwork lifts with no miss to measure.
|
|
17
|
+
|
|
16
18
|
The axes also said nothing about a change that passes by lowering the bar it has to clear, such as a test skipped, a threshold moved, or a path excluded from a checker, nothing about performance, and one sentence about design with no procedure behind it. A refactor that only moved complexity read as a design gain, and a removal could call code dead without reading why it was added. The body carried no excuses, red flags, or closing checklist, so a session about to stop at the hunk met no answer first.
|
|
17
19
|
|
|
18
20
|
## Must
|
|
@@ -27,6 +29,7 @@ The axes also said nothing about a change that passes by lowering the bar it has
|
|
|
27
29
|
- State a design finding as a concrete cost, so it survives the procedure's filter against subjective suggestions
|
|
28
30
|
- Carry the evidence bar: confirm against the file at the reviewed head, quote a cited rule, name the breaking input, and drop what a gate owns or what rests on unread state
|
|
29
31
|
- Carry security as classes with an exclusion list, in a reference loaded when the diff reaches one
|
|
32
|
+
- Open the security reference with a threat model drawn from the diff, and carry destructive operations on a derived path as a class, so a cleanup deleting an unchecked variable's glob is read for the empty-value collapse
|
|
30
33
|
- Open the evidence images on a rendered change through `git show` at the row's own sha, never through the embedded address, within a stated read budget
|
|
31
34
|
- Test each ticked checklist box against an opened image, and name a ticked box no image covers as untested
|
|
32
35
|
- Flag a rendered change that carries no screenshot, as a finding where the trunk already keeps them and as a question elsewhere
|
|
@@ -36,7 +36,7 @@ An axis whose condition the diff meets is not optional. When the security or the
|
|
|
36
36
|
|
|
37
37
|
Read each of these when the diff reaches what it names.
|
|
38
38
|
|
|
39
|
-
7. **Security.** Read `${CLAUDE_SKILL_DIR}/references/security.md` when the diff runs a command, writes a file, handles input from outside the process, touches a secret, adds a dependency, or changes a default a consumer installs.
|
|
39
|
+
7. **Security.** Read `${CLAUDE_SKILL_DIR}/references/security.md` when the diff runs a command, writes or deletes a file, handles input from outside the process, touches a secret, adds a dependency, or changes a default a consumer installs.
|
|
40
40
|
8. **Rendered output.** Read `${CLAUDE_SKILL_DIR}/references/ui.md` when the diff touches a file that paints, such as markup, a stylesheet, a component, a template, or a design token, or when the pull request carries an evidence comment. A finding read off a stylesheet diff says what the author changed, and only the screenshot says what a user sees, so the reference opens the images and checks whether any exist.
|
|
41
41
|
9. **Developer experience and operations.** Ports, hooks, scripts, config, and scaffold defaults a consumer installs. A new required step nobody documented, a default that fails on a clean machine, or a hook that slows every commit is a finding even when the code is correct.
|
|
42
42
|
10. **Executable prose.** A skill body, a rule, or a prompt is instructions a model runs. Read it the way you read code: a step that races another, a precondition it never states, a branch with no exit, and two instructions that contradict each other are bugs.
|
|
@@ -34,6 +34,10 @@ From `addyosmani/agent-skills@2686b620`, `skills/constraint-driven-development/S
|
|
|
34
34
|
|
|
35
35
|
From `addyosmani/agent-skills@2686b620`, `skills/code-review-and-quality/SKILL.md` for the axis itself, a call inside a loop and an unbounded fetch, and `skills/performance-optimization/SKILL.md` for keep or revert: measure before and after the same way, and a neutral result argues for removing the added complexity. The repeated-run requirement against noise is stated here so one run on each side reads as an anecdote.
|
|
36
36
|
|
|
37
|
+
### Security additions
|
|
38
|
+
|
|
39
|
+
From `addyosmani/agent-skills@2686b620`, `skills/security-and-hardening/SKILL.md`: the threat model first and the derived-path rule. Adopted as the opening step of `references/security.md`, which names who supplies each input and what the code can reach before any class is read, and as the destructive-operations class, which asks for the empty-value collapse, the glob or symlink escape, the missing root check, and no read of what is there before the call. Both stay stack-neutral. No red run measures them, so they ship as lifts rather than as an answer to a miss.
|
|
40
|
+
|
|
37
41
|
### Closing sections
|
|
38
42
|
|
|
39
43
|
The excuses, red flags, and closing checklist follow the practice skill shape every practice skill in this toolkit carries, taken from `addyosmani/agent-skills@2686b620`, [`docs/skill-anatomy.md`](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/docs/skill-anatomy.md). Each excuse row rebuts a reason a review stops at the hunk, such as passing tests against a test the diff skipped, rather than an objection nobody raised.
|
|
@@ -46,4 +50,8 @@ The excuses, red flags, and closing checklist follow the practice skill shape ev
|
|
|
46
50
|
|
|
47
51
|
**Named structural remedies as a catalog.** A list of refactorings to propose reads as a menu a session fills in. A design finding states the cost, and the remedy is the author's.
|
|
48
52
|
|
|
53
|
+
**A dependency upgrade reference.** From `addyosmani/agent-skills@2686b620`, `skills/code-review-and-quality/SKILL.md`: read the changelog across the range, one dependency per change, and the lockfile diff. Declined because the seeded upgrade is not a miss. The body without such a reference reported the planted major bump and the install script in the lockfile on the second of two runs, which passed the assertion naming them. Revisit when a run on a changed lockfile misses what a reference would have named.
|
|
54
|
+
|
|
55
|
+
**STRIDE and abuse-case tests as a procedure.** They belong to a design session rather than a diff read, and the threat-model opening in the security reference takes the one step a diff supports, naming who supplies each input.
|
|
56
|
+
|
|
49
57
|
**The web and database tables from `performance-optimization`.** They name a stack, and the axis stays stack-neutral until a target asks for a per-stack reference.
|
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Read each class against the diff. A class the diff does not reach is skipped, not reported as clean. Name the input that reaches the sink and the path it takes, since a class named with no path is a suspicion rather than a finding.
|
|
4
4
|
|
|
5
|
+
## Open with the threat model
|
|
6
|
+
|
|
7
|
+
Before the classes, name from the diff who supplies each input and what the code can reach with it: a file, a process, a network, a credential. Skip a class that model rules out, and say which one and why, so the skip reads as a decision rather than an oversight.
|
|
8
|
+
|
|
5
9
|
## Classes to check
|
|
6
10
|
|
|
7
11
|
- **Shell and command injection.** A value from an argument, an environment variable, a file, or a network response reaching a shell: through `eval`, an unquoted expansion, a string built into a command, or a subprocess call that takes a single command string. Quoting the variable at the call site is the fix to look for.
|
|
8
12
|
- **Path traversal in a file write.** A path built from outside input and written without being resolved and checked against the directory it must stay inside. A `..` segment, an absolute path, and a symlink inside the target each escape a naive join.
|
|
13
|
+
- **Destructive operation on a derived path.** A delete, overwrite, move, or clean whose path is built from a variable, a config value, or a listing. Look for the empty or unset value that collapses it to a root, a glob or a symlink that carries it outside the folder it was meant for, no check that the resolved path sits at least one level below an expected root, and no read of what is there, owned by this tool or not, before the call. The fix to look for is resolve, require the root, then act. A write escaping its folder is path traversal. When a finding fits both, name the class whose fix applies.
|
|
9
14
|
- **Secrets and personal data leaving the process.** A token, a key, a password, or personal data reaching a log line, an error message, a session transcript, a published page, a pull request comment, or a sync to a remote. Check what a debug line prints and what a verbose flag adds.
|
|
10
15
|
- **Supply chain.** One-shot package execution of an unpinned version, which runs whatever the registry serves that day. A new dependency, and what its install scripts run. A lockfile that changes without a manifest change.
|
|
11
16
|
- **Time of check to time of use on a file write.** An existence or permission check followed by a write to the same path in a later step, and a predictable name in a shared temporary directory. Another process can swap the path in between.
|
|
@@ -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
|
|
|
@@ -18,6 +18,7 @@ A verdict also goes stale without saying so. A push after the pass changes what
|
|
|
18
18
|
- Drive every checklist box in the running app and give each exactly one verdict: pass or fail read off the page with the value quoted, pass or fail against a frame with what it shows, needs eyes for a box marked as taste, or not driven with the reason
|
|
19
19
|
- Drive a box written before the drivable format all the same, naming the route or width it guessed, so no box is skipped silently
|
|
20
20
|
- Read the checklist and the address from the evidence record rather than from the diff, the plan, or the author's description
|
|
21
|
+
- Drive only a build of the head the verdict names, and stop with nothing posted when the hosted preview was built from an older one
|
|
21
22
|
- Take the hosted preview, then the local preview, then an address the launch names, and refuse when none exists
|
|
22
23
|
- Report an address that does not answer as not driven rather than as a fail, and leave the review closed on a box no commit on the branch can settle, so an absent preview never holds the draft mark at every head
|
|
23
24
|
- Sweep console errors, sideways overflow at each named width, and the focus and details probes over the states reached, and nothing beyond them
|
|
@@ -21,6 +21,7 @@ rather than inside it, so the two passes finish on their own clocks.
|
|
|
21
21
|
- No address resolves under Step 3: stop and post nothing, `❌ No address to drive. PR #<number> carries no preview and no local preview, and the launch named none.`
|
|
22
22
|
- The wrapper refuses to open the browser because its revision is absent: stop and post nothing, passing its install command to whoever launched the pass. Never install mid-pass.
|
|
23
23
|
- The newest UI verdict is `## UI review closed` at the current head: stop, `The UI review already covers <short-sha>.` An open verdict at the head stops the same way only when nothing has arrived since it: drive again when a `## Review response` or `## Post-review findings` comment is newer than the verdict, or the launch names an address.
|
|
24
|
+
- The hosted preview was not built from the head: stop and post nothing, naming `built`, `tip`, and `canon pr preview <number> --json` for the dispatcher. A verdict posted against an older build carries a marker naming a head nobody drove.
|
|
24
25
|
- Post and stop. Never merge, never tick a box on the evidence comment, and never lift the draft mark.
|
|
25
26
|
|
|
26
27
|
## Step 1: resolve the pull request
|
|
@@ -55,6 +56,16 @@ Take the first rung that answers, testing each with `curl -s -o /dev/null -w '%{
|
|
|
55
56
|
2. The `local` address off the record.
|
|
56
57
|
3. An address the launch names.
|
|
57
58
|
|
|
59
|
+
When the hosted rung answers, check that it was built from the head before driving it:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
canon pr preview <number> --check --json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Branch on the record's `reason`. Only `fresh` continues. Any other stops with nothing posted, naming `built`, `tip`, and the next act: `stale` and `no-build` ask the dispatcher to run `canon pr preview <number> --json`, and `building` asks it to wait, since a mint is already running for the tip. This pass never mints. A `canon` that rejects `--check` predates the verb. Report that this pass needs a `canon` whose `pr preview` takes `--check`, naming the installed `canon --version`, and stop rather than reading the missing flag as `fresh`, the way Step 2 does for its own older binaries. A `reason` of `no-deploy`, `unfenced`, or `no-alias` means the project has no fenced deploy to read, so the hosted build cannot be verified. Stop on the hosted address then too, and say so.
|
|
66
|
+
|
|
67
|
+
The check covers the hosted address only. The local rung and an address the launch names have no deploy run to read, so say in the comment that they were driven unverified rather than implying the same coverage.
|
|
68
|
+
|
|
58
69
|
An address that exists and does not answer is a different outcome from no address at all. When every rung that exists fails to answer, skip the drive, record each box as not driven with the addresses tried and what each returned, and go to Step 7. A local address on another machine is the usual cause, and it says nothing about the change.
|
|
59
70
|
|
|
60
71
|
## Step 4: open the browser
|
|
@@ -52,5 +52,6 @@ The draft mark fails from both ends. On 2026-08-31 four sessions re-drafted a pu
|
|
|
52
52
|
|
|
53
53
|
- Entering the worktree, which `session-worktree` owns
|
|
54
54
|
- The chain from implement through pull request, which `auto-ship` owns
|
|
55
|
+
- How the build moves through the plan, slice by slice with a commit each, which `build-in-slices` owns
|
|
55
56
|
- Answering a posted review, which `review-address` owns
|
|
56
57
|
- The controlling session's half of the channel, the review poll, and the watch beside it, which `role-orchestrator` and its runbooks hold
|
|
@@ -20,6 +20,10 @@ from the skill that owns it and invoke none of the three from here. The ordinary
|
|
|
20
20
|
path arrives through `auto-ship` Step 0, which means that chain is already
|
|
21
21
|
running and re-invoking it would restart the build.
|
|
22
22
|
|
|
23
|
+
This body holds what the session may write. How it builds, in committed slices
|
|
24
|
+
with an out-of-scope finding noted rather than fixed, is `build-in-slices`,
|
|
25
|
+
which `auto-ship` Step 2 loads.
|
|
26
|
+
|
|
23
27
|
## Where the session stands
|
|
24
28
|
|
|
25
29
|
- Resolve `.canon/plans/`, `.canon/tasks/`, `.canon/review/`, `.canon/memory/`, and `.canon/ready/` at the main worktree root, never against the linked worktree this session builds in. Those folders are gitignored, so `git worktree add` never creates them and the copy beside the build is absent rather than empty.
|
|
@@ -14,6 +14,7 @@ Without this skill, a session implementing a planned change writes the test afte
|
|
|
14
14
|
- Write or extend the test before the implementation it covers, for any behavior whose shape is already known
|
|
15
15
|
- Run the test before implementing and confirm it fails for the missing behavior, not for an unrelated mistake in the test itself
|
|
16
16
|
- Implement the minimum the current test demands, and start a new test before extending past it
|
|
17
|
+
- Load `canon:code-craft` before writing the implementation when its shape is still open and the session has not loaded the skill, so the shape of the code is settled before the body rather than during refactor
|
|
17
18
|
- Re-run the test after implementing and confirm the pass is the one the test was written to prove
|
|
18
19
|
- Refactor the implementation and the test once the suite is green, re-running it after each change, since the smallest change that passes leaves duplication and shortcuts the loop exists to remove before they reach history
|
|
19
20
|
|
|
@@ -33,4 +34,6 @@ Without this skill, a session implementing a planned change writes the test afte
|
|
|
33
34
|
- Choosing the layer a test belongs at and judging whether it is a good test: `canon:test-craft`, loaded at step 1 rather than restated here
|
|
34
35
|
- Finding the cause of an unexplained failure: `canon:systematic-debugging`
|
|
35
36
|
- Confirming visual output after a change lands: `567-planning.md` states the order and `ui-checklist` writes the list to confirm against
|
|
37
|
+
- Shaping the function, class, or module the implementation writes: `canon:code-craft`, loaded at step 4 rather than restated here
|
|
38
|
+
- Committing the behavior as a slice and ordering the slices of a larger build: `canon:build-in-slices`
|
|
36
39
|
- The mechanical audit of whether an implementation reached history ahead of its test: `canon gov test-order`, invoked from `auto-ship`
|
|
@@ -10,7 +10,7 @@ description: Write the failing test for a behavior before writing the code that
|
|
|
10
10
|
1. Load `canon:test-craft` and pick the layer the test belongs at before writing it. Then find or write the test at that layer before touching the code it covers. Follow the pairing convention the project already uses, which is commonly a test sitting beside its subject under one name, so that `foo.ts` takes `foo.test.ts` beside it. Report it rather than proceeding silently when `canon:test-craft` does not resolve, and write the test at the smallest layer that can observe the behavior.
|
|
11
11
|
2. Write the test against the behavior as it should exist once the change lands, naming the case for what it proves rather than for the function it calls.
|
|
12
12
|
3. Run only that test and read the failure. Confirm it fails because the behavior is missing, not because of a typo, a missing import, or a signature the test itself got wrong. A test failing for the wrong reason still reads green the moment any code exists to satisfy that wrong reason, so treat any other failure as a defect in the test and fix the test before moving on.
|
|
13
|
-
4.
|
|
13
|
+
4. Load `canon:code-craft` and settle the shape of the code before writing it, unless the shape is already fixed or this session already loaded the skill. Report it rather than proceeding silently when `canon:code-craft` does not resolve, and write the plainest code the test asks for. Then implement the smallest change that turns the failure into a pass. Do not add behavior the test does not ask for. A second behavior wants its own test written first, not a shortcut folded into the change already open.
|
|
14
14
|
5. Run the test again and confirm it passes for the reason it was written for, not by accident. Then run the surrounding suite so a change made to satisfy this test has not broken another.
|
|
15
15
|
6. Refactor with the suite green. Remove the duplication and the shortcuts step 4 left, in the implementation and in the test, without changing what either does. Run the suite after each change, and undo a change that turns anything red rather than fixing forward.
|
|
16
16
|
|
|
@@ -23,4 +23,5 @@ description: Write the failing test for a behavior before writing the code that
|
|
|
23
23
|
|
|
24
24
|
- Which layer a test belongs at and what makes it a good one. `canon:test-craft` owns that judgment, and step 1 loads it.
|
|
25
25
|
- A failure with no known cause. Route through `canon:systematic-debugging` first, whose own fix phase already writes the reproducing test as part of finding the cause. This skill starts once the shape of the fix or the feature is already decided.
|
|
26
|
+
- Committing the green, refactored behavior as one slice of a larger build. `canon:build-in-slices` owns the commit and the order slices land in.
|
|
26
27
|
- Confirming a change looks right once it has landed, which is a separate concern from whether the test passed and runs after implementation rather than before 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
|
|
@@ -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
|
|
|
@@ -46,19 +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.
|
|
61
|
-
| `check-writes` | `--check` was passed with `--preview`, `--local`, or `--checklist`.
|
|
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`. |
|
|
62
62
|
|
|
63
63
|
`no-evidence` is not a refusal a caller reports. A project on a stack that
|
|
64
64
|
carries no evidence path, such as `base` or `python`, hits this reason on
|
|
@@ -76,8 +76,9 @@ shows a reviewer, each field present only when that comment holds it:
|
|
|
76
76
|
|
|
77
77
|
These come from the comment already posted, never from the flags the call
|
|
78
78
|
passed, so a skill driving a review reads which address and which checklist a
|
|
79
|
-
reviewer has without parsing the comment itself. A checklist posted
|
|
80
|
-
|
|
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
|
|
81
82
|
them means the thread is read before the `no-evidence` answer too, so an
|
|
82
83
|
unreadable thread refuses as `gh-failed` on both reasons rather than
|
|
83
84
|
reporting the fields absent.
|
|
@@ -156,11 +157,11 @@ already holds, the same way the preview address is carried. That is what keeps
|
|
|
156
157
|
already ticked, since `git-pr` deletes the handoff once the first post reports
|
|
157
158
|
success and no later call has a file to pass.
|
|
158
159
|
|
|
159
|
-
The option
|
|
160
|
-
|
|
161
|
-
checklist
|
|
162
|
-
|
|
163
|
-
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
|
|
164
165
|
`unreadable-checklist` rather than rendering without it: the caller deletes the
|
|
165
166
|
handoff once a post succeeds, so a silently dropped checklist is the only copy
|
|
166
167
|
gone.
|
|
@@ -175,8 +176,8 @@ the local address the marked comment already holds, the same as the other two.
|
|
|
175
176
|
|
|
176
177
|
The option does not turn `no-evidence` into `ok` on its own. A branch with a
|
|
177
178
|
dev server running and no rendered change would otherwise get a comment holding
|
|
178
|
-
a link and nothing else. Together with `--checklist`
|
|
179
|
-
|
|
179
|
+
a link and nothing else. Together with `--checklist` the link and the
|
|
180
|
+
checklist land in one comment.
|
|
180
181
|
`canon docs pr-local` covers where the address comes from and how the line is
|
|
181
182
|
removed at close.
|
|
182
183
|
|
|
@@ -214,9 +215,9 @@ those ask a read to write.
|
|
|
214
215
|
|
|
215
216
|
The thread cannot separate a skipped preview step from a failed one. A pull
|
|
216
217
|
request whose deploy run failed or timed out reads as owing a preview, and the
|
|
217
|
-
session that ran it holds the cause. A checklist
|
|
218
|
-
|
|
219
|
-
|
|
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
|
|
220
221
|
workflow is read from the checkout rather than the pull request's head, so a
|
|
221
222
|
pull request that adds or removes its own deploy workflow reads against trunk's.
|
|
222
223
|
|
|
@@ -14,6 +14,7 @@ rather than screenshots and a checklist alone.
|
|
|
14
14
|
```bash
|
|
15
15
|
canon pr preview --json
|
|
16
16
|
canon pr preview 1341 --json --timeout 20
|
|
17
|
+
canon pr preview 1341 --check --json
|
|
17
18
|
```
|
|
18
19
|
|
|
19
20
|
## Which workflow it dispatches
|
|
@@ -61,22 +62,49 @@ keeps the match independent of the local clock.
|
|
|
61
62
|
|
|
62
63
|
`reason` on the record is what a caller branches on, not the exit code:
|
|
63
64
|
|
|
64
|
-
| Reason
|
|
65
|
-
|
|
|
66
|
-
| `ok`
|
|
67
|
-
| `no-deploy`
|
|
68
|
-
| `unfenced`
|
|
69
|
-
| `no-alias`
|
|
70
|
-
| `run-failed`
|
|
71
|
-
| `timeout`
|
|
72
|
-
| `bad-timeout`
|
|
73
|
-
| `gh-missing`
|
|
74
|
-
| `gh-failed`
|
|
75
|
-
| `no-branch`
|
|
65
|
+
| Reason | What it means |
|
|
66
|
+
| --------------- | -------------------------------------------------------------------------- |
|
|
67
|
+
| `ok` | The preview was published. `url` carries the address and `runId` the run. |
|
|
68
|
+
| `no-deploy` | No dispatchable workflow runs `pages deploy`. |
|
|
69
|
+
| `unfenced` | The deploy passes no `--branch`, so nothing was dispatched. |
|
|
70
|
+
| `no-alias` | The workflow prints no alias line, or the finished run's log carried none. |
|
|
71
|
+
| `run-failed` | The deploy run finished without succeeding. `runId` names it. |
|
|
72
|
+
| `timeout` | The run did not finish inside `--timeout` minutes, 15 by default. |
|
|
73
|
+
| `bad-timeout` | `--timeout` was not a positive number. |
|
|
74
|
+
| `gh-missing` | `gh` is not on the path. |
|
|
75
|
+
| `gh-failed` | `gh` could not read the pull request, or list or dispatch the workflow. |
|
|
76
|
+
| `no-branch` | The pull request carries no head branch name. |
|
|
77
|
+
| `check-timeout` | `--check` was combined with `--timeout`. |
|
|
76
78
|
|
|
77
79
|
The exit is 0 on `ok` and 1 on every refusal. A `timeout` leaves the run
|
|
78
80
|
going, so the preview may still land after the verb has given up on it.
|
|
79
81
|
|
|
82
|
+
## Checking which head a preview was built from
|
|
83
|
+
|
|
84
|
+
`--check` dispatches nothing and waits on nothing. It lists the branch's
|
|
85
|
+
`workflow_dispatch` runs, takes the newest successful one by creation time, and
|
|
86
|
+
compares the head it ran at with the branch tip read from the remote. The tip
|
|
87
|
+
comes from the remote rather than the pull request object's `headRefOid`, which
|
|
88
|
+
lags a push. `--check` takes no `--timeout` and refuses one as `check-timeout`.
|
|
89
|
+
|
|
90
|
+
The alias serves the newest successful deployment for the branch and names no
|
|
91
|
+
sha, so the run listing is the only record of the built head. The
|
|
92
|
+
`workflow_dispatch` filter also drops the cleanup run a closed pull request
|
|
93
|
+
fires, which concludes `success` with its deploy skipped. A project that deploys
|
|
94
|
+
on `push` to a feature branch would need that filter widened.
|
|
95
|
+
|
|
96
|
+
| Reason | What it means |
|
|
97
|
+
| ---------- | --------------------------------------------------------------------- |
|
|
98
|
+
| `fresh` | The newest successful deploy built the tip. Exit 0. |
|
|
99
|
+
| `stale` | It built an earlier head. `built` and `tip` name both. Mint again. |
|
|
100
|
+
| `building` | A deploy of the tip is still running. Wait rather than minting again. |
|
|
101
|
+
| `no-build` | No deploy of the branch has succeeded. |
|
|
102
|
+
|
|
103
|
+
The record also carries `runId` for the deploy it read. The check covers the
|
|
104
|
+
hosted address only, so a local address has no run to read and stays unverified.
|
|
105
|
+
`review-ui` runs it before driving a hosted preview and posts nothing on any
|
|
106
|
+
reason but `fresh`.
|
|
107
|
+
|
|
80
108
|
## How the address reaches the pull request
|
|
81
109
|
|
|
82
110
|
`canon pr evidence --preview <url>` puts `**Preview:** <url>` on the first line
|
|
@@ -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
|
|
|
@@ -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
|
|