@erclx/canon 5.33.0 → 5.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +3 -5
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/REQUIREMENT.md +2 -3
  4. package/claude/skills/api-design/SKILL.md +2 -3
  5. package/claude/skills/api-design/references/adopted.md +1 -1
  6. package/claude/skills/auto-ship/references/draft-mark.md +1 -1
  7. package/claude/skills/canon-cli/SKILL.md +10 -11
  8. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -0
  9. package/claude/skills/canon-feedback/SKILL.md +10 -28
  10. package/claude/skills/canon-feedback/references/template.md +53 -0
  11. package/claude/skills/canvas-board/SKILL.md +4 -1
  12. package/claude/skills/canvas-board/references/canvas.md +26 -3
  13. package/claude/skills/code-craft/REQUIREMENT.md +1 -1
  14. package/claude/skills/code-craft/SKILL.md +0 -1
  15. package/claude/skills/create-rule/SKILL.md +1 -1
  16. package/claude/skills/create-rule/references/rule.md +3 -1
  17. package/claude/skills/create-skill/SKILL.md +2 -1
  18. package/claude/skills/create-skill/references/skill-paths.md +12 -15
  19. package/{standards/standard.md → claude/skills/create-skill/references/skill-reference.md} +50 -45
  20. package/claude/skills/create-skill/references/skill.md +10 -4
  21. package/claude/skills/draft-and-pick/SKILL.md +1 -1
  22. package/claude/skills/git-commit/references/versioning.md +13 -13
  23. package/claude/skills/git-issue/references/issue.md +4 -1
  24. package/claude/skills/git-pr/SKILL.md +1 -1
  25. package/claude/skills/git-pr/references/publish.md +1 -1
  26. package/claude/skills/review-address/REQUIREMENT.md +1 -1
  27. package/claude/skills/review-address/SKILL.md +2 -2
  28. package/claude/skills/review-craft/references/ui.md +1 -1
  29. package/claude/skills/review-pr/SKILL.md +3 -3
  30. package/claude/skills/review-pr/references/post.md +1 -1
  31. package/claude/skills/review-ui/REQUIREMENT.md +1 -1
  32. package/claude/skills/review-ui/SKILL.md +8 -6
  33. package/claude/skills/review-ui/references/driving.md +8 -8
  34. package/claude/skills/review-ui/references/post.md +52 -16
  35. package/claude/skills/role-orchestrator/REQUIREMENT.md +2 -2
  36. package/claude/skills/role-orchestrator/SKILL.md +11 -12
  37. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +3 -1
  38. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +11 -8
  39. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +10 -4
  40. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +11 -2
  41. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +11 -12
  42. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +12 -15
  43. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +6 -4
  44. package/claude/skills/role-orchestrator/scripts/poll.ts +50 -1
  45. package/claude/skills/role-reviewer/REQUIREMENT.md +17 -7
  46. package/claude/skills/role-reviewer/SKILL.md +17 -10
  47. package/claude/skills/role-worker/REQUIREMENT.md +1 -1
  48. package/claude/skills/role-worker/SKILL.md +6 -6
  49. package/claude/skills/session-compact/references/handoff-note.md +1 -1
  50. package/claude/skills/target-setup/SKILL.md +12 -6
  51. package/claude/skills/target-setup/references/detect.md +22 -5
  52. package/claude/skills/test-craft/REQUIREMENT.md +2 -3
  53. package/claude/skills/test-craft/SKILL.md +15 -3
  54. package/docs/agents/audits.md +1 -1
  55. package/docs/agents/canvas.md +5 -1
  56. package/docs/agents/commands.md +3 -5
  57. package/docs/agents/counts.md +5 -6
  58. package/docs/agents/drift-surfaces.md +15 -19
  59. package/docs/agents/gov-detect.md +47 -0
  60. package/docs/agents/index.md +6 -4
  61. package/docs/agents/install-and-sync.md +11 -31
  62. package/docs/agents/markdown-audit.md +10 -12
  63. package/docs/agents/migrate.md +1 -1
  64. package/docs/agents/pr-evidence-layout.md +70 -0
  65. package/docs/agents/pr-evidence.md +8 -9
  66. package/docs/agents/pr-frames.md +7 -2
  67. package/docs/agents/pr-lift.md +132 -0
  68. package/docs/agents/records-stale.md +1 -1
  69. package/docs/agents/records-validate.md +11 -23
  70. package/docs/agents/records.md +1 -1
  71. package/docs/agents/routing.md +1 -1
  72. package/docs/agents/rule-citations.md +11 -14
  73. package/docs/agents/scripting.md +4 -21
  74. package/docs/agents/state-scoped-risk.md +1 -1
  75. package/docs/agents/tasks-validate.md +1 -1
  76. package/docs/agents/teach.md +1 -1
  77. package/docs/target/index.md +1 -0
  78. package/docs/target/migrations.md +4 -0
  79. package/docs/target/projects.md +11 -11
  80. package/docs/target/scenarios.md +5 -6
  81. package/docs/target/standards-moved.md +32 -0
  82. package/docs/target/sync.md +5 -5
  83. package/docs/workflow/operating-model.md +16 -18
  84. package/docs/workflow/skill-map.md +1 -1
  85. package/governance/detect.toml +197 -0
  86. package/governance/renames.toml +0 -1
  87. package/governance/rules/code/000-code.md +1 -13
  88. package/governance/rules/code/010-testing.md +2 -30
  89. package/governance/rules/ui/400-ui.md +1 -1
  90. package/governance/rules/ui/480-canvas.md +13 -0
  91. package/governance/stacks/base.toml +15 -8
  92. package/governance/stacks/go.toml +2 -0
  93. package/governance/stacks/node.toml +1 -1
  94. package/governance/stacks/php.toml +2 -0
  95. package/governance/stacks/python.toml +1 -1
  96. package/package.json +1 -4
  97. package/scripts/core/install-check.sh +2 -3
  98. package/scripts/core/regen-hero.ts +0 -6
  99. package/scripts/lib/ui.sh +0 -9
  100. package/src/audits/catalog.ts +0 -9
  101. package/src/canvas/arrange.ts +66 -0
  102. package/src/canvas/capture.ts +20 -6
  103. package/src/canvas/content.ts +39 -0
  104. package/src/canvas/fit.ts +238 -0
  105. package/src/canvas/tokens.ts +28 -10
  106. package/src/capture/frame-values.ts +2 -32
  107. package/src/claude/routing.ts +1 -1
  108. package/src/claude/skills-reach.ts +4 -6
  109. package/src/cli/help.ts +3 -4
  110. package/src/cli.ts +0 -2
  111. package/src/commands/canvas.ts +179 -1
  112. package/src/commands/gov.ts +149 -10
  113. package/src/commands/init.ts +1 -1
  114. package/src/commands/labels.ts +4 -44
  115. package/src/commands/migrate.ts +1 -1
  116. package/src/commands/pr.ts +376 -1
  117. package/src/commands/records.ts +4 -20
  118. package/src/commands/tooling.ts +2 -4
  119. package/src/counts/catalogs.ts +0 -6
  120. package/src/feedback/body.ts +26 -5
  121. package/src/gate/boundaries.ts +2 -2
  122. package/src/gate/measures.ts +64 -72
  123. package/src/gate/sequencer.ts +51 -2
  124. package/src/gate/stages.ts +3 -22
  125. package/src/gov/citations.ts +11 -43
  126. package/src/gov/detect.ts +301 -0
  127. package/src/gov/list.ts +23 -2
  128. package/src/gov/stacks.ts +9 -0
  129. package/src/markdown/bans.ts +1 -1
  130. package/src/migrate/scratch-evidence.ts +2 -2
  131. package/src/pr/evidence.ts +218 -45
  132. package/src/pr/frames.ts +23 -3
  133. package/src/pr/lift.ts +418 -0
  134. package/src/pr/rest.ts +3 -0
  135. package/src/pr/review-scope.ts +76 -0
  136. package/src/records/validate.ts +6 -194
  137. package/src/sandbox/equivalence.ts +14 -7
  138. package/src/sandbox/provision.ts +0 -5
  139. package/src/secrets/shipped.ts +1 -2
  140. package/src/serve/static.ts +1 -2
  141. package/src/shipped/references.ts +29 -80
  142. package/src/sync/check.ts +18 -14
  143. package/src/tooling/inject.ts +6 -37
  144. package/src/tooling/read.ts +2 -3
  145. package/src/tooling/scan.ts +4 -17
  146. package/src/tooling/subfolder.ts +2 -66
  147. package/tooling/base/configs/scripts/verify.json +1 -1
  148. package/tooling/base/configs/scripts/verify.ts +1 -12
  149. package/tooling/base/manifest.toml +1 -2
  150. package/tooling/base/reference.md +10 -16
  151. package/tooling/base/seeds/.github/workflows/verify.yml +0 -3
  152. package/tooling/base/seeds/.lintstagedrc +1 -2
  153. package/tooling/base/seeds/canon/context/ci.md +0 -1
  154. package/tooling/base/seeds/canon/context/development.md +1 -1
  155. package/tooling/claude/reference.md +1 -1
  156. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +13 -1
  157. package/tooling/go/reference.md +1 -1
  158. package/tooling/php/reference.md +1 -1
  159. package/tooling/python/reference.md +2 -2
  160. package/tooling/web/configs/.github/workflows/verify.yml +0 -3
  161. package/tooling/web/manifest.toml +0 -1
  162. package/tooling/web/reference.md +2 -4
  163. package/docs/agents/standards-audit.md +0 -40
  164. package/governance/rules/tooling/765-spelling.md +0 -19
  165. package/governance/stacks/astro.toml +0 -2
  166. package/governance/stacks/nextjs.toml +0 -2
  167. package/governance/stacks/node-server.toml +0 -2
  168. package/governance/stacks/python-fastapi.toml +0 -2
  169. package/governance/stacks/react.toml +0 -2
  170. package/src/commands/standards.ts +0 -278
  171. package/src/labels/spelling.ts +0 -120
  172. package/src/standards/audit.ts +0 -146
  173. package/src/standards/list.ts +0 -33
  174. package/src/standards/read.ts +0 -177
  175. package/src/standards/scope.ts +0 -56
  176. package/standards/index.md +0 -10
  177. package/tooling/base/configs/.vscode/extensions.json +0 -9
  178. package/tooling/base/configs/.vscode/settings.json +0 -3
  179. package/tooling/base/seeds/.cspell/project-terms.txt +0 -0
  180. package/tooling/base/seeds/.cspell/tech-stack.txt +0 -25
  181. package/tooling/base/seeds/cspell.json +0 -20
  182. package/tooling/go/seeds/.cspell/tech-stack.txt +0 -16
  183. package/tooling/nextjs/seeds/.cspell/tech-stack.txt +0 -3
  184. package/tooling/php/seeds/.cspell/tech-stack.txt +0 -5
  185. package/tooling/python/seeds/.cspell/tech-stack.txt +0 -18
  186. package/tooling/vite-react/seeds/.cspell/project-terms.txt +0 -1
  187. package/tooling/vite-react/seeds/.cspell/tech-stack.txt +0 -2
  188. package/tooling/web/configs/.vscode/extensions.json +0 -13
  189. package/tooling/web/configs/.vscode/settings.json +0 -10
  190. package/tooling/web/seeds/.cspell/tech-stack.txt +0 -21
@@ -1,75 +1,83 @@
1
1
  ---
2
- title: Standard reference
3
- description: Shape and content rules for authoring a standard
2
+ title: Reference file reference
3
+ description: Shape and content rules for a reference that sets the shape of one artifact
4
4
  ---
5
5
 
6
- # Standard reference
6
+ # Reference file reference
7
7
 
8
- Applies to each authored standard in the folder. Skip for `index.md`, which is generated rather than authored.
8
+ Applies to each file under a skill's `references/` that sets the shape of one document type, or of one attribute carried across every document. A session reads it at the point the skill body names it, and skills and developers consume it alike. This file governs itself, so every rule below applies to it.
9
9
 
10
- ## Overview
10
+ ## Contents
11
11
 
12
- A standard is a target-facing authoring convention for one document type, or for one attribute carried across every document. Nothing installs it into a project, so a reader resolves it with `canon standards <name>` or reads it at `standards/<name>.md`, and skills and developers consume it alike. This file governs itself, so every rule below applies to it.
12
+ - [Scope](#scope)
13
+ - [What a working reference looks like](#what-a-working-reference-looks-like)
14
+ - [Scoping rules](#scoping-rules)
15
+ - [Frontmatter](#frontmatter)
16
+ - [Structure](#structure)
17
+ - [Rules](#rules)
18
+ - [Success criterion](#success-criterion)
19
+ - [Changing a reference](#changing-a-reference)
20
+ - [Examples](#examples)
21
+ - [Template](#template)
13
22
 
14
23
  ## Scope
15
24
 
16
- Governs each authored standard under `standards/`: its stated jurisdiction, success criterion, frontmatter, structure, and rule phrasing.
25
+ Governs a shape reference at `skills/<name>/references/<file>.md`: its stated jurisdiction, success criterion, frontmatter, structure, and rule phrasing.
17
26
 
18
27
  Does not govern:
19
28
 
20
- - The voice, rhythm, and sentence construction a standard is written in: the `write-human` skill
21
- - The punctuation, formatting, and word choice a standard is written in: `markdown.md`
22
- - The shape of any artifact a standard governs, which is that standard's own subject
29
+ - The `references/` folder's place in the skill, its line ceiling, and the body naming each file: `skill.md`
30
+ - How a body or a reference cites another skill's reference: `skill-paths.md`
31
+ - The voice, rhythm, and sentence construction a reference is written in: the `write-human` skill
32
+ - The punctuation, formatting, and word choice a reference is written in: `../markdown-craft/references/markdown.md`
33
+ - The shape of any artifact a reference governs, which is that reference's own subject
23
34
 
24
- ## What a working standard looks like
35
+ ## What a working reference looks like
25
36
 
26
- A standard answers these questions. Each can be answered wrong, which is what makes them a test rather than a preamble.
37
+ A shape reference answers these questions. Each can be answered wrong, which is what makes them a test rather than a preamble.
27
38
 
28
39
  - Which single document type or attribute does this govern, and where does it apply?
29
40
  - Can an author who has seen no example produce a conforming document from this file alone?
30
41
  - Does every rule state a shape the document must have, rather than a fact about the repository that happens to store it?
31
42
  - What does a conforming document achieve, stated so a reviewer can call one non-conforming without appealing to taste?
32
43
 
33
- A standard failing these questions is non-conforming even when it satisfies every shape rule below.
44
+ A reference failing these questions is non-conforming even when it satisfies every shape rule below.
34
45
 
35
46
  ## Scoping rules
36
47
 
37
48
  ### Declaring scope
38
49
 
39
- - Govern one document type per standard, or one attribute across every document. Split unrelated conventions into separate files.
40
- - Open with a `## Scope` section stating what the standard governs and what it does not, placed above the shape rules. A standard that specifies shape exhaustively and jurisdiction nowhere cannot refuse a rule, so the rule with no obvious owner lands in whichever standard sits nearest.
41
- - Write it as one line naming the artifact or attribute and where it applies, then a `Does not govern:` list. Give each entry the excluded concern and the owner it goes to. Name a sibling standard by bare filename, since the corpus is one flat folder, and name the surface instead where the owner is one, such as a coding rule, a project policy, or the code.
50
+ - Govern one document type per reference, or one attribute across every document. Split unrelated conventions into separate files.
51
+ - Open with a `## Scope` section stating what the reference governs and what it does not, placed above the shape rules. A reference that specifies shape exhaustively and jurisdiction nowhere cannot refuse a rule, so the rule with no obvious owner lands in whichever reference sits nearest.
52
+ - Write it as one line naming the artifact or attribute and where it applies, then a `Does not govern:` list. Give each entry the excluded concern and the owner it goes to.
53
+ - Name an owner in the same `references/` folder by bare filename and one in another skill by its sibling path, `../<skill>/references/<name>.md`. Name the surface instead where the owner is one, such as a coding rule, a project policy, or the code.
42
54
  - Put the governed path in backticks inside the first sentence of that line, anchored deep enough to resolve from a project root. A bare folder name matches a same-named folder elsewhere in the tree, and a path held back until a later sentence sits beside every other path the statement mentions, including the ones it excludes.
43
- - Say in that same sentence when the standard governs an attribute rather than a document type. An attribute is written across every document and has no path to name, so the silence reads as an omission unless the sentence claims it.
55
+ - Say in that same sentence when the reference governs an attribute rather than a document type. An attribute is written across every document and has no path to name, so the silence reads as an omission unless the sentence claims it.
44
56
  - Cut an entry that names no owner at all. It is either excluding something nothing was going to claim, or it is a content exclusion, which the rule below sends to the shape rules instead.
45
- - Declare a boundary from both sides. A yield, an exemption, or a handoff stated in one standard alone is never checked against the standard on the other side of it, which is how two files come to claim the same rule or neither does.
46
- - Separate a jurisdiction exclusion from a content exclusion. The first names a concern another standard owns and belongs in `## Scope`. The second names what does not belong inside the document and stays with the shape rules. Merging them puts a boundary claim where no sibling will read it.
47
- - Stay silent on a section the standard holds today but should not own. Claiming it makes the scope statement false the moment it moves, and the mismatch is the evidence that moves it.
57
+ - Declare a boundary from both sides. A yield, an exemption, or a handoff stated in one reference alone is never checked against the reference on the other side of it, which is how two files come to claim the same rule or neither does.
58
+ - Separate a jurisdiction exclusion from a content exclusion. The first names a concern another reference owns and belongs in `## Scope`. The second names what does not belong inside the document and stays with the shape rules. Merging them puts a boundary claim where no sibling will read it.
59
+ - Stay silent on a section the reference holds today but should not own. Claiming it makes the scope statement false the moment it moves, and the mismatch is the evidence that moves it.
48
60
 
49
61
  ### Naming the file
50
62
 
51
63
  - Name the file for the artifact the scope statement governs, taking the word from the deepest path segment that names the artifact rather than the folder holding it. `plan.md` over `.canon/plans/feature-<slug>.md` and `session.md` over `.canon/tasks/session-<slug>.md` both follow it.
52
- - Take the singular or the plural of that word, whichever reads as the artifact. A standard over one document takes the singular, and one over a set may take either.
53
- - Name an attribute standard for the attribute itself, since it governs no path to derive a word from.
54
- - Write the derived word alone. A standard installs as a sibling and is cited by bare filename, so a qualifier makes an outlier that every later citation has to carry.
55
- - Rename an outlier at the moment it is found, and state the reach in the change that does it. The name is installed in every target and cited in surfaces that never see the rename, so the cost only grows.
56
64
 
57
65
  ### Staying inside it
58
66
 
59
- - Name no path, filename, or folder outside the document type the standard governs. A standard reaches projects whose layout is their own, so a path borrowed from the authoring repository is wrong in a target and nothing reports it.
67
+ - Name no path, filename, or folder outside the document type the reference governs. A reference reaches projects whose layout is their own, so a path borrowed from the authoring repository is wrong in a target and nothing reports it.
60
68
  - State the rule, never the mechanism enforcing it. Hooks, scripts, checks, and skill catalogs are facts about one repository. Name the condition the document must meet and let the enforcing surface name its own case.
61
- - Invent inline examples rather than citing a real file elsewhere in the project. A cited file moves or is deleted and the standard goes stale in silence.
69
+ - Invent inline examples rather than citing a real file elsewhere in the project. A cited file moves or is deleted and the reference goes stale in silence.
62
70
 
63
71
  ## Frontmatter
64
72
 
65
73
  - Start the file with a frontmatter block carrying at least `title` and `description`. A consuming surface may require more.
66
74
  - `title`: names the doc type in sentence case, suffixed `reference` (`Commit reference`, `Branch reference`)
67
- - `description`: one line naming what the standard covers. It becomes the index link label on install.
75
+ - `description`: one line naming what the reference covers
68
76
 
69
77
  ## Structure
70
78
 
71
79
  - Use sentence case for every heading
72
- - Flat `##` rule groups for a single-topic standard. Group `##` headers by concern for a multi-topic one.
80
+ - Flat `##` rule groups for a single-topic reference. Group `##` headers by concern for a multi-topic one.
73
81
  - When one `##` section covers more than one sub-concern, split its bullets into `###` subgroups, one subgroup per sub-concern. A flat bullet list under an `##` covers a single sub-concern. Roughly seven bullets is a signal to split, not a hard cap.
74
82
  - Order groups from the most-used rule down to the edge case
75
83
 
@@ -83,13 +91,12 @@ A standard failing these questions is non-conforming even when it satisfies ever
83
91
 
84
92
  ## Success criterion
85
93
 
86
- - State what a conforming artifact achieves, not only what shape it takes. A standard that specifies structure exhaustively and success nowhere cannot be argued against, only edited on taste.
94
+ - State what a conforming artifact achieves, not only what shape it takes. A reference that specifies structure exhaustively and success nowhere cannot be argued against, only edited on taste.
87
95
  - Write the criterion as a small set of questions the artifact must answer, or a task a reader must be able to complete from it. Keep it checkable by a person in one sitting.
88
96
  - Place it near the top, above the shape rules it governs. The shape rules are the means and the criterion is the test.
89
97
  - Say that an artifact failing the criterion is non-conforming even when it satisfies every shape rule. Without that line the criterion reads as advice.
90
- - Add a criterion to an existing standard when that standard is next exercised, not in a sweep. A criterion written without a failure to point at is the taste-based edit this section exists to prevent, so a standard with no criterion yet is a known gap rather than a violation.
91
98
 
92
- ## Changing a standard
99
+ ## Changing a reference
93
100
 
94
101
  ### The checkpoint
95
102
 
@@ -98,12 +105,12 @@ Answer all four before editing, and carry the answers into wherever the change i
98
105
  - What problem does this solve? Name the artifact that went wrong, rather than the improvement the change makes.
99
106
  - Which surface owns the rule today? A rule already stated somewhere moves or is cited, never restated in a second place.
100
107
  - What deterministic check catches a regression? Name it, or say none exists and the rule holds on reading alone.
101
- - What does this collide with? Name the sibling standard, rule, or template it contradicts, or state that nothing does.
108
+ - What does this collide with? Name the sibling reference, rule, or template it contradicts, or state that nothing does.
102
109
 
103
110
  ### What justifies a change
104
111
 
105
- - Change a standard on a failure, not on a finding. A finding is that the docs say X or a paper suggests Y. A failure is a conforming artifact that satisfied every shape rule and still missed the success criterion.
106
- - Park findings wherever the project tracks pending work, or in the standard's own backlog section when it tracks none. They are hypotheses to test, not instructions to apply.
112
+ - Change a reference on a failure, not on a finding. A finding is that the docs say X or a paper suggests Y. A failure is a conforming artifact that satisfied every shape rule and still missed the success criterion.
113
+ - Park findings wherever the project tracks pending work, or in the reference's own backlog section when it tracks none. They are hypotheses to test, not instructions to apply.
107
114
  - Cite the failing artifact in the change that fixes it, so the next reader can tell which rules were paid for by evidence.
108
115
 
109
116
  ## Examples
@@ -115,20 +122,19 @@ Answer all four before editing, and carry the answers into wherever the change i
115
122
 
116
123
  ## Template
117
124
 
118
- - Carry one fenced template of the document the standard governs, so an author copies a shape instead of reconstructing it from prose.
119
- - Bind this to a standard governing a document type. An attribute standard governs a scan, a string, or a label rather than a file, so it has no document to template and carries none.
120
- - State that exemption in the sentence declaring the standard an attribute standard. An exemption left to inference reads as an omission, and the next author writes a template that teaches nothing.
121
- - Place the template below the rules it satisfies, under a `## Template` heading or inside the section holding those rules. A reader arrives at it having already read what each part means.
125
+ - Carry one fenced template of the document the reference governs, so an author copies a shape instead of reconstructing it from prose.
126
+ - Bind this to a reference governing a document type. An attribute reference governs a scan, a string, or a label rather than a file, so it has no document to template and carries none. State that exemption in the sentence declaring it an attribute reference.
127
+ - Place the template below the rules it satisfies, under a `## Template` heading or inside the section holding those rules.
122
128
  - Show the skeleton alone: every required section, one placeholder line for what each holds. A full worked document is a second document to maintain.
123
- - Write placeholders in angle brackets rather than copying a real document. A copied file goes stale, and its backticked filenames read as citations to anything parsing the standard.
124
- - Switch to a bare word where the fenced language reads `<` as syntax of its own, as Mermaid and HTML do, and say in the line above the fence that the names are placeholders. A template that does not parse in its own language teaches a shape the author cannot run.
125
- - Carry any header, key, or label a consuming tool parses verbatim. The template is the only place an author learns which strings are load-bearing, since prose calling them fixed does not say what they are.
126
- - Treat the template as authoritative where it and the prose disagree. An author copies the block, so a contradiction ships as the block, and naming the winner turns a drift into a visible defect rather than a silent one.
129
+ - Write placeholders in angle brackets rather than copying a real document. A copied file goes stale, and its backticked filenames read as citations to anything parsing the reference.
130
+ - Switch to a bare word where the fenced language reads `<` as syntax of its own, as Mermaid and HTML do, and say in the line above the fence that the names are placeholders.
131
+ - Carry any header, key, or label a consuming tool parses verbatim. The template is the only place an author learns which strings are load-bearing.
132
+ - Treat the template as authoritative where it and the prose disagree. An author copies the block, so a contradiction ships as the block.
127
133
 
128
134
  ````markdown
129
135
  ---
130
136
  title: <Document type> reference
131
- description: <one line naming what this standard covers>
137
+ description: <one line naming what this reference covers>
132
138
  ---
133
139
 
134
140
  # <Document type> reference
@@ -137,7 +143,7 @@ Applies to `<path/to/document>`. <One line on what the document is for and when
137
143
 
138
144
  ## Scope
139
145
 
140
- Governs `<path/to/document>`: <the aspects this standard sets>.
146
+ Governs `<path/to/document>`: <the aspects this reference sets>.
141
147
 
142
148
  Does not govern:
143
149
 
@@ -160,7 +166,6 @@ A <document type> failing these is non-conforming even when it satisfies every s
160
166
 
161
167
  ## <Shape rule group>
162
168
 
163
- - <imperative rule, one concern per bullet>
164
169
  - <imperative rule, one concern per bullet>
165
170
 
166
171
  ## Template
@@ -32,7 +32,8 @@ Does not govern:
32
32
 
33
33
  - What a `REQUIREMENT.md` must answer, its sections, and its template: `skill-requirement.md`
34
34
  - A practice skill's closing sections and ledger: `skill-practice.md`
35
- - Which root a path in a body resolves against, and how a body cites a standard: `skill-paths.md`
35
+ - Which root a path in a body resolves against, and how a body cites another skill's reference: `skill-paths.md`
36
+ - The jurisdiction, success criterion, and rule phrasing of a reference setting one artifact's shape: `skill-reference.md`
36
37
  - Path-scoped coding rules, which load on a file match rather than on a request match: `rule.md`
37
38
  - Voice, rhythm, and sentence construction in a skill body: the `write-human` skill
38
39
  - Punctuation, formatting, and word choice in a skill body: `markdown.md`
@@ -50,7 +51,7 @@ Answer all four before editing, and carry the answers into wherever the change i
50
51
 
51
52
  ## Whether a rule belongs beside the skill
52
53
 
53
- A skill fires when a session invokes it or its description matches the request. A path-scoped rule fires when a session reads a file matching its glob, with no decision from the session at all. The rule is the floor and the skill is the depth.
54
+ A skill fires when a session invokes it or its description matches the request. A path-scoped rule fires when a session reads or writes a file matching its glob, with no decision from the session at all. The rule is the floor and the skill is the depth.
54
55
 
55
56
  Run the two-part test over what the body states before calling the skill finished. Does the invariant fire when a specific path is edited, and does violating it ship silently? An invariant passing both halves belongs in a rule as well, since a session that never invoked the skill still edits that path. An invariant failing either half stays here, which is most of a body.
56
57
 
@@ -160,9 +161,14 @@ allowed-tools: <tools required>
160
161
  ## Scripts
161
162
 
162
163
  - Use `scripts/` for operations that must be deterministic or repetitive
164
+ - Ask whether a CLI verb the project already has does the job before writing a script. A verb is already installed and tested, and a script beside it is a second copy that drifts
165
+ - Write a script in TypeScript and run it as `bun ${CLAUDE_SKILL_DIR}/scripts/<name>.ts`. Keep bash for a few lines that start one command
166
+ - Import no package. A plugin loads from a cache that carries no `node_modules`, so only `node:` built-ins and the CLIs the skill already requires resolve
163
167
  - Use XML tags in script output for reliable parsing: `<SECTION>content</SECTION>`
164
- - Use `#!/usr/bin/env bash` shebang
165
- - Always include `2>/dev/null || echo "FALLBACK"` guards on git and shell commands
168
+
169
+ ### Inline commands
170
+
171
+ - Always include `2>/dev/null || echo "FALLBACK"` guards on git and shell commands a skill body runs inline. A TypeScript script handles failure with try and catch instead
166
172
 
167
173
  ## Invocation
168
174
 
@@ -9,7 +9,7 @@ metadata:
9
9
 
10
10
  Some decisions are settled by looking rather than by reasoning, and no draft is wrong until one is picked. Every step here puts several candidates in front of the operator and keeps the real surface untouched until they have chosen.
11
11
 
12
- The candidates live on the local design canvas, the surface `canon:canvas-board` drives. Every verb below is `canon canvas`, and `canon standards canvas` fixes the content format a frame takes. Read that standard before writing the first frame.
12
+ The candidates live on the local design canvas, the surface `canon:canvas-board` drives. Every verb below is `canon canvas`, and `${CLAUDE_SKILL_DIR}/../canvas-board/references/canvas.md` fixes the content format a frame takes. Read that reference before writing the first frame.
13
13
 
14
14
  ## Guards
15
15
 
@@ -39,19 +39,19 @@ External release identity used in git tags and release notes. Independent of pha
39
39
 
40
40
  ## Where each appears
41
41
 
42
- | Surface | Phase labels | Semver tags |
43
- | ------------------------------------------------------------------- | ------------ | ----------------------------------- |
44
- | `.canon/tasks/` | yes | no |
45
- | Chat with the operator | yes | no |
46
- | Tracked prose (context entries) | conditional | no |
47
- | Shipped prose (`standards/`, `claude/skills/`, `governance/rules/`) | no | no |
48
- | PR titles | no | only when the PR cuts a release |
49
- | PR bodies | no | only when the PR cuts a release |
50
- | Review comments | no | only when referencing a release |
51
- | Issue titles and bodies | no | only when referencing a release |
52
- | Commit messages | no | only when the commit cuts a release |
53
- | Git tags | no | yes |
54
- | README and `CHANGELOG.md` | no | yes |
42
+ | Surface | Phase labels | Semver tags |
43
+ | ----------------------------------------------------- | ------------ | ----------------------------------- |
44
+ | `.canon/tasks/` | yes | no |
45
+ | Chat with the operator | yes | no |
46
+ | Tracked prose (context entries) | conditional | no |
47
+ | Shipped prose (`claude/skills/`, `governance/rules/`) | no | no |
48
+ | PR titles | no | only when the PR cuts a release |
49
+ | PR bodies | no | only when the PR cuts a release |
50
+ | Review comments | no | only when referencing a release |
51
+ | Issue titles and bodies | no | only when referencing a release |
52
+ | Commit messages | no | only when the commit cuts a release |
53
+ | Git tags | no | yes |
54
+ | README and `CHANGELOG.md` | no | yes |
55
55
 
56
56
  ## Rules
57
57
 
@@ -59,7 +59,10 @@ Does not govern:
59
59
  - `### Expected` (optional): the expected behavior, or `unclear`.
60
60
  - `### Repro` (optional): repro details, or `none`.
61
61
  - `### Proposed fix` (required): a proposed fix, or `open` when the session settled on no direction.
62
- - A required field is refused when present but empty. Write the fallback literal for an optional field rather than leaving it blank.
62
+ - `### Suggested shape` (optional): the template, output, or field list the change should take, inside a `<details>` block. Omit the heading when there is none.
63
+ - `### Why` (optional): the reasons for the fix, one bullet each. Omit the heading when there are none.
64
+ - `### Links` (optional): the issues, pull requests, or documents the report cites, one per line. Omit the heading when there are none.
65
+ - A required field is refused when present but empty. Write the fallback literal for From project, Expected, and Repro rather than leaving one blank.
63
66
 
64
67
  ## Formatting
65
68
 
@@ -87,7 +87,7 @@ canon labels scan --title "<title>" --body-file .canon/tmp/pr/body.md --json
87
87
 
88
88
  Branch on the JSON record rather than the exit code. An operator's shell can wrap `canon` in a function whose status comes from a trailing command, flattening a non-zero exit to 0, the same reason the labels step below branches on its own record rather than the exit.
89
89
 
90
- Stop and fix the title or body on a non-empty `phaseLabels`, `boardReferences`, `sessionLinks`, `unspelledWords`, `titleFormatIssues`, `bannedCharacters`, or a `sections` record with anything in `outside` or `missing`. Do not proceed to `### Final command` until a re-run comes back clean on all seven. `titleFormatIssues` names which `## Title` rule in `${CLAUDE_SKILL_DIR}/references/pr.md` the title breaks, structure, casing, or length, so fix the named rule rather than guessing. `sections.outside` lists each heading to rename or drop, `sections.missing` each required heading to add, and `bannedCharacters` names the character to restructure the sentence around. Leave `cutsRelease` and `semverTags` alone, since a release-please pull request legitimately carries version references its own fixed shape explains.
90
+ Stop and fix the title or body on a non-empty `phaseLabels`, `boardReferences`, `sessionLinks`, `titleFormatIssues`, `bannedCharacters`, or a `sections` record with anything in `outside` or `missing`. Do not proceed to `### Final command` until a re-run comes back clean on all six. `titleFormatIssues` names which `## Title` rule in `${CLAUDE_SKILL_DIR}/references/pr.md` the title breaks, structure, casing, or length, so fix the named rule rather than guessing. `sections.outside` lists each heading to rename or drop, `sections.missing` each required heading to add, and `bannedCharacters` names the character to restructure the sentence around. Leave `cutsRelease` and `semverTags` alone, since a release-please pull request legitimately carries version references its own fixed shape explains.
91
91
 
92
92
  The scan stays required even where a `pull_request` workflow job runs the same verb, since a project holding an older `canon` carries no such job and no `titleFormatIssues`, `sections`, or `bannedCharacters` key.
93
93
 
@@ -66,7 +66,7 @@ A number referring to a pull request or an issue takes the form its destination
66
66
 
67
67
  Text published to a remote is the auto-linking half: a pull request body, an issue body, a comment on either, and a commit message. Write `#123` there, and `owner/repo#123` where the reference crosses repositories, which the same auto-linking reaches. A markdown file browsed from the repository tree is the other half, where neither spelling links and the backticked one marks the number as an identifier. <!-- canon-allow-reference: the two spellings this section defines, which a qualified form would destroy -->
68
68
 
69
- Content that installs into another repository is the third destination, and it splits on which repository the number names. A skill body loads from a plugin cache, a docs page is read through `canon docs`, and a standard through `canon standards`, so the reader holds their own repository rather than the one a bare number belongs to. Qualifying a number against a different, resolvable repository fixes that, since the reader can open that repository even without this one.
69
+ Content that installs into another repository is the third destination, and it splits on which repository the number names. A skill body loads from a plugin cache and a docs page is read through `canon docs`, so the reader holds their own repository rather than the one a bare number belongs to. Qualifying a number against a different, resolvable repository fixes that, since the reader can open that repository even without this one.
70
70
 
71
71
  Qualifying it against `erclx/canon` fixes nothing, because a reader holding only the plugin cache or the published package still cannot open this repository's own history. A same-repository citation takes no number here at all, bare or qualified. State the fact the citation was standing in for instead, and where the identifier is the only trace of a one-off incident rather than a reproducible count, carry it into the `canon/context/` entry that owns the surface.
72
72
 
@@ -55,5 +55,5 @@ A declined finding fails on a third axis, which is where its reason ends up. A w
55
55
  - Writing the review, which `review-pr` owns. The split is by side of the channel: that one posts findings from an independent session and this one is the worker's return leg.
56
56
  - Staging, committing, and pushing the follow-up, which `git-followup` owns under this skill's direction
57
57
  - Refreshing the `.claude/` docs the fixes made stale, which `context-fold` owns
58
- - Re-reviewing its own fixes, which hands back to the orchestrator
58
+ - Re-reviewing its own fixes, which hands back to the reviewer
59
59
  - Re-reading a rewritten branch, which `review-pr` absorbs by testing whether the prior reviewed commit still reaches the head and paying for a full pass when it does not
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: review-address
3
- description: Pulls review findings and CI status on the current branch's open PR, fixes each in the working tree, refreshes any stale `.claude/` docs, replies with a summary comment, and pushes a follow-up commit. The worker's return leg after `review-pr`. Use when asked to "address the review", "fix the PR comments", "respond to review", or after an orchestrator posts findings. Do NOT use to write a review. That is `review-pr`.
3
+ description: Pulls review findings and CI status on the current branch's open PR, fixes each in the working tree, refreshes any stale `.claude/` docs, replies with a summary comment, and pushes a follow-up commit. The worker's return leg after `review-pr`. Use when asked to "address the review", "fix the PR comments", "respond to review", or after a reviewer posts findings. Do NOT use to write a review. That is `review-pr`.
4
4
  metadata:
5
5
  family: after-pr
6
6
  ---
@@ -247,7 +247,7 @@ addressed, and leads with the rebase instead:
247
247
  Rebased PR #<number> onto origin/main. <N> files resolved by hand, <N> rebuilt by the check.
248
248
  ```
249
249
 
250
- Do not merge. Hand back to the orchestrator for re-review.
250
+ Do not merge. Hand back to the reviewer for re-review, or to the orchestrator where no live reviewer answers.
251
251
 
252
252
  ## Post-review findings
253
253
 
@@ -45,7 +45,7 @@ mkdir -p .canon/tmp/pr/review/evidence/<number>
45
45
  git show <sha>:<path> > .canon/tmp/pr/review/evidence/<number>/<side>-<name>.png
46
46
  ```
47
47
 
48
- Take the sha from the row, so the base and head sides are exactly what the comment shows. Then open each file with the file-reading tool. A `*(new)*` base cell has no before image, and a state whose cases are all added has no Base column at all. Read the URL out of the `src=` of each `<img>`, or out of `![](` in a comment posted before the embed changed.
48
+ Take the sha from the row, so the base and head sides are exactly what the comment shows. Then open each file with the file-reading tool. A `*(new)*` base cell has no before image, and a view or flat block whose cases are all added has no base column at all. A view row holds one case per theme cell, so a width row names two images where a flat row names one. Read the URL out of the `src=` of each `<img>`, or out of `![](` in a comment posted before the embed changed.
49
49
 
50
50
  ## How many to open
51
51
 
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: review-pr
3
- description: Reviews an open pull request from an independent session and posts findings as a review comment on the PR. Posts a first pass against the whole change and every later pass against only the commits added since, under `## Review` while any finding is open and `## Review closed` once a pass carries none. Reads project docs and the task board for cross-feature context a self-review lacks. Use when asked to "review the PR", "review this feature's PR", "post a PR review", "re-review the PR", "close out the review", "confirm the findings are fixed", or acting as the orchestrator reviewing a worker's PR. Do NOT use to review local uncommitted changes.
3
+ description: Reviews an open pull request from an independent session and posts findings as a review comment on the PR. Posts a first pass against the whole change and every later pass against only the commits added since, under `## Review` while any finding is open and `## Review closed` once a pass carries none. Reads project docs and the task board for cross-feature context a self-review lacks. Use when asked to "review the PR", "review this feature's PR", "post a PR review", "re-review the PR", "close out the review", "confirm the findings are fixed", or acting as the dispatched reviewer of a worker's PR. Do NOT use to review local uncommitted changes.
4
4
  metadata:
5
5
  family: after-pr
6
6
  ---
7
7
 
8
8
  # Review PR
9
9
 
10
- This is the orchestrator's independent review. It reviews an open PR the session
10
+ This is a dispatched reviewer's independent review. It reviews an open PR the session
11
11
  did not write and posts the findings to the PR, so the vantage is independent
12
12
  and the output is durable.
13
13
 
@@ -19,7 +19,7 @@ none, so the most recent comment's heading reports whether any work is owed.
19
19
  Every pass is this skill, and which one it is gets detected from the thread
20
20
  rather than named by the caller.
21
21
 
22
- The threshold is stated here and nowhere else, and every other surface acting on it cites this skill rather than restating the grades. One rule governs both the heading and the dispatch: a pass carrying anything owed takes `## Review` and owes a dispatch to the session holding the branch, and a pass carrying nothing at all takes `## Review closed` and owes none. Owed covers a finding at any severity, a Testing question, and a reviewer request nobody has answered alike, which is what keeps the two halves from separating. Sending that dispatch is `role-orchestrator`'s step rather than this one, which posts and stops. Post the open heading whether it is the first pass or the fourth. A pull request thread then reads as `## Review`, the worker's answer under `## Review response` from `review-address`, another `## Review` while anything stays open, and `## Review closed` when nothing does.
22
+ The threshold is stated here and nowhere else, and every other surface acting on it cites this skill rather than restating the grades. One rule governs both the heading and the dispatch: a pass carrying anything owed takes `## Review` and owes a dispatch to the session holding the branch, and a pass carrying nothing at all takes `## Review closed` and owes none. Owed covers a finding at any severity, a Testing question, and a reviewer request nobody has answered alike, which is what keeps the two halves from separating. Sending that dispatch is `role-reviewer`'s step rather than this one, which posts and stops, and `role-orchestrator` sends it only as the fallback where no live reviewer can. Post the open heading whether it is the first pass or the fourth. A pull request thread then reads as `## Review`, the worker's answer under `## Review response` from `review-address`, another `## Review` while anything stays open, and `## Review closed` when nothing does.
23
23
 
24
24
  Both of this skill's headings anchor as a section distinct from human threads, and neither invents beyond what the whole set already states. That set is eight headings across four families, stated here once so `role-orchestrator`'s poll and every reply-posting skill cite it rather than carry a copy. The review family, `## Review` and `## Review closed`, belongs to this skill alone. The reply family, `## Review response`, `## Rebase`, and `## Post-review findings`, belongs to `review-address`. The third family is a single heading, `## Evidence`, which `canon pr evidence` posts through `git-pr` and `git-followup` and which answers no comment already on the thread, so the poll excludes it from the unclassified count without reading it as a reply that owes a re-review. The fourth, `## UI review` and `## UI review closed`, belongs to `review-ui`, which posts it as a review beside this one, and nothing in this skill reads it.
25
25
 
@@ -56,7 +56,7 @@ X critical, Y should-fix, Z minor. Reviewed against project docs and the board.
56
56
 
57
57
  A stale ticked box goes in a `**PR body**` block, in place of a `**`path/to/file.ext`**` block and ahead of every one of those, since it precedes the code the diff carries rather than sitting inside it.
58
58
 
59
- Run `canon labels scan --title "<title>" --body "<body>" --head <headRefName>` against the PR under review, since Step 1 already holds all three and this pass is the last human-shaped gate before merge. A hit lands in the same `**PR body**` block, `should-fix`, naming each finding the scan returns: a token quoted from the title or body for a phase label, a board identifier, a session link, or an unspelled word, and the broken rule's name, `structure`, a casing issue, or `length`, for a title-format hit. A heading in `sections.outside`, a heading in `sections.missing`, or a character in `bannedCharacters` is a hit of the same weight, naming the heading or the character. This reads the pull request being reviewed, distinct from the comment this pass is about to post, which the scan later in this step still covers.
59
+ Run `canon labels scan --title "<title>" --body "<body>" --head <headRefName>` against the PR under review, since Step 1 already holds all three and this pass is the last human-shaped gate before merge. A hit lands in the same `**PR body**` block, `should-fix`, naming each finding the scan returns: a token quoted from the title or body for a phase label, a board identifier, or a session link, and the broken rule's name, `structure`, a casing issue, or `length`, for a title-format hit. A heading in `sections.outside`, a heading in `sections.missing`, or a character in `bannedCharacters` is a hit of the same weight, naming the heading or the character. This reads the pull request being reviewed, distinct from the comment this pass is about to post, which the scan later in this step still covers.
60
60
 
61
61
  A later pass carrying findings keeps that shape and changes only the summary line:
62
62
 
@@ -54,7 +54,7 @@ A verdict also goes stale without saying so. A push after the pass changes what
54
54
 
55
55
  - Reviewing the code and the stills, which `review-pr` owns. The two run as separate sessions so each finishes on its own clock and neither hears the other.
56
56
  - Writing the checklist and its drivable format, which `ui-checklist` owns
57
- - Dispatching the pass, polling its verdict, and lifting the draft mark, which `role-orchestrator` owns
57
+ - Dispatching the pass and polling its verdict, which `role-orchestrator` owns, and the lift's gates, which `canon pr lift` reads whichever session runs it
58
58
  - A subagent inside the code reviewer, dropped because its cost stays invisible until it returns
59
59
  - Writing a tracked file or checking anything out to host a frame. The push goes through the GitHub API onto the frames branch alone, so the reviewer still enters no worktree and touches no branch a pull request holds.
60
60
  - Dropping a closed pull request's frames, which a scheduled workflow runs, and purging a dropped frame GitHub still serves by commit, which needs a platform request
@@ -24,7 +24,7 @@ rather than inside it, so the two passes finish on their own clocks.
24
24
  - 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.
25
25
  - 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.
26
26
  - 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.
27
- - Post and stop. Never merge, never lift the draft mark, and never edit the evidence comment except through `canon pr tick`.
27
+ - Post, then run `canon pr lift <number>` on a close. Never merge or ready the PR by hand, and edit the evidence comment only through `canon pr tick`.
28
28
 
29
29
  ## Step 1: resolve the pull request
30
30
 
@@ -94,11 +94,13 @@ Read `${CLAUDE_SKILL_DIR}/references/driving.md` on reaching this step for how a
94
94
 
95
95
  Give every box exactly one verdict, in checklist order. A box the pass could not place on a route or a width is still driven, from the opened address at 1440 wide, and the verdict names the guess. Skipping a box silently reads the same as passing it.
96
96
 
97
- Never judge a box ending in `(taste)`. Drive to the state, capture the frame, and mark it needs eyes. Drive a ticked box the same as an unchecked one, since a tick is a claim this pass exists to check. A tick stamped at the current head still gets driven.
97
+ Never judge a box ending in `(taste)`. Drive to the state, capture both themes, and mark it needs eyes. Drive a ticked box the same as an unchecked one, since a tick is a claim this pass exists to check. A tick stamped at the current head still gets driven.
98
98
 
99
- A frame the verdict rests on is published only when the worker's evidence lacks it. Compare the box's route, width, and theme against the `states` Step 2 kept, and when a state and stem show the same thing, cite that stem and push nothing. The match is this pass's judgment over the box's wording, so the verb never makes it. Otherwise push the frame and keep the `link` the record returns:
99
+ A frame the verdict rests on is published only when the worker's evidence lacks it, matched per theme against the `states` Step 2 kept, as `references/driving.md` states. The match is this pass's judgment over the box's wording, never the verb's. Otherwise push the frame and keep the `link` the record returns:
100
100
 
101
101
  ```bash
102
+ # one shot of a taste box's pair, then a pass or fail frame with no theme
103
+ canon pr frames <number> --add frames/<box-number>-<theme>.png --box <box-number> --theme <dark|light> --head <head> --pass <pass> --json
102
104
  canon pr frames <number> --add frames/<box-number>.png --box <box-number> --head <head> --pass <pass> --json
103
105
  ```
104
106
 
@@ -118,7 +120,7 @@ Close the browser with `${CLAUDE_SKILL_DIR}/scripts/pw.sh -s=<project>-<number>
118
120
 
119
121
  ## Step 7: post
120
122
 
121
- Read `${CLAUDE_SKILL_DIR}/references/post.md` for the heading rule, the body shape, the marker every body ends on, and the post command. Each Evidence cell holds words and names the evidence stem it matched, and the `link` its Step 5 push returned goes as given into the Frames block below the table.
123
+ Read `${CLAUDE_SKILL_DIR}/references/post.md` for the heading rule, the body shape, the marker every body ends on, and the post command. Each box lands in the section its verdict names, and the `link` its Step 5 push returned goes as given into that box's own entry.
122
124
 
123
125
  ## Step 8: tick the passed boxes
124
126
 
@@ -139,10 +141,10 @@ gh run list --workflow phase-label-gate.yml --event pull_request_review --limit
139
141
  Read `<heading>` off the first line of the file Step 7 posted, never composed here, so the line reports what the review carries.
140
142
 
141
143
  ```plaintext
142
- P passed, F failed, E need eyes, N not driven. Posted to PR #<number> under <heading>.
144
+ F failed · E need your eyes · P passed · N not driven. Posted to PR #<number> under <heading>.
143
145
  ```
144
146
 
145
- Add `Review-event checks: <passing|failing|unread>.` and `Ticks: <ticked N|reason>.` after it, the second naming the count Step 8 ticked or the verb's refusal `reason`. Add `S sweep finding(s).` when the sweep raised any. Report no merge recommendation, since this pass saw the app and not the change.
147
+ Add `Review-event checks: <passing|failing|unread>.` and `Ticks: <ticked N|reason>.` after it, the second naming the count ticked or the refusal `reason`. Add `S sweep finding(s).` when the sweep raised any. Report no merge recommendation, since this pass saw the app and not the change.
146
148
 
147
149
  ## Rules
148
150
 
@@ -32,20 +32,20 @@ A box written before that format may carry no route, no width, and a verb such a
32
32
  - Text, presence, and attributes: `pw --raw eval "<expression>"`, quoting the value back.
33
33
  - Computed style: `getComputedStyle(<element>).<property>`.
34
34
  - Geometry and overflow: `getBoundingClientRect()`, and `scrollWidth` against `clientWidth` on `document.documentElement`.
35
- - A frame: `pw screenshot --filename=frames/<box-number>.png`, then open it with the file-reading tool before saying what it shows.
35
+ - A frame: `pw screenshot --filename=frames/<box-number>.png`, then open it with the file-reading tool before saying what it shows. A taste box takes the shot twice, once per theme, naming the theme in the file as `frames/<box-number>-<theme>.png`. Reach each theme through the page's own control when the box names one, and through `pw set-color-scheme <dark|light>` otherwise, then read the page's background before the shot to confirm it changed. A page that paints the same under both has no second theme to show, so the box is not driven, with the reason naming that. `pw clear-color-scheme` restores the default.
36
36
 
37
37
  ## The four verdicts
38
38
 
39
39
  Each box takes exactly one.
40
40
 
41
- | Verdict | When | Evidence it carries |
42
- | ------------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
43
- | pass or fail, read | The result is a fact the page reports | The value read, quoted, such as `scrollWidth 436 against clientWidth 320` |
44
- | pass or fail, frame | The result has a stated criterion only an image settles | The matching evidence stem or the pushed frame's link going to the Frames block, and what the frame shows, in words |
45
- | needs eyes | The box ends in `(taste)` | The matching evidence stem or the pushed frame's link going to the Frames block, and what the frame showed, with nothing about whether it looks right |
46
- | not driven | The state could not be reached | The reason, such as an unreachable address, a `(local only)` box on a hosted preview, or a target the snapshot does not hold |
41
+ | Verdict | When | Evidence it carries |
42
+ | ------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
43
+ | pass or fail, read | The result is a fact the page reports | The value read, quoted, such as `scrollWidth 436 against clientWidth 320` |
44
+ | pass or fail, frame | The result has a stated criterion only an image settles | The matching evidence stem or the pushed frame's link, inline under the failed box's heading, and what the frame shows, in words |
45
+ | needs eyes | The box ends in `(taste)` | The dark and the light shot as a pair, each the matching evidence stem or a pushed frame's link, and what the frames showed, with nothing about whether it looks right |
46
+ | not driven | The state could not be reached | The reason, such as an unreachable address, a `(local only)` box on a hosted preview, or a target the snapshot does not hold |
47
47
 
48
- A frame verdict carries one image at most, and never one the worker's evidence already shows. When a state and stem in the evidence record match the box's route, width, and theme, the evidence names that stem and nothing is pushed. Otherwise the frame goes up through `canon pr frames` and the `link` the record returned, which names the frame's path on the frames branch, goes under the Frames block and never inside the table row. Either way the words stay, describing the value or region judged, such as the element, its position, and the colors or text read, so a reader whose image fails to load can still check it.
48
+ A pass or fail resting on a frame carries one image at most, and never one the worker's evidence already shows. A needs-eyes box carries the pair, dark and light, since a taste call is made by comparing them. Match each theme separately: when a state and stem in the evidence record match the box's route, width, and that theme, the evidence names that stem and nothing is pushed for it, so a view with the dark shot in evidence pushes the light one alone. Otherwise the frame goes up through `canon pr frames` with `--theme`, and the `link` the record returned, which names the frame's path on the frames branch, goes in the box's own section of the body and never inside a folded block. Either way the words stay, describing the value or region judged, such as the element, its position, and the colors or text read, so a reader whose image fails to load can still check it.
49
49
 
50
50
  A push that refuses leaves the words alone, with the reason named. Never cite the local frame path. A path under `.canon/` is a board identifier the label scan rejects, and it resolves only on this machine.
51
51