@erclx/canon 5.43.0 → 5.45.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/README.md +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/backlog-triage/references/apply.md +6 -6
- package/claude/skills/canon-cli/SKILL.md +4 -5
- package/claude/skills/canvas-board/REQUIREMENT.md +1 -1
- package/claude/skills/canvas-board/SKILL.md +1 -1
- package/claude/skills/context-fold/references/context.md +1 -1
- package/claude/skills/create-skill/REQUIREMENT.md +1 -1
- package/claude/skills/create-skill/SKILL.md +2 -2
- package/claude/skills/create-skill/references/skill-requirement.md +68 -9
- package/claude/skills/create-skill/references/skill.md +1 -1
- package/claude/skills/design-identity/REQUIREMENT.md +40 -0
- package/claude/skills/design-identity/SKILL.md +138 -0
- package/claude/skills/{draft-identity → design-identity}/references/card-route.md +2 -2
- package/claude/skills/design-taste/REQUIREMENT.md +6 -6
- package/claude/skills/design-taste/SKILL.md +2 -2
- package/claude/skills/design-taste/references/kinds.md +1 -1
- package/claude/skills/design-taste/references/preflight.md +1 -1
- package/claude/skills/draft-and-pick/REQUIREMENT.md +8 -69
- package/claude/skills/draft-and-pick/SKILL.md +3 -153
- package/claude/skills/draft-doc/REQUIREMENT.md +9 -30
- package/claude/skills/draft-doc/SKILL.md +4 -76
- package/claude/skills/draft-figure/REQUIREMENT.md +8 -42
- package/claude/skills/draft-figure/SKILL.md +3 -77
- package/claude/skills/draft-identity/REQUIREMENT.md +8 -23
- package/claude/skills/draft-identity/SKILL.md +3 -130
- package/claude/skills/draft-ready/REQUIREMENT.md +8 -37
- package/claude/skills/draft-ready/SKILL.md +3 -128
- package/claude/skills/draft-screencast/REQUIREMENT.md +8 -23
- package/claude/skills/draft-screencast/SKILL.md +3 -62
- package/claude/skills/draft-slides/REQUIREMENT.md +8 -27
- package/claude/skills/draft-slides/SKILL.md +3 -72
- package/claude/skills/draw-figure/REQUIREMENT.md +59 -0
- package/claude/skills/draw-figure/SKILL.md +85 -0
- package/claude/skills/{draft-figure → draw-figure}/references/architecture-set.md +2 -2
- package/claude/skills/{draft-figure → draw-figure}/references/hand-drawn.md +2 -2
- package/claude/skills/{draft-figure → draw-figure}/references/mermaid-path.md +2 -2
- package/claude/skills/{draft-figure → draw-figure}/references/mermaid.md +1 -1
- package/claude/skills/make-deck/REQUIREMENT.md +44 -0
- package/claude/skills/make-deck/SKILL.md +80 -0
- package/claude/skills/markdown-craft/REQUIREMENT.md +1 -1
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/pick-by-eye/REQUIREMENT.md +36 -0
- package/claude/skills/pick-by-eye/SKILL.md +161 -0
- package/claude/skills/plan-feature/SKILL.md +2 -1
- package/claude/skills/plan-feature/references/plan.md +24 -10
- package/claude/skills/plan-groundwork/SKILL.md +1 -1
- package/claude/skills/plan-intake/SKILL.md +1 -1
- package/claude/skills/plan-ready/REQUIREMENT.md +54 -0
- package/claude/skills/plan-ready/SKILL.md +136 -0
- package/claude/skills/{draft-ready → plan-ready}/references/assembly.md +1 -1
- package/claude/skills/{draft-ready → plan-ready}/references/ready.md +1 -1
- package/claude/skills/record-screencast/REQUIREMENT.md +3 -3
- package/claude/skills/record-screencast/SKILL.md +2 -2
- package/claude/skills/role-orchestrator/REQUIREMENT.md +16 -99
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +5 -2
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +18 -13
- package/claude/skills/role-planner/REQUIREMENT.md +15 -73
- package/claude/skills/role-planner/SKILL.md +2 -1
- package/claude/skills/role-worker/REQUIREMENT.md +13 -41
- package/claude/skills/role-worker/SKILL.md +9 -0
- package/claude/skills/script-screencast/REQUIREMENT.md +40 -0
- package/claude/skills/script-screencast/SKILL.md +70 -0
- package/claude/skills/{draft-screencast → script-screencast}/references/beats-template.md +2 -2
- package/claude/skills/search-craft/REQUIREMENT.md +4 -4
- package/claude/skills/search-craft/SKILL.md +1 -1
- package/claude/skills/target-setup/SKILL.md +3 -2
- package/claude/skills/target-setup/references/detect.md +0 -1
- package/claude/skills/target-setup/references/verify.md +2 -2
- package/claude/skills/task-board/SKILL.md +11 -9
- package/claude/skills/task-board/references/board.md +15 -12
- package/claude/skills/teach-workspace/REQUIREMENT.md +1 -1
- package/claude/skills/teach-workspace/SKILL.md +1 -1
- package/claude/skills/teach-workspace/references/lesson-craft.md +2 -2
- package/claude/skills/teach-workspace/references/promotion.md +5 -5
- package/claude/skills/ui-checklist/SKILL.md +2 -0
- package/claude/skills/write-doc/REQUIREMENT.md +46 -0
- package/claude/skills/write-doc/SKILL.md +83 -0
- package/claude/skills/{draft-doc → write-doc}/references/context.md +2 -2
- package/claude/skills/{draft-doc → write-doc}/references/docs.md +2 -2
- package/claude/skills/{draft-doc → write-doc}/references/readme.md +2 -2
- package/claude/skills/{draft-doc → write-doc}/references/wiki-kind.md +3 -3
- package/docs/agents/install-and-sync.md +2 -2
- package/docs/agents/markdown-audit.md +4 -2
- package/docs/agents/migrate.md +2 -2
- package/docs/agents/output-shape.md +1 -2
- package/docs/target/migrations.md +35 -4
- package/docs/target/projects.md +2 -3
- package/docs/target/scenarios.md +4 -1
- package/docs/workflow/parallel-features.md +3 -2
- package/docs/workflow/skill-map-on-request.md +19 -13
- package/docs/workflow/skill-map.md +13 -12
- package/docs/workflow/visual-design-workflow.md +2 -2
- package/governance/detect.toml +4 -0
- package/governance/ledger/framework/astro.md +73 -0
- package/governance/ledger/framework/fastapi.md +76 -0
- package/governance/ledger/framework/nextjs.md +86 -0
- package/governance/ledger/framework/react.md +83 -0
- package/governance/ledger/framework/shadcn.md +60 -0
- package/governance/ledger/framework/tailwind.md +55 -0
- package/governance/ledger/lang/go.md +61 -0
- package/governance/ledger/lang/php.md +50 -0
- package/governance/ledger/lang/python.md +68 -0
- package/governance/ledger/lang/typescript.md +64 -0
- package/governance/ledger/lib/database.md +65 -0
- package/governance/ledger/lib/e2e-reliability.md +57 -0
- package/governance/ledger/lib/pydantic.md +61 -0
- package/governance/ledger/lib/security-server.md +62 -0
- package/governance/ledger/lib/security-web.md +51 -0
- package/governance/ledger/lib/tanstack-query.md +57 -0
- package/governance/ledger/lib/test-scope.md +43 -0
- package/governance/ledger/lib/testing-go.md +57 -0
- package/governance/ledger/lib/testing-php.md +51 -0
- package/governance/ledger/lib/testing-py.md +67 -0
- package/governance/ledger/lib/testing-ts.md +63 -0
- package/governance/ledger/lib/zod.md +47 -0
- package/governance/ledger/tooling/ci-workflow.md +33 -0
- package/governance/ledger/tooling/code-comments.md +48 -0
- package/governance/ledger/tooling/config-comments.md +27 -0
- package/governance/ledger/tooling/dependencies.md +38 -0
- package/governance/ledger/ui/a11y.md +55 -0
- package/governance/ledger/ui/copy.md +49 -0
- package/governance/ledger/ui/design-reference.md +42 -0
- package/governance/ledger/ui/design-taste.md +19 -0
- package/governance/ledger/ui/forms.md +71 -0
- package/governance/ledger/ui/interface-casing.md +47 -0
- package/governance/ledger/ui/keyboard.md +68 -0
- package/governance/ledger/ui/link-behavior.md +29 -0
- package/governance/ledger/ui/motion.md +33 -0
- package/governance/ledger/ui/surface-capture.md +69 -0
- package/governance/ledger/ui/ux-completeness.md +79 -0
- package/governance/rules/framework/astro.md +12 -14
- package/governance/rules/framework/fastapi.md +20 -24
- package/governance/rules/framework/nextjs.md +19 -27
- package/governance/rules/framework/react.md +22 -33
- package/governance/rules/framework/shadcn.md +11 -15
- package/governance/rules/framework/tailwind.md +12 -14
- package/governance/rules/lang/go.md +7 -16
- package/governance/rules/lang/php.md +3 -3
- package/governance/rules/lang/python.md +9 -18
- package/governance/rules/lang/typescript.md +9 -19
- package/governance/rules/lib/database.md +5 -5
- package/governance/rules/lib/e2e-reliability.md +4 -6
- package/governance/rules/lib/pydantic.md +14 -16
- package/governance/rules/lib/security-server.md +4 -4
- package/governance/rules/lib/security-web.md +6 -10
- package/governance/rules/lib/tanstack-query.md +10 -12
- package/governance/rules/lib/test-scope.md +4 -4
- package/governance/rules/lib/testing-go.md +1 -2
- package/governance/rules/lib/testing-php.md +4 -5
- package/governance/rules/lib/testing-py.md +11 -19
- package/governance/rules/lib/testing-ts.md +7 -16
- package/governance/rules/lib/zod.md +6 -8
- package/governance/rules/tooling/code-comments.md +2 -4
- package/governance/rules/tooling/config-comments.md +1 -4
- package/governance/rules/tooling/dependencies.md +1 -1
- package/governance/rules/ui/a11y.md +16 -45
- package/governance/rules/ui/copy.md +6 -9
- package/governance/rules/ui/forms.md +13 -19
- package/governance/rules/ui/interface-casing.md +5 -7
- package/governance/rules/ui/keyboard.md +38 -0
- package/governance/rules/ui/link-behavior.md +3 -3
- package/governance/rules/ui/motion.md +3 -3
- package/governance/rules/ui/surface-capture.md +15 -27
- package/governance/rules/ui/ux-completeness.md +16 -39
- package/governance/rules/writing/markdown.md +1 -1
- package/package.json +1 -1
- package/scripts/core/install-check.sh +1 -1
- package/src/claude/cases/authoring.ts +15 -3
- package/src/claude/cases/misc.ts +12 -0
- package/src/claude/cases/workflow.ts +19 -1
- package/src/claude/skills-audit.ts +113 -1
- package/src/cli/help.ts +0 -1
- package/src/cli.ts +0 -2
- package/src/commands/claude.ts +34 -11
- package/src/commands/demo.ts +1 -1
- package/src/commands/gov.ts +4 -0
- package/src/commands/init.ts +2 -2
- package/src/commands/markdown.ts +1 -1
- package/src/commands/migrate.ts +4 -0
- package/src/commands/pr.ts +30 -6
- package/src/commands/tasks.ts +383 -2
- package/src/commands/tooling.ts +18 -5
- package/src/context/audit.ts +1 -1
- package/src/demo/beats.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/gov/audit.ts +25 -4
- package/src/init/plan.ts +1 -8
- package/src/init/steps.ts +0 -8
- package/src/inventory/subjects.ts +1 -1
- package/src/markdown/scope.ts +49 -35
- package/src/migrate/record-layout.ts +1 -1
- package/src/migrate/scratch-evidence.ts +12 -4
- package/src/migrate/skill-names.ts +68 -21
- package/src/pr/frames.ts +14 -3
- package/src/records/backup.ts +3 -3
- package/src/records/validate.ts +31 -0
- package/src/roots/record.ts +17 -8
- package/src/tasks/board.ts +854 -0
- package/src/tasks/record.ts +20 -1
- package/src/tasks/validate.ts +206 -9
- package/src/tooling/inject.ts +26 -7
- package/src/tooling/package.ts +32 -0
- package/src/tooling/read.ts +46 -3
- package/src/tooling/scan.ts +8 -2
- package/tooling/astro/configs/card-src/pages/og-card.astro +1 -1
- package/tooling/astro/reference.md +64 -93
- package/tooling/base/configs/.github/workflows/phase-label-gate.yml +1 -1
- package/tooling/base/configs/scripts/verify.ts +1 -1
- package/tooling/base/reference.md +1 -9
- package/tooling/base/seeds/canon/context/{ci.md → development/ci.md} +1 -1
- package/tooling/base/seeds/canon/context/development/index.md +11 -0
- package/tooling/base/seeds/canon/context/{development.md → development/setup.md} +8 -12
- package/tooling/base/seeds/canon/context/index.md +1 -2
- package/tooling/claude/manifest.toml +1 -5
- package/tooling/claude/reference.md +36 -59
- package/tooling/claude/seeds/.claude/hooks/board-validate.sh +65 -0
- package/tooling/claude/seeds/.claude/hooks/index-reminder.sh +2 -7
- package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +2 -7
- package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +3 -10
- package/tooling/claude/seeds/.claude/hooks/search-reminder.sh +2 -7
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +2 -4
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/tooling/nextjs/reference.md +0 -6
- package/tooling/php/reference.md +0 -4
- package/tooling/web/configs/.github/workflows/verify.yml +28 -0
- package/tooling/web/configs/.oxlintrc.json +7 -0
- package/tooling/web/configs/e2e/capture-types.ts +35 -0
- package/tooling/web/configs/e2e/screenshot.ts +23 -72
- package/tooling/web/manifest.toml +1 -1
- package/tooling/web/reference.md +77 -124
- package/tooling/web/seeds/e2e/capture/cases.ts +47 -0
- package/src/commands/wiki.ts +0 -100
- package/src/wiki/init.ts +0 -85
- /package/claude/skills/{draft-figure → draw-figure}/references/figures.md +0 -0
- /package/claude/skills/{draft-slides → make-deck}/references/deck.md +0 -0
- /package/claude/skills/{draft-and-pick → pick-by-eye}/references/live-arms.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/agent-facing.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/application.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/cli.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/library.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/plugin.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/requirements.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/wiki.md +0 -0
|
@@ -1,31 +1,22 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce strict Python type hints,
|
|
2
|
+
description: Enforce strict Python type hints, exception handling, data shapes, and import patterns
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.py'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Python standards
|
|
8
8
|
|
|
9
|
-
## Casing conventions
|
|
10
|
-
|
|
11
|
-
- Use `snake_case` for modules, functions, variables, and methods.
|
|
12
|
-
- Use `PascalCase` for classes, type aliases, `TypeVar`, and `ParamSpec`.
|
|
13
|
-
- Use `UPPER_SNAKE_CASE` for module-level constants and environment variables.
|
|
14
|
-
- Use `_leading_underscore` for module-private names. Reserve `__dunder__` for the standard protocol.
|
|
15
|
-
|
|
16
9
|
## Type hints
|
|
17
10
|
|
|
18
|
-
- Annotate
|
|
19
|
-
- Use `X | None`
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- Do not use `Any`. Reach for `object` or `typing.cast` at boundaries instead.
|
|
11
|
+
- Annotate every public function and method, since a type checker skips the body of an unannotated function.
|
|
12
|
+
- Use `X | None`, `X | Y`, and built-in generics such as `list[str]` over `Optional`, `Union`, and `typing.List`.
|
|
13
|
+
- Do not add `from __future__ import annotations`. Python plans to deprecate and remove it.
|
|
14
|
+
- Use `typing.Protocol` for an interface a class satisfies by shape, over an abstract base class it must subclass.
|
|
15
|
+
- Type a value that can be anything as `object` and narrow it. Never use `Any`, which turns checking off.
|
|
24
16
|
|
|
25
17
|
## Errors
|
|
26
18
|
|
|
27
|
-
- Raise specific built-in
|
|
28
|
-
- Define a project-rooted exception hierarchy for domain errors.
|
|
19
|
+
- Raise a specific built-in exception or one from a project-rooted hierarchy, never bare `Exception`.
|
|
29
20
|
- Catch the narrowest exception class. Never use bare `except:`.
|
|
30
21
|
- Re-raise with `raise ... from err` to preserve the cause chain.
|
|
31
22
|
|
|
@@ -37,6 +28,6 @@ paths:
|
|
|
37
28
|
|
|
38
29
|
## Imports and modules
|
|
39
30
|
|
|
40
|
-
- Use absolute imports rooted at the package
|
|
31
|
+
- Use absolute imports rooted at the package over relative ones.
|
|
41
32
|
- Do not alias imports to shorten internal names. Ecosystem conventions (`numpy as np`, `pandas as pd`) are exceptions.
|
|
42
|
-
- Do not place executable code at module scope. Guard with `if __name__ == "__main__"
|
|
33
|
+
- Do not place executable code at module scope. Guard it with `if __name__ == "__main__":` and call a `main` function.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce strict TypeScript type safety and patterns
|
|
2
|
+
description: Enforce strict TypeScript type safety, declarations, and import patterns
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.ts'
|
|
5
5
|
- '**/*.tsx'
|
|
@@ -7,34 +7,24 @@ paths:
|
|
|
7
7
|
|
|
8
8
|
# TypeScript standards
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## File names
|
|
11
11
|
|
|
12
|
-
- Use `kebab-case` for filenames and directories.
|
|
13
|
-
- Use `camelCase` for variables, functions, and methods.
|
|
14
|
-
- Use `PascalCase` for types, interfaces, classes, and components.
|
|
15
|
-
- Use `UPPER_SNAKE_CASE` for constants and environment variables.
|
|
12
|
+
- Use `kebab-case` for filenames and directories, since a case-only difference resolves on macOS and fails on Linux.
|
|
16
13
|
|
|
17
14
|
## Type declarations
|
|
18
15
|
|
|
19
|
-
-
|
|
20
|
-
- Use `
|
|
21
|
-
- Use `
|
|
22
|
-
- Use `type` for unions, intersections, and utility types.
|
|
23
|
-
- Do not prefix interfaces with `I`.
|
|
24
|
-
- Use constant objects or union types instead of `enum`.
|
|
16
|
+
- Use `unknown` over `any`, and narrow it before use.
|
|
17
|
+
- Use `interface` for an object shape until it needs a feature only `type` has, such as a union or a mapped type.
|
|
18
|
+
- Use a constant object with `as const` or a union of literals instead of `enum`.
|
|
25
19
|
|
|
26
20
|
## Type safety
|
|
27
21
|
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
- Use built-in utility types (`Partial`, `Pick`, `Omit`) over manual type manipulation.
|
|
31
|
-
- Prefer `readonly` properties for data objects.
|
|
32
|
-
- Do not use non-null assertions.
|
|
33
|
-
- Use `Promise.all()` for independent async operations.
|
|
22
|
+
- Narrow with a type guard or a runtime check over a type assertion or a non-null `!`, neither of which checks at runtime.
|
|
23
|
+
- Run independent async operations through `Promise.all()` rather than awaiting each in turn.
|
|
34
24
|
|
|
35
25
|
## Imports and configuration
|
|
36
26
|
|
|
37
|
-
-
|
|
27
|
+
- Import through the `@/` alias where tsconfig.json and the bundler both map it to `src/`, over a `../../` chain.
|
|
38
28
|
- Import from the module's source file directly over barrel `index` re-exports.
|
|
39
29
|
- Use `import type` for type-only imports.
|
|
40
30
|
- Enable `strict: true` in tsconfig.json with no exceptions.
|
|
@@ -14,22 +14,22 @@ paths:
|
|
|
14
14
|
## Schema changes
|
|
15
15
|
|
|
16
16
|
- Express every schema change as a migration file committed to version control.
|
|
17
|
-
- Ship a
|
|
17
|
+
- Ship a way back with every schema migration, as a down step or a forward migration that reverses it.
|
|
18
18
|
- Never alter a deployed schema outside a migration.
|
|
19
19
|
- Never edit a migration that has run in a shared environment. Add a new one.
|
|
20
|
-
-
|
|
20
|
+
- Drop a column or table only after a deploy that stops reading and writing it.
|
|
21
21
|
|
|
22
22
|
## Query construction
|
|
23
23
|
|
|
24
24
|
- Pass every runtime value as a bound parameter.
|
|
25
25
|
- Never interpolate, concatenate, or format a value into a statement string.
|
|
26
|
-
-
|
|
26
|
+
- Map a table name, column, or sort direction through an allow-list, since none of them can be bound.
|
|
27
27
|
|
|
28
28
|
## Transactions
|
|
29
29
|
|
|
30
30
|
- Give each transaction one owner that opens it, commits it, and rolls it back.
|
|
31
|
-
- Never
|
|
32
|
-
- Keep network calls, queue publishes, and filesystem writes outside an open transaction.
|
|
31
|
+
- Never commit a transaction a function was handed. Take a savepoint, such as a nested `atomic`, for a partial rollback.
|
|
32
|
+
- Keep network calls, queue publishes, and filesystem writes outside an open transaction, running them after commit.
|
|
33
33
|
|
|
34
34
|
## Access patterns
|
|
35
35
|
|
|
@@ -8,13 +8,12 @@ paths:
|
|
|
8
8
|
|
|
9
9
|
## Waiting
|
|
10
10
|
|
|
11
|
-
- Settle on the condition a step waits for
|
|
11
|
+
- Settle on the condition a step waits for with a web-first assertion or `expect.poll`, never `page.waitForTimeout`.
|
|
12
12
|
- Reserve a fixed duration for an assertion that nothing happened across a window.
|
|
13
|
-
- Bound every settle with an explicit timeout.
|
|
13
|
+
- Bound every settle with an explicit timeout. `toPass` defaults to none and ignores the expect timeout.
|
|
14
14
|
- Do not raise a timeout to clear a failure that reproduces under load. Replace the wait with a settle.
|
|
15
|
-
- Do not read a value once after a pause. Poll it.
|
|
16
15
|
- Settle a smooth scroll on the `scrollend` event. Fall back to a stillness window only when the target was already in view.
|
|
17
|
-
- Run with
|
|
16
|
+
- Run with `reducedMotion: 'reduce'` unless the test asserts motion, and opt back in per test.
|
|
18
17
|
|
|
19
18
|
## Falsifiable guards
|
|
20
19
|
|
|
@@ -26,9 +25,8 @@ paths:
|
|
|
26
25
|
## Reproducing a failure that only appears in CI
|
|
27
26
|
|
|
28
27
|
- Reproduce under `Emulation.setCPUThrottlingRate` rather than by rerunning the gate.
|
|
29
|
-
- Read the state the assertion does not
|
|
28
|
+
- Read the failure's trace for the state the assertion does not read, such as which markers were set and which listeners fired.
|
|
30
29
|
- Vary the condition under suspicion deliberately. Do not compare counts across runs that differed in something uncontrolled.
|
|
31
|
-
- Read the check conclusion as its own act. A green diff review reports nothing about the gate.
|
|
32
30
|
|
|
33
31
|
## Authority
|
|
34
32
|
|
|
@@ -8,31 +8,29 @@ paths:
|
|
|
8
8
|
|
|
9
9
|
## Models
|
|
10
10
|
|
|
11
|
-
- Use `pydantic.BaseModel` over `dataclass` at I/O and API boundaries.
|
|
12
|
-
-
|
|
13
|
-
- Set `extra="forbid"` on
|
|
14
|
-
-
|
|
11
|
+
- Use `pydantic.BaseModel` over a standard library `dataclass` at I/O and API boundaries, since a `dataclass` validates nothing.
|
|
12
|
+
- On Pydantic 2, configure a model with `model_config = ConfigDict(...)`, never the deprecated nested `Config` class.
|
|
13
|
+
- Set `extra="forbid"` on a model receiving external input, since the default ignores an unknown key silently.
|
|
14
|
+
- Declare a constraint with `Field(...)`, such as `gt=0`, so validation enforces it rather than a docstring.
|
|
15
15
|
|
|
16
16
|
## Validation
|
|
17
17
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
- Use `@model_validator(mode="after")` for cross-field invariants.
|
|
18
|
+
- Validate an untrusted dict with `Model.model_validate(data)`, and a JSON string with `Model.model_validate_json(s)` rather than `json.loads` first.
|
|
19
|
+
- On Pydantic 2, write `@field_validator` and `@model_validator`, never the deprecated `@validator` or `@root_validator`.
|
|
20
|
+
- Check a cross-field invariant in `@model_validator(mode="after")`.
|
|
22
21
|
|
|
23
22
|
## Types
|
|
24
23
|
|
|
25
|
-
- Use `
|
|
26
|
-
- Use
|
|
27
|
-
-
|
|
24
|
+
- Use `SecretStr` for a credential, so its value stays out of logs and tracebacks.
|
|
25
|
+
- Use a constrained type such as `PositiveInt` or `EmailStr` over a hand-rolled regex.
|
|
26
|
+
- Share a constrained type as `Annotated[T, Field(...)]`.
|
|
27
|
+
- Never type a field `Any`, which allows any value including `None`. Use `JsonValue` or a union of concrete types.
|
|
28
28
|
|
|
29
29
|
## Settings
|
|
30
30
|
|
|
31
|
-
-
|
|
32
|
-
- Load environment through a single `Settings` model. Do not read `os.environ` directly elsewhere.
|
|
31
|
+
- Load environment through one `pydantic_settings.BaseSettings` model. Never read `os.environ` directly elsewhere.
|
|
33
32
|
|
|
34
33
|
## Serialization
|
|
35
34
|
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
- Use `by_alias=True` when serializing to external schemas with non-Python field names.
|
|
35
|
+
- On Pydantic 2, serialize with `model_dump(mode="json")` or `model_dump_json()`, never the deprecated `.dict()` or `.json()`.
|
|
36
|
+
- Pass `by_alias=True` when serializing to an external schema, since a dump ignores aliases by default.
|
|
@@ -19,7 +19,7 @@ paths:
|
|
|
19
19
|
|
|
20
20
|
## Credentials
|
|
21
21
|
|
|
22
|
-
- Hash passwords with
|
|
22
|
+
- Hash passwords with Argon2id, or scrypt or bcrypt where it is missing, and a per-password salt. Never store a reversible password.
|
|
23
23
|
- Compare tokens, signatures, and password hashes with a constant-time function.
|
|
24
24
|
- Expire and revoke sessions and refresh tokens on the server. Do not rely on client-side deletion.
|
|
25
25
|
|
|
@@ -27,7 +27,7 @@ paths:
|
|
|
27
27
|
|
|
28
28
|
- Read every secret from the environment or a secret manager at runtime.
|
|
29
29
|
- Never commit a secret, connection string, or private key to the repository.
|
|
30
|
-
- Never return a secret, connection string, or internal hostname in a response body.
|
|
30
|
+
- Never return a secret, connection string, stack trace, or internal hostname in a response body.
|
|
31
31
|
|
|
32
32
|
## Abuse limits
|
|
33
33
|
|
|
@@ -37,5 +37,5 @@ paths:
|
|
|
37
37
|
|
|
38
38
|
## Transport
|
|
39
39
|
|
|
40
|
-
- Serve every route over TLS
|
|
41
|
-
-
|
|
40
|
+
- Serve every route over TLS. Fail a plaintext API request rather than redirecting it.
|
|
41
|
+
- List CORS origins explicitly whenever credentials are allowed, since a wildcard is refused then. Never reflect the request origin.
|
|
@@ -9,24 +9,20 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
# Web security standards
|
|
11
11
|
|
|
12
|
-
## Link safety
|
|
13
|
-
|
|
14
|
-
- Add `rel="noopener noreferrer"` to all external links with `target="_blank"`.
|
|
15
|
-
|
|
16
12
|
## Content sanitization
|
|
17
13
|
|
|
18
|
-
- Sanitize
|
|
19
|
-
-
|
|
14
|
+
- Sanitize HTML with DOMPurify before passing it to `dangerouslySetInnerHTML`, `innerHTML`, or `set:html`. Never render it raw.
|
|
15
|
+
- Allow only `http:` and `https:` in a user-supplied URL before rendering it in `href` or `src`.
|
|
20
16
|
|
|
21
17
|
## Input validation
|
|
22
18
|
|
|
23
|
-
-
|
|
19
|
+
- Parse URL parameters and query strings through a schema before use.
|
|
24
20
|
|
|
25
21
|
## Storage and tokens
|
|
26
22
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
23
|
+
- Never store a session token, password, or personal data in `localStorage` or `sessionStorage`, which any script on the page can read.
|
|
24
|
+
- Keep an authentication token in an `HttpOnly` cookie, out of reach of JavaScript.
|
|
29
25
|
|
|
30
26
|
## Third-party scripts
|
|
31
27
|
|
|
32
|
-
-
|
|
28
|
+
- Pin a third-party script to a version and load it with an `integrity` hash.
|
|
@@ -9,24 +9,22 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
## Query conventions
|
|
11
11
|
|
|
12
|
-
- Define query
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
12
|
+
- Define a query's key and function together with `queryOptions()`, and reuse that object at every call site.
|
|
13
|
+
- Include every variable the query function reads in its query key.
|
|
14
|
+
- Set `staleTime` per query from how often its data changes, since the default treats cached data as stale at once.
|
|
15
|
+
- Throw from a query function on a response that is not `ok`, since `fetch` does not reject on an HTTP error.
|
|
16
16
|
|
|
17
17
|
## Mutations
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- Handle `onError` at the mutation site with user-facing feedback.
|
|
19
|
+
- Write data through `useMutation`, never by calling the API from an event handler and patching the cache.
|
|
20
|
+
- Invalidate the related query keys in `onSuccess` and return that promise. Reserve `setQueryData` for an optimistic update.
|
|
21
|
+
- Handle `onError` at the mutation site with feedback the user sees.
|
|
23
22
|
|
|
24
23
|
## Cache management
|
|
25
24
|
|
|
26
|
-
-
|
|
27
|
-
- Prefetch predictable navigations with `queryClient.prefetchQuery` at route boundaries.
|
|
25
|
+
- Prefetch a predictable navigation's data in its route loader.
|
|
28
26
|
|
|
29
27
|
## Separation of concerns
|
|
30
28
|
|
|
31
|
-
- Keep query
|
|
32
|
-
- Use the query `enabled` option for conditional
|
|
29
|
+
- Keep a query function a pure data fetcher with no UI logic or side effects, since a background refetch runs it again.
|
|
30
|
+
- Use the query `enabled` option for a conditional or dependent fetch, never `useEffect`.
|
|
@@ -9,9 +9,9 @@ paths:
|
|
|
9
9
|
## Selecting a run
|
|
10
10
|
|
|
11
11
|
- Narrow an end-to-end run by spec path or by test name. Never narrow it by engine.
|
|
12
|
-
- Run one named test while iterating on a behavior
|
|
13
|
-
- Run one surface while iterating on that surface
|
|
14
|
-
- Run `
|
|
12
|
+
- Run `playwright test -g '<name>'` for one named test while iterating on a behavior.
|
|
13
|
+
- Run `playwright test e2e/<area>.spec.ts` for one surface while iterating on that surface.
|
|
14
|
+
- Run `playwright test --only-changed` to select the specs a branch changed.
|
|
15
15
|
- Run the whole suite before pushing.
|
|
16
16
|
- Pass `--project` in a local run only to reproduce a failure that engine has already reported. The CI matrix passes it on every job, one engine per leg, which is the gate rather than a narrowed run.
|
|
17
17
|
- Do not add a script that pins a default run to one engine.
|
|
@@ -19,6 +19,6 @@ paths:
|
|
|
19
19
|
## Instruments
|
|
20
20
|
|
|
21
21
|
- Answer a question about the running page with a script against the dev server rather than with the suite.
|
|
22
|
-
- Do not enable `fullyParallel` in
|
|
22
|
+
- Do not enable `fullyParallel` in the Playwright config.
|
|
23
23
|
- Follow `.claude/rules/canon/ui/surface-capture.md` for capture scope.
|
|
24
24
|
- Follow `.claude/rules/canon/lib/e2e-reliability.md` for waits and guards.
|
|
@@ -13,7 +13,6 @@ paths:
|
|
|
13
13
|
## Framework
|
|
14
14
|
|
|
15
15
|
- Use the standard `testing` package. Do not add an assertion library for what `t.Errorf` and `t.Fatalf` already state.
|
|
16
|
-
- Place a test beside the code it tests, in a `_test.go` file of the same package.
|
|
17
16
|
- Use an external `<pkg>_test` package when a test should see only the exported API.
|
|
18
17
|
|
|
19
18
|
## Table-driven cases
|
|
@@ -24,7 +23,7 @@ paths:
|
|
|
24
23
|
## Helpers and setup
|
|
25
24
|
|
|
26
25
|
- Call `t.Helper()` first in every test helper.
|
|
27
|
-
- Use `t.Cleanup` over `defer` for teardown a helper registers.
|
|
26
|
+
- Use `t.Cleanup` over `defer` for teardown a helper registers, since a `defer` runs when the helper returns.
|
|
28
27
|
- Use `t.TempDir` and `t.Setenv` over hand-rolled temp directories or environment stashes.
|
|
29
28
|
- Use `net/http/httptest` over a real listener.
|
|
30
29
|
|
|
@@ -15,16 +15,15 @@ paths:
|
|
|
15
15
|
|
|
16
16
|
- Use PHPUnit for all tests.
|
|
17
17
|
- Declare each test class `final` and extend `PHPUnit\Framework\TestCase`.
|
|
18
|
-
- Place tests under `tests/`, mirroring the `src/` namespace layout, in files named `*Test.php`.
|
|
19
18
|
|
|
20
19
|
## Attributes
|
|
21
20
|
|
|
22
|
-
-
|
|
23
|
-
- Use a static data provider method for table-driven cases over per-case test methods.
|
|
21
|
+
- On PHPUnit 10 or later, use attributes (`#[Test]`, `#[DataProvider]`, `#[CoversClass]`) over docblock annotations, which PHPUnit 12 no longer reads.
|
|
22
|
+
- Use a `public static` data provider method for table-driven cases over per-case test methods.
|
|
24
23
|
|
|
25
24
|
## Assertions and doubles
|
|
26
25
|
|
|
27
|
-
- Use `assertSame` over `assertEquals
|
|
28
|
-
-
|
|
26
|
+
- Use `assertSame` over `assertEquals`, which compares with `==`.
|
|
27
|
+
- Call `expectException` before the throwing call, over `try` and `catch`, for an expected exception.
|
|
29
28
|
- Use `createStub` where no interaction is asserted. Reserve `createMock` for asserting a call.
|
|
30
29
|
- Do not make real network calls. Use a fake or a stubbed client.
|
|
@@ -10,35 +10,27 @@ paths:
|
|
|
10
10
|
|
|
11
11
|
## Framework
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
- Place tests under `tests/`, mirroring the `src/` package layout.
|
|
15
|
-
- Name files `test_*.py` and test functions `test_*`.
|
|
13
|
+
- Write tests as plain `pytest` functions, never `unittest.TestCase` subclasses, which lose fixtures and parametrization.
|
|
16
14
|
|
|
17
15
|
## Fixtures
|
|
18
16
|
|
|
19
|
-
-
|
|
20
|
-
- Place shared
|
|
21
|
-
-
|
|
22
|
-
- Use `tmp_path` and `monkeypatch` over hand-rolled temp directories or
|
|
17
|
+
- Write setup and teardown as a `@pytest.fixture` that yields, over setup and teardown methods.
|
|
18
|
+
- Place a shared fixture in the `conftest.py` of the narrowest directory whose tests need it.
|
|
19
|
+
- Widen a fixture's `scope=` past the `function` default only for state no test mutates.
|
|
20
|
+
- Use `tmp_path` and `monkeypatch` over hand-rolled temp directories or environment stashes, since both undo themselves.
|
|
23
21
|
|
|
24
22
|
## Parametrize
|
|
25
23
|
|
|
26
24
|
- Use `@pytest.mark.parametrize` for table-driven cases over per-case test functions.
|
|
27
|
-
- Use `ids=` to label parametrized cases when their repr is unclear.
|
|
28
25
|
|
|
29
26
|
## Async
|
|
30
27
|
|
|
31
|
-
- Mark async
|
|
32
|
-
-
|
|
28
|
+
- Mark each async test `@pytest.mark.asyncio`, or set `asyncio_mode = "auto"`, since strict mode runs only marked tests.
|
|
29
|
+
- Run on the event loop `pytest-asyncio` provides. Never call `asyncio.run()` or create a loop inside a test.
|
|
33
30
|
|
|
34
31
|
## Assertions and mocks
|
|
35
32
|
|
|
36
|
-
- Use plain `assert
|
|
37
|
-
- Use `pytest.raises(...)` over `try
|
|
38
|
-
-
|
|
39
|
-
- Do not make real network calls. Use `responses`, `
|
|
40
|
-
|
|
41
|
-
## Conventions
|
|
42
|
-
|
|
43
|
-
- Arrange, act, assert per test, with one logical assertion group.
|
|
44
|
-
- Use descriptive `test_*` names that read as the assertion. Do not prefix with `should_`.
|
|
33
|
+
- Use plain `assert`, which pytest rewrites to report the values, over `self.assertEqual`.
|
|
34
|
+
- Use `pytest.raises(...)` over `try` and `except` for an expected exception.
|
|
35
|
+
- Patch with `monkeypatch.setattr` or `unittest.mock.patch`, never by assigning a module attribute by hand.
|
|
36
|
+
- Do not make real network calls. Use `responses`, `pytest-httpx`, or a fake.
|
|
@@ -12,29 +12,20 @@ paths:
|
|
|
12
12
|
## Unit and integration
|
|
13
13
|
|
|
14
14
|
- Use Vitest for unit and integration tests.
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- Select elements by accessibility attributes first (`getByRole`, `getByLabelText`).
|
|
15
|
+
- Simulate interaction with `userEvent` over `fireEvent`, since it refuses what a browser would, such as a click on a hidden element.
|
|
16
|
+
- Mock the network with MSW. Never mock `fetch` or axios by hand, and never let a unit test make a real call.
|
|
17
|
+
- Query by role or label first, such as `getByRole` and `getByLabelText`, and by test ID only when neither matches.
|
|
19
18
|
|
|
20
19
|
## End-to-end
|
|
21
20
|
|
|
22
21
|
- Use Playwright for end-to-end tests.
|
|
23
|
-
- Place
|
|
24
|
-
- Never place Playwright tests inside `src/`.
|
|
25
|
-
- Scope the three rules above to tests the Playwright runner executes. A Vitest test importing a browser driver to exercise project code stays beside its module, where Vitest looks for it.
|
|
26
|
-
- Keep specs apart from their fixtures, page objects, and helpers inside `e2e/`. Load the `canon:codebase-layout` skill for the folder shape.
|
|
22
|
+
- Place every test the Playwright runner executes under `e2e/`, never `src/`. A Vitest test that drives a browser stays beside its module.
|
|
27
23
|
|
|
28
24
|
## Timers and async
|
|
29
25
|
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- Restore real timers with `vi.useRealTimers()` in a matching `afterEach`.
|
|
26
|
+
- Pass `advanceTimers: vi.advanceTimersByTime` to `userEvent.setup()` whenever fake timers are on.
|
|
27
|
+
- Restore real timers with `vi.useRealTimers()` in `afterEach`, after `vi.runOnlyPendingTimers()`.
|
|
33
28
|
|
|
34
29
|
## Conventions
|
|
35
30
|
|
|
36
|
-
-
|
|
37
|
-
- Use `.spec.ts` / `.spec.tsx` for integration tests and for Playwright tests under `e2e/`.
|
|
38
|
-
- Do not make real network calls in unit tests.
|
|
39
|
-
- `describe()` labels use the exact identifier of the subject under test in its natural casing.
|
|
40
|
-
- `it()` descriptions use "should" + sentence case.
|
|
31
|
+
- Name a unit test `.test.ts` or `.test.tsx`, and an integration or Playwright test `.spec.ts` or `.spec.tsx`.
|
|
@@ -9,17 +9,15 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
## Type inference
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
- Do not manually declare interfaces that duplicate Zod schemas.
|
|
14
|
-
- Do not export the runtime Schema if only the inferred Type is required by consumers.
|
|
12
|
+
- Derive a schema's type with `z.infer<typeof Schema>`, never a hand-written interface that duplicates the schema.
|
|
15
13
|
|
|
16
14
|
## Boundary validation
|
|
17
15
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
16
|
+
- Parse untrusted input with `z.strictObject()` so an unknown key fails, never with a method the Zod 4 changelog marks legacy.
|
|
17
|
+
- Narrow a schema with `.pick()` or `.omit()`, never by passing unknown keys through with `z.looseObject()`.
|
|
18
|
+
- Call `.parse()` where a failure should throw, and `.safeParse()` where the caller recovers, such as a form.
|
|
19
|
+
- Restrict `z.coerce` to string input at an I/O boundary such as URL params, since it converts with `String()` or `Boolean()`.
|
|
21
20
|
|
|
22
21
|
## Schema safety
|
|
23
22
|
|
|
24
|
-
- Use `z.unknown()` for
|
|
25
|
-
- Prefer `.strict()` at boundaries or explicit `.pick()`/`.omit()` over `.passthrough()`.
|
|
23
|
+
- Use `z.unknown()` for an input of unknown shape, never `z.any()`, which infers `any` and switches off checking downstream.
|
|
@@ -16,14 +16,12 @@ paths:
|
|
|
16
16
|
- Write a comment only when it records a fact the reader cannot recover from the code: an external contract, a rejected alternative, or the reason a surprising line is correct.
|
|
17
17
|
- Do not restate in prose what the line beside it already says.
|
|
18
18
|
- Do not comment a self-contained function whose signature and body already carry its behavior.
|
|
19
|
-
-
|
|
20
|
-
- Do not add or delete a comment to move a file toward a density figure.
|
|
19
|
+
- Do not add or delete a comment to move a file toward a density figure, since density follows how much of its behavior is decided outside it.
|
|
21
20
|
|
|
22
21
|
## What a comment may claim
|
|
23
22
|
|
|
24
|
-
-
|
|
23
|
+
- Keep each comment true of the code as written, and update or delete one a change invalidates in that same change.
|
|
25
24
|
- Describe a function's contract and its constraints, never its steps line by line.
|
|
26
|
-
- Update or delete an invalidated comment in the same change that invalidates it.
|
|
27
25
|
- Do not name a person, a ticket, or a date in place of the fact itself.
|
|
28
26
|
|
|
29
27
|
## What never goes in a comment
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Keep comments
|
|
2
|
+
description: Keep comments in dotfiles, config, and workflow files to what a key does or accepts
|
|
3
3
|
paths:
|
|
4
4
|
- '**/.env*'
|
|
5
5
|
- '**/.gitignore'
|
|
@@ -16,7 +16,4 @@ paths:
|
|
|
16
16
|
|
|
17
17
|
## Comments
|
|
18
18
|
|
|
19
|
-
- Keep each comment to one short line. Do not wrap a single key in a multi-line explanation.
|
|
20
|
-
- Prefer a one-word category label over a sentence for a group header.
|
|
21
|
-
- Match the comment density of the surrounding file. Do not add a verbose comment next to terse ones.
|
|
22
19
|
- Comment what a key does or its allowed values. Do not restate the key name.
|
|
@@ -15,7 +15,7 @@ paths:
|
|
|
15
15
|
## Declaration
|
|
16
16
|
|
|
17
17
|
- Declare a package in the project manifest before importing it anywhere in the source.
|
|
18
|
-
- Add a package with the
|
|
18
|
+
- Add a package with the command that writes the manifest and the lockfile together, such as `bun add` or `uv add`. Re-lock in the same change after any hand edit to the manifest.
|
|
19
19
|
- Commit the lockfile with the manifest change in the same commit.
|
|
20
20
|
- Declare a package used only by tests, builds, or tooling as a development dependency.
|
|
21
21
|
- Never import a package that arrives only as a transitive dependency of another package.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Semantics, text alternatives, contrast, and reflow for rendered UI
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.tsx'
|
|
5
5
|
- '**/*.jsx'
|
|
@@ -8,56 +8,27 @@ paths:
|
|
|
8
8
|
- '**/*.css'
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
# Accessibility
|
|
11
|
+
# Accessibility standards
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Semantics
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
15
|
+
- Use a native `<button>` or `<a>` over a `<div>` or `<span>` carrying a click handler, since the native element brings its role, focus, and keyboard activation.
|
|
16
|
+
- 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
|
+
- 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
|
+
- Give an interactive element with no visible text label a name through `aria-label` or `aria-labelledby`.
|
|
18
19
|
|
|
19
|
-
##
|
|
20
|
+
## Text alternatives
|
|
20
21
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- Space: activates buttons and checkboxes, toggles selection in listboxes.
|
|
24
|
-
- Arrow keys: navigate within composite widgets. Do not let them exit the widget.
|
|
25
|
-
- Escape: closes any overlay, popover, dialog, or dropdown. Cancels in-progress edits.
|
|
26
|
-
- Do not introduce non-standard key bindings for common actions.
|
|
27
|
-
- Give every author-defined drag a single-pointer alternative and a keyboard path, such as move buttons or arrow-key reordering (WCAG 2.2 Dragging Movements, 2.5.7).
|
|
22
|
+
- Give every `<img>` an `alt`, and use `alt=""` for a decorative image.
|
|
23
|
+
- Describe what an image means, or the action an icon control takes, never its appearance. Do not prefix it with "Image of" or "Photo of".
|
|
28
24
|
|
|
29
|
-
##
|
|
25
|
+
## Contrast and color
|
|
30
26
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
## Composite widgets
|
|
35
|
-
|
|
36
|
-
- Roving tabindex for interactive collections: one item in the tab sequence at a time.
|
|
37
|
-
- Combobox: arrow keys navigate options, Enter selects, Escape closes, typing filters.
|
|
38
|
-
|
|
39
|
-
## Focus management
|
|
40
|
-
|
|
41
|
-
- Move focus into any overlay, popover, or dialog on open. Return focus to the trigger on close.
|
|
42
|
-
- Never move focus on hover. Only on keyboard input or explicit pointer activation.
|
|
43
|
-
- Do not let a sticky header, footer, or overlay fully cover the focused control. Scroll it into view clear of them (WCAG 2.2 Focus Not Obscured, 2.4.11).
|
|
44
|
-
|
|
45
|
-
## ARIA semantics
|
|
46
|
-
|
|
47
|
-
- Use semantic HTML over custom elements: `<button>` over a `<div>` carrying a click handler, `<a>` over a `<span>` carrying one.
|
|
48
|
-
- A `<div>` with a click handler requires a role, a tab index, and keyboard handlers. Use `<button>` instead.
|
|
49
|
-
- Spell an attribute the way the file's syntax spells it: `onclick` and `tabindex` in HTML and Astro markup, `onClick` and `tabIndex` in JSX.
|
|
50
|
-
- Set role on custom controls: `role="combobox"`, `role="listbox"`, `role="menu"`, `role="option"`.
|
|
51
|
-
- Synchronize state attributes with visual state: `aria-expanded`, `aria-selected`, `aria-checked`, `aria-disabled`.
|
|
52
|
-
- Add `aria-label` or `aria-labelledby` to interactive elements with no visible text label.
|
|
53
|
-
- Always provide `alt` on `<img>`. Use `alt=""` for decorative images.
|
|
54
|
-
- Describe the content or function of the image, not its appearance. Do not prefix with "Image of" or "Photo of".
|
|
55
|
-
- Alt text for functional images (icons, buttons) should describe the action, not the graphic.
|
|
56
|
-
- Give the visual boundary of a control and every graphic that carries meaning at least 3:1 contrast against adjacent colors (WCAG Non-text Contrast, 1.4.11).
|
|
57
|
-
- Never make color the only carrier of a state, error, or distinction. Pair it with text, an icon, or a pattern (WCAG Use of Color, 1.4.1).
|
|
27
|
+
- 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
|
+
- 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).
|
|
58
29
|
|
|
59
30
|
## Reflow
|
|
60
31
|
|
|
61
|
-
- Let content reflow at
|
|
62
|
-
- Treat 320 as
|
|
63
|
-
- Hold the same 320 floor for the content region beside persistent chrome a person can resize.
|
|
32
|
+
- Let content reflow at 320 CSS pixels wide with no loss and no two-dimensional scrolling, except a data table, map, or diagram (WCAG 1.4.10).
|
|
33
|
+
- Treat 320 as a 1280 pixel window at 400 percent zoom rather than a device width, so a layout breaking there breaks for a person who zooms.
|
|
34
|
+
- Hold the same 320 floor for the content region beside persistent chrome a person can resize. This extends the criterion, which measures the viewport alone.
|