@erclx/canon 5.68.0 → 5.70.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 (125) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +33 -159
  3. package/assets/brand/mark.svg +17 -9
  4. package/claude/.claude-plugin/plugin.json +1 -1
  5. package/claude/skills/app-drive/REQUIREMENT.md +5 -5
  6. package/claude/skills/app-drive/SKILL.md +17 -6
  7. package/claude/skills/app-drive/references/drive-record.md +61 -8
  8. package/claude/skills/app-drive/references/isolate.md +1 -1
  9. package/claude/skills/canon-cli/SKILL.md +2 -2
  10. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
  11. package/claude/skills/canon-feedback/SKILL.md +1 -1
  12. package/claude/skills/design-identity/REQUIREMENT.md +4 -4
  13. package/claude/skills/design-identity/SKILL.md +7 -7
  14. package/claude/skills/{pick-by-eye → design-pick}/REQUIREMENT.md +6 -6
  15. package/claude/skills/{pick-by-eye → design-pick}/SKILL.md +19 -10
  16. package/claude/skills/{pick-by-eye → design-pick}/references/board.md +17 -11
  17. package/claude/skills/design-pick/references/design-config.md +33 -0
  18. package/claude/skills/design-record/REQUIREMENT.md +2 -2
  19. package/claude/skills/design-record/SKILL.md +1 -1
  20. package/claude/skills/design-taste/REQUIREMENT.md +2 -2
  21. package/claude/skills/design-taste/SKILL.md +3 -3
  22. package/claude/skills/design-taste/references/preflight.md +1 -1
  23. package/claude/skills/git-issue/REQUIREMENT.md +1 -1
  24. package/claude/skills/git-issue/references/issue.md +1 -1
  25. package/claude/skills/plan-feature/SKILL.md +1 -1
  26. package/claude/skills/plan-feature/references/plan.md +21 -6
  27. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  28. package/claude/skills/pr-evidence/references/evidence.md +2 -2
  29. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +3 -3
  30. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +1 -1
  31. package/claude/skills/role-orchestrator/references/orchestrator-planning-wait.md +24 -0
  32. package/claude/skills/role-planner/SKILL.md +4 -2
  33. package/claude/skills/role-worker/SKILL.md +5 -6
  34. package/claude/skills/task-board/references/tasks.md +1 -1
  35. package/claude/skills/task-complete/references/receipt-sweep.md +1 -1
  36. package/claude/skills/{ux-audit → ui-audit}/REQUIREMENT.md +3 -3
  37. package/claude/skills/{ux-audit → ui-audit}/SKILL.md +7 -7
  38. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  39. package/claude/skills/ui-craft/SKILL.md +1 -1
  40. package/claude/skills/ui-craft/references/copy.md +4 -1
  41. package/claude/skills/{ui-record → ui-film}/REQUIREMENT.md +6 -4
  42. package/claude/skills/{ui-record → ui-film}/SKILL.md +26 -13
  43. package/claude/skills/ui-film/references/compose-craft.md +81 -0
  44. package/claude/skills/{ui-record → ui-film}/references/config.md +9 -4
  45. package/claude/skills/{ui-record → ui-film}/references/handoff.md +17 -7
  46. package/claude/skills/{ui-record → ui-film}/references/pr-clip.md +5 -5
  47. package/claude/skills/{ui-record → ui-film}/references/take-craft.md +28 -2
  48. package/claude/skills/{ux-measure → ui-measure}/REQUIREMENT.md +3 -3
  49. package/claude/skills/{ux-measure → ui-measure}/SKILL.md +6 -6
  50. package/docs/agents/audits.md +1 -1
  51. package/docs/agents/migrate.md +13 -13
  52. package/docs/index.md +1 -0
  53. package/docs/migrations/by-hand.md +107 -0
  54. package/docs/migrations/by-verb.md +118 -0
  55. package/docs/migrations/index.md +14 -0
  56. package/docs/target/index.md +1 -2
  57. package/docs/target/projects.md +3 -3
  58. package/docs/target/sync.md +23 -3
  59. package/docs/workflow/ai-workflow.md +1 -1
  60. package/docs/workflow/skill-map-on-request.md +1 -2
  61. package/docs/workflow/skill-map.md +9 -10
  62. package/docs/workflow/visual-design-workflow.md +6 -1
  63. package/governance/ledger/claude/background.md +26 -0
  64. package/governance/ledger/skills/ui-craft/copy.md +8 -4
  65. package/governance/rules/claude/background.md +19 -0
  66. package/governance/stacks/base.toml +1 -0
  67. package/package.json +6 -4
  68. package/scripts/ci/install-playwright-deps.sh +52 -0
  69. package/scripts/core/design-sync.ts +204 -0
  70. package/scripts/core/regen-web-favicon.ts +27 -12
  71. package/scripts/core/regen-web-previews.ts +8 -1
  72. package/scripts/core/render-film.ts +179 -0
  73. package/src/capture/frame-values.ts +12 -12
  74. package/src/claude/cases/authoring.ts +2 -2
  75. package/src/claude/cases/misc.ts +1 -1
  76. package/src/claude/cases/setup.ts +0 -5
  77. package/src/claude/cases/workflow.ts +6 -6
  78. package/src/commands/fixtures/gh.sh +64 -0
  79. package/src/commands/gov.ts +33 -3
  80. package/src/commands/migrate.ts +12 -2
  81. package/src/commands/records.ts +3 -2
  82. package/src/commands/sandbox.ts +9 -2
  83. package/src/commands/take.ts +159 -11
  84. package/src/commands/tasks.ts +183 -0
  85. package/src/design/favicon.ts +85 -13
  86. package/src/design/reference.ts +98 -0
  87. package/src/design/render.ts +16 -14
  88. package/src/design/tokens.ts +4 -3
  89. package/src/gate/stages.ts +8 -2
  90. package/src/gov/audit.ts +48 -11
  91. package/src/gov/detect.ts +1 -1
  92. package/src/init/steps.ts +2 -2
  93. package/src/markdown/scope.ts +9 -14
  94. package/src/migrate/record-layout.ts +5 -3
  95. package/src/migrate/skill-names.ts +21 -4
  96. package/src/migrate/status.ts +3 -3
  97. package/src/records/validate.ts +15 -2
  98. package/src/sandbox/expect.ts +32 -0
  99. package/src/sandbox/headless/dispatch-shim.sh +15 -0
  100. package/src/sandbox/headless/dispatch.ts +12 -14
  101. package/src/sandbox/headless/run.ts +6 -3
  102. package/src/sandbox/stub-gh.sh +26 -0
  103. package/src/sandbox/stub-remote.ts +8 -29
  104. package/src/sync/engine.ts +1 -1
  105. package/src/take/camera.ts +100 -11
  106. package/src/take/film.ts +55 -4
  107. package/src/take/fixtures/input.html +138 -0
  108. package/src/take/keys.ts +193 -0
  109. package/src/take/log.ts +94 -1
  110. package/src/take/perform.ts +165 -10
  111. package/src/take/plan.ts +101 -6
  112. package/src/take/pointer.ts +2 -1
  113. package/src/take/screencast.ts +28 -3
  114. package/src/take/stepper.ts +141 -23
  115. package/src/take/zoom/NOTICE.md +1 -1
  116. package/src/tasks/launch-wait.ts +160 -0
  117. package/tooling/claude/reference.md +1 -1
  118. package/claude/skills/canon-feedback-triage/REQUIREMENT.md +0 -34
  119. package/claude/skills/canon-feedback-triage/SKILL.md +0 -98
  120. package/claude/skills/plan-ready/REQUIREMENT.md +0 -35
  121. package/claude/skills/plan-ready/SKILL.md +0 -136
  122. package/claude/skills/plan-ready/references/assembly.md +0 -75
  123. package/claude/skills/plan-ready/references/ready.md +0 -128
  124. package/docs/target/migrations.md +0 -203
  125. /package/claude/skills/{pick-by-eye → design-pick}/references/live-arms.md +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.70.0](https://github.com/erclx/canon/compare/v5.69.0...v5.70.0) (2026-10-27)
4
+
5
+
6
+ ### Features
7
+
8
+ * **app-drive:** give each drive log finding a heading and fields ([#2791](https://github.com/erclx/canon/issues/2791)) ([f853659](https://github.com/erclx/canon/commit/f853659f5d7793c1af820fcbf55d56fd2f71b981))
9
+ * **brand:** replace the ledger with the ink c and vermilion pip mark ([#2775](https://github.com/erclx/canon/issues/2775)) ([2b7d71e](https://github.com/erclx/canon/commit/2b7d71e329dbaa2ca828dba749ec8c236dc6676b))
10
+ * **design:** land board frames in canon/design through a design sync ([#2792](https://github.com/erclx/canon/issues/2792)) ([b635a33](https://github.com/erclx/canon/commit/b635a33f722a51606b51e1d8539e322233206e39))
11
+ * **design:** land the brand mark sheet as the foundations reference ([#2796](https://github.com/erclx/canon/issues/2796)) ([116caec](https://github.com/erclx/canon/commit/116caec1b233ae58dec8060ada8020381c9722b8))
12
+ * **readme:** open on the mark, claim, launch loop, and install ([#2783](https://github.com/erclx/canon/issues/2783)) ([c86fa26](https://github.com/erclx/canon/commit/c86fa264421cada9ad58c90dd46cf39224330c0f))
13
+ * **sandbox:** read the runner cap from the envelope subtype ([#2794](https://github.com/erclx/canon/issues/2794)) ([4fc750e](https://github.com/erclx/canon/commit/4fc750edc03c302fbfd098c4bf237d745d3124d1))
14
+ * **take:** film drags, key presses, double clicks, and modified clicks ([#2795](https://github.com/erclx/canon/issues/2795)) ([52926e3](https://github.com/erclx/canon/commit/52926e3714a07e13d2efb535c2b8771ea204548d))
15
+ * **take:** name the fallback on a refused beat and add camera controls ([#2789](https://github.com/erclx/canon/issues/2789)) ([6ce5be6](https://github.com/erclx/canon/commit/6ce5be646601274c4b7203527bd6b6cd5e005be8))
16
+ * **ui-craft:** bar the trailing period on every short rendered string ([#2788](https://github.com/erclx/canon/issues/2788)) ([1fc3b4b](https://github.com/erclx/canon/commit/1fc3b4bdd1921a39c21bee225905a138d7422cc5))
17
+ * **ui-film:** add footage guidance for composing takes ([#2793](https://github.com/erclx/canon/issues/2793)) ([dc98a98](https://github.com/erclx/canon/commit/dc98a981bae97921d796e1412a36fb89844e3bba))
18
+ * **web:** rebuild the landing page around one change, plan to merge ([#2787](https://github.com/erclx/canon/issues/2787)) ([c6fdf16](https://github.com/erclx/canon/commit/c6fdf160f7e5140a8066f9370a5703d6d021c2e1))
19
+
20
+ ## [5.69.0](https://github.com/erclx/canon/compare/v5.68.0...v5.69.0) (2026-10-26)
21
+
22
+
23
+ ### Features
24
+
25
+ * **app-drive:** keep pasted images as evidence and cite them in plans ([#2757](https://github.com/erclx/canon/issues/2757)) ([89939db](https://github.com/erclx/canon/commit/89939db9be70811f96613a294947efcac2c0ed91))
26
+ * **claude:** retire the plan-ready skill ([#2760](https://github.com/erclx/canon/issues/2760)) ([808806d](https://github.com/erclx/canon/commit/808806d494dee9ae93ef348b1a48e5b50f777871))
27
+ * **governance:** run slow commands in the background by default ([#2762](https://github.com/erclx/canon/issues/2762)) ([ffb86f3](https://github.com/erclx/canon/commit/ffb86f334d9cbd829a329d2576095416f45f0e8f))
28
+ * **gov:** record why each core rule bullet exists in a ledger ([#2769](https://github.com/erclx/canon/issues/2769)) ([f8d4058](https://github.com/erclx/canon/commit/f8d40585f244a58afba0c34a576d52b39e2b93e0))
29
+ * **skills:** draft pick rounds in the board record folder by default ([#2768](https://github.com/erclx/canon/issues/2768)) ([a3cc12a](https://github.com/erclx/canon/commit/a3cc12a80d6a6da60e205be5842f346f81dbe72f))
30
+ * **skills:** draft pick rounds on the design board the project names ([#2759](https://github.com/erclx/canon/issues/2759)) ([6eff8ce](https://github.com/erclx/canon/commit/6eff8ce998e3007e5a2847934c6af4a6b49fba89))
31
+ * **skills:** let a drive session plan the rows its intake produced ([#2758](https://github.com/erclx/canon/issues/2758)) ([0dd775d](https://github.com/erclx/canon/commit/0dd775d3507b094bad9f0c808516b3c288b4b500))
32
+ * **tasks:** wait in the background for a row to become launchable ([#2764](https://github.com/erclx/canon/issues/2764)) ([b45a23a](https://github.com/erclx/canon/commit/b45a23af5301fadd8598afb4d8559c06d7b91354))
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * **take:** let a take request raise its stepped frame stall limit ([#2771](https://github.com/erclx/canon/issues/2771)) ([140aec3](https://github.com/erclx/canon/commit/140aec340b3e43c12bc67bd74fc96155661bd92b))
38
+
3
39
  ## [5.68.0](https://github.com/erclx/canon/compare/v5.67.0...v5.68.0) (2026-10-26)
4
40
 
5
41
 
package/README.md CHANGED
@@ -1,193 +1,67 @@
1
1
  <div align="center">
2
2
 
3
3
  <picture>
4
- <source media="(prefers-color-scheme: dark)" srcset="assets/brand/mark-accent.svg">
5
- <img src="assets/brand/mark-accent-light.svg" alt="canon" width="56" height="56">
4
+ <source media="(prefers-color-scheme: dark)" srcset="assets/brand/mark-color.svg">
5
+ <img src="assets/brand/mark-color-light.svg" alt="canon" width="56" height="56">
6
6
  </picture>
7
7
 
8
8
  # canon
9
9
 
10
+ A CLI and Claude Code plugin that runs your agent's work from plan to merge, holds it to established engineering practice, and installs the same setup in every repo.
11
+
10
12
  [![npm version](https://img.shields.io/npm/v/@erclx/canon)](https://www.npmjs.com/package/@erclx/canon)
11
13
  [![CI status](https://img.shields.io/github/actions/workflow/status/erclx/canon/verify.yml?branch=main)](https://github.com/erclx/canon/actions/workflows/verify.yml)
12
14
  [![License MIT](https://img.shields.io/npm/l/@erclx/canon)](LICENSE)
13
15
 
14
- canon is a CLI and Claude Code plugin that runs your agent's work from plan to merge, holds it to the practices that make code worth keeping, and installs the same setup in every repository.
15
- **[See it run at canon.erclx.dev](https://canon.erclx.dev)**
16
+ <picture>
17
+ <source media="(prefers-color-scheme: dark)" srcset="assets/loops/launch.gif">
18
+ <img src="assets/loops/launch-light.gif" alt="One change running through canon, from the groundwork that measured it through its plan, dispatch, build, and review to the merge" width="960">
19
+ </picture>
16
20
 
17
21
  </div>
18
22
 
19
- That page is one real session the toolkit ran on itself, and every count on it is read from this repository when the page builds.
20
-
21
- ## Why
22
-
23
- If an agent writes code for you in more than one repository, this is for you. canon runs that work from plan to merge. A planner writes the plan, a worker builds it on its own branch, and a separate session reviews the pull request.
24
-
25
- It holds the work to a practice, with rules that load when a matching path is edited and checks that fail when a rule is ignored. Both run on one setup, installed the same way in every repository you keep.
26
-
27
- ### The shared setup
28
-
29
- That shared setup is what the rest of this page describes, and it drifts without a source. Every AI coding setup accumulates the same assets. Prompts to reuse, rules agents should follow, slash commands, skills, seed docs, sync scripts. Once you have enough projects, your copies drift and your agents stop getting consistent signals.
30
-
31
- Three design choices shape the toolkit.
32
-
33
- - Agent-first: every command has a non-interactive path and a JSON catalog. If a Claude Code skill or any other agent cannot drive the CLI without prompts, the design is wrong.
34
- - Text-native: conventions, rules, and prompts are authored as markdown that you and your agents read the same way. No hidden behavior, no compiled state.
35
- - One source, many consumers: this repo is the authoritative copy. Your projects install and sync on demand, never author in place.
36
-
37
- Two limits worth knowing before you install. Claude Code is the only agent runtime the plugin targets, and the CLI needs Bun on your path.
38
-
39
- ## Install
40
-
41
- Add the marketplace, then install the Claude Code plugin.
23
+ ## Quick start
42
24
 
43
25
  ```bash
44
26
  claude plugin marketplace add https://github.com/erclx/canon
45
27
  claude plugin install canon@canon
46
- ```
47
-
48
- <picture>
49
- <source media="(prefers-color-scheme: dark)" srcset="assets/frames/install.png">
50
- <img src="assets/frames/install-light.png" alt="Adding the canon marketplace and installing the plugin in Claude Code">
51
- </picture>
52
-
53
- The skills land as `/canon:<name>`. If your session was already open, run `/reload-plugins` to pick them up.
54
-
55
- Several skills call the `canon` CLI to read catalogs and run installs, and the plugin doesn't put it on your path. Install it from the registry.
56
-
57
- ```bash
58
28
  bun install --global @erclx/canon
59
29
  ```
60
30
 
61
- [Bun](https://bun.sh) is the CLI runtime and has to be on your path first. Confirm the install by resolving `canon --help`.
62
-
63
- ## What is inside
64
-
65
- Each domain has a canonical source in this repo and a thin install or sync CLI on your side. The domains split on one line: some are copied into your project and become yours to edit, and some are never copied at all.
66
-
67
- ### Domain catalog
68
-
69
- | Domain | What it is | How it reaches you |
70
- | -------------- | ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
71
- | Plugin skills | Skills that plan a feature, review a diff, sync the planning docs, and run the ship chain | Loaded live from the plugin, never copied |
72
- | Governance | Coding and authoring rules that load into a Claude session when a matching path is edited | Installed per project by `canon gov install`, refreshed by sync |
73
- | Tooling stacks | Golden configs, seeds, and a reference per framework | Laid down by `canon init`, reconciled by `canon tooling sync` |
74
- | Design system | Ships a `DESIGN.md` intent format pointing at your stylesheet for values, and a skill that drafts one | `canon:design-record` drafts it in your repo |
75
- | Transcripts | A YouTube transcript with metadata frontmatter | `canon transcripts <url>` writes it into any repo |
76
- | Sandbox | Scenario scaffolds that provision an isolated project state for verifying each domain flow | `canon sandbox` |
77
-
78
- The design board lives outside canon in [Frameboard](https://www.npmjs.com/package/frameboard), which `canon:pick-by-eye` drives for each round of candidates.
79
-
80
- ### How domains reach you
81
-
82
- Those domains reach you in three shapes. A tooling stack lands as real files under version control, because a config is something your build reads and your project owns. A plugin skill and the references it carries are never copied, so there is no copy in your repo to drift from this one.
83
-
84
- Governance is the third shape. A rule with a path glob loads only when a matching path is edited, and a rule with none loads every session. Run `canon gov list` to see the glob beside each rule.
85
-
86
- ## It runs on itself
87
-
88
- The workflow this toolkit ships is the workflow that built it. Several Claude Code sessions run at once, each in its own git worktree on its own branch, and each opens its own pull request.
89
-
90
- <picture>
91
- <source media="(prefers-color-scheme: dark)" srcset="demos/agent-view/demo.gif">
92
- <img src="demos/agent-view-light/demo.gif" alt="The canon landing page scrolling from the dispatch section to the branch graph, three workers and a planner on disjoint file sets with the pull request each opened">
93
- </picture>
94
-
95
- That recording is the landing page's own `dispatch` and `workers` sections, driven through a browser against a local build. The branch graph beside the pull request numbers is authored rather than read, because nothing on a build machine records which files four sessions held.
96
-
97
- ## Documentation
98
-
99
- Scaffolding your first project? Start with target projects, then the AI workflow loop. Everything else answers questions that arrive later.
100
-
101
- Working with an agent rather than reading this yourself? It loads `CLAUDE.md` at your project root first, then whichever rules under `.claude/rules/` match the paths it edits. Run `canon docs agents` for the command catalog with flags, exit codes, and JSON shapes.
102
-
103
- - [AI workflow](docs/workflow/ai-workflow.md): feature-development loop inside a toolkit-managed project
104
- - [Operating model](docs/workflow/operating-model.md): orchestrator, planner, and worker roles for building across parallel sessions
105
- - [Skill map](docs/workflow/skill-map.md): plugin skills grouped by the moment a project meets them
106
- - [Skill map on request](docs/workflow/skill-map-on-request.md): plugin skills that serve a request rather than a moment
107
- - [Visual design workflow](docs/workflow/visual-design-workflow.md): how canon plans, builds, and reviews a UI
108
- - [Target projects](docs/target/projects.md): scaffold, add a domain later, sync upstream drift
109
- - [Agents](docs/agents/index.md): CLI flags, exit codes, and JSON output shapes
110
- - [Docs index](docs/index.md): every reference doc in this repo
111
-
112
- ## Update
113
-
114
- Nothing refreshes on its own. Claude Code ships auto-update off for third-party marketplaces, so an installed copy serves whatever version it was installed at until you refresh it.
115
-
116
- ```bash
117
- claude plugin marketplace update canon
118
- claude plugin update canon@canon
119
- canon upgrade
120
- ```
121
-
122
- The first two update the skills, the third updates the CLI, and they move independently. Restart Claude Code, or run `/reload-plugins`, to pick the skills up.
31
+ The skills land as `/canon:<name>`, and the CLI needs Bun on your path. canon runs on Linux and macOS.
123
32
 
124
- `canon upgrade` reads the package manager off its own install path and reinstalls with that one, so you don't have to remember which put it there. It names what it detected before it runs anything, and it refuses a source checkout rather than reinstalling over your clone.
33
+ Set up a repository with `canon init`, which lays down its rules, seeds, and configs.
125
34
 
126
- ### Checking for drift
35
+ ## How a change runs
127
36
 
128
- You don't have to wait until something breaks to find out you're behind. `canon sync --check` and `canon claude skills drift` both report the installed version against the newest published one, and neither changes its exit code over it, so an offline machine reads unknown rather than red.
37
+ | 1. Plan | 2. Build | 3. Review | 4. Merge |
38
+ | -------------------------------------------------------- | ------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------- |
39
+ | A planner reads the code and writes one plan you approve | A worker builds it on its own branch, held to the rules | A fresh session reviews the pull request and posts findings | You read the review and merge |
129
40
 
130
- To stop doing this by hand, turn auto-update on once under `/plugin` in the Marketplaces tab. Confirm what you are running with `canon --version` and `claude plugin list`.
41
+ Each session works in its own worktree, so several changes run at once.
131
42
 
132
- ## Development
43
+ ## What lands in your repo
133
44
 
134
- Working on the toolkit starts from a clone. Running the CLI doesn't, since it installs from the registry. Skip this section unless you're changing the toolkit itself.
45
+ | Part | How it reaches you |
46
+ | ----------------- | ------------------------------------------------------------------------------ |
47
+ | Skills | Loaded live from the plugin, so there is no copy to drift |
48
+ | Rules | Files under `.claude/rules/` that load when you edit a matching path |
49
+ | Configs and seeds | Real files you own, laid down by `canon init` and kept current by `canon sync` |
135
50
 
136
- ### Prerequisites
51
+ ## For your agent
137
52
 
138
- Bun, Git, and a shell are required, and the GitHub CLI is optional.
53
+ - Every command runs without a prompt, and data on stdout pipes clean
54
+ - `canon <command> --help` prints each command's flags, exit codes, and examples
55
+ - Rules load by path, so the agent gets the rule for the file it is editing
139
56
 
140
- - [Bun](https://bun.sh) for the CLI runtime and scripts
141
- - [Git](https://git-scm.com) with worktree support
142
- - [GitHub CLI](https://cli.github.com) (optional) for ship flows
143
- - Shell: `zsh`, since bootstrap appends its aliases to `~/.zshrc`.
57
+ ## Docs
144
58
 
145
- Clone the repo, then run the bootstrap script. It installs dependencies, links the CLI globally, and appends a marked block of Claude Code shell aliases to your `~/.zshrc`.
146
-
147
- ```bash
148
- git clone https://github.com/erclx/canon.git
149
- cd canon
150
- bun install
151
- bun run bootstrap
152
- ```
153
-
154
- The script is idempotent, so re-run it after pulling upstream changes without duplicating anything. It confirms the install by resolving `canon --help` on the last step.
155
-
156
- - It leaves an alias block you already have alone rather than refreshing it, so an alias added upstream needs the block deleted and the script re-run.
157
- - [Zshrc aliases](docs/workflow/zshrc-aliases.md) covers what each alias does, how to pick up a new one, and how to opt out of the block.
158
-
159
- With the CLI linked, scaffold a fresh project.
160
-
161
- ```bash
162
- mkdir ~/my-project && cd ~/my-project
163
- git init
164
- canon init
165
- ```
166
-
167
- `canon init` installs base tooling configs, Claude seeds, and governance rules in one pass.
168
-
169
- - Governance defaults to the `base` stack, so a bare init lands the workflow and doc-authoring rules in `.claude/rules/`.
170
- - Each rule names the skill it loads, so no corpus is copied into your project.
171
- - Pass `--stack <name>` for a language stack such as `node` or `python`, or `--skip governance` to leave rules out.
172
- - Run `canon tooling list --json` to see the catalog.
173
-
174
- For the full journey from scaffold through adding a domain later to syncing upstream drift, see [target projects](docs/target/projects.md).
175
-
176
- ### Internal narrative
177
-
178
- Each domain carries an entry written for someone maintaining the toolkit rather than installing it. These paths resolve in a clone only. The published package ships `docs` and not `.claude`, so an installed copy does not carry them.
179
-
180
- - [Claude Code plugin](canon/context/surfaces/plugin.md)
181
- - [Governance rules](canon/context/surfaces/governance.md)
182
- - [Tooling stacks](canon/context/surfaces/tooling.md)
183
- - [Design system](canon/context/features/design.md)
184
- - [Transcripts](canon/context/features/transcripts.md)
185
- - [Sandbox](canon/context/development/sandbox.md)
59
+ - [AI workflow](docs/workflow/ai-workflow.md): the loop a feature runs
60
+ - [Operating model](docs/workflow/operating-model.md): planners, workers, and reviewers in parallel
61
+ - [Skill map](docs/workflow/skill-map.md): every skill by the moment you reach for it
62
+ - [Agents](docs/agents/index.md): flags, exit codes, and output shapes
63
+ - [Docs index](docs/index.md): every reference doc, updating canon among them
186
64
 
187
65
  ## Contributing
188
66
 
189
- Portfolio project. Issues are welcome. Pull requests are accepted by invitation only, so open an issue rather than a branch. Read the [contributing guidelines](CONTRIBUTING.md) for the local loop, the authoring split, and the commit convention before you file anything.
190
-
191
- ## License
192
-
193
- [MIT](LICENSE)
67
+ Issues are welcome. Pull requests are by invitation, so read the [contributing guide](CONTRIBUTING.md) before you open one. Released under the [MIT license](LICENSE).
@@ -1,10 +1,18 @@
1
- <!-- A bound ledger: two pages fanned open around a spine, drawn as three
2
- solid masses rather than thin strokes, so the shape survives being
3
- rendered at favicon size instead of averaging into grey. The 10-unit
4
- gap between each page and the spine, against an 80-unit frame, is what
5
- keeps the split a visible channel at 16px; a first draft at half that
6
- gap closed into an unreadable blob at the same size. -->
7
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="10 10 80 80">
8
- <path d="M34,20 L15,28 L15,72 L34,80 Z M66,20 L85,28 L85,72 L66,80 Z" fill="currentColor" />
9
- <rect x="44" y="15" width="12" height="70" rx="2" fill="currentColor" />
1
+ <!-- A squarish bold c with one pip just past its mouth, in a 100 unit grid.
2
+ The body is a 76 square at (8, 12) with corner radius 30, stroked 20, so
3
+ the counter is a 36 square at (28, 32) with corner radius 10. The mouth is
4
+ cut from x 46 to the right edge level with the counter, so the inside runs
5
+ straight out of its curve, and the arm ends fall where that cut meets the
6
+ outer corners. The pip is one stroke wide, a 20 square at (81.3, 40) with
7
+ corner radius 3.8, on the center line. The view is centered on the bounds
8
+ so the pip does not clip.
9
+
10
+ The c is one outline rather than a masked square, and nothing carries an
11
+ id, since the nav, the hero, and the card inline this file and two inlined
12
+ copies sharing an id collide. The c fills currentColor so an inlining
13
+ surface hands it the text ink, and the pip carries its own fill under a
14
+ class a CSS rule overrides with the brand pair. -->
15
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.35 -5 110 110">
16
+ <path d="M82.28,32 A30,30 0 0 0 54,12 H38 A30,30 0 0 0 8,42 V58 A30,30 0 0 0 38,88 H54 A30,30 0 0 0 82.28,68 H38 A10,10 0 0 1 28,58 V42 A10,10 0 0 1 38,32 Z" fill="currentColor" />
17
+ <rect class="pip" x="81.3" y="40" width="20" height="20" rx="3.8" fill="#c2380e" />
10
18
  </svg>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "canon",
3
3
  "description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
4
- "version": "5.68.0",
4
+ "version": "5.70.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -15,8 +15,8 @@ Nothing ties the drive to what the app is for, so a goal goes untried and nobody
15
15
 
16
16
  - The drive runs from a copy outside the project, and the copy is gone when the drive closes
17
17
  - Every requirements goal is driven per persona, or marked not driven with its reason
18
- - Every finding names its source and its severity, and carries its evidence inside the intake folder
19
- - The drive files one intake folder, each finding sorted as a bug, a requirements conflict, or a taste call
18
+ - Every finding names its source and its severity, and carries its evidence inside the intake folder, as does every image the operator pastes during the drive
19
+ - The drive files one intake folder, each finding sorted as a bug, a requirements conflict, or a taste call, and a session staying to plan its rows answers it before any row is promoted
20
20
  - `canon intake drive-check` fails a drive that skipped a goal, touched the checkout, or left evidence outside the folder
21
21
 
22
22
  ## Must not
@@ -28,8 +28,8 @@ Nothing ties the drive to what the app is for, so a goal goes untried and nobody
28
28
 
29
29
  ## Out of scope
30
30
 
31
- - Reading source for roughness, which `ux-audit` owns
31
+ - Reading source for roughness, which `ui-audit` owns
32
32
  - Driving one pull request's checklist, which `review-ui` owns
33
- - Measuring paint and layout cost, which `ux-measure` owns
34
- - Picking between a now frame and a fix frame, which `pick-by-eye` owns
33
+ - Measuring paint and layout cost, which `ui-measure` owns
34
+ - Picking between a now frame and a fix frame, which `design-pick` owns
35
35
  - Messaging the controller and ending the session, which `role-planner` owns
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: app-drive
3
- description: Drives a throwaway copy of a built app with the operator, tries every requirements goal per persona, re-checks the last drive's findings, measures each operator ask, sorts each finding as a bug, a requirements conflict, or a taste call, and files the lot as an intake folder that `canon intake drive-check` holds. Use when asked to "drive the app", "kick the tires", "run an app drive", or "drive the build with me", typically after a release or a wave and before planning the next. Do NOT use to read source for UI roughness, which is `ux-audit`, to drive one pull request's checklist, which is `review-ui`, to measure paint or layout cost, which is `ux-measure`, or to fix anything the drive finds.
3
+ description: Drives a throwaway copy of a built app with the operator, tries every requirements goal per persona, re-checks the last drive's findings, measures each operator ask, sorts each finding as a bug, a requirements conflict, or a taste call, and files the lot as an intake folder that `canon intake drive-check` holds. Use when asked to "drive the app", "kick the tires", "run an app drive", or "drive the build with me", typically after a release or a wave and before planning the next. Do NOT use to read source for UI roughness, which is `ui-audit`, to drive one pull request's checklist, which is `review-ui`, to measure paint or layout cost, which is `ui-measure`, or to fix anything the drive finds.
4
4
  metadata:
5
5
  family: check
6
6
  ---
@@ -32,11 +32,11 @@ Read `${CLAUDE_SKILL_DIR}/references/config.md` for `canon/config/app-drive.toml
32
32
  1. Derive `<slug>` from the build being driven, such as `app-drive-0-12-0` for a tag. Claim the folder with `canon records ordinal intake <slug> --claim`.
33
33
  2. Record the baseline with `canon intake drive-check <slug> --baseline --json` from the main root, before the first build step. Stop on any `reason` other than `recorded`.
34
34
  3. Make the throwaway worktree, build it, and serve it per `${CLAUDE_SKILL_DIR}/references/isolate.md`, which also carries the close and the recovery after a crash.
35
- 4. Confirm the address with `canon pr local --root <worktree> --json` and hand it to the operator before driving.
35
+ 4. Confirm the address with `canon pr local --root <worktree> --json`, write it as the drive log's `Address` row, and hand it to the operator before driving.
36
36
 
37
37
  ## Step 2: drive
38
38
 
39
- Read `${CLAUDE_SKILL_DIR}/references/drive-record.md` before the first finding, for the log line, the severity scale, and the record the check reads.
39
+ Read `${CLAUDE_SKILL_DIR}/references/drive-record.md` before the first finding, for the drive log's shape, the severity scale, and the record the check reads.
40
40
 
41
41
  Work through three sources in this order, and name the source on every finding:
42
42
 
@@ -61,7 +61,9 @@ A drive reaches the app the way its personas do, through the page or through the
61
61
  Append each finding to the drive log as it happens, never batched at the end, since a compaction drops what chat alone holds.
62
62
 
63
63
  - Move each frame a finding cites from scratch into the intake folder's `evidence/`, and cite it by that path
64
+ - Copy each image the operator pastes into `evidence/` in the turn its message arrives, under its finding's number, or under a `ref-` prefix when no finding cites it yet
64
65
  - Keep the measured number beside the claim in the log, never only in chat
66
+ - Write an operator's decision under the finding it settles, even when later findings already sit below it, since it is the one edit above the end of the log
65
67
  - Write `drive.json` into the intake folder in the shape `drive-record.md` sets, with one entry per goal
66
68
 
67
69
  ## Step 4: sort
@@ -70,7 +72,7 @@ Give every finding one kind, and keep the severity it was logged with.
70
72
 
71
73
  - **Bug.** The app breaks a goal or its own contract. It becomes an item whose fix a worker can build, with the repro and the evidence path. `systematic-debugging` owns finding its cause.
72
74
  - **Requirements conflict.** The app does what the record says and the operator wants otherwise, or the record contradicts itself. The item carries the drafted diff as text, and the operator decides.
73
- - **Taste.** The call is settled by looking. The item carries a now frame and a fix frame for a `pick-by-eye` pass, written to the config's `proposals` folder.
75
+ - **Taste.** The call is settled by looking. The item carries a now frame and a fix frame for a `design-pick` pass, written to the config's `proposals` folder.
74
76
 
75
77
  ## Step 5: file
76
78
 
@@ -90,6 +92,15 @@ Close only on the operator's word, while the app stays up for as long as they ke
90
92
  4. Run `canon records validate intake <slug>` and fix each `structure` entry it names.
91
93
  5. Hand the operator the text of `canon/config/app-drive.toml` built from Step 1's answers, when the project carried none. Never write it, since a tracked file is the operator's or a worker's.
92
94
 
95
+ ### Planning the drive's rows
96
+
97
+ Run this tail only when the operator, staying after the close, asks this session to plan the drive's rows. The session holds measurements and calls the intake records only as outcomes, so a drive the operator leaves at the close ends there.
98
+
99
+ 1. Answer the intake's `You:` slots with `plan-intake-answer` before any row is promoted from it.
100
+ 2. Send the controller the ready list, naming no item whose `You:` slot is still open, and say this session is planning those rows, so it holds a cold planner for each.
101
+ 3. Wait for the controller to file the rows and name each back. Plan only a row named to this session, and write no task file.
102
+ 4. Plan each named row under `plan-feature`, then link it with `canon tasks plan-link` and announce it per `role-planner` before starting the next.
103
+
93
104
  ## Output
94
105
 
95
106
  Emit the full relative path of every file written, the drive-check `reason`, and the routing counts.
@@ -100,7 +111,7 @@ Emit the full relative path of every file written, the drive-check `reason`, and
100
111
  **Drive:** <N> goals across <P> personas, <F> findings (<B> bugs, <R> requirements conflicts, <T> taste)
101
112
  **Check:** drive-check clean, worktree removed
102
113
 
103
- Next: /plan-intake-answer to answer the You: slots from here, then /task-board to promote what is ready
114
+ Next: /plan-intake-answer to answer the You: slots from here, then /task-board to promote what is ready, or ask this session to plan the rows per Planning the drive's rows
104
115
  ```
105
116
 
106
117
  ## What this delegates
@@ -108,5 +119,5 @@ Next: /plan-intake-answer to answer the You: slots from here, then /task-board t
108
119
  - The controller messages, the talk clause, and the session's end: `role-planner`
109
120
  - The intake folder's shape and its routing test: `plan-intake`
110
121
  - The cause of a bug: `systematic-debugging`
111
- - The pick between a now frame and a fix frame: `pick-by-eye`
122
+ - The pick between a now frame and a fix frame: `design-pick`
112
123
  - The voice of every recorded passage: `write-human`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Drive record
3
- description: The drive log line, the severity scale, the finding sources, and the drive.json shape that canon intake drive-check reads
3
+ description: The drive log, the severity scale, the finding sources, and the drive.json shape that canon intake drive-check reads
4
4
  ---
5
5
 
6
6
  # Drive record
@@ -9,16 +9,69 @@ Read before the first finding of `app-drive`. A drive leaves two records in its
9
9
 
10
10
  ## The drive log
11
11
 
12
- Write the log to `evidence/drive-log.md` inside the intake folder, one line per finding, appended as the finding happens.
12
+ Write the log to `evidence/drive-log.md` inside the intake folder. It opens on a setup table, then takes one heading per finding, appended as the finding happens.
13
13
 
14
- ```plaintext
15
- - <nn>. [<severity>] [<source>] <persona>: did <action>, saw <result>. Evidence: evidence/<nn>-<name>.png
14
+ ```markdown
15
+ # Drive log
16
+
17
+ | Setup | Value |
18
+ | --------- | ------------------------------------------------- |
19
+ | Commit | `v0.13.138` |
20
+ | Copy | `/tmp/tmp.Xy12/app` |
21
+ | Launch | `bun install && bun run build && bun run preview` |
22
+ | Address | `http://127.0.0.1:4530` |
23
+ | In flight | `feat/landing-page` holds `web/` |
24
+
25
+ ## 02. Layers click leaves a half-hidden frame in place
26
+
27
+ `minor` · operator · developer
28
+
29
+ - **Did:** clicked the frame in Layers
30
+ - **Saw:** the view stayed put, with 64% of the frame under the panel edge
31
+ - **Cause:** from code, the reveal acts only when the box is wholly outside the view
32
+ - **Evidence:** `evidence/02-partial-no-pan.png`
33
+ - **Decision (operator):** center the frame unless it is wholly visible
16
34
  ```
17
35
 
18
36
  - `<nn>` numbers findings in the order they were found, and the frame carries the same number
19
- - `<source>` is `goal`, `last-drive`, or `operator`. A finding naming none sorts as taste.
20
- - `<result>` carries the number read off the page or the app when the claim has one, such as `scrollWidth 436 against clientWidth 320`
21
- - A goal tried and passed takes a line too, as `[pass] [goal]`, so the next drive can tell a goal checked from one skipped
37
+ - The title names what the persona met, in sentence case with no trailing period
38
+ - The meta line holds the severity, the source, and the persona, in that order. The source is `goal`, `last-drive`, or `operator`, and a finding naming none sorts as taste.
39
+ - A `last-drive` finding adds `fixed`, `still open`, or `changed` to its meta line
40
+
41
+ ### Setup rows
42
+
43
+ The setup table is written once, before the first finding, and every row stays even when its value is empty.
44
+
45
+ - `Commit`, `Copy`, and `Launch` come from making the copy, per `isolate.md`
46
+ - `Address` is the `url` that `canon pr local --root <worktree> --json` confirmed in Step 1
47
+ - `In flight` names each open branch or live plan holding a path the drive covers, as `canon:role-planner` reads what is in flight, and reads `none` when nothing is
48
+
49
+ ### Fields
50
+
51
+ The fields under the meta line carry the drive itself, one fact to a line.
52
+
53
+ - `Saw` carries the number read off the page or the app when the claim has one, such as `scrollWidth 436 against clientWidth 320`
54
+ - `Cause` is optional, and says whether it was measured or read from code
55
+ - Write the operator's call as `Decision (operator)` under the finding it settles, even when it arrives after later findings
56
+ - A decision settling two findings sits under the first, and the second carries `Decision (operator):` naming that finding's number, such as `see 02`
57
+ - Keep each field to one line. A field that runs long splits into a second field rather than growing.
58
+
59
+ ### Passed goals
60
+
61
+ A goal tried and passed takes a heading too, so the next drive can tell a goal checked from one skipped. Its meta line reads `pass` · goal · persona, and it carries `Did` and `Evidence` alone.
62
+
63
+ ### Operator images
64
+
65
+ Operator images count as evidence on arrival. One showing a finding takes that finding's number and is cited from its `Evidence` field. One no finding cites yet is a reference shot with a heading of its own.
66
+
67
+ ```markdown
68
+ ## ref-01. The operator's Figma typography panel
69
+
70
+ - **Evidence:** `evidence/ref-01-figma-typography.png`
71
+ ```
72
+
73
+ - `ref-<nn>` numbers reference shots apart from findings, so a later finding citing one keeps the path it already has
74
+ - Keep the pasted file's own extension when it is not a PNG
22
75
 
23
76
  ## Severity
24
77
 
@@ -52,7 +105,7 @@ Write it to the intake folder root before the close. `canon intake drive-check`
52
105
 
53
106
  - `goals` holds one entry per `## Goals` bullet, with the bullet's text. A bold label and a trailing period may stay or go, since the check strips both.
54
107
  - `status` is `driven` or `not-driven`, and a `not-driven` entry carries the `reason` the goal could not be reached
55
- - `evidence` lists every frame a finding cites, each a path under `evidence/` relative to the intake folder
108
+ - `evidence` lists every frame a finding cites and every image the operator pasted, reference shots included, each a path under `evidence/` relative to the intake folder
56
109
  - `worktree` is the throwaway worktree's path, which the check fails on while it still exists
57
110
 
58
111
  ### What the check fails
@@ -13,7 +13,7 @@ Run each command from the main worktree root.
13
13
 
14
14
  1. Run `git worktree prune` first, which drops the registration a crashed drive left behind once its folder is gone.
15
15
  2. Make a folder with `mktemp -d`, outside the repository, and add the worktree with `git worktree add --detach <dir>/app <commit>`. The commit is the tag or sha the operator names, or the trunk's tip.
16
- 3. Record the commit, the folder, and the launch command as the first lines of the drive log.
16
+ 3. Record the commit, the folder, and the launch command as rows of the drive log's setup table, in the shape `drive-record.md` sets.
17
17
  4. Put the worktree's path in `drive.json` as `worktree`, so the check fails a drive whose close never removed it.
18
18
 
19
19
  A folder under the repository is the wrong home. The parent repository becomes the app's repository root, and a walk-up search for config or a lockfile finds the project instead of the copy.
@@ -48,9 +48,9 @@ Each verb here has a skill that owns the job. Load the skill rather than driving
48
48
  | Render an HTML source to a PNG | `canon capture` | `canon:design-identity` |
49
49
  | Serve a directory and print the link | `canon serve` | none |
50
50
  | Report one computed property across routes | `canon inventory` | `canon:target-check` |
51
- | Walk a page through interactions and measure | `canon drive` | `canon:ux-measure` |
51
+ | Walk a page through interactions and measure | `canon drive` | `canon:ui-measure` |
52
52
  | Drive the pinned agent browser | `canon browser` | `canon:review-ui` |
53
- | Film a web app with a click log and camera | `canon take` | `canon:ui-record` |
53
+ | Film a web app with a click log and camera | `canon take` | `canon:ui-film` |
54
54
  | Fetch a YouTube transcript | `canon transcripts` | `canon:youtube-transcripts` |
55
55
 
56
56
  The design board is Frameboard, a separate CLI outside canon, so a board job runs a `frameboard` verb rather than a `canon` one.
@@ -29,6 +29,6 @@ Asked to report, a session also starts diagnosing, which spends the context the
29
29
  ## Out of scope
30
30
 
31
31
  - Fixing the defect, which happens in the toolkit repository against its own source
32
- - Draining the queue this fills, which `canon-feedback-triage` owns
32
+ - Draining the queue this fills, which the toolkit's maintainers do in its own repository
33
33
  - Filing an issue against the current project, which `git-issue` owns
34
34
  - Complaints about tooling the toolkit does not own
@@ -7,7 +7,7 @@ metadata:
7
7
 
8
8
  # Canon feedback
9
9
 
10
- Format a `## Toolkit feedback` block from the current session, then open it as a GitHub issue on the toolkit repo, labeled `feedback` plus the domain label its surface type names. `canon-feedback-triage` reads that queue.
10
+ Format a `## Toolkit feedback` block from the current session, then open it as a GitHub issue on the toolkit repo, labeled `feedback` plus the domain label its surface type names. The toolkit's maintainers triage that queue.
11
11
 
12
12
  ## Guards
13
13
 
@@ -15,7 +15,7 @@ A session building this alone restates the render-and-pick loop from scratch, wh
15
15
 
16
16
  - The icon size sequence and the write folder come from the project's own head, manifest, or static-asset convention before a stated default, and the run names which one decided
17
17
  - Every arm is drafted inside the card frame, so one pick settles the mark's shape and its composition together
18
- - The render, hand-off, pick, and loop follow `pick-by-eye` rather than a copy of it
18
+ - The render, hand-off, pick, and loop follow `design-pick` rather than a copy of it
19
19
  - The final mark lands as its own SVG source, not only baked into a raster
20
20
  - Every final size and the card render in one capture call, each landing at its literal target size
21
21
 
@@ -23,12 +23,12 @@ A session building this alone restates the render-and-pick loop from scratch, wh
23
23
 
24
24
  - Draft a mark the operator did not ask for, or mutate an existing logo file, which is a plain edit
25
25
  - Add a logo section to the design document's fixed section set, which its parser reads as a fixed key set
26
- - Modify `pick-by-eye` or `canon capture`, which this skill composes
26
+ - Modify `design-pick` or `canon capture`, which this skill composes
27
27
  - Be taken as reached by more than an operator typing its name, which a later review reads back rather than assumes
28
28
 
29
29
  ## Out of scope
30
30
 
31
- - The render, hand-off, pick, and loop mechanics, which `pick-by-eye` owns
31
+ - The render, hand-off, pick, and loop mechanics, which `design-pick` owns
32
32
  - Carrying a picked direction into the design document, which `design-record` owns
33
- - Auditing an implemented UI against its tokens, which `ux-audit` owns
33
+ - Auditing an implemented UI against its tokens, which `ui-audit` owns
34
34
  - Wiring the produced files into the project's head or manifest, which the operator owns