@erclx/canon 5.62.0 → 5.64.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 (101) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/references/adopted.md +1 -1
  4. package/claude/skills/context-fold/REQUIREMENT.md +2 -3
  5. package/claude/skills/context-fold/SKILL.md +1 -11
  6. package/claude/skills/context-fold/references/completion-report.md +8 -9
  7. package/claude/skills/create-skill/references/skill-practice.md +17 -1
  8. package/claude/skills/design-record/references/design.md +1 -1
  9. package/claude/skills/design-taste/REQUIREMENT.md +2 -1
  10. package/claude/skills/design-taste/SKILL.md +6 -5
  11. package/claude/skills/design-taste/references/adopted.md +56 -8
  12. package/claude/skills/design-taste/references/craft.md +1 -1
  13. package/claude/skills/design-taste/references/kinds.md +8 -2
  14. package/claude/skills/design-taste/references/preflight.md +3 -3
  15. package/claude/skills/design-taste/references/tells.md +26 -5
  16. package/claude/skills/document-health/REQUIREMENT.md +1 -1
  17. package/claude/skills/document-health/SKILL.md +3 -14
  18. package/claude/skills/document-health/references/axes.md +14 -16
  19. package/claude/skills/plan-feature/SKILL.md +2 -2
  20. package/claude/skills/plan-feature/references/plan.md +24 -3
  21. package/claude/skills/review-craft/SKILL.md +1 -1
  22. package/claude/skills/role-worker/SKILL.md +2 -1
  23. package/claude/skills/ui-checklist/SKILL.md +1 -1
  24. package/claude/skills/ui-craft/REQUIREMENT.md +29 -0
  25. package/claude/skills/ui-craft/SKILL.md +44 -0
  26. package/{governance/rules/ui → claude/skills/ui-craft/references}/a11y.md +0 -10
  27. package/claude/skills/ui-craft/references/adopted.md +27 -0
  28. package/{governance/rules/ui/surface-capture.md → claude/skills/ui-craft/references/capture.md} +0 -10
  29. package/{governance/rules/ui/ux-controls.md → claude/skills/ui-craft/references/controls.md} +3 -10
  30. package/claude/skills/ui-craft/references/copy.md +45 -0
  31. package/{governance/rules/ui → claude/skills/ui-craft/references}/forms.md +0 -9
  32. package/{governance/rules/ui → claude/skills/ui-craft/references}/keyboard.md +0 -10
  33. package/{governance/rules/ui → claude/skills/ui-craft/references}/motion.md +0 -10
  34. package/{governance/rules/ui → claude/skills/ui-craft/references}/pointer.md +0 -10
  35. package/{governance/rules/ui/ux-completeness.md → claude/skills/ui-craft/references/states.md} +0 -10
  36. package/claude/skills/ux-audit/SKILL.md +1 -1
  37. package/claude/skills/write-human/references/adopted.md +4 -1
  38. package/docs/agents/audits.md +2 -6
  39. package/docs/agents/context-audit.md +1 -1
  40. package/docs/agents/install-and-sync.md +2 -2
  41. package/docs/target/migrations.md +3 -3
  42. package/docs/target/sync.md +3 -2
  43. package/docs/workflow/skill-map.md +1 -0
  44. package/docs/workflow/visual-design-workflow.md +2 -2
  45. package/governance/detect.toml +1 -45
  46. package/governance/ledger/lib/test-scope.md +1 -1
  47. package/governance/ledger/skills/api-design/SKILL.md +62 -0
  48. package/governance/ledger/skills/code-craft/SKILL.md +53 -0
  49. package/governance/ledger/skills/deprecation-migration/SKILL.md +68 -0
  50. package/governance/ledger/skills/design-taste/SKILL.md +64 -0
  51. package/governance/ledger/skills/design-taste/craft.md +66 -0
  52. package/governance/ledger/skills/design-taste/kinds.md +58 -0
  53. package/governance/ledger/skills/design-taste/systems.md +42 -0
  54. package/governance/ledger/skills/design-taste/tells.md +103 -0
  55. package/governance/ledger/{ui → skills/ui-craft}/a11y.md +3 -3
  56. package/governance/ledger/{ui/surface-capture.md → skills/ui-craft/capture.md} +3 -3
  57. package/governance/ledger/{ui/ux-controls.md → skills/ui-craft/controls.md} +12 -7
  58. package/governance/ledger/skills/ui-craft/copy.md +102 -0
  59. package/governance/ledger/{ui → skills/ui-craft}/forms.md +3 -3
  60. package/governance/ledger/{ui → skills/ui-craft}/keyboard.md +3 -3
  61. package/governance/ledger/{ui → skills/ui-craft}/motion.md +3 -3
  62. package/governance/ledger/{ui → skills/ui-craft}/pointer.md +3 -3
  63. package/governance/ledger/{ui/ux-completeness.md → skills/ui-craft/states.md} +3 -3
  64. package/governance/ledger/ui/craft.md +19 -0
  65. package/governance/renames.toml +17 -3
  66. package/governance/rules/lib/test-scope.md +1 -1
  67. package/governance/rules/ui/craft.md +22 -0
  68. package/governance/splits.toml +0 -2
  69. package/package.json +1 -1
  70. package/src/audits/catalog.ts +0 -52
  71. package/src/claude/cases/misc.ts +5 -0
  72. package/src/claude/skills-audit.ts +226 -12
  73. package/src/cli/retired.ts +8 -0
  74. package/src/commands/claude.ts +15 -1
  75. package/src/commands/context.ts +0 -425
  76. package/src/commands/tooling.ts +4 -1
  77. package/src/context/citations.ts +9 -3
  78. package/src/gate/measures.ts +4 -3
  79. package/src/git/files.ts +8 -3
  80. package/src/gov/audit.ts +6 -1
  81. package/src/inventory/subjects.ts +1 -1
  82. package/src/markdown/gated.ts +1 -1
  83. package/src/markdown/scope.ts +0 -1
  84. package/src/tooling/package.ts +22 -13
  85. package/tooling/web/reference.md +3 -1
  86. package/claude/skills/context-fold/references/classify.md +0 -87
  87. package/governance/ledger/ui/copy.md +0 -49
  88. package/governance/ledger/ui/design-taste.md +0 -19
  89. package/governance/ledger/ui/interface-casing.md +0 -47
  90. package/governance/ledger/ui/link-behavior.md +0 -29
  91. package/governance/rules/ui/copy.md +0 -28
  92. package/governance/rules/ui/design-taste.md +0 -18
  93. package/governance/rules/ui/interface-casing.md +0 -29
  94. package/governance/rules/ui/link-behavior.md +0 -19
  95. package/src/context/classify/extract.ts +0 -443
  96. package/src/context/classify/ollama.ts +0 -172
  97. package/src/context/classify/patterns.ts +0 -75
  98. package/src/context/classify/prompts.ts +0 -74
  99. package/src/context/classify/run.ts +0 -348
  100. package/src/context/classify/settings.ts +0 -196
  101. /package/tooling/web/{configs → seeds}/e2e/home.spec.ts +0 -0
@@ -38,7 +38,7 @@ Read these in parallel from the project root, skipping any that do not exist:
38
38
 
39
39
  Also read `canon/DESIGN.md` when the feature touches code or UI, for visual intent and component rules, with values read from the stylesheet its lead names. Skip it for prose, docs, catalog, or config-only changes. For a UI feature, read `canon/design/index.md` too, if it exists, for the surfaces with an accepted design.
40
40
 
41
- Coding standards live in `.claude/rules/`. Claude Code loads them automatically, and path-scoped rules apply to the files they match. For a UI feature, load `canon:design-taste` whether or not `canon/DESIGN.md` exists.
41
+ Coding standards live in `.claude/rules/`. Claude Code loads them automatically, and path-scoped rules apply to the files they match. For a UI feature, load `canon:ui-craft` for how it behaves and `canon:design-taste` for how it looks, whether or not `canon/DESIGN.md` exists.
42
42
 
43
43
  ### Read the domain's context entry
44
44
 
@@ -86,7 +86,7 @@ Every `- Suggested:` line takes senior judgment, picking the best option in one
86
86
  - Suggest a real default when best practice, the codebase, or prior context points to one
87
87
  - Before `## Files to touch`, load `canon:codebase-layout` for a new path (its reason) and `canon:api-design` for a changed verb, flag, output, record shape, or endpoint. Report either if missing.
88
88
  - Fill `## Design references` with the `canon/design/<surface>/` folder for each surface a UI file in `## Files to touch` renders, and write `None identified.` in a project with no folder
89
- - Write `## Verification` as one bullet per outcome naming the test or command that proves it
89
+ - Write `## Verification` as one bullet per outcome naming the test or command that proves it, with a grep bullet per `## Verbatim` block of settled wording
90
90
  - Write `## Review focus` as the inputs or states that would break the change, carrying the risk you understood to the executor and the reviewer
91
91
 
92
92
  ### Sources and size
@@ -75,6 +75,7 @@ The document opens with `# Feature: <short title>` and one paragraph stating wha
75
75
  | `## Current behavior` | each command run against the thing being changed and what it showed | When the change touches something that runs |
76
76
  | `## Constraints` | durable rules the work must respect | When supplied |
77
77
  | `## Files to touch` | each file with a one-line reason | Always |
78
+ | `## Verbatim` | settled wording that lands unchanged in an existing file, one H3 per block | When wording is settled |
78
79
  | `## Design references` | the tracked design folders the change builds against, each with its surface | When Files to touch names a rendered-surface file |
79
80
  | `## Verification` | the test or command that proves each outcome | Always |
80
81
  | `## Risks` | conflicts, coupling, and the tricky spots | Always |
@@ -171,6 +172,16 @@ A batch in a fan-in set declares its side in a constraint bullet, ``Fan-in membe
171
172
 
172
173
  A constraint naming a `.canon/ready/` folder is a third shape beside the hold and the shared path. It makes that folder's files the verbatim source for the paths this plan's `## Files to touch` lists, per `ready.md`, so the executing session copies those paths rather than authoring them.
173
174
 
175
+ ### Verbatim
176
+
177
+ A `## Verbatim` section carries wording someone settled, landing in an existing file exactly as written. Wording the planner only proposes stays a `- Suggested:` question, and a whole new file goes in the ready folder per `ready.md`, so the two never describe the same file.
178
+
179
+ - Give each block an H3 naming it, then a lead sentence with the action, the full path, and the anchor, then a fenced `text` block holding the wording
180
+ - Name the action as Add, Insert, or Replace. A Replace quotes the old line in the lead's code span.
181
+ - Write the block as the project's formatter leaves it, since a formatter that re-pads a table row or rewraps a line makes the grep fail on correct text
182
+ - Name the outcome in a grep bullet and put a command past 200 characters in a fenced `bash` block under it, since `S4` reports a longer bullet
183
+ - Give each block one `## Verification` bullet running `grep -cF -e` on its whole first line against its file, so a reworded line fails a check the reviewer already runs.
184
+
174
185
  ### Design references
175
186
 
176
187
  A plan whose `## Files to touch` names a rendered-surface file (`.tsx`, `.jsx`, `.astro`, `.vue`, `.svelte`, `.html`, or `.css`) carries this section. It tells the building session which accepted design to open before it writes a line.
@@ -258,9 +269,9 @@ This contract inverts the one an intake folder keeps, where an empty slot means
258
269
 
259
270
  ## Template
260
271
 
261
- Each H3 below shows where a section groups once it passes 5 bullets. A section of 5 or fewer drops its H3s and keeps its bullets flat, except `## Risks`, which takes an H3 per risk at any count.
272
+ Each H3 below shows where a section groups once it passes 5 bullets. A section of 5 or fewer drops its H3s and keeps its bullets flat, except `## Risks` and `## Verbatim`, which take an H3 per risk or block at any count.
262
273
 
263
- ```markdown
274
+ ````markdown
264
275
  # Feature: <short title>
265
276
 
266
277
  <One paragraph on what is being built and why now.>
@@ -300,6 +311,16 @@ The files below share <the reason>.
300
311
 
301
312
  - `<path/to/file>`: <reason>
302
313
 
314
+ ## Verbatim
315
+
316
+ ### <Block name>
317
+
318
+ Add as <where> in `<path/to/file>`, after <anchor>.
319
+
320
+ ```text
321
+ <the wording, as the formatter leaves it>
322
+ ```
323
+
303
324
  ## Design references
304
325
 
305
326
  - `canon/design/<surface>/`: <the surface it governs>
@@ -335,4 +356,4 @@ The questions below decide <what>, numbered across the whole section.
335
356
  ## Sources
336
357
 
337
358
  - [<title>](url), backing <decision>: "<passage relied on>"
338
- ```
359
+ ````
@@ -49,7 +49,7 @@ An axis whose condition the diff meets is not optional. When the security or the
49
49
  Read each of these when the diff reaches what it names.
50
50
 
51
51
  7. **Security.** Read `${CLAUDE_SKILL_DIR}/references/security.md` when the diff runs a command, writes or deletes a file, takes outside input, touches a secret, adds a dependency, or changes a default.
52
- 8. **Rendered output.** Read `${CLAUDE_SKILL_DIR}/references/ui.md` when the diff touches a file that paints, or when the pull request carries an evidence comment.
52
+ 8. **Rendered output.** Read `${CLAUDE_SKILL_DIR}/references/ui.md` when the diff paints or the pull request carries evidence. Judge behavior by `ui-craft` and the look by `design-taste`.
53
53
  - A file that paints is markup, a stylesheet, a component, a template, or a design token
54
54
  - 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
55
55
  9. **Developer experience and operations.** Ports, hooks, scripts, config, and scaffold defaults a consumer installs.
@@ -23,6 +23,7 @@ This body states the role, the boundaries, and the channel, and starts no step o
23
23
  - Resolve `.canon/plans/`, `.canon/tasks/`, `.canon/review/`, and `.canon/ready/` at the main worktree root, never the linked worktree. Being gitignored, they are absent there rather than empty.
24
24
  - Report a plan that fails to resolve as unreadable from here, naming the main-root path. Reporting the task as having no plan is wrong about the world, and a reader cannot tell the two apart.
25
25
  - Build the plan the launch named. Never write a second one when the path fails to resolve, since a row citing a plan already has one.
26
+ - Load `ui-craft` before editing a rendered surface, pointer rule or not
26
27
  - Keep a task list from launch, one item per slice, and tick each as its slice lands. Skip it on a host that offers no list tool, since the list is for the operator watching and not a gate.
27
28
 
28
29
  ### Ready folders and the draft mark
@@ -60,7 +61,7 @@ A plan carrying a `**Design references:**` section names the accepted design for
60
61
 
61
62
  - Open each cited folder's light and dark images and its frame HTML before the first edit to that surface
62
63
  - Take sizes, spacing, and colors from the frame HTML rather than from the image
63
- - Report a reference that does not resolve in the working tree, naming the path, rather than building without it
64
+ - Report a missing reference by its path rather than building without it
64
65
  - Leave `None identified.` as it stands and build without a reference
65
66
 
66
67
  ## Scope after dispatch
@@ -48,7 +48,7 @@ The checkbox stays `- [ ]` followed by the action and the result, since the evid
48
48
 
49
49
  ## Boxes no engine reads
50
50
 
51
- The UI review runs axe over every route it reaches, so a box restating what axe checks, such as contrast, a missing name, or a page title, adds a drive and catches nothing. Derive a box instead for each behavior below that the changed surface carries:
51
+ The UI review runs axe over every route it reaches, so a box restating what axe checks, such as contrast, a missing name, or a page title, adds a drive and catches nothing. Derive a box instead from the `ui-craft` references the changed surface reads, for each behavior below that it carries:
52
52
 
53
53
  - **Hover content.** Content shown on hover or focus stays while the pointer moves onto it, and Escape dismisses it, per WCAG 1.4.13.
54
54
  - **Keyboard trap.** Tab and Shift+Tab leave every widget the change added, per WCAG 2.1.2.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: ui-craft
3
+ description: Why the UI behavior practice lives in one skill every role reads by name, and where it stops beside design-taste and design-record
4
+ ---
5
+
6
+ # UI craft requirement
7
+
8
+ ## Gap
9
+
10
+ Without this skill, the UI behavior practice reaches a session only as path rules a target has to sync, so a project holding the plugin without governance builds a component with none of it. A role that plans, builds, or reviews a rendered change has no name to load the practice by, and each one restates the part it remembers.
11
+
12
+ ## Must
13
+
14
+ - Every rule the retired ui practice rules carried sits in a reference, unchanged in wording, with its source row in a ledger beside the reference
15
+ - A rendered change reaches accessibility, keyboard, and state coverage on every read, and the other references by the change that needs them
16
+ - A rendered change that is about to be handed over reaches the capture reference
17
+ - A planning, building, or reviewing role reaches the skill by name, with or without the governance pointer installed
18
+
19
+ ## Must not
20
+
21
+ - Reword a moved rule in the move, since a wording change is a separate change with its own ledger row
22
+ - Restate the look, being layout, type, color, or the layer order
23
+ - Be reached only by an author typing its name, since the `craft` pointer rule and the planning, building, and reviewing skills are its callers
24
+
25
+ ## Out of scope
26
+
27
+ - How a surface looks, which `design-taste` owns
28
+ - The design folder, its references, and the comparison a pull request shows, which `design-record` and the `design-reference` rule own
29
+ - The visual checklist a reviewer reads, which `ui-checklist` owns
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: ui-craft
3
+ description: Carries the behavior practice for rendered UI, being accessibility, keyboard and pointer operation, forms, motion, controls, state coverage, interface copy, and the capture a rendered change owes, routed from the kind of change to the references it reads. Use before building or changing a component, a page, a form, or any rendered surface, when judging one in review, or when asked "is this accessible", "what states does this need", "how should this form validate", "what should the button say", or "what do I capture after this change". Do NOT use for how a surface looks, being layout, type, color, and the layer order, which is `design-taste`, or for the design folder and its references, which is `design-record`.
4
+ metadata:
5
+ family: build
6
+ ---
7
+
8
+ # UI craft
9
+
10
+ A rendered change that skips this practice ships a control a keyboard cannot reach, a list with no empty state, or an error that names the fault and never the fix, and none of it fails a build. The references below carry the rules. This body routes a change to the ones it reads.
11
+
12
+ Load this before building rather than after, since a missing state or a trapped focus is cheaper to design in than to retrofit.
13
+
14
+ ## Read by the change
15
+
16
+ Read every reference on the always row for any rendered change, then each row the change matches.
17
+
18
+ | The change | Read |
19
+ | ------------------------------------------------------------------ | ------------------------------------- |
20
+ | Any rendered change | `a11y.md`, `keyboard.md`, `states.md` |
21
+ | A click, press, drag, gesture, or popover dismissal | `pointer.md` |
22
+ | A form, a field, validation, or a sign-in step | `forms.md` |
23
+ | An animation, transition, autoplay, or carousel | `motion.md` |
24
+ | A destructive action, an edit cancel, or a hover or disabled state | `controls.md` |
25
+ | A rendered string, heading, label, or link | `copy.md` |
26
+ | A rendered surface has changed and is about to be handed over | `capture.md` |
27
+
28
+ Each name sits under `${CLAUDE_SKILL_DIR}/references/`. A row's reference is read whole, since its sections name the cases a change reaches without saying so.
29
+
30
+ ## Hold the floor over taste
31
+
32
+ The references state a floor, and no aesthetic choice trades against it. A contrast ratio, a focus ring, or a state the design leaves out is restored before the look is judged, and `design-taste` decides the look inside that floor.
33
+
34
+ ## Sources
35
+
36
+ Read `${CLAUDE_SKILL_DIR}/references/adopted.md` only when extending this guidance or arguing against a rule in it. It names the authorities the references draw on and where each bullet's source row sits.
37
+
38
+ ## What this delegates
39
+
40
+ - How a surface looks, being the layer order, the coherence locks, and the defaults a model reaches for: `design-taste`
41
+ - The accepted designs under the design folder and how a reference lands there: `design-record`
42
+ - The visual checklist a reviewer reads beside the screenshots: `ui-checklist`
43
+ - Reading source for roughness a rule does not state: `ux-audit`
44
+ - Prose on the surface beyond its interface copy: the `write-human` skill
@@ -1,13 +1,3 @@
1
- ---
2
- description: Semantics, text alternatives, contrast, and reflow for rendered UI
3
- paths:
4
- - '**/*.tsx'
5
- - '**/*.jsx'
6
- - '**/*.astro'
7
- - '**/*.html'
8
- - '**/*.css'
9
- ---
10
-
11
1
  # Accessibility standards
12
2
 
13
3
  ## Semantics
@@ -0,0 +1,27 @@
1
+ ---
2
+ title: Adopted and declined
3
+ description: The authorities the ui-craft references draw on, and where the per-bullet source rows for each reference sit
4
+ ---
5
+
6
+ # Adopted and declined
7
+
8
+ Every bullet in a reference has its own source row in a ledger outside the plugin, so this record names the authorities once and points at the rows. A reader arguing against one bullet opens its ledger, and a session extending a reference adds the row there in the same change.
9
+
10
+ ## Authorities
11
+
12
+ Each field below names the source its references cite, and a house choice covers a threshold or a scope no source states.
13
+
14
+ - **Web accessibility.** The W3C's [WCAG 2.2](https://www.w3.org/TR/WCAG22/) and the [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/) back the accessibility, keyboard, pointer, and motion references.
15
+ - **CSS behavior.** [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) and the CSS specifications back the focus ring, `color-scheme`, and overflow bullets.
16
+ - **Native targets.** Apple's and Android's platform guidelines back the native touch target figures in `pointer.md`.
17
+ - **Forms and copy.** The [GOV.UK Design System](https://design-system.service.gov.uk/) and its style guide back `forms.md` and the copy and casing sections of `copy.md`.
18
+ - **Usability research.** The [Nielsen Norman Group](https://www.nngroup.com/articles/) backs most of `states.md`, part of `controls.md`, and the link sections of `copy.md`.
19
+ - **Capture.** `capture.md` is a house procedure, with its reflow width taken from the WCAG reflow criterion `a11y.md` cites.
20
+
21
+ ## Where the rows sit
22
+
23
+ The rows sit in the toolkit's own repository rather than the plugin, one ledger per reference and one table row per bullet under the H2 the bullet sits under. The toolkit's skill audit fails a reference whose bullets and rows disagree in count under any heading, and a target never carries the rows.
24
+
25
+ ## Declined
26
+
27
+ Each ledger carries its own `## Declined` list, recording the bullets cut or reworded when the source rules were last rewritten. The move into this skill changed no bullet's wording, so it declined nothing.
@@ -1,13 +1,3 @@
1
- ---
2
- description: Require a capture against a running preview after a rendered surface changes
3
- paths:
4
- - '**/routes/**/*.{tsx,jsx,vue,svelte,astro}'
5
- - '**/pages/**/*.{tsx,jsx,vue,svelte,astro}'
6
- - '**/app/**/page.{tsx,jsx}'
7
- - '**/components/**/*.{tsx,jsx,vue,svelte,astro}'
8
- - '**/*.html'
9
- ---
10
-
11
1
  # Surface capture standards
12
2
 
13
3
  ## What a surface is
@@ -1,13 +1,3 @@
1
- ---
2
- description: Destructive actions, edit cancel, and element states for interactive controls
3
- paths:
4
- - '**/*.tsx'
5
- - '**/*.jsx'
6
- - '**/*.astro'
7
- - '**/*.html'
8
- - '**/*.css'
9
- ---
10
-
11
1
  # UX controls standards
12
2
 
13
3
  ## Destructive actions
@@ -21,5 +11,8 @@ paths:
21
11
  - Never flash an intermediate state, such as a light frame before a dark theme or a layout jump before data arrives. Reserve the space or settle it first.
22
12
  - Say why a control is disabled, in text beside it or a tooltip, and keep it focusable through `aria-disabled` when the reason matters.
23
13
  - Declare `color-scheme` on `:root` to match each theme, so scrollbars and form controls follow the theme instead of staying light.
14
+
15
+ ## Hover and focus effects
16
+
24
17
  - Keep content shown on hover or focus dismissible without moving the pointer, hoverable, and visible until the trigger leaves or the person dismisses it (WCAG 1.4.13).
25
18
  - Change no context, such as navigating, submitting, or moving focus, when a control gains focus or changes value, unless the person was told first (WCAG 3.2.1, 3.2.2).
@@ -0,0 +1,45 @@
1
+ # UI copy standards
2
+
3
+ ## Punctuation
4
+
5
+ - Write no em dash (`—`) or semicolon in rendered copy. Use a comma or a period, or restructure the sentence.
6
+ - Add no trailing punctuation to a button label or a short action string.
7
+
8
+ ## Button copy
9
+
10
+ - Label a button with the verb of the action it performs, such as `Save` or `Delete`, never with filler such as `Click to delete`.
11
+
12
+ ## Error messages
13
+
14
+ - Tell the person how to fix the error, such as `Enter an email address` over `Email is invalid`.
15
+ - Keep an error message to one short sentence in plain language, with no technical jargon or error codes.
16
+
17
+ ## Placeholder text
18
+
19
+ - Never use placeholder text as a label, a hint, or an example. Put a format example such as `name@example.com` in hint text under the label.
20
+
21
+ ## Sentence case
22
+
23
+ - Use sentence case for rendered headings, labels, nav items, tab titles, and dialog titles, since title case on every heading reads as a template default.
24
+ - Keep the original casing of a proper noun or product name, such as `GitHub`, `macOS`, or `TypeScript`.
25
+
26
+ ## Uppercase labels
27
+
28
+ - Keep small uppercase labels above headings to `ceil(sections / 3)`, the first screen counting as one. Delete the extra labels, since position already names a section.
29
+
30
+ ## Where it applies
31
+
32
+ - Apply the same casing to interface copy kept outside the globs, such as a locale file, which this rule never fires on.
33
+
34
+ ## Overriding
35
+
36
+ - Depart from sentence case only where the case needs it, such as an acronym, a brand mark, or a set-in-caps identity the design chose on purpose.
37
+
38
+ ## Default target
39
+
40
+ - Open a link in the same tab. Reserve `target="_blank"` for a page the person must consult while finishing a task in the current one.
41
+ - Never add `target="_blank"` as a default for every external link.
42
+
43
+ ## mailto: links
44
+
45
+ - Open a `mailto:` link in the same tab. It hands off to the mail client rather than replacing the page, so a new tab leaves an empty tab behind.
@@ -1,12 +1,3 @@
1
- ---
2
- description: Form validation timing, submission, error placement, and derived state for rendered forms
3
- paths:
4
- - '**/*.tsx'
5
- - '**/*.jsx'
6
- - '**/*.astro'
7
- - '**/*.html'
8
- ---
9
-
10
1
  # Form standards
11
2
 
12
3
  ## Validation timing
@@ -1,13 +1,3 @@
1
- ---
2
- description: Focus styles, keyboard operation, composite widgets, and focus management for rendered UI
3
- paths:
4
- - '**/*.tsx'
5
- - '**/*.jsx'
6
- - '**/*.astro'
7
- - '**/*.html'
8
- - '**/*.css'
9
- ---
10
-
11
1
  # Keyboard and focus standards
12
2
 
13
3
  ## Focus styles
@@ -1,13 +1,3 @@
1
- ---
2
- description: Moving content controls and the reduced-motion preference for rendered UI
3
- paths:
4
- - '**/*.tsx'
5
- - '**/*.jsx'
6
- - '**/*.astro'
7
- - '**/*.html'
8
- - '**/*.css'
9
- ---
10
-
11
1
  # Motion standards
12
2
 
13
3
  ## Moving content
@@ -1,13 +1,3 @@
1
- ---
2
- description: Pointer actions, gestures, outside-press dismissal, and target size for rendered UI
3
- paths:
4
- - '**/*.tsx'
5
- - '**/*.jsx'
6
- - '**/*.astro'
7
- - '**/*.html'
8
- - '**/*.css'
9
- ---
10
-
11
1
  # Pointer standards
12
2
 
13
3
  ## Pointer actions
@@ -1,13 +1,3 @@
1
- ---
2
- description: UX completeness checklist for interactive components and views
3
- paths:
4
- - '**/*.tsx'
5
- - '**/*.jsx'
6
- - '**/*.astro'
7
- - '**/*.html'
8
- - '**/*.css'
9
- ---
10
-
11
1
  # UX completeness standards
12
2
 
13
3
  ## Feedback
@@ -36,7 +36,7 @@ For each surface, look for:
36
36
  3. **Inconsistencies**: spacing, tone of voice, interaction patterns, icon use, keyboard affordances
37
37
  4. **Roughness in daily use**: friction, redundant steps, unclear affordances, ambiguous labels
38
38
 
39
- Use `canon/DESIGN.md` as ground truth for intent where it exists. Observations only, no implementation suggestions or fixes. Take what consistent interaction means from the `ui` rules in `.claude/rules/`, and skip that when the project installed none.
39
+ Use `canon/DESIGN.md` as ground truth for intent where it exists. Observations only, no implementation suggestions or fixes. Take what consistent interaction means from the `ui-craft` skill's references.
40
40
 
41
41
  Where Step 1 found a committed capture for this surface, judge composed output (spacing, overlap, contrast, wrapping) against it rather than inferring layout from markup. Where none exists, judge from source and say so in that surface's findings, since a source read cannot see what only a render shows.
42
42
 
@@ -5,7 +5,10 @@ description: Which external writing patterns this skill adopted, which it declin
5
5
 
6
6
  # Source material
7
7
 
8
- Two external writing skills were read as source material for this one. The first catalogs 31 patterns of machine-sounding prose. The second layers document mode, sentence construction, information density, and ambiguity prevention.
8
+ Two external writing skills were read as source material for this one.
9
+
10
+ - **[humanizer](https://github.com/blader/humanizer)** catalogs 31 patterns of machine-sounding prose
11
+ - **An unidentified second skill** layers document mode, sentence construction, information density, and ambiguity prevention. No record of the read named it, so it carries no link.
9
12
 
10
13
  Neither was imported wholesale, and one measurement settles why. Read this before adding a rule from outside this corpus, and extend the position below rather than deriving a second one.
11
14
 
@@ -57,18 +57,15 @@ An audit that finds no corpus reports `absent`, which moves neither the verdict
57
57
 
58
58
  **In `bun run check`.**
59
59
 
60
- `bun run check` runs `--corpus tracked --corpus per-machine` as a reporting stage after the gating stages, and never fails on it. `summary` is a flat object of unique scalar keys that a shell stage greps without a JSON parser. `deps` runs weekly instead.
61
-
62
- The placement entry runs pinned to `--backend off`, so its tally stays comparable across machines. Each audit runs as the CLI the caller is running, never a global `canon`.
60
+ `bun run check` runs `--corpus tracked --corpus per-machine` as a reporting stage after the gating stages, and never fails on it. `summary` is a flat object of unique scalar keys that a shell stage greps without a JSON parser. `deps` runs weekly instead. Each audit runs as the CLI the caller is running, never a global `canon`.
63
61
 
64
62
  **Catalog.**
65
63
 
66
- `canon audits list` reports the first 19 rows. The rows marked `outside` run by hand or from a skill and sit beside the aggregate.
64
+ `canon audits list` reports the first 18 rows. The rows marked `outside` run by hand or from a skill and sit beside the aggregate.
67
65
 
68
66
  | Id | Verb | Measures | Finding |
69
67
  | -------------------- | ----------------------------------- | ---------------------------------------------------------------------------------- | -------------- |
70
68
  | `context` | `canon context audit` | Context folder structure, citations, and the requirements record's word cap | Gates |
71
- | `placement` | `canon context classify sweep` | Keep, rewrite, and move tally per context section, regex layer only | Reports |
72
69
  | `markdown` | `canon markdown audit` | Bans, dead links, density, and reference shape | Gates |
73
70
  | `skills` | `canon claude skills audit` | Both skill corpora against the skill standards | Gates |
74
71
  | `skills-reach` | `canon claude skills reach` | Skill bodies citing a path no target receives | Reports |
@@ -90,7 +87,6 @@ The placement entry runs pinned to `--backend off`, so its tally stays comparabl
90
87
  | `outside` | `canon gov superseded <old> <new>` | Where the tree still asserts a value a changed convention no longer produces | Reports |
91
88
  | `outside` | `canon claude skills drift <ref>` | Shipped skill bodies rewritten since a ref | Reports |
92
89
  | `outside` | `canon claude routing` | Per `CLAUDE.md` section, how many bullets name a path and whether a rule covers it | Reports |
93
- | `outside` | `canon context classify diff` | Classification of the chunks a git range changed | Reports |
94
90
 
95
91
  A deliberate secret takes a `canon-allow-secret: <reason>` marker. A deliberate citation takes `canon-allow-citation: <reason>` and a deliberate superseded value takes `canon-allow-superseded: <reason>`, each on its own line or the one above. Run any verb with `--help` for its flags and refusal reasons.
96
92
 
@@ -62,7 +62,7 @@ The exit code follows the mode the run took. The bullets cover where the gate ru
62
62
  - A root resolving no audited folder refuses with `1` and warns, a root measuring no entry warns, and a seed short a section fails with `2`
63
63
  - A seed omitting a required section on purpose sets `stub: true` in its frontmatter. Only the value `true` counts, and both install paths strip the field.
64
64
 
65
- The citation check skips fenced blocks, fixture and harness trees including `*.test.ts`, and a path into a folder the project lacks.
65
+ The citation check skips fenced blocks, fixture and harness trees including `*.test.ts`, the install stamp at any of its spellings, and a path into a folder the project lacks.
66
66
 
67
67
  Append `<!-- audit-ignore-citations: <path> -->` to a line that displays a path without pointing at it. The marker excuses only the paths it names, and a bare `<!-- audit-ignore-citations -->` excuses every citation on the line. In seeds, plugin skill bodies, and stack references, which install into a target, reword the line instead.
68
68
 
@@ -62,11 +62,11 @@ After a rename the new name shows as `missing` when the stamp records a stack, a
62
62
 
63
63
  ## Tooling
64
64
 
65
- - `canon tooling diff <stack> [target]` is the read-only comparison, exiting 1 on any difference
65
+ - `canon tooling diff <stack> [target]` is the read-only comparison, exiting 1 on any difference, and it reads a dependency on a later major than the stack pins as `ahead`, which counts as no change
66
66
  - A `--json` refusal answers `{ ok: false, reason, message }`, so branch on the record
67
67
  - `withheld` entries are `{ rel, stack, present }`, hold every `.github/` file below the git root, and count toward no exit
68
68
  - `present` marks a copy an earlier sync left, which is reported and never deleted
69
- - `canon tooling sync <stack> [target]` writes only under `--write`. `--check` reports and exits 0, and a headless run with neither flag exits 1.
69
+ - `canon tooling sync <stack> [target]` writes only under `--write`. `--check` reports and exits 0, and a headless run with neither flag exits 1. It never installs over an `ahead` dependency.
70
70
 
71
71
  ### Drift cause and the write hold
72
72
 
@@ -187,12 +187,12 @@ A web project's `e2e/screenshot.ts` is a config. It now loads `CASES` from a see
187
187
  - Evidence now defaults to `e2e/evidence/`. Set `export const EVIDENCE_ROOT = 'evidence'` in `e2e/capture/cases.ts` to keep a committed baseline at the old path.
188
188
  - A run from a folder with no `e2e/capture/cases.ts` exits 1 and names the file.
189
189
 
190
- ## Add the rules a split left behind, once
190
+ ## Fold the ui rules onto one pointer, once
191
191
 
192
- The splits created `pointer` and `ux-controls`, and sync refreshes only held rules. `canon gov sync` now names the missing partner of `keyboard.md` and `ux-completeness.md` on every run and adds nothing itself. `a11y.md` gained two bullets and lost none, so it needs no partner.
192
+ Eleven ui rules moved unchanged into the `ui-craft` skill, being `a11y`, `keyboard`, `pointer`, `forms`, `motion`, `ux-controls`, `ux-completeness`, `surface-capture`, `copy`, `interface-casing`, and `link-behavior`. Update the plugin, then sync, which folds each one you hold and `design-taste.md` onto one `craft.md` pointer without local edits.
193
193
 
194
194
  ```bash
195
- canon gov install --add pointer,ux-controls --yes .
195
+ canon gov sync .
196
196
  ```
197
197
 
198
198
  ## Group a long paths section in `CLAUDE.md`, once
@@ -45,6 +45,7 @@ Add `--json` for a machine-readable report and `--exit-code` to fail CI when a t
45
45
  - Seed docs such as `CLAUDE.md` and `canon/REQUIREMENTS.md`: merge by hand, keeping the project's customizations
46
46
  - Installed governance rules: `canon gov sync <path>`, which adds no new rules and reports coverage afterward
47
47
  - Tooling configs and seeds: read differences with `canon tooling diff <stack> <path>`, then `canon tooling sync <stack> <path> --write`, which holds an edited config and copies each seed once
48
+ - Tooling dependencies: a dependency on a later major than the stack pins reads as `ahead`, and sync leaves it
48
49
  - Index regeneration: `canon indexes regen`
49
50
 
50
51
  After `canon gov sync` applies, it lists each rule it copied with its globs and how many project files match. A `ui/` rule adds a pointer to `/canon:ux-audit`. `--json` writes `{ "coverage": [{ "rule", "paths", "files", "ui" }] }` to stdout, empty when nothing was copied, with `files` null outside git. The report never changes the exit code.
@@ -59,13 +60,13 @@ A project can also opt out of one golden file without leaving the stack. Each ve
59
60
 
60
61
  ```bash
61
62
  canon tooling decline .github/workflows/readme-screenshot.yml --reason "no screenshots here"
62
- canon tooling customize e2e/home.spec.ts
63
+ canon tooling customize e2e/screenshot.ts
63
64
  canon tooling lift .github/workflows/readme-screenshot.yml
64
65
  ```
65
66
 
66
67
  - `decline` keeps sync and inject from writing the file again, and leaves a copy the project still holds in place
67
68
  - `customize` keeps the project's copy of a config through every write, and `diff` exits 1 once the stack ships a newer golden copy
68
- - A seed cannot be customized, since sync never overwrites one
69
+ - A seed cannot be customized, since sync never overwrites one, and the starter `e2e/home.spec.ts` is one
69
70
  - `lift` hands the file back, so the next sync writes it
70
71
 
71
72
  These verbs are the only writers of the record in `canon/config/config.json`, so never edit it there by hand.
@@ -45,6 +45,7 @@ Groups run in the order a project meets them. Every name `canon claude skills li
45
45
  | `canon:search-craft` | Before searching outside the project |
46
46
  | `canon:systematic-debugging` | A test fails or a bug surfaces |
47
47
  | `canon:design-taste` | Drafting or judging an interface |
48
+ | `canon:ui-craft` | Building or judging a component's behavior |
48
49
  | `canon:ui-checklist` | After a UI change, to list what to check |
49
50
 
50
51
  ## Check the work before it leaves the branch
@@ -19,8 +19,8 @@ Canon runs a UI feature through one loop. A plan cites the design, a worker buil
19
19
 
20
20
  The worker opens each cited reference, light and dark, before its first edit to that surface. It takes sizes, spacing, and colors from the frame HTML rather than the image, and reports a reference that does not resolve instead of building without it.
21
21
 
22
- - The ui rules fire as a family on the files the worker edits, and `governance/rules/ui/` holds the set.
23
- - The `surface-capture` rule has the worker capture the full page in every theme the surface ships, against a preview server and never a dev server.
22
+ - The `craft` rule fires on the files the worker edits and loads `ui-craft` for behavior and `design-taste` for look.
23
+ - The `ui-craft` capture reference has the worker capture the full page in every theme the surface ships, against a preview server and never a dev server.
24
24
  - It sets the widths too, being 320 plus each breakpoint in `canon/DESIGN.md` for a layout case, and one width for a state case.
25
25
 
26
26
  ## Self-check
@@ -160,54 +160,10 @@ deps = [
160
160
  ]
161
161
  files = ["**/migrations", "**/schema.prisma", "**/*.sql"]
162
162
 
163
- ["copy"]
164
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
165
- files = ["index.html", "*/index.html"]
166
-
167
- ["a11y"]
168
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
169
- files = ["index.html", "*/index.html"]
170
-
171
- ["keyboard"]
172
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
173
- files = ["index.html", "*/index.html"]
174
-
175
- ["pointer"]
176
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
177
- files = ["index.html", "*/index.html"]
178
-
179
- ["forms"]
180
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
181
- files = ["index.html", "*/index.html"]
182
-
183
- ["ux-completeness"]
184
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
185
- files = ["index.html", "*/index.html"]
186
-
187
- ["ux-controls"]
188
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
189
- files = ["index.html", "*/index.html"]
190
-
191
- ["surface-capture"]
192
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
193
- files = ["index.html", "*/index.html"]
194
-
195
- ["link-behavior"]
196
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
197
- files = ["index.html", "*/index.html"]
198
-
199
- ["design-taste"]
163
+ ["craft"]
200
164
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
201
165
  files = ["canon/DESIGN.md", "index.html", "*/index.html"]
202
166
 
203
- ["interface-casing"]
204
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
205
- files = ["index.html", "*/index.html"]
206
-
207
- ["motion"]
208
- deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
209
- files = ["index.html", "*/index.html"]
210
-
211
167
  ["design-reference"]
212
168
  deps = []
213
169
  files = ["canon/design/*/"]
@@ -25,7 +25,7 @@ The field is browser test automation, and the authority is the Playwright docume
25
25
  | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
26
26
  | A script, not the suite | House choice: a suite run answers a question about the page only through assertions written for another question, and costs the whole run | 2026-10-18 |
27
27
  | No `fullyParallel` | [Parallelism](https://playwright.dev/docs/test-parallel): by default "Tests in a single file are run in order, in the same worker process", and parallel tests "cannot share any state or global variables" | 2026-10-18 |
28
- | Pointer to `surface-capture` | House choice: a pointer to the rule that owns capture scope, claiming no practice of its own | 2026-10-18 |
28
+ | Pointer to `ui-craft` | House choice: a pointer to the skill that owns capture scope, claiming no practice of its own | 2026-10-18 |
29
29
  | Pointer to `e2e-reliability` | House choice: a pointer to the rule that owns waits and guards, claiming no practice of its own | 2026-10-18 |
30
30
 
31
31
  ## Declined