@erclx/canon 5.44.0 → 5.46.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/api-design/REQUIREMENT.md +15 -31
- package/claude/skills/auto-ship/REQUIREMENT.md +14 -25
- package/claude/skills/backlog-triage/REQUIREMENT.md +12 -23
- package/claude/skills/build-in-slices/REQUIREMENT.md +15 -25
- package/claude/skills/canon-cli/REQUIREMENT.md +15 -27
- package/claude/skills/canon-cli/SKILL.md +0 -1
- package/claude/skills/canon-feedback/REQUIREMENT.md +10 -18
- package/claude/skills/canon-feedback-triage/REQUIREMENT.md +10 -15
- package/claude/skills/canvas-board/REQUIREMENT.md +14 -28
- package/claude/skills/ci-workflow/REQUIREMENT.md +12 -21
- package/claude/skills/code-craft/REQUIREMENT.md +14 -28
- package/claude/skills/codebase-layout/REQUIREMENT.md +14 -31
- package/claude/skills/context-fold/REQUIREMENT.md +15 -39
- package/claude/skills/context-fold/references/context.md +3 -3
- package/claude/skills/create-rule/REQUIREMENT.md +10 -24
- package/claude/skills/create-rule/SKILL.md +3 -0
- package/claude/skills/create-skill/REQUIREMENT.md +10 -21
- package/claude/skills/decision-escalate/REQUIREMENT.md +12 -24
- package/claude/skills/deploy-app/REQUIREMENT.md +12 -22
- package/claude/skills/deprecation-migration/REQUIREMENT.md +14 -42
- package/claude/skills/design-identity/REQUIREMENT.md +14 -20
- package/claude/skills/design-taste/REQUIREMENT.md +16 -57
- package/claude/skills/docs-sync/REQUIREMENT.md +14 -23
- package/claude/skills/document-health/REQUIREMENT.md +15 -29
- package/claude/skills/document-health/SKILL.md +2 -2
- package/claude/skills/document-repair/REQUIREMENT.md +32 -0
- package/claude/skills/document-repair/SKILL.md +76 -0
- package/claude/skills/document-repair/references/batches.md +44 -0
- package/claude/skills/draft-and-pick/REQUIREMENT.md +4 -3
- package/claude/skills/draft-doc/REQUIREMENT.md +4 -3
- package/claude/skills/draft-figure/REQUIREMENT.md +4 -3
- package/claude/skills/draft-identity/REQUIREMENT.md +4 -3
- package/claude/skills/draft-ready/REQUIREMENT.md +4 -3
- package/claude/skills/draft-screencast/REQUIREMENT.md +4 -3
- package/claude/skills/draft-slides/REQUIREMENT.md +4 -3
- package/claude/skills/draw-figure/REQUIREMENT.md +15 -39
- package/claude/skills/git-branch/REQUIREMENT.md +12 -26
- package/claude/skills/git-commit/REQUIREMENT.md +11 -15
- package/claude/skills/git-followup/REQUIREMENT.md +11 -22
- package/claude/skills/git-issue/REQUIREMENT.md +9 -15
- package/claude/skills/git-pr/REQUIREMENT.md +13 -32
- package/claude/skills/git-pr/SKILL.md +10 -2
- package/claude/skills/git-pr/references/closing-issues.md +47 -0
- package/claude/skills/git-pr/references/pr.md +4 -0
- package/claude/skills/git-ship/REQUIREMENT.md +13 -26
- package/claude/skills/git-split/REQUIREMENT.md +10 -17
- package/claude/skills/git-stage/REQUIREMENT.md +12 -18
- package/claude/skills/git-worktree/REQUIREMENT.md +15 -19
- package/claude/skills/make-deck/REQUIREMENT.md +13 -21
- package/claude/skills/markdown-craft/REQUIREMENT.md +9 -3
- package/claude/skills/pick-by-eye/REQUIREMENT.md +17 -67
- package/claude/skills/plan-feature/REQUIREMENT.md +15 -24
- package/claude/skills/plan-groundwork/REQUIREMENT.md +12 -28
- package/claude/skills/plan-groundwork/SKILL.md +5 -2
- package/claude/skills/plan-groundwork/references/output.md +47 -1
- package/claude/skills/plan-intake/REQUIREMENT.md +11 -26
- package/claude/skills/plan-intake/references/intake.md +2 -2
- package/claude/skills/plan-intake-answer/REQUIREMENT.md +14 -29
- package/claude/skills/plan-intake-answer/SKILL.md +7 -1
- package/claude/skills/plan-ready/REQUIREMENT.md +17 -36
- package/claude/skills/pr-evidence/REQUIREMENT.md +11 -17
- package/claude/skills/read-frames/REQUIREMENT.md +3 -8
- package/claude/skills/record-screencast/REQUIREMENT.md +14 -17
- package/claude/skills/review-address/REQUIREMENT.md +14 -38
- package/claude/skills/review-craft/REQUIREMENT.md +14 -32
- package/claude/skills/review-pr/REQUIREMENT.md +15 -34
- package/claude/skills/review-ui/REQUIREMENT.md +14 -39
- package/claude/skills/role-orchestrator/REQUIREMENT.md +16 -99
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +5 -0
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +9 -0
- package/claude/skills/role-planner/REQUIREMENT.md +15 -73
- package/claude/skills/role-reviewer/REQUIREMENT.md +15 -65
- package/claude/skills/role-reviewer/SKILL.md +5 -1
- package/claude/skills/role-worker/REQUIREMENT.md +13 -41
- package/claude/skills/role-worker/SKILL.md +2 -0
- package/claude/skills/script-screencast/REQUIREMENT.md +10 -16
- package/claude/skills/search-craft/REQUIREMENT.md +12 -36
- package/claude/skills/search-craft/SKILL.md +1 -1
- package/claude/skills/search-craft/references/adopted.md +2 -2
- package/claude/skills/session-compact/REQUIREMENT.md +13 -23
- package/claude/skills/session-map/REQUIREMENT.md +13 -29
- package/claude/skills/session-relay/REQUIREMENT.md +14 -58
- package/claude/skills/session-relay/SKILL.md +6 -0
- package/claude/skills/session-resume/REQUIREMENT.md +13 -27
- package/claude/skills/session-worktree/REQUIREMENT.md +14 -43
- package/claude/skills/systematic-debugging/REQUIREMENT.md +13 -34
- package/claude/skills/target-check/REQUIREMENT.md +16 -23
- package/claude/skills/target-setup/REQUIREMENT.md +11 -34
- package/claude/skills/target-setup/SKILL.md +2 -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/REQUIREMENT.md +13 -22
- package/claude/skills/task-board/SKILL.md +7 -0
- package/claude/skills/task-board/references/tasks.md +1 -1
- package/claude/skills/task-complete/REQUIREMENT.md +11 -24
- package/claude/skills/task-complete/references/archive.md +1 -0
- package/claude/skills/teach-workspace/REQUIREMENT.md +14 -45
- package/claude/skills/teach-workspace/references/promotion.md +5 -5
- package/claude/skills/test-craft/REQUIREMENT.md +15 -46
- package/claude/skills/test-first/REQUIREMENT.md +14 -20
- package/claude/skills/ui-checklist/REQUIREMENT.md +14 -29
- package/claude/skills/ux-audit/REQUIREMENT.md +3 -7
- package/claude/skills/ux-measure/REQUIREMENT.md +14 -28
- package/claude/skills/video-craft/REQUIREMENT.md +14 -27
- package/claude/skills/write-doc/REQUIREMENT.md +14 -24
- package/claude/skills/write-human/REQUIREMENT.md +15 -27
- package/claude/skills/youtube-transcripts/REQUIREMENT.md +9 -15
- package/docs/agents/context-audit.md +19 -12
- package/docs/agents/install-and-sync.md +2 -2
- package/docs/agents/markdown-audit.md +15 -10
- package/docs/agents/output-shape.md +1 -2
- package/docs/target/migrations.md +18 -0
- package/docs/target/projects.md +3 -2
- package/docs/target/scenarios.md +4 -1
- package/docs/workflow/skill-map-on-request.md +1 -1
- package/docs/workflow/skill-map.md +6 -5
- package/governance/detect.toml +4 -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/renames.toml +0 -2
- package/governance/rules/claude/output.md +5 -1
- package/governance/rules/code/routing.md +5 -1
- 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/stacks/base.toml +0 -1
- package/package.json +1 -1
- package/scripts/core/install-check.sh +1 -1
- package/src/claude/cases/workflow.ts +12 -0
- package/src/cli/help.ts +0 -1
- package/src/cli.ts +0 -2
- package/src/commands/context.ts +57 -3
- package/src/commands/gov.ts +4 -0
- package/src/commands/init.ts +2 -2
- package/src/commands/labels.ts +83 -3
- package/src/commands/markdown.ts +188 -21
- package/src/commands/sessions.ts +36 -3
- package/src/commands/tasks.ts +180 -0
- package/src/commands/tooling.ts +18 -5
- package/src/commands/worktrees.ts +2 -0
- package/src/context/coverage.ts +210 -0
- package/src/context/gate.ts +12 -3
- package/src/design/components.ts +1 -1
- package/src/gate/stages.ts +1 -1
- package/src/gov/audit.ts +22 -2
- package/src/init/plan.ts +1 -8
- package/src/init/steps.ts +44 -7
- package/src/intake/items.ts +14 -0
- package/src/inventory/subjects.ts +1 -1
- package/src/labels/closing.ts +46 -0
- package/src/markdown/gated.ts +250 -0
- package/src/markdown/scope.ts +119 -2
- package/src/migrate/rename.ts +6 -0
- package/src/migrate/scratch-evidence.ts +12 -4
- package/src/records/backup.ts +3 -3
- package/src/records/validate.ts +3 -3
- package/src/roots/record.ts +17 -8
- package/src/sessions/claim.ts +7 -0
- package/src/sessions/live.ts +53 -6
- package/src/sessions/registry.ts +11 -0
- package/src/sessions/resolve.ts +32 -5
- package/src/tasks/closes.ts +136 -0
- package/src/tasks/record.ts +1 -1
- 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/src/worktrees/reclaim.ts +16 -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 +2 -2
- 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 +1 -1
- 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.md +2 -2
- 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/governance/rules/canon/task-scope.md +0 -12
- package/src/commands/wiki.ts +0 -100
- package/src/wiki/init.ts +0 -85
|
@@ -22,18 +22,25 @@ canon context audit tooling/base/seeds --gate
|
|
|
22
22
|
|
|
23
23
|
## Output
|
|
24
24
|
|
|
25
|
-
| Check | Reports
|
|
26
|
-
| ------------------- |
|
|
27
|
-
| Citations | A path into an audited folder that resolves nowhere
|
|
28
|
-
| Requirements record | Words past the cap the record states as `This record holds at most 600 words.`
|
|
29
|
-
| Required sections | An entry missing `Overview` or `Layout`. A split folder answers by any sibling
|
|
30
|
-
| Closed set | An H2 outside `Overview`, `Layout`, and `Gotchas`, under `extraSections`
|
|
31
|
-
| Shape | `retired-section`, `gotcha-count`, `gotcha-heading`, `gotcha-paragraph`, `layout-heading`, `layout-bullets`, `layout-paragraphs`, `layout-depth`
|
|
32
|
-
| Index drift | An entry its index does not link, or a link resolving to nothing
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
25
|
+
| Check | Reports | Reaches | Finding |
|
|
26
|
+
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ----------------------------------------------------------- |
|
|
27
|
+
| Citations | A path into an audited folder that resolves nowhere | Every audited folder | Gates always |
|
|
28
|
+
| Requirements record | Words past the cap the record states as `This record holds at most 600 words.` | `canon/REQUIREMENTS.md` | Gates past a stated cap, never under `--citations-only` |
|
|
29
|
+
| Required sections | An entry missing `Overview` or `Layout`. A split folder answers by any sibling | `canon/context/` | Gates under `--gate` |
|
|
30
|
+
| Closed set | An H2 outside `Overview`, `Layout`, and `Gotchas`, under `extraSections` | `canon/context/` | Gates under `--gate` |
|
|
31
|
+
| Shape | `retired-section`, `gotcha-count`, `gotcha-heading`, `gotcha-paragraph`, `layout-heading`, `layout-bullets`, `layout-paragraphs`, `layout-depth` | `canon/context/` | Gates under `--gate` in a `SHAPE_GATED_FOLDERS` folder only |
|
|
32
|
+
| Index drift | An entry its index does not link, or a link resolving to nothing | Every audited folder | Gates under `--gate` |
|
|
33
|
+
| Coverage | A folder directly under a code root that no Layout names, one with a Layout H3 in two entries, and a declared root matching nothing, under `coverage` | `canon/context/` | Gates under `--gate`, never under `--citations-only` |
|
|
34
|
+
| Reference form | A backticked bare filename matching a sibling entry, under `bareReferences` | Split folders | Reports |
|
|
35
|
+
| Length | An entry past about 150 rendered lines at 80 columns, with its `causes` | Every audited folder | Reports |
|
|
36
|
+
| Tables | Six or more body rows whose first column mostly carries a path, command, or link | Every audited folder | Reports |
|
|
37
|
+
| Provenance | A date, change number, or release label. A date after measured, verified, driven, passed, or fired is excluded | `canon/context/` | Reports |
|
|
38
|
+
|
|
39
|
+
The coverage roots come from `roots` in `canon/config/context.toml`, a list of folders or globs such as `packages/*/src`.
|
|
40
|
+
|
|
41
|
+
- Without the file the root defaults to `src` when that folder exists, and `roots = []` opts out
|
|
42
|
+
- A file that is not valid TOML, or holds no list of strings under `roots`, gates under `--gate`
|
|
43
|
+
- With no declaration and no `src/`, the audit reports no code root and never gates
|
|
37
44
|
|
|
38
45
|
A shape break is any of these:
|
|
39
46
|
|
|
@@ -9,9 +9,9 @@ What each verb writes, refuses, and leaves alone. `canon --help` lists flags.
|
|
|
9
9
|
|
|
10
10
|
## Bootstrap
|
|
11
11
|
|
|
12
|
-
`canon init [path]` installs up to
|
|
12
|
+
`canon init [path]` installs up to four core domains and reports each independently. A failed domain does not abort the run, which finishes the rest and exits 1 naming the failures.
|
|
13
13
|
|
|
14
|
-
Any flag skips the confirmation prompt, but the `base` default of `--stack` does not count, so a bare `canon init` still prompts. `--skip` takes `
|
|
14
|
+
Any flag skips the confirmation prompt, but the `base` default of `--stack` does not count, so a bare `canon init` still prompts. `--skip` takes `governance` and `records`, and warns on any other value.
|
|
15
15
|
|
|
16
16
|
## Governance install
|
|
17
17
|
|
|
@@ -22,14 +22,14 @@ An argument is a file, a directory, or a glob, taken against the corpus git list
|
|
|
22
22
|
|
|
23
23
|
The ban set and checkpoints ship in `src/markdown/bans.ts` and `src/markdown/structure.ts`. `markdown.md` states each rule and the `write-human` skill states the cadence numbers, so move a number in both places in one change.
|
|
24
24
|
|
|
25
|
-
| Finding | Reports | Gates
|
|
26
|
-
| --------------- | ------------------------------------------------------------------------------------ |
|
|
27
|
-
| Bans | The two characters `markdown.md` bans, outside frontmatter, fences, spans, and links | Always
|
|
28
|
-
| Links | A relative link resolving to nothing on disk | Always
|
|
29
|
-
| Density | The six limits below, under `density` | On a
|
|
30
|
-
| Reference shape | A `kind: reference` page breaking its shape, under `referenceShape` | On a
|
|
31
|
-
| Colons | A colon followed by more text in a prose line, under `colons` | Never
|
|
32
|
-
| Heading case | A capital after the first word of a heading or `title`, under `headingCase` | Never
|
|
25
|
+
| Finding | Reports | Gates |
|
|
26
|
+
| --------------- | ------------------------------------------------------------------------------------ | ----------------- |
|
|
27
|
+
| Bans | The two characters `markdown.md` bans, outside frontmatter, fences, spans, and links | Always |
|
|
28
|
+
| Links | A relative link resolving to nothing on disk | Always |
|
|
29
|
+
| Density | The six limits below, under `density` | On a gated prefix |
|
|
30
|
+
| Reference shape | A `kind: reference` page breaking its shape, under `referenceShape` | On a gated prefix |
|
|
31
|
+
| Colons | A colon followed by more text in a prose line, under `colons` | Never |
|
|
32
|
+
| Heading case | A capital after the first word of a heading or `title`, under `headingCase` | Never |
|
|
33
33
|
|
|
34
34
|
A page marked `kind: reference` holds its opening, then `Output`, `Refusals`, and `See also` as H2s, each at most once and in that order. It takes no H3 and no table headed `Flag` or `Option`. An unmarked page is never measured.
|
|
35
35
|
|
|
@@ -46,9 +46,14 @@ A page marked `kind: reference` holds its opening, then `Output`, `Refusals`, an
|
|
|
46
46
|
- A table, fence, list, heading, or bold section marker ends a run of paragraphs
|
|
47
47
|
- A run whose every item opens with a bold label or a link is exempt, and numbered items never count
|
|
48
48
|
- Only context entries, docs, skill bodies, references, and requirements, tooling seeds and stack references, the wiki, `README.md`, and `CONTRIBUTING.md` take a finding
|
|
49
|
-
- A
|
|
49
|
+
- A requirement gates only once the gated list below names its own file, never through its skill's prefix and never on a bullet run alone
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
| Root | A density or reference shape finding gates |
|
|
52
|
+
| ----------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
53
|
+
| Canon's checkout | Under a `GATED_PATHS` prefix in `src/markdown/scope.ts`, and a bullet run on every density path above |
|
|
54
|
+
| Any other project | Under a prefix `canon/config/markdown.toml` lists, a bullet run included. With no such file nothing gates. |
|
|
55
|
+
|
|
56
|
+
A project's list grows through `canon markdown gated add <prefix>`, which appends a folder only once it carries no finding, and `canon init` starts a new project with every root that passes already listed. A config that does not parse refuses the audit with its path named.
|
|
52
57
|
|
|
53
58
|
Five measures report and never set the exit code on their own.
|
|
54
59
|
|
|
@@ -62,14 +62,13 @@ Discover names at runtime rather than hardcoding them.
|
|
|
62
62
|
Set `CANON_NON_INTERACTIVE=1` to refuse every prompt.
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
CANON_NON_INTERACTIVE=1 canon init --stack node --skip
|
|
65
|
+
CANON_NON_INTERACTIVE=1 canon init --stack node --skip records /path/to/project
|
|
66
66
|
CANON_NON_INTERACTIVE=1 canon sync /path/to/project
|
|
67
67
|
CANON_NON_INTERACTIVE=1 canon gov install node --add astro,shadcn /path/to/project
|
|
68
68
|
CANON_NON_INTERACTIVE=1 canon gov sync /path/to/project
|
|
69
69
|
CANON_NON_INTERACTIVE=1 canon gov build /path/to/project
|
|
70
70
|
CANON_NON_INTERACTIVE=1 canon tooling diff astro /path/to/project
|
|
71
71
|
CANON_NON_INTERACTIVE=1 canon tooling sync astro /path/to/project --write
|
|
72
|
-
CANON_NON_INTERACTIVE=1 canon wiki init /path/to/project
|
|
73
72
|
canon tooling inject base /path/to/project --configs --seeds
|
|
74
73
|
canon tooling prune-gitignore base /path/to/project
|
|
75
74
|
canon tooling verify vite-react
|
|
@@ -160,3 +160,21 @@ canon migrate session-defaults --write --json
|
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
The verb only adds a key that is absent. A person who wants auto memory back sets it in their own `.claude/settings.local.json`.
|
|
163
|
+
|
|
164
|
+
## Move the capture cases out of the harness, once
|
|
165
|
+
|
|
166
|
+
A web project's `e2e/screenshot.ts` is a config, so sync overwrites it. It now loads `CASES` from a seeded `e2e/capture/cases.ts` that sync copies once and never overwrites. Cases edited in the old harness leave the working tree on the first sync and stay in git history.
|
|
167
|
+
|
|
168
|
+
- Copy your cases from the old `e2e/screenshot.ts` into `e2e/capture/cases.ts` before the next sync.
|
|
169
|
+
- 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.
|
|
170
|
+
- A run from a folder with no `e2e/capture/cases.ts` exits 1 and names the file.
|
|
171
|
+
|
|
172
|
+
## Add the keyboard rule beside a held a11y rule, once
|
|
173
|
+
|
|
174
|
+
The `a11y` rule split in two. Focus styles, Escape and shortcuts, composite widgets, focus management, and pointer target size moved to a new `keyboard` rule. `canon gov sync` refreshes only the rules a project holds, so it rewrites `a11y.md` without those bullets and never adds `keyboard.md`.
|
|
175
|
+
|
|
176
|
+
A project holding `.claude/rules/canon/ui/a11y.md` adds the new rule alone:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
canon gov install --add keyboard --yes .
|
|
180
|
+
```
|
package/docs/target/projects.md
CHANGED
|
@@ -70,10 +70,11 @@ The default is `base`. Escalate only for a project writing code, and `target-set
|
|
|
70
70
|
|
|
71
71
|
### Core domains and skips
|
|
72
72
|
|
|
73
|
-
`canon init` installs base tooling, the Claude workflow, and governance
|
|
73
|
+
`canon init` installs base tooling, the Claude workflow, and governance. Pass `--stack <name>` for a language stack.
|
|
74
|
+
|
|
75
|
+
Init then lists each markdown root that already passes the density limits in `canon/config/markdown.toml`, so those folders fail a push from the start. A root carrying a finding is named and left out, and `canon:document-repair` brings it to zero later. An existing config is kept as it is.
|
|
74
76
|
|
|
75
77
|
- `--skip governance` leaves `.claude/rules/` empty. The run prints the `canon gov install <stack> <path>` command that restores the rules it dropped.
|
|
76
|
-
- `--skip wiki` skips the `.claude/wiki/` scaffold. A root `wiki/` is kept.
|
|
77
78
|
|
|
78
79
|
## Add a domain later
|
|
79
80
|
|
package/docs/target/scenarios.md
CHANGED
|
@@ -42,4 +42,7 @@ canon tooling sync python ./backend --skip base --write
|
|
|
42
42
|
|
|
43
43
|
`--skip base` keeps husky, oxfmt, commitlint, and CI at the root. Every subtree still receives `scripts/verify.ts` and `scripts/verify.json`, and its own framework configs.
|
|
44
44
|
|
|
45
|
-
A sync into a subfolder withholds `.github/`, so run the subtree from the root workflow with `working-directory` set to the path the sync prints.
|
|
45
|
+
A sync into a subfolder withholds `.github/`, so run the subtree from the root workflow with `working-directory` set to the path the sync prints. Run `bun scripts/verify.ts` in the subtree, since the `check` script lives at the root.
|
|
46
|
+
|
|
47
|
+
- A subtree with no `package.json` gets a minimal one holding the folder's name, version `0.0.0`, and `type: module`, then the install runs into it
|
|
48
|
+
- An existing file is never rewritten, and one that is not valid JSON ends the sync on `package.json is not valid JSON: fix it in <path>, then sync again`
|
|
@@ -40,4 +40,4 @@ These skills serve a request rather than a moment. With the [skill map](skill-ma
|
|
|
40
40
|
| `canon:markdown-craft` | Before a substantial markdown edit |
|
|
41
41
|
| `canon:write-human` | Before drafting or revising prose |
|
|
42
42
|
|
|
43
|
-
Ask `canon:teach-workspace` to promote a learning workspace's reference pages and glossaries. It proposes a destination per page and waits. An Anthropic-owned subject goes to the wiki, an internal one to the matching context entry, and the rest to the public docs. A project with no wiki folder gets a refusal naming
|
|
43
|
+
Ask `canon:teach-workspace` to promote a learning workspace's reference pages and glossaries. It proposes a destination per page and waits. An Anthropic-owned subject goes to the wiki, an internal one to the matching context entry, and the rest to the public docs. A project with no wiki folder gets a refusal naming the folder to create.
|
|
@@ -99,8 +99,9 @@ Groups run in the order a project meets them. Every name `canon claude skills li
|
|
|
99
99
|
|
|
100
100
|
## Keep the project current with the toolkit
|
|
101
101
|
|
|
102
|
-
| Skill | When to use
|
|
103
|
-
| ----------------------------- |
|
|
104
|
-
| `canon:target-check` | In a target, to compare each domain with the toolkit
|
|
105
|
-
| `canon:
|
|
106
|
-
| `canon:canon-feedback
|
|
102
|
+
| Skill | When to use |
|
|
103
|
+
| ----------------------------- | ------------------------------------------------------- |
|
|
104
|
+
| `canon:target-check` | In a target, to compare each domain with the toolkit |
|
|
105
|
+
| `canon:document-repair` | Rewrite a failing docs folder to the limits and gate it |
|
|
106
|
+
| `canon:canon-feedback` | The toolkit is broken, missing, or off |
|
|
107
|
+
| `canon:canon-feedback-triage` | In the toolkit repo, to file feedback issues |
|
package/governance/detect.toml
CHANGED
|
@@ -169,6 +169,10 @@ files = ["index.html", "*/index.html"]
|
|
|
169
169
|
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
170
170
|
files = ["index.html", "*/index.html"]
|
|
171
171
|
|
|
172
|
+
["keyboard"]
|
|
173
|
+
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
174
|
+
files = ["index.html", "*/index.html"]
|
|
175
|
+
|
|
172
176
|
["forms"]
|
|
173
177
|
deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
|
|
174
178
|
files = ["index.html", "*/index.html"]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Go rule ledger
|
|
3
|
+
description: Sources for governance/rules/lang/go.md, one row per bullet
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Go rule ledger
|
|
7
|
+
|
|
8
|
+
The field is Go programming, and the authority is the Go project's own documentation at go.dev and pkg.go.dev, with the Code Review Comments wiki as the team's review guide. The package pages read name go1.27.2, and the wiki and layout pages name no release.
|
|
9
|
+
|
|
10
|
+
## Errors
|
|
11
|
+
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
14
|
+
| Wrap with `%w` | [errors](https://pkg.go.dev/errors): "An easy way to create wrapped errors is to call fmt.Errorf and apply the %w verb to the error argument" | 2026-10-18, go1.27.2 |
|
|
15
|
+
| Match with `Is` or `As` | [errors](https://pkg.go.dev/errors): `Is` "should be used in preference to simple equality checks", since it walks the wrapped chain | 2026-10-18, go1.27.2 |
|
|
16
|
+
| Never discard with `_` | [Code Review Comments](https://go.dev/wiki/CodeReviewComments#handle-errors): "Do not discard errors using `_` variables" | 2026-10-18 |
|
|
17
|
+
| `panic` for broken invariant | [Code Review Comments](https://go.dev/wiki/CodeReviewComments#dont-panic): "Don't use panic for normal error handling. Use error and multiple return values." | 2026-10-18 |
|
|
18
|
+
|
|
19
|
+
## Context
|
|
20
|
+
|
|
21
|
+
| Bullet | Source | Read |
|
|
22
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- |
|
|
23
|
+
| First parameter, `ctx` | [context](https://pkg.go.dev/context): "The Context should be the first parameter, typically named ctx" | 2026-10-18, go1.27.2 |
|
|
24
|
+
| Never in a struct | [context](https://pkg.go.dev/context): "Do not store Contexts inside a struct type", and "pass a Context explicitly to each function that needs it" | 2026-10-18, go1.27.2 |
|
|
25
|
+
| No `nil`, `context.TODO` | [context](https://pkg.go.dev/context): "Do not pass a nil Context, even if a function permits it. Pass context.TODO if you are unsure about which Context to use." | 2026-10-18, go1.27.2 |
|
|
26
|
+
|
|
27
|
+
## Interfaces
|
|
28
|
+
|
|
29
|
+
| Bullet | Source | Read |
|
|
30
|
+
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
31
|
+
| In the consumer, only its calls | [Code Review Comments](https://go.dev/wiki/CodeReviewComments#interfaces): "Go interfaces generally belong in the package that uses values of the interface type", and [Effective Go](https://go.dev/doc/effective_go#interfaces): "Interfaces with only one or two methods are common" | 2026-10-18 |
|
|
32
|
+
| Accept interfaces, return concrete | [Code Review Comments](https://go.dev/wiki/CodeReviewComments#interfaces): "The implementing package should return concrete (usually pointer or struct) types" | 2026-10-18 |
|
|
33
|
+
|
|
34
|
+
## Packages
|
|
35
|
+
|
|
36
|
+
| Bullet | Source | Read |
|
|
37
|
+
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
38
|
+
| `internal/` for private code | [Organizing a Go module](https://go.dev/doc/modules/layout): `internal` "prevents other modules from depending on packages we don't necessarily want to expose", and "keep packages in internal as much as possible" | 2026-10-18 |
|
|
39
|
+
| No side effects in `init` | House choice: `init` runs on every import, tests included, in an order the reader cannot see from the call site, so a dependency it wires is hidden and cannot be swapped | 2026-10-18 |
|
|
40
|
+
| No mutable package state | House choice: a package-level variable is shared by every caller and every parallel test, so one test's write leaks into another and a data race needs no visible goroutine | 2026-10-18 |
|
|
41
|
+
|
|
42
|
+
## Declined
|
|
43
|
+
|
|
44
|
+
Every bullet the rewrite removed or reshaped, grouped by why.
|
|
45
|
+
|
|
46
|
+
### A convention Claude follows unprompted
|
|
47
|
+
|
|
48
|
+
The four casing bullets went under the plan's question 1, whose suggestion stood. `gofmt`, [Effective Go](https://go.dev/doc/effective_go#names), and Code Review Comments set each of them, and Claude writes them without the rule. The error-position bullet went on the same test.
|
|
49
|
+
|
|
50
|
+
- Cut "`MixedCaps` for exported names, never underscores", which Effective Go states as "the convention in Go is to use MixedCaps or mixedCaps rather than underscores".
|
|
51
|
+
- Cut "one short lowercase package name, not `util`, `common`, or `helpers`", which Effective Go and the wiki's "Avoid meaningless package names like util, common, misc" both state.
|
|
52
|
+
- Cut "do not repeat the package name in an exported identifier", which Effective Go shows with `bufio.Reader` over `BufReader`.
|
|
53
|
+
- Cut "keep initialisms in one case". No sampled session was run to test it, so the suggestion's condition for keeping it was never met.
|
|
54
|
+
- Cut "return an error as the last result value", a convention every Go signature Claude writes already follows.
|
|
55
|
+
|
|
56
|
+
### Merged or reworded
|
|
57
|
+
|
|
58
|
+
- Merged "keep an interface to the methods its consumer calls" into the consumer-placement bullet, since both state where an interface's method set comes from.
|
|
59
|
+
- Reworded the `errors.Is` bullet to ban `==` as well as string matching, since the package page sets `Is` against "simple equality checks".
|
|
60
|
+
- Gave the discard ban the wiki's own alternative, to handle, return, or panic.
|
|
61
|
+
- Gave the package-state ban an alternative, a struct the caller owns.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: PHP rule ledger
|
|
3
|
+
description: Sources for governance/rules/lang/php.md, one row per bullet
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PHP rule ledger
|
|
7
|
+
|
|
8
|
+
The field is PHP programming, and the authority is the PHP manual at php.net, with the PHP Framework Interop Group's standards at php-fig.org for autoloading and file layout. The manual pages read belong to the PHP 8.5 manual.
|
|
9
|
+
|
|
10
|
+
## Strictness
|
|
11
|
+
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
|
|
14
|
+
| `strict_types=1` | [Type declarations](https://www.php.net/manual/en/language.types.declarations.php): "By default, PHP will coerce values of the wrong type into the expected scalar type declaration if possible", and strict mode is enabled "on a per-file basis" | 2026-10-18, PHP 8.5 |
|
|
15
|
+
| Native types over docblocks | [Type declarations](https://www.php.net/manual/en/language.types.declarations.php): native declarations "ensure that the value is of the specified type at call time, otherwise a TypeError is thrown", which no docblock does | 2026-10-18, PHP 8.5 |
|
|
16
|
+
| `===` over `==` | [Comparison operators](https://www.php.net/manual/en/language.operators.comparison.php): `==` is "equal after type juggling", and the page's warning shows `"1" == "01"` and `100 == "1e2"` both true in PHP 8 | 2026-10-18, PHP 8.5 |
|
|
17
|
+
|
|
18
|
+
## Layout
|
|
19
|
+
|
|
20
|
+
| Bullet | Source | Read |
|
|
21
|
+
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
22
|
+
| PSR-4 autoloading | [PSR-4](https://www.php-fig.org/psr/psr-4/): "This PSR describes a specification for autoloading classes from file paths", and "The terminating class name corresponds to a file name ending in .php" | 2026-10-18 |
|
|
23
|
+
| One symbol per file | [PSR-1](https://www.php-fig.org/psr/psr-1/): "This means each class is in a file by itself, and is in a namespace of at least one level" | 2026-10-18 |
|
|
24
|
+
|
|
25
|
+
## Data shapes
|
|
26
|
+
|
|
27
|
+
| Bullet | Source | Read |
|
|
28
|
+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
|
|
29
|
+
| `enum` for a closed set | [Enumerations](https://www.php.net/manual/en/language.enumerations.overview.php): a type "limited to one of a discrete number of possible values", and [backed enums](https://www.php.net/manual/en/language.enumerations.backed.php) exist for a case that "needs to be able to round-trip to a database or similar datastore" | 2026-10-18, PHP 8.5 |
|
|
30
|
+
| `readonly` value objects | [Properties](https://www.php.net/manual/en/language.oop5.properties.php): `readonly` "prevents modification of the property after initialization", and [a readonly class](https://www.php.net/manual/en/language.oop5.basic.php) adds it "to every declared property" | 2026-10-18, PHP 8.5 |
|
|
31
|
+
| `final` unless designed for it | House choice: a subclass nobody planned for couples to the parent's internals, so a refactor of the parent breaks code its author never saw | 2026-10-18 |
|
|
32
|
+
| No associative array boundary | House choice: a misspelled or missing array key reads as `null` with a warning rather than failing, and no native type declares an array's keys, so the shape drifts unchecked | 2026-10-18 |
|
|
33
|
+
|
|
34
|
+
## Errors
|
|
35
|
+
|
|
36
|
+
| Bullet | Source | Read |
|
|
37
|
+
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
|
|
38
|
+
| Domain exception, not `false` | House choice: a caller that forgets to test a `false` or `null` return carries on with a bad value, and `0` and `false` look alike under the loose checks the strictness bullets ban | 2026-10-18 |
|
|
39
|
+
| No `@` | House choice: [Error control](https://www.php.net/manual/en/language.operators.errorcontrol.php) says `@` suppresses "any diagnostic error that might be generated by that expression", so the failure leaves no trace for whoever debugs it | 2026-10-18, PHP 8.5 |
|
|
40
|
+
| No `extract` or `eval` | [eval](https://www.php.net/manual/en/function.eval.php): "very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged.", and [extract](https://www.php.net/manual/en/function.extract.php) overwrites a colliding variable by default | 2026-10-18, PHP 8.5 |
|
|
41
|
+
|
|
42
|
+
## Declined
|
|
43
|
+
|
|
44
|
+
Every bullet stayed, so nothing was cut. Three were reshaped.
|
|
45
|
+
|
|
46
|
+
### Merged or reworded
|
|
47
|
+
|
|
48
|
+
- Reworded "a backed `enum` for a closed set" to an `enum`, backed only when stored or serialized. The manual gives a pure enum for a closed set and a backing value for a datastore round trip.
|
|
49
|
+
- Gave the `@` ban an alternative, to check the condition first or catch the exception.
|
|
50
|
+
- Gave the `extract`, variable variables, and `eval` ban an alternative, to name each variable and call each function directly.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Python rule ledger
|
|
3
|
+
description: Sources for governance/rules/lang/python.md, one row per bullet
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Python rule ledger
|
|
7
|
+
|
|
8
|
+
The field is Python programming, and the authority is the Python documentation at docs.python.org with the PEPs at peps.python.org. The library pages read are the Python 3.15 documentation.
|
|
9
|
+
|
|
10
|
+
## Type hints
|
|
11
|
+
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
|
|
14
|
+
| Annotate public functions | House choice: a gradual type checker treats an unannotated function as dynamically typed and leaves its body unchecked, so a public function with no hints hides its callers' mistakes | 2026-10-18 |
|
|
15
|
+
| `X \| None` and built-in generics | [typing](https://docs.python.org/3/library/typing.html): the `int \| str` shorthand "is recommended", `Optional[X]` "is equivalent to `X \| None`", and `typing.List` is a "Deprecated alias to list" since 3.9 | 2026-10-18, Python 3.15 |
|
|
16
|
+
| No `from __future__ import annotations` | [`__future__`](https://docs.python.org/3/library/__future__.html): "This feature will eventually be deprecated and removed. See PEP 649 and PEP 749." | 2026-10-18, Python 3.15 |
|
|
17
|
+
| `Protocol` over an ABC | [PEP 544](https://peps.python.org/pep-0544/): with an ABC "a class has to be explicitly marked to support them", and protocols provide "structural subtyping (static duck typing)" | 2026-10-18 |
|
|
18
|
+
| `object` over `Any` | [typing](https://docs.python.org/3/library/typing.html#the-any-type): "Use object to indicate that a value could be any type in a typesafe manner. Use Any to indicate that a value is dynamically typed." | 2026-10-18, Python 3.15 |
|
|
19
|
+
|
|
20
|
+
## Errors
|
|
21
|
+
|
|
22
|
+
| Bullet | Source | Read |
|
|
23
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
|
|
24
|
+
| Specific exception class | [PEP 8](https://peps.python.org/pep-0008/#programming-recommendations): "Design exception hierarchies based on the distinctions that code catching the exceptions is likely to need" | 2026-10-18 |
|
|
25
|
+
| Narrowest catch | [PEP 8](https://peps.python.org/pep-0008/#programming-recommendations): "When catching exceptions, mention specific exceptions whenever possible instead of using a bare `except:` clause" | 2026-10-18 |
|
|
26
|
+
| `raise ... from err` | [PEP 8](https://peps.python.org/pep-0008/#programming-recommendations): "`raise X from Y` should be used to indicate explicit replacement without losing the original traceback" | 2026-10-18 |
|
|
27
|
+
|
|
28
|
+
## Data shapes
|
|
29
|
+
|
|
30
|
+
| Bullet | Source | Read |
|
|
31
|
+
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
|
|
32
|
+
| Frozen, slotted dataclass | [dataclasses](https://docs.python.org/3/library/dataclasses.html): with `frozen`, "assigning to fields will generate an exception", and `slots` generates `__slots__`, added in 3.10 | 2026-10-18, Python 3.15 |
|
|
33
|
+
| `Enum` for a closed set | [enum](https://docs.python.org/3/library/enum.html): an enumeration "is a set of symbolic names (members) bound to unique values", and `StrEnum` members "are also strings", added in 3.11 | 2026-10-18, Python 3.15 |
|
|
34
|
+
| `pathlib` over `os.path` | [pathlib](https://docs.python.org/3/library/pathlib.html): "`Path` is most likely what you need", and its normalization is "more opinionated and consistent than `os.path`", keeping `..` segments "for greater safety" | 2026-10-18, Python 3.15 |
|
|
35
|
+
|
|
36
|
+
## Imports and modules
|
|
37
|
+
|
|
38
|
+
| Bullet | Source | Read |
|
|
39
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
|
|
40
|
+
| Absolute imports | [PEP 8](https://peps.python.org/pep-0008/#imports): "Absolute imports are recommended, as they are usually more readable and tend to be better behaved" | 2026-10-18 |
|
|
41
|
+
| No shortening aliases | House choice: an internal name aliased at import no longer matches its definition, so a search for the name misses every call site behind the alias | 2026-10-18 |
|
|
42
|
+
| `__main__` guard | [`__main__`](https://docs.python.org/3/library/__main__.html): imported "to unit test it, the script code would unintentionally execute as well", and "Most often, a function named main encapsulates the program's primary behavior" | 2026-10-18, Python 3.15 |
|
|
43
|
+
|
|
44
|
+
## Declined
|
|
45
|
+
|
|
46
|
+
Every bullet the rewrite removed or reshaped, grouped by why.
|
|
47
|
+
|
|
48
|
+
### Contradicted by the docs
|
|
49
|
+
|
|
50
|
+
- Reworded the pydantic-only `__future__` caveat to a plain ban, since the docs say the feature "will eventually be deprecated and removed".
|
|
51
|
+
- Reworded the ban on parent-relative imports to a preference for absolute ones. PEP 8 calls explicit relative imports "an acceptable alternative to absolute imports", so a ban overstated it.
|
|
52
|
+
- Cut `typing.cast` as the alternative to `Any`, since the docs say it "returns the value unchanged" and checks nothing. The bullet now names `object`.
|
|
53
|
+
|
|
54
|
+
### A convention Claude follows unprompted
|
|
55
|
+
|
|
56
|
+
PEP 8's naming conventions set all four casing bullets, and Claude writes them without the rule.
|
|
57
|
+
|
|
58
|
+
- Cut "`snake_case` for modules, functions, variables, and methods".
|
|
59
|
+
- Cut "`PascalCase` for classes, type aliases, `TypeVar`, and `ParamSpec`".
|
|
60
|
+
- Cut "`UPPER_SNAKE_CASE` for module-level constants and environment variables", which PEP 8 states as "written in all capital letters with underscores separating words".
|
|
61
|
+
- Cut "`_leading_underscore` for module-private names, `__dunder__` for the protocol".
|
|
62
|
+
|
|
63
|
+
### Merged or reworded
|
|
64
|
+
|
|
65
|
+
- Merged the `X | None` bullet and the built-in generics bullet, since both replace a `typing` spelling with the native one.
|
|
66
|
+
- Merged "raise specific built-in exceptions" and "define a project-rooted exception hierarchy" into one bullet naming both kinds a raise may take.
|
|
67
|
+
- Narrowed "annotate all public functions, methods, and class attributes" to functions and methods, and gave it the unchecked-body reason.
|
|
68
|
+
- Gave the `__main__` guard the docs' own shape, a `main` function the guard calls.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TypeScript rule ledger
|
|
3
|
+
description: Sources for governance/rules/lang/typescript.md, one row per bullet
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# TypeScript rule ledger
|
|
7
|
+
|
|
8
|
+
The field is TypeScript programming, and the authority is the TypeScript documentation at typescriptlang.org, with MDN for the JavaScript runtime the language compiles to. The handbook names no release, so rows read the handbook as TypeScript 5.
|
|
9
|
+
|
|
10
|
+
## File names
|
|
11
|
+
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
|
|
14
|
+
| `kebab-case` filenames | House choice: an import differing from its file only in case resolves on a case-insensitive filesystem such as macOS and fails on Linux CI, and one casing leaves no such pair | 2026-10-18 |
|
|
15
|
+
|
|
16
|
+
## Type declarations
|
|
17
|
+
|
|
18
|
+
| Bullet | Source | Read |
|
|
19
|
+
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
|
|
20
|
+
| `unknown` over `any` | [More on Functions](https://www.typescriptlang.org/docs/handbook/2/functions.html): `unknown` "is similar to the `any` type, but is safer because it's not legal to do anything with an `unknown` value" | 2026-10-18, TypeScript 5 |
|
|
21
|
+
| `interface` until `type` is needed | [Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html): "If you would like a heuristic, use `interface` until you need to use features from `type`." | 2026-10-18, TypeScript 5 |
|
|
22
|
+
| `as const` over `enum` | [Enums](https://www.typescriptlang.org/docs/handbook/enums.html): "you may not need an enum when an object with `as const` could suffice", which "keeps your codebase aligned with the state of JavaScript" | 2026-10-18, TypeScript 5 |
|
|
23
|
+
|
|
24
|
+
## Type safety
|
|
25
|
+
|
|
26
|
+
| Bullet | Source | Read |
|
|
27
|
+
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ |
|
|
28
|
+
| Narrow over assert or `!` | [Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html): "there is no runtime checking associated with a type assertion", and the non-null `!` likewise "doesn't change the runtime behavior of your code" | 2026-10-18, TypeScript 5 |
|
|
29
|
+
| `Promise.all` for independent work | [Promise.all()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all): sequential `await` makes the function "pause until the choice is made, and then again until the prices are fetched", and `Promise.all` runs "them concurrently" | 2026-10-18 |
|
|
30
|
+
|
|
31
|
+
## Imports and configuration
|
|
32
|
+
|
|
33
|
+
| Bullet | Source | Read |
|
|
34
|
+
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
|
|
35
|
+
| `@/` alias where mapped | House choice: a `../../` chain breaks whenever the importing file moves. The condition comes from [Modules reference](https://www.typescriptlang.org/docs/handbook/modules/reference.html), where `paths` "does not change the import path in the code emitted", so an alias the bundler lacks "will crash at runtime" | 2026-10-18, TypeScript 5 |
|
|
36
|
+
| No barrel re-exports | House choice: importing through a barrel loads every module it re-exports, which slows tests and opens import cycles that surface as `undefined` at load time | 2026-10-18 |
|
|
37
|
+
| `import type` | [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html): `import type` "always gets fully erased, so there's no remnant of it at runtime" | 2026-10-18, TypeScript 5 |
|
|
38
|
+
| `strict: true` | [TSConfig strict](https://www.typescriptlang.org/tsconfig/#strict): "The strict flag enables a wide range of type checking behavior that results in stronger guarantees of program correctness" | 2026-10-18, TypeScript 5 |
|
|
39
|
+
|
|
40
|
+
## Declined
|
|
41
|
+
|
|
42
|
+
Every bullet the rewrite removed or reshaped, grouped by why.
|
|
43
|
+
|
|
44
|
+
### Cut without a source or a bug class
|
|
45
|
+
|
|
46
|
+
- Cut "enforce explicit types or strict inference", which no reviewer can check against a line of code.
|
|
47
|
+
- Cut "discriminated unions for error handling over throwing exceptions". No TypeScript page takes that side, and this repository's own CLI throws, so the bullet loaded against the code it governs.
|
|
48
|
+
- Cut "built-in utility types over manual type manipulation". The utility types page describes them and sets them against nothing.
|
|
49
|
+
- Cut "prefer `readonly` properties for data objects". The object types page describes `readonly` and takes no side on when to use it.
|
|
50
|
+
|
|
51
|
+
### A convention Claude follows unprompted
|
|
52
|
+
|
|
53
|
+
- Cut "`camelCase` for variables, functions, and methods".
|
|
54
|
+
- Cut "`PascalCase` for types, interfaces, classes, and components".
|
|
55
|
+
- Cut "`UPPER_SNAKE_CASE` for constants and environment variables".
|
|
56
|
+
- Cut "do not prefix interfaces with `I`", a prefix Claude does not write without being asked.
|
|
57
|
+
|
|
58
|
+
### Merged or reworded
|
|
59
|
+
|
|
60
|
+
- Reworded the `interface` bullet to the handbook's heuristic, and merged "`type` for unions, intersections, and utility types" into it as the point where `type` takes over.
|
|
61
|
+
- Merged "do not use non-null assertions" into the narrowing bullet, since the handbook groups `!` with the type assertion it is.
|
|
62
|
+
- Reworded the `@/` bullet to apply only where both tsconfig.json and the bundler map the alias, under the plan's question 2, whose suggestion stood.
|
|
63
|
+
- Moved the `kebab-case` filename bullet under a `File names` heading, since it was the one casing bullet kept, and gave it the case-sensitivity reason.
|
|
64
|
+
- Gave the `unknown` bullet the narrowing step `unknown` requires before use.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Persistence rule ledger
|
|
3
|
+
description: Sources for governance/rules/lib/database.md, one row per bullet
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Persistence rule ledger
|
|
7
|
+
|
|
8
|
+
The field is database engineering, plus application security for query construction. The authorities are the migration and ORM documentation of Rails, Prisma, Django, and SQLAlchemy, the PostgreSQL manual, Martin Fowler's article on evolutionary database design, and the OWASP Cheat Sheet Series. Spike S1 of the rule-standard groundwork drafted this ledger, and its three unopened leads were read for it.
|
|
9
|
+
|
|
10
|
+
## Schema changes
|
|
11
|
+
|
|
12
|
+
| Bullet | Source | Read |
|
|
13
|
+
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
14
|
+
| Every change is a migration | [Evolutionary Database Design](https://martinfowler.com/articles/evodb.html): every change is "a database migration script which is version controlled together with application code changes" | 2026-10-18 |
|
|
15
|
+
| A way back, down or forward | [Rails migrations](https://guides.rubyonrails.org/active_record_migrations.html): "you can raise `ActiveRecord::IrreversibleMigration` in your `down` block", and [Prisma down migrations](https://www.prisma.io/docs/orm/prisma-migrate/workflows/generating-down-migrations) undoes an applied one with "you will instead need to revert your `schema.prisma` file" and a new migration | 2026-10-18 |
|
|
16
|
+
| No change outside a migration | [Evolutionary Database Design](https://martinfowler.com/articles/evodb.html): the authors never "run ad hoc DDL or DML", and "all changes are made by migrations" | 2026-10-18 |
|
|
17
|
+
| Never edit a run migration | [Rails migrations](https://guides.rubyonrails.org/active_record_migrations.html): "editing existing migrations that have been already committed to source control is not a good idea" | 2026-10-18 |
|
|
18
|
+
| Drop after reads and writes stop | [Expand and contract](https://www.prisma.io/dataguide/types/relational/expand-and-contract-pattern): "Once all clients have been updated to stop writing to the original schema, you can safely delete the original data structure" | 2026-10-18 |
|
|
19
|
+
|
|
20
|
+
## Query construction
|
|
21
|
+
|
|
22
|
+
| Bullet | Source | Read |
|
|
23
|
+
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
24
|
+
| Bind every runtime value | [SQL Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html): developers "should be told to use prepared statements with variable binding (aka parameterized queries)" | 2026-10-18 |
|
|
25
|
+
| Never interpolate a value | [SQL Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html): building the string by hand ranks last, as "STRONGLY DISCOURAGED: Escaping All User Supplied Input" | 2026-10-18 |
|
|
26
|
+
| Allow-list identifiers | [SQL Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html): for "table names, column names, or sort order indicators", "input validation or query redesign is the most appropriate defense" | 2026-10-18 |
|
|
27
|
+
|
|
28
|
+
## Transactions
|
|
29
|
+
|
|
30
|
+
| Bullet | Source | Read |
|
|
31
|
+
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
|
|
32
|
+
| One owner per transaction | [SQLAlchemy session basics](https://docs.sqlalchemy.org/en/20/orm/session_basics.html): "Keep the lifecycle of the session (and usually the transaction) separate and external" | 2026-10-18 |
|
|
33
|
+
| Savepoint, never commit a handed one | [Django transactions](https://docs.djangoproject.com/en/5.2/topics/db/transactions/): Django "creates a savepoint when entering an inner `atomic` block" and commits "when exiting the outermost block", and [PostgreSQL SAVEPOINT](https://www.postgresql.org/docs/current/sql-savepoint.html) "establishes a new savepoint within the current transaction" | 2026-10-18 |
|
|
34
|
+
| Side effects after commit | [Django transactions](https://docs.djangoproject.com/en/5.2/topics/db/transactions/): `on_commit()` callbacks run "after the open transaction is successfully committed", for "a background task, an email notification, or a cache invalidation" | 2026-10-18 |
|
|
35
|
+
|
|
36
|
+
## Access patterns
|
|
37
|
+
|
|
38
|
+
| Bullet | Source | Read |
|
|
39
|
+
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
|
|
40
|
+
| Load relations with parents | [Django optimization](https://docs.djangoproject.com/en/5.2/topics/db/optimization/): "Retrieve everything at once if you know you will need it", naming `select_related()` and `prefetch_related()`, and [Rails querying](https://guides.rubyonrails.org/active_record_querying.html) solves N + 1 queries with `includes` | 2026-10-18 |
|
|
41
|
+
| Session per request | [SQLAlchemy session basics](https://docs.sqlalchemy.org/en/20/orm/session_basics.html): "create a Session at the start of a web request" and "close the session at the end of web request" | 2026-10-18 |
|
|
42
|
+
|
|
43
|
+
## Declined
|
|
44
|
+
|
|
45
|
+
Every bullet the rewrite removed or reshaped, grouped by why.
|
|
46
|
+
|
|
47
|
+
### Contradicted by the docs
|
|
48
|
+
|
|
49
|
+
- Cut "name the columns a read needs, never select every column by wildcard". The [Django optimization](https://docs.djangoproject.com/en/5.2/topics/db/optimization/) page says "Don't be too aggressive in deferring fields without profiling", and no page read backs the ban.
|
|
50
|
+
- Narrowed "never open a transaction inside a function that was handed one". Django designs a nested `atomic` as a savepoint, so the bullet now bans committing the caller's transaction.
|
|
51
|
+
- Reworded "ship a tested rollback path with every migration". Prisma has no down step and undoes a migration with a new one, which the old wording read as missing.
|
|
52
|
+
|
|
53
|
+
### Merged or reworded
|
|
54
|
+
|
|
55
|
+
- Reworded "separate a destructive migration from the deploy that stops reading the dropped column" to the order expand and contract states, removal after reads and writes stop.
|
|
56
|
+
|
|
57
|
+
### Gaps filled
|
|
58
|
+
|
|
59
|
+
- Added the allow-list bullet. OWASP names identifiers as the part of a query no bind reaches, the case a model gets wrong after it binds every value.
|
|
60
|
+
|
|
61
|
+
### Leads read
|
|
62
|
+
|
|
63
|
+
- Fowler's article backs the migration bullets but says nothing on editing an applied migration, so Rails carries that row.
|
|
64
|
+
- The PostgreSQL `SAVEPOINT` page backs the savepoint wording beside Django's.
|
|
65
|
+
- The Rails querying guide backs eager loading through `includes`.
|