@erclx/canon 5.40.0 → 5.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +34 -17
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/references/adopted.md +34 -14
  4. package/claude/skills/auto-ship/REQUIREMENT.md +2 -0
  5. package/claude/skills/auto-ship/SKILL.md +28 -2
  6. package/claude/skills/auto-ship/references/draft-mark.md +32 -6
  7. package/claude/skills/auto-ship/references/failure-recovery.md +15 -13
  8. package/claude/skills/auto-ship/references/fan-in.md +59 -0
  9. package/claude/skills/auto-ship/references/tier-failures.md +31 -10
  10. package/claude/skills/auto-ship/references/ui-checklist.md +9 -4
  11. package/claude/skills/auto-ship/references/worktree-name.md +9 -3
  12. package/claude/skills/build-in-slices/references/adopted.md +35 -21
  13. package/claude/skills/canvas-board/references/canvas.md +17 -6
  14. package/claude/skills/canvas-board/references/design.md +26 -7
  15. package/claude/skills/code-craft/references/adopted.md +58 -20
  16. package/claude/skills/codebase-layout/references/adopted.md +49 -16
  17. package/claude/skills/codebase-layout/references/frontend.md +11 -4
  18. package/claude/skills/codebase-layout/references/tests.md +4 -2
  19. package/claude/skills/context-fold/references/classify.md +10 -15
  20. package/claude/skills/context-fold/references/completion-report.md +11 -9
  21. package/claude/skills/context-fold/references/context-refresh.md +26 -9
  22. package/claude/skills/context-fold/references/unusable-baseline.md +5 -3
  23. package/claude/skills/create-rule/REQUIREMENT.md +5 -0
  24. package/claude/skills/create-rule/SKILL.md +9 -1
  25. package/claude/skills/create-rule/references/checklist.md +26 -0
  26. package/claude/skills/create-rule/references/rule.md +98 -20
  27. package/claude/skills/create-skill/SKILL.md +1 -0
  28. package/claude/skills/create-skill/references/skill-disclosure.md +10 -2
  29. package/claude/skills/create-skill/references/skill-frontmatter.md +43 -0
  30. package/claude/skills/create-skill/references/skill-paths.md +7 -4
  31. package/claude/skills/create-skill/references/skill-practice.md +6 -3
  32. package/claude/skills/create-skill/references/skill-requirement.md +4 -2
  33. package/claude/skills/create-skill/references/skill.md +67 -44
  34. package/claude/skills/decision-escalate/REQUIREMENT.md +1 -1
  35. package/claude/skills/decision-escalate/SKILL.md +1 -2
  36. package/claude/skills/deploy-app/references/vercel.md +2 -1
  37. package/claude/skills/deprecation-migration/references/adopted.md +44 -25
  38. package/claude/skills/design-taste/references/adopted.md +9 -1
  39. package/claude/skills/design-taste/references/craft.md +3 -1
  40. package/claude/skills/design-taste/references/kinds.md +8 -7
  41. package/claude/skills/design-taste/references/preflight.md +12 -0
  42. package/claude/skills/design-taste/references/systems.md +7 -6
  43. package/claude/skills/design-taste/references/tells.md +24 -25
  44. package/claude/skills/design-taste/references/vocabulary.md +7 -5
  45. package/claude/skills/document-health/references/axes.md +54 -30
  46. package/claude/skills/draft-and-pick/references/live-arms.md +2 -2
  47. package/claude/skills/draft-doc/references/context.md +4 -3
  48. package/claude/skills/draft-doc/references/docs.md +6 -3
  49. package/claude/skills/draft-doc/references/readme/agent-facing.md +6 -0
  50. package/claude/skills/draft-doc/references/readme/application.md +8 -2
  51. package/claude/skills/draft-doc/references/readme/cli.md +5 -1
  52. package/claude/skills/draft-doc/references/readme/library.md +4 -0
  53. package/claude/skills/draft-doc/references/readme/plugin.md +9 -1
  54. package/claude/skills/draft-doc/references/readme.md +30 -13
  55. package/claude/skills/draft-doc/references/requirements.md +17 -4
  56. package/claude/skills/draft-doc/references/wiki-kind.md +20 -10
  57. package/claude/skills/draft-figure/references/architecture-set.md +7 -3
  58. package/claude/skills/draft-figure/references/figures.md +8 -6
  59. package/claude/skills/draft-figure/references/hand-drawn.md +3 -1
  60. package/claude/skills/draft-figure/references/mermaid-path.md +19 -9
  61. package/claude/skills/draft-figure/references/mermaid.md +10 -5
  62. package/claude/skills/draft-ready/references/ready.md +22 -15
  63. package/claude/skills/git-branch/REQUIREMENT.md +17 -6
  64. package/claude/skills/git-branch/SKILL.md +63 -7
  65. package/claude/skills/git-branch/references/branch.md +11 -1
  66. package/claude/skills/git-branch/references/slug.md +17 -5
  67. package/claude/skills/git-commit/references/commit.md +8 -0
  68. package/claude/skills/git-commit/references/versioning.md +23 -17
  69. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  70. package/claude/skills/git-followup/SKILL.md +5 -6
  71. package/claude/skills/git-issue/references/issue.md +29 -16
  72. package/claude/skills/git-pr/REQUIREMENT.md +1 -5
  73. package/claude/skills/git-pr/SKILL.md +11 -22
  74. package/claude/skills/git-pr/references/final-command.md +21 -8
  75. package/claude/skills/git-pr/references/labels.md +45 -28
  76. package/claude/skills/git-pr/references/pr.md +28 -9
  77. package/claude/skills/git-pr/references/publish.md +42 -28
  78. package/claude/skills/git-pr/references/task-number.md +20 -8
  79. package/claude/skills/git-ship/SKILL.md +1 -1
  80. package/claude/skills/plan-feature/references/batches.md +48 -1
  81. package/claude/skills/plan-feature/references/plan-lifecycle.md +10 -3
  82. package/claude/skills/plan-feature/references/plan.md +59 -20
  83. package/claude/skills/plan-groundwork/references/groundwork-spikes.md +4 -1
  84. package/claude/skills/plan-groundwork/references/groundwork.md +14 -16
  85. package/claude/skills/plan-intake/references/intake.md +29 -24
  86. package/claude/skills/plan-intake-answer/REQUIREMENT.md +1 -1
  87. package/claude/skills/plan-intake-answer/SKILL.md +1 -2
  88. package/claude/skills/pr-evidence/REQUIREMENT.md +40 -0
  89. package/claude/skills/pr-evidence/SKILL.md +53 -0
  90. package/claude/skills/pr-evidence/references/evidence.md +150 -0
  91. package/claude/skills/review-address/references/post-review-findings.md +10 -3
  92. package/claude/skills/review-address/references/rebase-conflicts.md +22 -7
  93. package/claude/skills/review-address/references/rest-reads.md +3 -1
  94. package/claude/skills/review-craft/references/adopted.md +35 -18
  95. package/claude/skills/review-craft/references/security.md +42 -7
  96. package/claude/skills/review-craft/references/ui.md +23 -8
  97. package/claude/skills/review-pr/SKILL.md +6 -6
  98. package/claude/skills/review-pr/references/body-variants.md +29 -9
  99. package/claude/skills/review-pr/references/close-out.md +20 -5
  100. package/claude/skills/review-pr/references/key-changes.md +27 -3
  101. package/claude/skills/review-pr/references/post.md +83 -31
  102. package/claude/skills/review-pr/references/scope.md +54 -19
  103. package/claude/skills/review-ui/SKILL.md +2 -0
  104. package/claude/skills/review-ui/references/close-out.md +49 -0
  105. package/claude/skills/review-ui/references/driving.md +24 -4
  106. package/claude/skills/review-ui/references/post.md +43 -13
  107. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +67 -17
  108. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +81 -40
  109. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +52 -15
  110. package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +48 -26
  111. package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +12 -13
  112. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +72 -36
  113. package/claude/skills/role-orchestrator/references/orchestrator-output.md +12 -4
  114. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +64 -24
  115. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +80 -26
  116. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +41 -18
  117. package/claude/skills/role-orchestrator/references/orchestrator-resume.md +19 -7
  118. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +22 -12
  119. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +15 -6
  120. package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +25 -7
  121. package/claude/skills/role-orchestrator/references/orchestrator-watch.md +34 -8
  122. package/claude/skills/role-orchestrator/scripts/poll.ts +16 -24
  123. package/claude/skills/role-worker/REQUIREMENT.md +2 -0
  124. package/claude/skills/role-worker/SKILL.md +17 -0
  125. package/claude/skills/search-craft/references/adopted.md +18 -6
  126. package/claude/skills/session-map/references/session.md +26 -7
  127. package/claude/skills/session-worktree/references/main-root-writes.md +25 -8
  128. package/claude/skills/systematic-debugging/references/adopted.md +30 -16
  129. package/claude/skills/target-check/references/domains.md +39 -11
  130. package/claude/skills/target-setup/references/detect.md +80 -65
  131. package/claude/skills/target-setup/references/indexes.md +8 -6
  132. package/claude/skills/task-board/references/board.md +86 -30
  133. package/claude/skills/task-board/references/decline.md +29 -13
  134. package/claude/skills/task-board/references/tasks-decline.md +12 -5
  135. package/claude/skills/task-board/references/tasks.md +65 -33
  136. package/claude/skills/task-complete/references/archive.md +41 -17
  137. package/claude/skills/task-complete/references/receipt-sweep.md +23 -9
  138. package/claude/skills/task-complete/references/unusable-baseline.md +10 -3
  139. package/claude/skills/teach-workspace/REQUIREMENT.md +1 -1
  140. package/claude/skills/teach-workspace/SKILL.md +1 -2
  141. package/claude/skills/teach-workspace/references/glossary.md +6 -2
  142. package/claude/skills/teach-workspace/references/lesson-build.md +44 -16
  143. package/claude/skills/teach-workspace/references/lesson-craft.md +12 -7
  144. package/claude/skills/teach-workspace/references/pedagogy.md +6 -3
  145. package/claude/skills/teach-workspace/references/promotion-fold.md +17 -11
  146. package/claude/skills/teach-workspace/references/promotion.md +31 -8
  147. package/claude/skills/teach-workspace/references/revisit.md +8 -2
  148. package/claude/skills/teach-workspace/references/teach.md +17 -9
  149. package/claude/skills/test-craft/references/adopted.md +48 -14
  150. package/claude/skills/test-craft/references/component.md +7 -4
  151. package/claude/skills/test-craft/references/e2e.md +25 -7
  152. package/claude/skills/test-craft/references/unit.md +3 -1
  153. package/claude/skills/test-first/references/adopted.md +12 -4
  154. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  155. package/claude/skills/ui-checklist/SKILL.md +1 -1
  156. package/claude/skills/video-craft/references/adopted.md +62 -18
  157. package/claude/skills/write-human/references/adopted.md +21 -8
  158. package/docs/workflow/parallel-features.md +2 -1
  159. package/docs/workflow/skill-map.md +2 -1
  160. package/package.json +1 -1
  161. package/src/claude/cases/git.ts +4 -0
  162. package/src/claude/cases/workflow.ts +5 -0
  163. package/src/commands/pr.ts +174 -37
  164. package/src/commands/records.ts +11 -3
  165. package/src/context/shape-gated.ts +1 -0
  166. package/src/markdown/scope.ts +150 -2
  167. package/src/pr/frames.ts +53 -9
  168. package/src/pr/lift.ts +6 -3
  169. package/src/pr/review-state.ts +182 -0
  170. package/src/records/validate.ts +1 -0
  171. package/src/tasks/answers.ts +79 -2
  172. package/src/tasks/fan-in.ts +176 -0
  173. package/src/tasks/stack.ts +1 -1
  174. package/tooling/astro/reference.md +80 -39
  175. package/tooling/base/reference.md +63 -32
  176. package/tooling/base/seeds/canon/context/ci.md +7 -15
  177. package/tooling/base/seeds/canon/context/development.md +14 -14
  178. package/tooling/claude/reference.md +40 -22
  179. package/tooling/cloudflare/reference.md +31 -12
  180. package/tooling/go/reference.md +47 -23
  181. package/tooling/nextjs/reference.md +52 -19
  182. package/tooling/php/reference.md +35 -16
  183. package/tooling/python/reference.md +47 -30
  184. package/tooling/shell/reference.md +6 -5
  185. package/tooling/vite-react/reference.md +49 -21
  186. package/tooling/web/reference.md +130 -70
  187. package/claude/skills/git-pr/references/evidence.md +0 -124
@@ -2,65 +2,86 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- The base layer covers every project the toolkit scaffolds, whatever language sits on top. It ships formatting, conventional commits, git hooks, CI, and the verify runner. Every other stack extends it, so a decision made here is one every stack inherits. Shell formatting and linting live in the `shell` add-on stack, which a project syncs once it writes shell.
5
+ The base layer covers every project the toolkit scaffolds, whatever language sits on top. It ships formatting, conventional commits, git hooks, CI, and the verify runner. Every other stack extends it, so a decision made here is one every stack inherits. Shell formatting and linting live in the `shell` add-on stack.
6
6
 
7
7
  A repository with several language roots layers this stack once at the root and skips it per subtree, since git honors only one `core.hooksPath` and a re-dropped husky silently breaks. `canon docs scenarios` carries the recipe.
8
8
 
9
9
  ## What ships as golden configs
10
10
 
11
- Golden config files live in `tooling/base/configs/` and are copied into the target on `canon tooling sync base . --write`, replacing whatever sits at those paths. They are the source of truth. The reference covers rationale and tradeoffs. Configs show the concrete setup.
11
+ Golden configs live in `tooling/base/configs/`. `canon tooling sync base . --write` copies them into the target and replaces whatever sits at those paths. They are the source of truth, so this reference covers rationale and the configs show the setup.
12
12
 
13
- - `.oxfmtrc.json`: `semi: false`, `singleQuote: true`, `printWidth: 80`, and `sortPackageJson: false`, which keep the output Prettier wrote. The `astro` stack repeats these options in its own copy, so copy a change here into it.
14
- - `commitlint.config.js`: ESM default export extending `@commitlint/config-conventional`. Rules are `header-max-length: 72`, `scope-case: lower-case`, `subject-full-stop: never`, `subject-case` disabled, and a local `no-claude-co-author` rule refusing a `Co-authored-by` trailer that names Claude or Anthropic.
15
- - `.husky/`: `pre-commit`, `commit-msg`, `pre-push`, `post-merge`, `post-rewrite`.
16
- - `scripts/verify.ts`: the one verify runner every stack shares, and the command behind `check`. It runs typecheck, lint, format check, shell, unit tests, build, markdown bans, then card exclusion, always in that order, and skips any phase the folder's `scripts/verify.json` leaves out. Node modules only, since a target's own lint and typecheck read it.
17
- - `scripts/verify.json`: the phases a stack requires, plus any tools and preconditions it probes first. The nearest stack's copy wins. A required phase whose script `package.json` lacks fails the run. A base phase the list leaves out runs only where the folder declares its script. Base requires `check:format`, so a base-only target still fails on a missing one. The shell phase runs only where `package.json` declares `check:shell`, which the `shell` stack adds, and probes for `shfmt` and `shellcheck` first. These two files are base's `[sync] per_root` set, which a `--skip base` subfolder still receives.
13
+ ### Formatting and commit configs
14
+
15
+ Two configs fix how output looks and how commits read.
16
+
17
+ - `.oxfmtrc.json` sets `semi: false`, `singleQuote: true`, `printWidth: 80`, and `sortPackageJson: false`, keeping the output Prettier wrote.
18
+ - The `astro` stack repeats those options in its own copy, so copy a change here into it.
19
+ - `commitlint.config.js` is an ESM default export extending `@commitlint/config-conventional`. It sets `header-max-length: 72`, `scope-case: lower-case`, and `subject-full-stop: never`.
20
+ - Its `subject-case` rule is off, and a local `no-claude-co-author` rule refuses a `Co-authored-by` trailer that names Claude or Anthropic.
21
+ - `.husky/` holds `pre-commit`, `commit-msg`, `pre-push`, `post-merge`, and `post-rewrite`.
22
+
23
+ ### Verify runner
24
+
25
+ `scripts/verify.ts` is the one verify runner every stack shares, and the command behind `check`. It uses Node modules only, since a target's own lint and typecheck read it.
26
+
27
+ - It runs typecheck, lint, format check, shell, unit tests, build, markdown bans, then card exclusion, always in that order, and skips any phase the folder's `scripts/verify.json` leaves out.
28
+ - `scripts/verify.json` lists the phases a stack requires, plus any tools and preconditions it probes first. The nearest stack's copy wins.
29
+ - A required phase whose script `package.json` lacks fails the run. A base phase the list leaves out runs only where the folder declares its script.
30
+ - Base requires `check:format`, so a base-only target still fails on a missing one.
31
+ - The shell phase runs only where `package.json` declares `check:shell`, which the `shell` stack adds, and probes for `shfmt` and `shellcheck` first.
32
+
33
+ These two files are base's `[sync] per_root` set, which a `--skip base` subfolder still receives.
18
34
 
19
35
  ## What ships as user-owned seeds
20
36
 
21
37
  Seeds live in `tooling/base/seeds/`. Sync drops each once on first install and never overwrites it, so a project extends them freely.
22
38
 
23
- - `.lintstagedrc`: the glob map below.
24
- - `.github/workflows/verify.yml`: runs on pull requests targeting `main` and on `workflow_dispatch`. A project with more than one language root adds its own jobs here.
25
- - `.github/pull_request_template.md`: `## Summary`, `## Key changes`, `## Technical context`, `## Testing`. A project adds the checklist lines its own review needs.
26
- - `canon/context/`: extend the `ci` and `development` entries with project-specific commands, workflows, or deploy steps. Canonical rationale stays in this reference.
39
+ - `.lintstagedrc` holds the glob map below.
40
+ - `.github/workflows/verify.yml` runs on pull requests targeting `main` and on `workflow_dispatch`. A multi-root project adds its own jobs here.
41
+ - `.github/pull_request_template.md` has `## Summary`, `## Key changes`, `## Technical context`, and `## Testing`. A project adds its own checklist lines.
42
+ - `canon/context/` holds the `ci` and `development` entries. Extend them with project-specific commands, workflows, or deploy steps, and keep canonical rationale in this reference.
27
43
 
28
44
  ## Tool pairing
29
45
 
30
- - Runtime: `bun` as package manager and script runner, `bunx` over `npx` for a one-off executable.
31
- - Formatting: oxfmt for what it parses, pinned to an exact version so an upgrade arrives as a reviewed diff. oxfmt has no shell parser, so shell formatting is the `shell` stack's.
32
- - Commits: commitlint against conventional commits, wired through the husky `commit-msg` hook. Format is `<type>(<scope>): <subject>` in imperative mood with no trailing period.
33
- - Dev dependencies: `oxfmt`, `husky`, `@commitlint/cli`, `@commitlint/config-conventional`. Install via `bun add -D`.
46
+ - Runtime is `bun` as package manager and script runner, with `bunx` over `npx` for a one-off executable.
47
+ - Formatting is oxfmt for what it parses, pinned to an exact version so an upgrade arrives as a reviewed diff. Shell formatting is the `shell` stack's, since oxfmt has no shell parser.
48
+ - Commits go through commitlint against conventional commits, wired through the husky `commit-msg` hook. The format is `<type>(<scope>): <subject>` in imperative mood with no trailing period.
49
+ - Dev dependencies are `oxfmt`, `husky`, `@commitlint/cli`, and `@commitlint/config-conventional`, installed via `bun add -D`.
34
50
 
35
51
  ## oxfmt
36
52
 
37
53
  - Add a project's own ignores to `.prettierignore`, which oxfmt reads beside `.gitignore` by default. Sync overwrites `.oxfmtrc.json`, so an entry in its `ignorePatterns` is lost on the next sync.
38
- - Delete a leftover `.prettierrc` and run `bun remove prettier` by hand after the first sync onto oxfmt. Sync deletes nothing a stack stopped shipping, and the script overrides already stop Prettier from running.
54
+ - After the first sync onto oxfmt, delete a leftover `.prettierrc` and run `bun remove prettier`. Sync deletes nothing a stack stopped shipping.
39
55
 
40
56
  ## File layout
41
57
 
42
- - Hooks live in `.husky/`, seeded context docs in `canon/context/`.
43
- - The `canon/context/` location matches the three-tier context model: project-wide invariants in `CLAUDE.md` and `canon/REQUIREMENTS.md`, path-scoped rules in `.claude/rules/`, and on-demand domain narrative in `canon/context/`. Indexes stay opt-in.
58
+ Hooks live in `.husky/` and seeded context docs in `canon/context/`. That location matches the three-tier context model.
59
+
60
+ - Project-wide invariants sit in `CLAUDE.md` and `canon/REQUIREMENTS.md`.
61
+ - Path-scoped rules sit in `.claude/rules/`.
62
+ - On-demand domain narrative sits in `canon/context/`, with indexes opt-in.
44
63
 
45
64
  ## Hooks
46
65
 
47
66
  - `pre-commit` runs `bunx lint-staged`.
48
67
  - `commit-msg` runs `bunx commitlint --edit "$1"`.
49
68
  - `pre-push` runs `bun run check`.
50
- - `post-merge` runs `canon hooks post-merge`: archive the task a merged pull request closed, push the records, reclaim merged worktrees, reinstall the CLI, and update the plugin. It does nothing when the board is absent. `CANON_SKIP_RECLAIM`, `CANON_SKIP_UPGRADE`, and `CANON_SKIP_PLUGIN_UPDATE` turn off the three steps that act on the machine. Run `canon hooks post-merge --help` for the contract.
51
69
  - `post-rewrite` delegates to `post-merge` on `rebase`, so a `pull.rebase=true` machine still gets the check.
70
+ - `post-merge` runs `canon hooks post-merge`, which archives the task a merged pull request closed, pushes the records, reclaims merged worktrees, reinstalls the CLI, and updates the plugin.
71
+
72
+ The hook does nothing when the board is absent. `CANON_SKIP_RECLAIM`, `CANON_SKIP_UPGRADE`, and `CANON_SKIP_PLUGIN_UPDATE` turn off the three steps that act on the machine, and `canon hooks post-merge --help` states the contract.
52
73
 
53
74
  ## lint-staged
54
75
 
55
- Seeded baseline globs:
76
+ The seeded baseline globs.
56
77
 
57
78
  - `**/*.{json,md}` runs `oxfmt --no-error-on-unmatched-pattern`. Without the flag, a staged file every pattern ignores, such as `CHANGELOG.md`, exits 2 and fails the commit.
58
- - `**/*.md` runs `canon indexes regen`
79
+ - `**/*.md` runs `canon indexes regen`.
59
80
 
60
81
  ## CI
61
82
 
62
- - Steps: checkout, setup Bun at latest, `bun install --frozen-lockfile`, then `check:format`.
63
- - CI asserts and never writes. Format must be clean before push.
83
+ - Steps are checkout, setup Bun at latest, `bun install --frozen-lockfile`, then `check:format`.
84
+ - CI asserts and never writes, so format must be clean before push.
64
85
 
65
86
  ## Gitignore
66
87
 
@@ -71,22 +92,32 @@ Seeded baseline globs:
71
92
 
72
93
  ## Anti-patterns
73
94
 
74
- Sticky negative knowledge. Do not relearn.
95
+ Negative knowledge that costs a failed run to relearn.
75
96
 
76
97
  - Do NOT pass `--ignore-path` to oxfmt. It replaces the default `.gitignore` and `.prettierignore` pair rather than adding to it.
77
98
  - Do NOT put logic in a husky hook and expect its shebang to hold. Husky runs hooks as `sh -e`, so a hook carrying logic is POSIX sh under errexit whatever the first line says.
78
99
 
79
100
  ## CLI
80
101
 
81
- | Script | What it does |
82
- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
83
- | `bun run check` | Gates a checkout through `scripts/verify.ts` and writes nothing. Honors `VERIFY_NESTED=true` to suppress timeline boundaries when another script calls it. |
84
- | `bun run check:format` | Asserts oxfmt formatting without writing |
85
- | `bun run format` | Writes oxfmt formatting in place |
86
- | `bun run prepare` | Initializes husky hooks, run automatically on `bun install` |
102
+ | Script | What it does |
103
+ | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
104
+ | `bun run check` | Gates a checkout through `scripts/verify.ts`, writing nothing. `VERIFY_NESTED=true` suppresses timeline boundaries in a call. |
105
+ | `bun run check:format` | Asserts oxfmt formatting without writing |
106
+ | `bun run format` | Writes oxfmt formatting in place |
107
+ | `bun run prepare` | Initializes husky hooks, run automatically on `bun install` |
108
+
109
+ ### The check script
87
110
 
88
111
  Base writes `check` as a `[scripts.override]`, so a sync replaces whatever `check` a target declared, including one that chained further checks after the runner. Re-add a chained check as its own script after a sync.
89
112
 
90
- `bun run check` gates a checkout and writes nothing. Formatting drift fails it at `check:format`, and the failure line names `bun run format`, the one command that writes. It once ran `format` first to auto-fix drift, which rewrote files in a checkout several sessions share on every push and left a gate that could not fail. That was rejected, so the writing pass stays in `bun run format` and a push fails until it runs. The pull request workflow calls `check:format` directly as well.
113
+ - `bun run check` writes nothing. Formatting drift fails it at `check:format`, and the failure line names `bun run format`, the one command that writes.
114
+ - Auto-fixing drift inside `check` rewrote files in a shared checkout on every push and left a gate that could not fail, so the writing pass stays in `bun run format`.
115
+ - The pull request workflow calls `check:format` directly as well.
116
+
117
+ ### The markdown bans stage
118
+
119
+ The `Markdown bans` stage of `scripts/verify.ts` runs `canon markdown audit` over every tracked markdown file except `CHANGELOG.md`, since a generated changelog carries commit subjects nobody wrote against the ban set.
91
120
 
92
- `scripts/verify.ts`'s `Markdown bans` stage gates on banned characters. It runs `canon markdown audit` over every tracked markdown file except `CHANGELOG.md`, since a generated changelog carries commit subjects nobody wrote against the ban set, and exits `2` on a finding or `3` on a shipped-empty ban set, failing `bun run check` and the `pre-push` hook that calls it. A refusal to measure exits `1` and is logged as a skip rather than a failure, as does a corpus with no file left to check once `CHANGELOG.md` is set aside. The stage needs `canon` on PATH. `canon docs projects` names the install command. Without it, the stage is skipped and logged, and coverage falls back to the format check above.
121
+ - It exits `2` on a finding or `3` on a shipped-empty ban set, failing `bun run check` and the `pre-push` hook that calls it.
122
+ - A refusal to measure exits `1` and is logged as a skip, as does a corpus with no file left once `CHANGELOG.md` is set aside.
123
+ - The stage needs `canon` on PATH, and `canon docs projects` names the install command. Without it the stage is skipped and logged.
@@ -7,25 +7,17 @@ description: GitHub Actions workflow triggers and checks
7
7
 
8
8
  ## Overview
9
9
 
10
- Owns the GitHub Actions workflow that gates a merge: which events start a run, and which checks have to pass before the branch can land. The checks call package scripts rather than defining commands of their own, so what each one runs is the development entry's subject.
10
+ Owns the GitHub Actions workflow that gates a merge, being which events start a run and which checks have to pass before the branch can land. The checks call package scripts rather than defining commands of their own, so what each one runs is the development entry's subject.
11
11
 
12
12
  ## Layout
13
13
 
14
- - `.github/workflows/` owns the workflow definitions a trigger below starts
14
+ ### `.github/workflows/`
15
15
 
16
- ### Triggers
16
+ Holds `verify.yml`, the workflow that gates a merge. A pull request targeting `main` starts it, and so does a manual `workflow_dispatch` run from the Actions tab.
17
17
 
18
- - Pull requests targeting `main`
19
- - `workflow_dispatch` (manual run from the Actions tab)
18
+ - Every job must pass before merge
19
+ - The Format check runs `bun run check:format` and asserts oxfmt is clean
20
20
 
21
- ### Checks
21
+ ## Gotchas
22
22
 
23
- Defined in `.github/workflows/verify.yml`. All jobs must pass before merge.
24
-
25
- | Check | Command | What it asserts |
26
- | ------ | ---------------------- | --------------- |
27
- | Format | `bun run check:format` | oxfmt is clean |
28
-
29
- ### Running CI locally
30
-
31
- `bun run check` runs the same assert and writes nothing. If CI fails on format, run `bun run format` locally and commit the diff.
23
+ - `bun run check` runs the same assert as CI and writes nothing, so a CI format failure is fixed by running `bun run format` locally and committing the diff
@@ -7,31 +7,31 @@ description: Local dev workflow, scripts, and husky hooks
7
7
 
8
8
  ## Overview
9
9
 
10
- Owns how the project runs on a developer machine: installing the toolchain, the scripts that verify a change, and the git hooks that run them before a commit or a push leaves. CI calls the same scripts from a workflow, which is the CI entry's subject.
10
+ Owns how the project runs on a developer machine, being the toolchain install, the scripts that verify a change, and the git hooks that run them before a commit or a push leaves. CI calls the same scripts from a workflow, which is the CI entry's subject.
11
11
 
12
12
  ## Layout
13
13
 
14
- - `scripts/` owns the shell scripts the package scripts below call
15
- - `.husky/` owns the git hooks
14
+ ### `scripts/`
16
15
 
17
- ### Setup
16
+ Holds every shell script, since none belongs outside this folder. The package scripts below call them.
18
17
 
19
- - Install [Bun](https://bun.sh): `curl -fsSL https://bun.sh/install | bash`
20
- - Install dependencies: `bun install`
18
+ ### `.husky/`
19
+
20
+ Holds the git hooks that run the checks before a commit or a push leaves.
21
+
22
+ - `pre-commit` runs `lint-staged` (oxfmt on staged files)
23
+ - `commit-msg` runs `commitlint` against the conventional commit format
24
+ - `pre-push` runs `bun run check`, and also gates on banned characters across every tracked markdown file except `CHANGELOG.md` when a markdown-bans audit tool is on PATH
21
25
 
22
26
  ### Scripts
23
27
 
28
+ Install [Bun](https://bun.sh) with `curl -fsSL https://bun.sh/install | bash` and run `bun install`, then use these commands.
29
+
24
30
  | Command | Purpose |
25
31
  | ---------------- | ---------------------------------------------------------------------------------------- |
26
32
  | `bun run check` | Gates locally and writes nothing. Fails on formatting drift until `bun run format` runs. |
27
33
  | `bun run format` | Auto-fix oxfmt formatting. |
28
34
 
29
- ### Shell scripts
30
-
31
- All `.sh` files live under `scripts/`. Do not place shell scripts outside `scripts/`.
32
-
33
- ### Husky hooks
35
+ ## Gotchas
34
36
 
35
- - `pre-commit` runs `lint-staged` (oxfmt on staged files).
36
- - `commit-msg` runs `commitlint` against the conventional commit format.
37
- - `pre-push` runs `bun run check`. When a markdown-bans audit tool is on PATH, it also gates on banned characters across every tracked markdown file except `CHANGELOG.md`. A push fails on formatting drift until `bun run format` runs, since the hook writes nothing.
37
+ - A push fails on formatting drift until `bun run format` runs, since the `pre-push` hook writes nothing
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- The claude stack installs the `.claude/` workflow directory into a project. State docs are seeds, written once and never overwritten by tooling. `CLAUDE.md` is a seed, filled in per project after init.
5
+ The claude stack installs the `.claude/` workflow directory into a project. Tooling writes state docs once and never overwrites them. `CLAUDE.md` is one of those seeds, and a project fills it in after init.
6
6
 
7
7
  ## Structure
8
8
 
@@ -26,52 +26,70 @@ canon/
26
26
  └── tmp/ ← ephemeral scratch space, safe to delete without loss
27
27
  ```
28
28
 
29
- One ignore entry covers `.canon/` whole, so nothing under it is named separately and nothing tracked may ever land there. A project scaffolded before the move keeps its records under `.claude/`, and every command reads either root.
29
+ One ignore entry covers `.canon/` whole, so nothing under it is named separately and nothing tracked may land there. A project scaffolded before the move keeps its records under `.claude/`, and every command reads either root.
30
30
 
31
31
  ## Moving the records to `.canon/`
32
32
 
33
- A project installed before the split still holds its records under `.claude/`. `canon migrate records` moves them and repoints every tracked file that cites one, reporting the plan until `--write` is passed.
33
+ A project installed before the split holds its records under `.claude/`. `canon migrate records` moves them and repoints every tracked file that cites one, reporting the plan until `--write` is passed.
34
34
 
35
- Run `canon tooling sync claude . --write` first. The verb refuses while the project does not ignore `.canon/`, because every folder it relocates is ignored where it stands and landing one under a tracked root commits the task board and the plans. Until the move runs, this project's records sit at a root the shipped ignore set no longer names, so a `git add -A` in that window picks them up.
36
-
37
- The verb ships with the change that split the roots and is not in a published release yet, so an installed binary answers `unknown command` until one carries it. Run it out of a canon checkout in the meantime, as `bun src/cli.ts migrate records --root <project> --write`, and read the `ok` field out of `--json` rather than the exit code, which a shell wrapper around `canon` can flatten.
35
+ - Run `canon tooling sync claude . --write` first. The verb refuses until the project ignores `.canon/`, since a relocated folder under a tracked root commits the task board and plans.
36
+ - Until the move runs, the records sit at a root the shipped ignore set no longer names, so a `git add -A` in that window picks them up.
37
+ - An installed binary answers `unknown command` until a published release carries the verb. Meanwhile run `bun src/cli.ts migrate records --root <project> --write` from a canon checkout.
38
+ - Read the `ok` field out of `--json` rather than the exit code, which a shell wrapper around `canon` can flatten.
38
39
 
39
40
  ## Upgrading from a single-file board
40
41
 
41
- A project installed before the board became a folder still holds `.claude/TASKS.md`. Nothing migrates it. `canon claude init` seeds an empty `.canon/tasks/index.md` beside it and leaves the old file untouched, so every skill reads the empty catalog while the real board sits unreferenced.
42
+ A project installed before the board became a folder still holds `.claude/TASKS.md`, and nothing migrates it. `canon claude init` seeds an empty `.canon/tasks/index.md` beside it and leaves the old file untouched, so every skill reads the empty catalog while the real board sits unreferenced.
42
43
 
43
- Convert by hand, once per project:
44
+ Convert by hand, once per project.
44
45
 
45
- 1. Split each `###` block into `.canon/tasks/vXX.Y-<slug>.md`, adding the `title` and `description` frontmatter the tasks reference in the `task-board` skill requires. Compare each new file against the block it came from rather than checking that every block landed somewhere.
46
+ 1. Split each `###` block into `.canon/tasks/vXX.Y-<slug>.md`, adding the `title` and `description` frontmatter the `task-board` skill requires. Compare each new file against its source block.
46
47
  2. Run `canon indexes regen --no-stage --root . .canon/tasks/<any-task>.md` to build the catalog.
47
48
  3. Delete `.claude/TASKS.md`, and swap its `.gitignore` entry for `.canon/tasks/`.
48
49
 
49
50
  ## Gitignore
50
51
 
51
- - `# Claude`: `.canon/`, `.claude/worktrees/`, `.claude/.tmp/` <!-- canon-keep-record-root -->
52
+ The `# Claude` group holds three entries, being `.canon/`, `.claude/worktrees/`, and `.claude/.tmp/`. <!-- canon-keep-record-root -->
52
53
 
53
- The first entry covers the whole record root, so a record folder added later needs no line here and no sync. The second is the carve-out the harness owns, since it creates a worktree under `.claude/` and requires its target to sit there. The third is the scratch rule's fallback spelling, carried for a project the record move has not reached and retired once none is left to reach.
54
+ - The first entry covers the whole record root, so a record folder added later needs no line here and no sync.
55
+ - The second is the carve-out the harness owns, since it creates a worktree under `.claude/` and requires its target to sit there.
56
+ - The third is the scratch rule's fallback spelling, carried for a project the record move has not reached and retired once none is left.
54
57
 
55
58
  ## CLI
56
59
 
57
- | Command | What it does |
58
- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
59
- | `canon claude init` | Seeds `.claude/` workflow docs, updates `.gitignore` |
60
- | `canon claude sync` | Reconciles `.gitignore` against the manifest. Reports seeded file status. |
61
- | `canon claude setup` | Installs user-level config to `~/.claude/`: statusline, attribution, and the `permissions.allow` and `permissions.deny` lists. Run once per machine. |
60
+ | Command | What it does |
61
+ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
62
+ | `canon claude init` | Seeds `.claude/` workflow docs, updates `.gitignore` |
63
+ | `canon claude sync` | Reconciles `.gitignore` against the manifest. Reports seeded file status. |
64
+ | `canon claude setup` | Installs user-level config to `~/.claude/` once per machine: statusline, attribution, and the permissions allow and deny lists. |
62
65
 
63
66
  ## CLAUDE.md
64
67
 
65
- - Ships as a seed with placeholder project name, description, and key paths. Fill these in after init.
66
- - Section layout: `Context`, `Commands`, `Key paths`. Each section groups rules that share a surface so skills can detect, extend, or skip by heading.
67
- - The `Context` section points at `.claude/` state docs one line. `plan-feature` does the parallel read when invoked. The seed intentionally does not re-list every file.
68
+ - It ships as a seed with placeholder project name, description, and key paths, to fill in after init.
69
+ - Its sections are `Context`, `Commands`, and `Key paths`. Each groups rules that share a surface, so skills can detect, extend, or skip by heading.
70
+ - The `Context` section points at `.claude/` state docs in one line. `plan-feature` does the parallel read when invoked, so the seed does not re-list every file.
68
71
 
69
72
  ## Seed docs
70
73
 
71
- - Seed docs ship with a guidelines preamble above the first H2. These are instructions Claude internalizes before filling in the sections below. They are not sections to populate.
74
+ Seed docs ship with a guidelines preamble above the first H2. Claude internalizes those instructions before filling in the sections below, and they are not sections to populate.
72
75
 
73
76
  ## settings.json
74
77
 
75
- - Project seed at `tooling/claude/seeds/.claude/settings.json` ships three PreToolUse hooks (pairing with `.claude/hooks/index-reminder.sh`, `.claude/hooks/search-reminder.sh`, and `.claude/hooks/scratch-guard.sh`) and a PostToolUse hook (pairs with `.claude/hooks/standards-audit.sh`). Project settings layer over user settings, so per-project files only carry what is genuinely project-specific.
76
- - User-level template at `tooling/claude/user/settings.template.json` carries `attribution.commit` and `attribution.pr` (empty strings to suppress co-author tags), `permissions.allow` with `Bash(bun run *)`, and `permissions.deny` with `Read(**/.env)` and `Read(**/.env.*)` to block accidental secret exposure across any project. Installed once per machine via `canon claude setup`.
78
+ The project and user files split what is project-specific from what is personal.
79
+
80
+ ### Project seed
81
+
82
+ The seed at `tooling/claude/seeds/.claude/settings.json` ships hooks that pair with scripts under `.claude/hooks/`.
83
+
84
+ - Three PreToolUse hooks pair with `index-reminder.sh`, `search-reminder.sh`, and `scratch-guard.sh`.
85
+ - A PostToolUse hook pairs with `standards-audit.sh`.
86
+ - Project settings layer over user settings, so a project file carries only what is project-specific.
87
+
88
+ ### User template
89
+
90
+ The template at `tooling/claude/user/settings.template.json` is installed once per machine by `canon claude setup`.
91
+
92
+ - It sets `attribution.commit` and `attribution.pr` to empty strings to suppress co-author tags.
93
+ - It allows `Bash(bun run *)` under `permissions.allow`.
94
+ - Its `permissions.deny` holds `Read(**/.env)` and `Read(**/.env.*)`, blocking accidental secret exposure across any project.
77
95
  - The deprecated `includeCoAuthoredBy` key is not used.
@@ -2,25 +2,44 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- The cloudflare stack ships one parameterized GitHub Actions workflow that deploys a static build to Cloudflare Pages. It is keyed on host rather than on framework and carries no dependencies, seeds, or scripts of its own, so it syncs onto a project already carrying `astro`, `vite-react`, or any other stack at the same root without colliding.
5
+ The cloudflare stack ships one parameterized GitHub Actions workflow that deploys a static build to Cloudflare Pages. It is keyed on host rather than on framework and carries no dependencies, seeds, or scripts of its own, so it syncs onto a project already carrying `astro`, `vite-react`, or any other stack without colliding.
6
6
 
7
7
  ## Deploy workflow
8
8
 
9
- - Separate `build` and `deploy` jobs, connected by an uploaded artifact, converged on the shape already running in the closest prior art rather than invented fresh.
10
- - The deploy job checks for `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` before doing anything else, and skips with a `::notice::` rather than failing when either is absent. A first merge lands ahead of the Pages project existing, and this guard is what keeps that push green.
11
- - `--branch=${{ github.ref_name }}` on every deploy, which gives every branch a Cloudflare preview URL rather than only `main`. A `workflow_dispatch` run from a branch therefore lands on a preview and never on production, which is what makes dispatching the workflow from an unmerged branch safe.
12
- - The Publish step carries `id: publish` and pins `wranglerVersion`, since the `pages-deployment-alias-url` output it reads first appears in wrangler 3.78. A step after it prints that alias to the job log as `canon-preview-alias: <url>` and to the step summary. `canon pr preview` reads the line out of the run log, so the marker text is a contract with the CLI rather than decoration.
13
- - The concurrency group carries `${{ github.ref_name }}`. GitHub cancels a pending run when a newer one queues in the same group, so a shared group would let a branch preview displace a production deploy waiting its turn.
14
- - A `pull_request` trigger on `closed` runs only the `cleanup-preview` job, which deletes every preview deployment Cloudflare holds for that branch. It lists them through the Pages REST API, because the wrangler listing has no branch filter, and deletes each with `force=true` so a deployment still holding the branch alias goes too. It skips with a notice when the secrets are absent, the same as the deploy job.
15
- - The deploy job checks out the repository and installs Bun even though it builds nothing. `wrangler-action` resolves its package manager from `bun.lock` in the checkout, and dropping that step breaks the deploy on every push once the toolchain it relies on silently goes missing.
9
+ ### Job shape
10
+
11
+ Separate `build` and `deploy` jobs connect through an uploaded artifact, converged on the shape already running in the closest prior art rather than invented fresh.
12
+
13
+ - The deploy job checks for `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` first, and skips with a `::notice::` when either is absent, so a first merge ahead of the Pages project stays green.
14
+ - The deploy job checks out the repository and installs Bun though it builds nothing, since `wrangler-action` resolves its package manager from `bun.lock` in the checkout.
15
+ - The concurrency group carries `${{ github.ref_name }}`. GitHub cancels a pending run when a newer one queues in its group, so a shared group lets a preview displace a production deploy.
16
+
17
+ ### Previews
18
+
19
+ Every branch gets a preview URL rather than only `main`.
20
+
21
+ - `--branch=${{ github.ref_name }}` on every deploy gives each branch a Cloudflare preview URL.
22
+ - A `workflow_dispatch` run from an unmerged branch therefore lands on a preview and never on production, which makes dispatching it safe.
23
+ - The Publish step carries `id: publish` and pins `wranglerVersion`, since the `pages-deployment-alias-url` output it reads first appears in wrangler 3.78.
24
+ - A step after Publish prints the alias to the job log as `canon-preview-alias: <url>` and to the step summary.
25
+ - `canon pr preview` reads that line out of the run log, so the marker text is a contract with the CLI.
26
+
27
+ ### Cleanup
28
+
29
+ A `pull_request` trigger on `closed` runs only the `cleanup-preview` job, which deletes every preview deployment Cloudflare holds for that branch.
30
+
31
+ - It lists them through the Pages REST API, because the wrangler listing has no branch filter.
32
+ - It deletes each with `force=true`, so a deployment still holding the branch alias goes too.
33
+ - It skips with a notice when the secrets are absent, the same as the deploy job.
16
34
 
17
35
  ## Parameters a project fills in by hand
18
36
 
19
- Three values in the seeded file have no generic default and are set once, right after sync:
37
+ Three values in the seeded file have no generic default, and a project sets them once right after sync.
20
38
 
21
- - The `paths:` filter under the `push` trigger. The shipped default is a single `src/**` glob. Widen it to cover every path the build reads when the build draws on catalogs or generated content living outside `src/`.
22
- - The `concurrency.group` name. The shipped default is `deploy-${{ github.ref_name }}`, which is enough for a single-deploy project. Give the `deploy` prefix a project-specific name only if the project runs more than one deploy workflow, and keep the ref suffix.
23
- - The Pages project name, written twice as `REPLACE_WITH_PROJECT_NAME`: once in the `--project-name` flag on the `wrangler pages deploy` command and once as `PROJECT_NAME` in the cleanup job. Set both to the name the `deploy-app` skill creates the Pages project under.
39
+ - The `paths:` filter under the `push` trigger ships as a single `src/**` glob. Widen it to every path the build reads when the build draws on catalogs or generated content outside `src/`.
40
+ - The `concurrency.group` name ships as `deploy-${{ github.ref_name }}`, enough for one deploy. Rename the `deploy` prefix only for a second deploy workflow, and keep the ref suffix.
41
+ - The Pages project name appears twice as `REPLACE_WITH_PROJECT_NAME`, in the `--project-name` flag and as `PROJECT_NAME` in the cleanup job.
42
+ - Set both to the name the `deploy-app` skill creates the project under.
24
43
 
25
44
  ## Re-sync
26
45
 
@@ -9,30 +9,48 @@ The go stack covers Go modules linted and formatted by `golangci-lint` v2, type-
9
9
  ## Scaffold checklist
10
10
 
11
11
  1. Scaffold with `go mod init <module-path>`. The module path is the project's own identity, so this stack never ships a `go.mod`.
12
- 2. Keep `./...` out of `node_modules`: `go mod edit -ignore=./node_modules`. At a root sync the base layer installs `node_modules/` inside the module, and a package there can ship a `.go` file that `go vet`, `go test`, and `golangci-lint` would otherwise walk. The directive needs Go 1.25 or later.
13
- 3. Seed `package.json` so the base layer's bun-side tools (husky, oxfmt, commitlint) have a target to install into: `bun init -y`.
14
- 4. Install base tooling: `canon tooling sync base . --write`
15
- 5. Install go tooling: `canon tooling sync go . --write`
16
- 6. Install the linter: `go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest`. The manifest declares no `[dependencies.dev]`, because manifest injection runs `bun add -D`, which cannot install a Go tool. This step stays manual.
12
+ 2. Keep `./...` out of `node_modules` with `go mod edit -ignore=./node_modules` (Go 1.25 or later). A root sync installs `node_modules/` in the module, and a package there can ship `.go` files.
13
+ 3. Seed `package.json` with `bun init -y`, so the base layer's bun-side tools (husky, oxfmt, commitlint) have a target to install into.
14
+ 4. Install base tooling with `canon tooling sync base . --write`.
15
+ 5. Install go tooling with `canon tooling sync go . --write`.
16
+ 6. Install the linter with `go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest`. This stays manual, since manifest injection runs `bun add -D`, which cannot install a Go tool.
17
17
  7. Run `bun run lint:fix`, then `bun run format`, then `bun run check`.
18
18
 
19
- The go stack also ships `smoke_test.go` at the module root as a copy-once seed. A module with no `.go` file fails `golangci-lint run`, `go vet`, and `go test` on an empty package list, so the seed is what lets `bun run check` pass on a fresh scaffold. It declares `package main`, so delete or rename it once the root package takes another name, or the build reports two packages in one folder.
19
+ ### The smoke test seed
20
+
21
+ The stack ships `smoke_test.go` at the module root as a copy-once seed. A module with no `.go` file fails the linter, `go vet`, and `go test` on an empty package list, so the seed lets `bun run check` pass on a fresh scaffold.
22
+
23
+ It declares `package main`. Delete or rename it once the root package takes another name, or the build reports two packages in one folder.
20
24
 
21
25
  ## golangci-lint
22
26
 
23
- - Use config `version: '2'`.
24
- - Start from `default: standard`.
25
- - Enable `bodyclose`, `errorlint`, `gosec`, `misspell`, `noctx`, `revive`, `sqlclosecheck`, `rowserrcheck`, and `unconvert`. The two SQL linters report only on `database/sql` call sites, so they cost nothing in a module without a database.
26
- - Enable formatters `gofmt` and `goimports`. `lint:fix` runs `golangci-lint fmt` ahead of `golangci-lint run --fix`.
27
- - Exclude `node_modules` from both linters and formatters. The `go.mod` `ignore` directive in the checklist covers every Go tool, but `go.mod` belongs to the project and sync cannot write it, so the config keeps `golangci-lint run` from reporting and `golangci-lint fmt` from rewriting a vendored `.go` file in a module that never added the directive.
27
+ The config uses `version: '2'` and starts from `default: standard`.
28
+
29
+ - Enable `bodyclose`, `errorlint`, `gosec`, `misspell`, `noctx`, `revive`, `sqlclosecheck`, `rowserrcheck`, and `unconvert`.
30
+ - The two SQL linters report only on `database/sql` call sites, so they cost nothing without a database.
31
+ - Enable formatters `gofmt` and `goimports`, with `lint:fix` running `golangci-lint fmt` ahead of `golangci-lint run --fix`.
32
+ - Exclude `node_modules` from both linters and formatters. The `go.mod` `ignore` directive covers every Go tool, but `go.mod` belongs to the project and sync cannot write it.
33
+ - That exclusion keeps `golangci-lint run` from reporting, and `golangci-lint fmt` from rewriting, a vendored `.go` file in a module that never added the directive.
28
34
 
29
35
  ## verify.json
30
36
 
31
- - Require Typecheck (`go vet`), Lint (`golangci-lint run`), and Unit tests (`go test -v`). Base's runner adds the four base phases wherever the folder declares their scripts, then the markdown bans stage.
37
+ ### Phases
38
+
39
+ The go phase list requires three phases and probes the tools first.
40
+
41
+ - Require Typecheck (`go vet`), Lint (`golangci-lint run`), and Unit tests (`go test -v`).
42
+ - Base's runner adds the four base phases where the folder declares their scripts, then the markdown bans stage.
32
43
  - Probe `go` and `golangci-lint` first, and name the `go install` command when `golangci-lint` is missing.
33
- - Keep `build` out of `verify.json`, even though the stack declares the script. `go build ./...` exits 1 with `no packages to build` on a module holding only a test file, and a seeded `main.go` would assume every module is a binary rather than a library.
34
- - Keep `-race` out of `test:run`. The race detector needs cgo and a C toolchain, so it belongs in CI rather than in a local `bun run check`.
35
- - The manifest's `[verify] prepare` runs checklist steps 3 and 6 for `canon tooling verify go`: `bun init -y`, then the `golangci-lint` `go install` when the binary is not already on PATH. The scaffold writes no `package.json`, and a verify that reaches its end with none fails.
44
+
45
+ ### Left out and prepared
46
+
47
+ Two things stay out of the list, and one step runs before it.
48
+
49
+ - Keep `build` out, though the stack declares the script. `go build ./...` exits 1 with `no packages to build` on a module holding only a test file.
50
+ - A seeded `main.go` would assume every module is a binary rather than a library.
51
+ - Keep `-race` out of `test:run`. The race detector needs cgo and a C toolchain, so it belongs in CI rather than a local `bun run check`.
52
+ - The manifest's `[verify] prepare` runs checklist steps 3 and 6 for `canon tooling verify go`, being `bun init -y` and the `go install` when the binary is not on PATH.
53
+ - The scaffold writes no `package.json`, and a verify that reaches its end with none fails.
36
54
 
37
55
  ## CI
38
56
 
@@ -48,15 +66,21 @@ The go stack also ships `smoke_test.go` at the module root as a copy-once seed.
48
66
 
49
67
  ## Development docs (extend)
50
68
 
51
- Append to the `## Scripts` table:
69
+ Append these rows to the `## Scripts` table.
52
70
 
53
- | `bun run lint` | Run `golangci-lint run`. |
54
- | `bun run lint:fix` | Format with `golangci-lint fmt`, then auto-fix with `golangci-lint run --fix`. |
55
- | `bun run typecheck` | Run `go vet`. |
56
- | `bun run test` | Run `go test`. |
57
- | `bun run test:run` | Run `go test -v` (used by `verify`). |
58
- | `bun run build` | Run `go build`. |
71
+ | Command | Purpose |
72
+ | ------------------- | ------------------------------------------------------------------------------ |
73
+ | `bun run lint` | Run `golangci-lint run`. |
74
+ | `bun run lint:fix` | Format with `golangci-lint fmt`, then auto-fix with `golangci-lint run --fix`. |
75
+ | `bun run typecheck` | Run `go vet`. |
76
+ | `bun run test` | Run `go test`. |
77
+ | `bun run test:run` | Run `go test -v` (used by `verify`). |
78
+ | `bun run build` | Run `go build`. |
59
79
 
60
80
  ## CI docs (extend)
61
81
 
62
- In `canon/context/development/ci.md`, the Typecheck row's assertion reads: `` `go vet ./...` passes ``. Add a Lint row whose assertion reads: `` `golangci-lint run` passes ``. Add a Tests row whose assertion reads: `` `go test -race ./...` exits 0 ``. <!-- audit-ignore-citations: canon/context/development/ci.md -->
82
+ In `canon/context/development/ci.md`, add or change three rows. <!-- audit-ignore-citations: canon/context/development/ci.md -->
83
+
84
+ - The Typecheck row asserts `` `go vet ./...` passes ``.
85
+ - A Lint row asserts `` `golangci-lint run` passes ``.
86
+ - A Tests row asserts `` `go test -race ./...` exits 0 ``.