@erclx/canon 5.61.0 → 5.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canon-cli/SKILL.md +2 -1
- package/claude/skills/create-skill/references/skill-practice.md +1 -0
- package/claude/skills/design-identity/references/card-route.md +3 -3
- package/claude/skills/design-record/references/design.md +1 -1
- package/claude/skills/design-taste/REQUIREMENT.md +2 -1
- package/claude/skills/design-taste/SKILL.md +6 -5
- package/claude/skills/design-taste/references/adopted.md +136 -8
- package/claude/skills/design-taste/references/craft.md +1 -1
- package/claude/skills/design-taste/references/kinds.md +8 -2
- package/claude/skills/design-taste/references/preflight.md +3 -3
- package/claude/skills/design-taste/references/tells.md +26 -5
- package/claude/skills/plan-feature/SKILL.md +2 -2
- package/claude/skills/plan-feature/references/plan.md +24 -3
- package/claude/skills/review-craft/SKILL.md +1 -1
- package/claude/skills/role-worker/SKILL.md +2 -1
- package/claude/skills/target-update/SKILL.md +9 -1
- package/claude/skills/ui-checklist/SKILL.md +1 -1
- package/claude/skills/ui-craft/REQUIREMENT.md +29 -0
- package/claude/skills/ui-craft/SKILL.md +44 -0
- package/{governance/rules/ui → claude/skills/ui-craft/references}/a11y.md +2 -10
- package/claude/skills/ui-craft/references/adopted.md +27 -0
- package/{governance/rules/ui/surface-capture.md → claude/skills/ui-craft/references/capture.md} +5 -15
- package/claude/skills/ui-craft/references/controls.md +18 -0
- package/claude/skills/ui-craft/references/copy.md +45 -0
- package/{governance/rules/ui → claude/skills/ui-craft/references}/forms.md +0 -9
- package/{governance/rules/ui → claude/skills/ui-craft/references}/keyboard.md +3 -16
- package/{governance/rules/ui → claude/skills/ui-craft/references}/motion.md +0 -10
- package/claude/skills/ui-craft/references/pointer.md +13 -0
- package/{governance/rules/ui/ux-completeness.md → claude/skills/ui-craft/references/states.md} +2 -20
- package/claude/skills/ux-audit/SKILL.md +1 -1
- package/claude/skills/write-human/references/adopted.md +4 -1
- package/docs/agents/install-and-sync.md +47 -13
- package/docs/index.md +1 -1
- package/docs/target/migrations.md +6 -8
- package/docs/target/sync.md +21 -1
- package/docs/workflow/ai-workflow.md +1 -1
- package/docs/workflow/index.md +3 -3
- package/docs/workflow/skill-map.md +1 -0
- package/docs/workflow/visual-design-workflow.md +58 -32
- package/governance/detect.toml +1 -37
- package/governance/ledger/lib/test-scope.md +1 -1
- package/governance/ledger/{ui → skills/ui-craft}/a11y.md +11 -9
- package/governance/ledger/{ui/surface-capture.md → skills/ui-craft/capture.md} +15 -15
- package/governance/ledger/skills/ui-craft/controls.md +31 -0
- package/governance/ledger/skills/ui-craft/copy.md +102 -0
- package/governance/ledger/{ui → skills/ui-craft}/forms.md +3 -3
- package/governance/ledger/skills/ui-craft/keyboard.md +67 -0
- package/governance/ledger/{ui → skills/ui-craft}/motion.md +3 -3
- package/governance/ledger/skills/ui-craft/pointer.md +24 -0
- package/governance/ledger/{ui/ux-completeness.md → skills/ui-craft/states.md} +14 -26
- package/governance/ledger/ui/craft.md +19 -0
- package/governance/renames.toml +17 -3
- package/governance/rules/lib/test-scope.md +1 -1
- package/governance/rules/ui/craft.md +22 -0
- package/governance/splits.toml +13 -0
- package/package.json +1 -1
- package/src/claude/cases/misc.ts +5 -0
- package/src/claude/skills-audit.ts +150 -12
- package/src/commands/claude.ts +5 -0
- package/src/commands/sync.ts +3 -1
- package/src/commands/tooling.ts +332 -10
- package/src/gate/measures.ts +4 -3
- package/src/gov/adapter.ts +53 -4
- package/src/gov/audit.ts +6 -1
- package/src/gov/splits.ts +36 -0
- package/src/inventory/subjects.ts +1 -1
- package/src/sync/check.ts +9 -1
- package/src/sync/stamp.ts +135 -11
- package/src/tooling/disposition.ts +167 -0
- package/src/tooling/inject.ts +17 -2
- package/src/tooling/package.ts +22 -13
- package/src/tooling/scan.ts +86 -7
- package/src/tooling/stamp.ts +51 -7
- package/tooling/web/reference.md +3 -1
- package/governance/ledger/ui/copy.md +0 -49
- package/governance/ledger/ui/design-taste.md +0 -19
- package/governance/ledger/ui/interface-casing.md +0 -47
- package/governance/ledger/ui/keyboard.md +0 -68
- package/governance/ledger/ui/link-behavior.md +0 -29
- package/governance/rules/ui/copy.md +0 -28
- package/governance/rules/ui/design-taste.md +0 -18
- package/governance/rules/ui/interface-casing.md +0 -29
- package/governance/rules/ui/link-behavior.md +0 -19
- /package/tooling/web/{configs → seeds}/e2e/home.spec.ts +0 -0
|
@@ -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
|
|
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
|
|
@@ -16,6 +6,7 @@ paths:
|
|
|
16
6
|
- Spell an attribute the way the file's syntax spells it, being `onclick` and `tabindex` in HTML and Astro markup and `onClick` and `tabIndex` in JSX.
|
|
17
7
|
- Give a custom control the role its pattern names, such as `combobox` or `listbox`, and keep `aria-expanded`, `aria-selected`, and `aria-checked` in step with what it shows.
|
|
18
8
|
- Give an interactive element with no visible text label a name through `aria-label` or `aria-labelledby`.
|
|
9
|
+
- Put the visible text in the accessible name, first where you can (WCAG 2.5.3).
|
|
19
10
|
|
|
20
11
|
## Text alternatives
|
|
21
12
|
|
|
@@ -26,6 +17,7 @@ paths:
|
|
|
26
17
|
|
|
27
18
|
- Give a control's visual boundary and every graphic that carries meaning at least 3:1 contrast against adjacent colors (WCAG 1.4.11).
|
|
28
19
|
- Never make color the only carrier of a state, error, or distinction. Pair it with text, an icon, or a pattern (WCAG 1.4.1).
|
|
20
|
+
- Give text 4.5:1 contrast, or 3:1 when large (WCAG 1.4.3).
|
|
29
21
|
|
|
30
22
|
## Reflow
|
|
31
23
|
|
|
@@ -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.
|
package/{governance/rules/ui/surface-capture.md → claude/skills/ui-craft/references/capture.md}
RENAMED
|
@@ -1,32 +1,22 @@
|
|
|
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
|
|
14
4
|
|
|
15
|
-
- Treat anything the project renders for a person as a surface,
|
|
5
|
+
- Treat anything the project renders for a person as a surface, generated pages included.
|
|
16
6
|
- Skip a component the production build strips out, such as a dev-only switcher.
|
|
17
7
|
|
|
18
8
|
## When to capture
|
|
19
9
|
|
|
20
|
-
- Run the project's capture command against a preview server, never a dev server, after changing a surface. Report
|
|
21
|
-
- Capture every theme the surface ships, and again after fixing a defect
|
|
10
|
+
- Run the project's capture command against a preview server, never a dev server, after changing a surface. Report a project with none.
|
|
11
|
+
- Capture every theme the surface ships, and again after fixing a defect found.
|
|
12
|
+
- Read your capture against the `canon:ui-checklist` boxes before opening the pull request, reporting a skill that does not resolve.
|
|
22
13
|
|
|
23
14
|
## What a capture covers
|
|
24
15
|
|
|
25
16
|
- Capture the full page, never a component in isolation.
|
|
26
17
|
- Capture a layout case at 320, the reflow floor in `a11y`, plus each breakpoint in the `## Layout` section of `DESIGN.md`, or at 320 alone when there is none.
|
|
27
18
|
- Capture resizable chrome at its narrowest and widest clamp, at the narrowest width keeping it persistent. Judge the content width beside it.
|
|
28
|
-
- Capture a state case at one width
|
|
29
|
-
- Drive a state an initial render cannot reach, such as an open menu or a rail tracking scroll.
|
|
19
|
+
- Capture a state case at one width, driving states a first render cannot reach, such as an open menu.
|
|
30
20
|
- Add a surface's case with the surface, and remove it with the surface.
|
|
31
21
|
|
|
32
22
|
## Sharing a capture
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# UX controls standards
|
|
2
|
+
|
|
3
|
+
## Destructive actions
|
|
4
|
+
|
|
5
|
+
- Confirm a destructive action, such as a delete, disconnect, or discard, before it runs, unless it can be undone afterward.
|
|
6
|
+
- Restore the value from before an edit when the edit is cancelled. Never discard typed work on Escape or an outside click unasked, but confirm first when the person has typed something.
|
|
7
|
+
|
|
8
|
+
## Element states
|
|
9
|
+
|
|
10
|
+
- Give every interactive element distinct hover, active, focus, and disabled styles.
|
|
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.
|
|
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.
|
|
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
|
+
|
|
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).
|
|
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,13 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Focus styles, keyboard operation, focus management, and pointer targets 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
|
|
@@ -15,24 +5,21 @@ paths:
|
|
|
15
5
|
- Style focus through the project's one focus ring rather than a per-component focus style.
|
|
16
6
|
- Never set `outline: none` or `outline-none` without a replacement focus indicator in the same rule.
|
|
17
7
|
- Give the focus ring 3:1 contrast against its background in every theme the project ships.
|
|
8
|
+
- Keep the focus ring whole. Where an ancestor's `overflow` would clip it, inset it with a negative `outline-offset` or pad the edge items of the list.
|
|
18
9
|
|
|
19
10
|
## Keyboard operation
|
|
20
11
|
|
|
21
12
|
- Close a dialog, popover, menu, or inline confirmation on Escape, and cancel an in-progress edit the same way.
|
|
13
|
+
- Never trap keyboard focus. A person who tabs into a component can leave it by keyboard alone, and a modal dialog leaves on Escape (WCAG 2.1.2).
|
|
22
14
|
- Bind no single printable character as a shortcut unless a person can turn it off or remap it, or it fires only while its control has focus (WCAG 2.1.4).
|
|
23
|
-
- Give every author-defined drag a single-pointer alternative and a keyboard path, such as move buttons or arrow-key reordering (WCAG 2.5.7).
|
|
24
15
|
|
|
25
16
|
## Composite widgets
|
|
26
17
|
|
|
27
18
|
- Keep one item of a composite widget in the tab sequence, and move between its items with the arrow keys through roving `tabindex` or `aria-activedescendant`.
|
|
28
19
|
- Open a combobox popup on Down Arrow, accept the focused option on Enter, and close the popup on Escape without changing the value.
|
|
20
|
+
- Give a custom number input the spinbutton keys, Up and Down to step and Home and End for the limits. Take the keys of any other custom widget from its ARIA Authoring Practices Guide pattern.
|
|
29
21
|
|
|
30
22
|
## Focus management
|
|
31
23
|
|
|
32
24
|
- Move focus into a dialog when it opens, and return it to the element that opened it when it closes.
|
|
33
25
|
- Never let a sticky header, footer, or overlay fully cover the focused control. Scroll it clear of them (WCAG 2.4.11).
|
|
34
|
-
|
|
35
|
-
## Pointer targets
|
|
36
|
-
|
|
37
|
-
- Size a web pointer target at least 24 by 24 CSS pixels, or space it so a 24 pixel circle centered on it touches no other target (WCAG 2.5.8).
|
|
38
|
-
- Size a native touch target at the platform figure, 44 points on iOS and 48 dp on Android, and never swap the web and native figures.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Pointer standards
|
|
2
|
+
|
|
3
|
+
## Pointer actions
|
|
4
|
+
|
|
5
|
+
- Dismiss a popover or menu on a press outside it and when focus leaves it, as well as on Escape.
|
|
6
|
+
- Run a pointer action on release rather than press, so a person can slide off the target to abort it (WCAG 2.5.2).
|
|
7
|
+
- Give a path-based or multipoint gesture, such as a swipe or pinch, a single-pointer alternative with no path (WCAG 2.5.1).
|
|
8
|
+
- Give every author-defined drag a single-pointer alternative and a keyboard path, such as move buttons or arrow-key reordering (WCAG 2.5.7).
|
|
9
|
+
|
|
10
|
+
## Pointer targets
|
|
11
|
+
|
|
12
|
+
- Size a web pointer target at least 24 by 24 CSS pixels, or space it so a 24 pixel circle centered on it touches no other target (WCAG 2.5.8).
|
|
13
|
+
- Size a native touch target at the platform figure, 44 points on iOS and 48 dp on Android, and never swap the web and native figures.
|
package/{governance/rules/ui/ux-completeness.md → claude/skills/ui-craft/references/states.md}
RENAMED
|
@@ -1,19 +1,10 @@
|
|
|
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
|
|
14
4
|
|
|
15
5
|
- Confirm every user-initiated mutation, such as a save, delete, or import, inline on success, and show an inline error when it fails.
|
|
16
6
|
- Auto-dismiss a success message only when its outcome stays visible elsewhere. Keep a message carrying the only copy of its information until dismissed (WCAG 2.2.1).
|
|
7
|
+
- Pause a timed message while it has pointer hover or keyboard focus, and take no focus for it. A person finishes reading it, and a status message never interrupts typing (WCAG 4.1.3).
|
|
17
8
|
- Show no optimistic status, such as a green dot or "connected", while unsaved edits are pending.
|
|
18
9
|
|
|
19
10
|
## Empty states
|
|
@@ -26,17 +17,8 @@ paths:
|
|
|
26
17
|
- Show a progress indicator for any operation a person waits on for longer than about one second.
|
|
27
18
|
- Mark previous content as updating while new content loads, rather than showing it unmarked as current.
|
|
28
19
|
|
|
29
|
-
## Destructive actions
|
|
30
|
-
|
|
31
|
-
- Confirm a destructive action, such as a delete, disconnect, or discard, before it runs, unless it can be undone afterward.
|
|
32
|
-
|
|
33
|
-
## Element states
|
|
34
|
-
|
|
35
|
-
- Give every interactive element distinct hover, active, focus, and disabled styles.
|
|
36
|
-
- 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.
|
|
37
|
-
|
|
38
20
|
## Overflow
|
|
39
21
|
|
|
40
22
|
- Truncate long text in a constrained container with an ellipsis rather than letting it overflow.
|
|
41
23
|
- Expose truncated text through an expand control or full text on focus, never through a `title` tooltip alone.
|
|
42
|
-
- Keep
|
|
24
|
+
- Keep interactive borders clear of a parent's `overflow` clipping, padding the edge items of a scrollable list.
|
|
@@ -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.
|
|
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.
|
|
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
|
|
|
@@ -32,7 +32,7 @@ A flat installed-rule layout makes `gov sync` report "No governance surfaces fou
|
|
|
32
32
|
- A retired `.claude/GOV.md` is removed
|
|
33
33
|
- A binary older than the stamp holds every rule it has no source for and asks for an upgrade
|
|
34
34
|
|
|
35
|
-
After a rename the new name shows as `missing` when the stamp records a stack, and `gov install <stack>` adds it.
|
|
35
|
+
After a rename the new name shows as `missing` when the stamp records a stack, and `gov install <stack>` adds it. A partner `governance/splits.toml` names shows as `missing` when the tree holds the split rule and lacks the partner, and `gov install --add <partner>` adds it.
|
|
36
36
|
|
|
37
37
|
`canon gov regen [--root <path>]` runs against the toolkit root alone. It rewrites `.claude/rules/canon/` and `.claude/rules/internal/` from `internal/`, and exits 1 when the record names something that does not resolve.
|
|
38
38
|
|
|
@@ -62,11 +62,45 @@ 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
|
+
|
|
71
|
+
### Drift cause and the write hold
|
|
72
|
+
|
|
73
|
+
A `drifted` entry in `configs` carries a `cause`, read against the golden hash the last write recorded for that path.
|
|
74
|
+
|
|
75
|
+
- `stale`: the target still hashes to the record, so canon moved and the project did not. `--write` replaces it.
|
|
76
|
+
- `edited`: the target no longer hashes to the record. `--write` holds it.
|
|
77
|
+
- `unattributed`: no hash is recorded, as on every target synced before hashes existed. `--write` holds it.
|
|
78
|
+
|
|
79
|
+
A config no stack in the recorded chain ships is a first install and is never held, so a fresh scaffold takes every golden config of a stack new to it, even after `canon init` recorded `base`.
|
|
80
|
+
|
|
81
|
+
A held path stays drifted, so the next headless run still exits 1. Pass `--replace <path>` once per path to take the golden copy, as the command the write prints does. A `--replace` naming no config the chain writes refuses with `unknown-replace`.
|
|
82
|
+
|
|
83
|
+
### Dispositions
|
|
84
|
+
|
|
85
|
+
`decline <path> [target] [--reason <text>]`, `customize <path> [target]`, and `lift <path> [target]` set or clear one path's disposition, each with `--json`. The path is relative to the target and resolves against the recorded chain, never a stack argument.
|
|
86
|
+
|
|
87
|
+
- A success answers `{ ok: true, action, path, entry? }`, where `entry` is the recorded `{ disposition, base?, reason? }` and is absent after a lift
|
|
88
|
+
- A declined or customized path leaves `configs`, `seeds`, and `withheld` for `dispositions`, as `{ rel, stack, kind, disposition, present, moved? }`
|
|
89
|
+
- `moved` is set on a customized config alone, and counts toward the exit once the golden copy no longer matches `base`
|
|
90
|
+
- Sync and inject never write a path in `dispositions`, and nothing deletes one the project still holds
|
|
91
|
+
|
|
92
|
+
A refusal answers `{ ok: false, reason, message }` with exit 1:
|
|
93
|
+
|
|
94
|
+
| `reason` | Meaning |
|
|
95
|
+
| ----------------------- | --------------------------------------------------------- |
|
|
96
|
+
| `no-chain` | No tooling chain is recorded, so run `tooling sync` first |
|
|
97
|
+
| `bad-path` | The path leaves the target |
|
|
98
|
+
| `not-golden` | No stack in the recorded chain ships the path |
|
|
99
|
+
| `already-held` | The path is already declined or customized, so lift it |
|
|
100
|
+
| `seed-not-customizable` | The path is a seed, which sync never overwrites |
|
|
101
|
+
| `missing-file` | `customize` named a config the target does not hold |
|
|
102
|
+
| `not-held` | `lift` named a path with no disposition |
|
|
103
|
+
| `toolkit-root` | The target is the toolkit checkout, the source of truth |
|
|
70
104
|
|
|
71
105
|
`canon tooling inject` and `prune-gitignore` apply one stack with no scan or prompt, and the latter prints the number removed on stdout. Use `sync` unless scripting provisioning, and pass `--nested` inside an open frame.
|
|
72
106
|
|
|
@@ -78,16 +112,16 @@ After a rename the new name shows as `missing` when the stamp records a stack, a
|
|
|
78
112
|
|
|
79
113
|
`canon sync --check` writes nothing and needs no clean tree. `--json` emits the record, `--exit-code` fails CI.
|
|
80
114
|
|
|
81
|
-
| State | Meaning
|
|
82
|
-
| ------------ |
|
|
83
|
-
| `stale` | Still matches what the toolkit installed
|
|
84
|
-
| `customized` | The project edited it
|
|
85
|
-
| `stranded` | Sits at a path the toolkit no longer installs to
|
|
86
|
-
| `orphaned` | The project authored it
|
|
87
|
-
| `drifted` | No stamp covers it
|
|
88
|
-
| `missing` | Governance only. The recorded stack lists it
|
|
89
|
-
| `retired` | Governance only. The toolkit no longer ships it
|
|
90
|
-
| `renamed` | Governance only. The toolkit ships it under a new name
|
|
115
|
+
| State | Meaning |
|
|
116
|
+
| ------------ | ----------------------------------------------------------------------- |
|
|
117
|
+
| `stale` | Still matches what the toolkit installed |
|
|
118
|
+
| `customized` | The project edited it |
|
|
119
|
+
| `stranded` | Sits at a path the toolkit no longer installs to |
|
|
120
|
+
| `orphaned` | The project authored it |
|
|
121
|
+
| `drifted` | No stamp covers it |
|
|
122
|
+
| `missing` | Governance only. The recorded stack lists it, or a split rule leaves it |
|
|
123
|
+
| `retired` | Governance only. The toolkit no longer ships it |
|
|
124
|
+
| `renamed` | Governance only. The toolkit ships it under a new name |
|
|
91
125
|
|
|
92
126
|
`retired` and `renamed` count toward `--exit-code`. `orphaned` and `missing` do not.
|
|
93
127
|
|
package/docs/index.md
CHANGED
|
@@ -9,4 +9,4 @@ One-line reference for each doc in this folder.
|
|
|
9
9
|
|
|
10
10
|
- [Agents](agents/index.md): CLI catalog and invocation rules for agents, split by command domain. Start with overview.
|
|
11
11
|
- [Target](target/index.md): Scaffold, sync, and migrate a toolkit-managed project, with worked setups for three project shapes.
|
|
12
|
-
- [Workflow](workflow/index.md): How a person and their agents run a feature, from the design
|
|
12
|
+
- [Workflow](workflow/index.md): How a person and their agents run a feature, from the design loop through the parallel-session loop to the shell that launches them.
|
|
@@ -75,7 +75,7 @@ The `memory` record kind left `canon records`, so `canon records validate memory
|
|
|
75
75
|
- `canon repo metadata`, `canon autoship`, and the `120-bash` rule are gone, and `canon gov sync` removes the rule <!-- canon-keep-retired -->
|
|
76
76
|
- `memory-capture`, the `603-memory` rule, and the `memory` standard are gone, so send a lesson to the context entry that owns the fact <!-- canon-keep-retired -->
|
|
77
77
|
|
|
78
|
-
Two held files run, `.husky/post-merge` and `.claude/hooks/pr-create-log.sh`, and a stale copy calls a missing binary or names a removed skill. Resync what the toolkit owns before sweeping what the project wrote, and run the second line once per stack
|
|
78
|
+
Two held files run, `.husky/post-merge` and `.claude/hooks/pr-create-log.sh`, and a stale copy calls a missing binary or names a removed skill. Resync what the toolkit owns before sweeping what the project wrote, and run the second line once per stack, naming a held hook with `--replace`.
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
81
|
canon gov sync
|
|
@@ -181,20 +181,18 @@ The verb adds `Bash(canon pr merge:*)` and `Bash(gh pr merge:*)` so a session ca
|
|
|
181
181
|
|
|
182
182
|
## Move the capture cases out of the harness, once
|
|
183
183
|
|
|
184
|
-
A web project's `e2e/screenshot.ts` is a config
|
|
184
|
+
A web project's `e2e/screenshot.ts` is a config. It now loads `CASES` from a seeded `e2e/capture/cases.ts` that sync copies once and never overwrites. A harness you edited is held on `--write`, so the new one lands only once you pass `--replace e2e/screenshot.ts`.
|
|
185
185
|
|
|
186
|
-
- Copy your cases from the old `e2e/screenshot.ts` into `e2e/capture/cases.ts
|
|
186
|
+
- Copy your cases from the old `e2e/screenshot.ts` into `e2e/capture/cases.ts`, then sync with `--replace e2e/screenshot.ts`.
|
|
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
|
-
##
|
|
190
|
+
## Fold the ui rules onto one pointer, once
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
A project holding `.claude/rules/canon/ui/a11y.md` adds the new rule alone:
|
|
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.
|
|
195
193
|
|
|
196
194
|
```bash
|
|
197
|
-
canon gov
|
|
195
|
+
canon gov sync .
|
|
198
196
|
```
|
|
199
197
|
|
|
200
198
|
## Group a long paths section in `CLAUDE.md`, once
|
package/docs/target/sync.md
CHANGED
|
@@ -44,13 +44,33 @@ Add `--json` for a machine-readable report and `--exit-code` to fail CI when a t
|
|
|
44
44
|
|
|
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
|
-
- Tooling configs and seeds: read differences with `canon tooling diff <stack> <path>`, then `canon tooling sync <stack> <path> --write`, which
|
|
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.
|
|
51
52
|
|
|
52
53
|
Try a scenario from [sandbox](../../canon/context/development/sandbox.md) before syncing a real project.
|
|
53
54
|
|
|
55
|
+
### Held, declined, and customized golden files
|
|
56
|
+
|
|
57
|
+
`--write` replaces a golden config only when canon changed it and the project did not. A config the project edited, or one no earlier write recorded, is held and listed with a `--replace` command that takes the golden copy. A config from a stack the target never synced is a first install and is never held.
|
|
58
|
+
|
|
59
|
+
A project can also opt out of one golden file without leaving the stack. Each verb below takes the path relative to the target, as `canon tooling diff` lists it.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
canon tooling decline .github/workflows/readme-screenshot.yml --reason "no screenshots here"
|
|
63
|
+
canon tooling customize e2e/screenshot.ts
|
|
64
|
+
canon tooling lift .github/workflows/readme-screenshot.yml
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- `decline` keeps sync and inject from writing the file again, and leaves a copy the project still holds in place
|
|
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
|
|
69
|
+
- A seed cannot be customized, since sync never overwrites one, and the starter `e2e/home.spec.ts` is one
|
|
70
|
+
- `lift` hands the file back, so the next sync writes it
|
|
71
|
+
|
|
72
|
+
These verbs are the only writers of the record in `canon/config/config.json`, so never edit it there by hand.
|
|
73
|
+
|
|
54
74
|
## Running sync from an agent session
|
|
55
75
|
|
|
56
76
|
`canon sync .` applies every domain sync, then offers a commit and pull request that needs a terminal. With no terminal on stdin the syncs apply, the git step is refused, and the command exits 0. Commit yourself. Sync refuses a dirty working tree, and `canon sync --check .` does not.
|
|
@@ -66,7 +66,7 @@ An independent session invokes `canon:review-pr` once the pull request is open,
|
|
|
66
66
|
|
|
67
67
|
### UI-heavy project
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
A UI feature runs the same plan, build, and review loop at any size. See [visual design workflow](visual-design-workflow.md).
|
|
70
70
|
|
|
71
71
|
## Skills
|
|
72
72
|
|
package/docs/workflow/index.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Workflow
|
|
3
|
-
subtitle: How a person and their agents run a feature, from the design
|
|
3
|
+
subtitle: How a person and their agents run a feature, from the design loop through the parallel-session loop to the shell that launches them.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Workflow
|
|
7
7
|
|
|
8
|
-
How a person and their agents run a feature, from the design
|
|
8
|
+
How a person and their agents run a feature, from the design loop through the parallel-session loop to the shell that launches them.
|
|
9
9
|
|
|
10
10
|
## Agent surface
|
|
11
11
|
|
|
@@ -17,5 +17,5 @@ How a person and their agents run a feature, from the design tier through the pa
|
|
|
17
17
|
- [Parallel features](parallel-features.md): Run independent features in parallel worktrees, with the records and board every session shares
|
|
18
18
|
- [Skill map on request](skill-map-on-request.md): When to reach for the plugin skills that serve a request rather than a moment in a project's life
|
|
19
19
|
- [Skill map](skill-map.md): When to reach for each plugin skill, grouped by the moment a project meets it
|
|
20
|
-
- [Visual design workflow](visual-design-workflow.md):
|
|
20
|
+
- [Visual design workflow](visual-design-workflow.md): How canon plans, builds, and reviews a UI, from the design reference a plan cites to the browser pass that holds a pull request open
|
|
21
21
|
- [Zshrc aliases for Claude Code](zshrc-aliases.md): Shell aliases that shorten common Claude Code invocations
|
|
@@ -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
|