@erclx/canon 5.69.0 → 5.71.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 (67) hide show
  1. package/CHANGELOG.md +25 -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/SKILL.md +3 -2
  6. package/claude/skills/app-drive/references/drive-record.md +52 -10
  7. package/claude/skills/app-drive/references/isolate.md +1 -1
  8. package/claude/skills/design-pick/SKILL.md +1 -0
  9. package/claude/skills/git-pr/references/task-number.md +13 -0
  10. package/claude/skills/markdown-craft/references/markdown.md +1 -0
  11. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +1 -0
  12. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +6 -20
  13. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +10 -0
  14. package/claude/skills/role-orchestrator/references/orchestrator-talk-launch.md +30 -0
  15. package/claude/skills/task-board/references/tasks-record-lines.md +40 -0
  16. package/claude/skills/task-board/references/tasks.md +4 -8
  17. package/claude/skills/ui-craft/references/copy.md +4 -1
  18. package/claude/skills/ui-film/REQUIREMENT.md +4 -2
  19. package/claude/skills/ui-film/SKILL.md +24 -11
  20. package/claude/skills/ui-film/references/compose-craft.md +81 -0
  21. package/claude/skills/ui-film/references/config.md +6 -1
  22. package/claude/skills/ui-film/references/handoff.md +13 -3
  23. package/claude/skills/ui-film/references/take-craft.md +27 -1
  24. package/docs/index.md +1 -0
  25. package/docs/migrations/by-hand.md +107 -0
  26. package/docs/migrations/by-verb.md +118 -0
  27. package/docs/migrations/index.md +14 -0
  28. package/docs/target/index.md +1 -2
  29. package/docs/target/projects.md +2 -2
  30. package/docs/target/sync.md +22 -2
  31. package/docs/workflow/ai-workflow.md +1 -1
  32. package/governance/ledger/skills/ui-craft/copy.md +8 -4
  33. package/package.json +3 -1
  34. package/scripts/core/design-sync.ts +204 -0
  35. package/scripts/core/regen-web-favicon.ts +27 -12
  36. package/scripts/core/regen-web-previews.ts +8 -1
  37. package/scripts/core/render-film.ts +179 -0
  38. package/src/capture/frame-values.ts +12 -12
  39. package/src/commands/markdown.ts +6 -1
  40. package/src/commands/records.ts +3 -2
  41. package/src/commands/sandbox.ts +9 -2
  42. package/src/commands/take.ts +159 -11
  43. package/src/commands/tasks.ts +133 -0
  44. package/src/design/favicon.ts +85 -13
  45. package/src/design/reference.ts +98 -0
  46. package/src/design/render.ts +16 -14
  47. package/src/design/tokens.ts +4 -3
  48. package/src/gate/stages.ts +6 -0
  49. package/src/init/steps.ts +2 -2
  50. package/src/markdown/colons.ts +102 -16
  51. package/src/migrate/status.ts +3 -3
  52. package/src/records/validate.ts +14 -2
  53. package/src/sandbox/expect.ts +32 -0
  54. package/src/sandbox/headless/run.ts +6 -3
  55. package/src/take/camera.ts +99 -10
  56. package/src/take/film.ts +35 -2
  57. package/src/take/fixtures/input.html +138 -0
  58. package/src/take/keys.ts +193 -0
  59. package/src/take/log.ts +94 -1
  60. package/src/take/perform.ts +165 -10
  61. package/src/take/plan.ts +101 -6
  62. package/src/take/screencast.ts +28 -3
  63. package/src/take/stepper.ts +122 -18
  64. package/src/tasks/archive.ts +54 -1
  65. package/src/tasks/record.ts +118 -0
  66. package/src/tasks/validate.ts +37 -0
  67. package/docs/target/migrations.md +0 -205
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.71.0](https://github.com/erclx/canon/compare/v5.70.0...v5.71.0) (2026-10-27)
4
+
5
+
6
+ ### Features
7
+
8
+ * **markdown:** read colon lists as labels ([#2797](https://github.com/erclx/canon/issues/2797)) ([f733a5f](https://github.com/erclx/canon/commit/f733a5f8d74e63cf5e257557a4d227b3478ca04a))
9
+ * **tasks:** name the sessions behind a task on a Sessions line ([#2799](https://github.com/erclx/canon/issues/2799)) ([acf80c4](https://github.com/erclx/canon/commit/acf80c4ce9d2c1adbc3e1ea2dfde433a08d46b4e))
10
+
11
+ ## [5.70.0](https://github.com/erclx/canon/compare/v5.69.0...v5.70.0) (2026-10-27)
12
+
13
+
14
+ ### Features
15
+
16
+ * **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))
17
+ * **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))
18
+ * **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))
19
+ * **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))
20
+ * **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))
21
+ * **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))
22
+ * **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))
23
+ * **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))
24
+ * **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))
25
+ * **ui-film:** add footage guidance for composing takes ([#2793](https://github.com/erclx/canon/issues/2793)) ([dc98a98](https://github.com/erclx/canon/commit/dc98a981bae97921d796e1412a36fb89844e3bba))
26
+ * **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))
27
+
3
28
  ## [5.69.0](https://github.com/erclx/canon/compare/v5.68.0...v5.69.0) (2026-10-26)
4
29
 
5
30
 
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:design-pick` 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.69.0",
4
+ "version": "5.71.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -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
 
@@ -63,6 +63,7 @@ Append each finding to the drive log as it happens, never batched at the end, si
63
63
  - Move each frame a finding cites from scratch into the intake folder's `evidence/`, and cite it by that path
64
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
65
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
66
67
  - Write `drive.json` into the intake folder in the shape `drive-record.md` sets, with one entry per goal
67
68
 
68
69
  ## Step 4: sort
@@ -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,23 +9,65 @@ 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.
22
62
 
23
63
  ### Operator images
24
64
 
25
- Operator images count as evidence on arrival. One showing a finding takes that finding's number and is cited from that finding's line, while one no finding cites yet is a reference shot with a log line of its own.
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
26
69
 
27
- ```plaintext
28
- - ref-<nn>. [operator] <what the image shows>. Evidence: evidence/ref-<nn>-<name>.png
70
+ - **Evidence:** `evidence/ref-01-figma-typography.png`
29
71
  ```
30
72
 
31
73
  - `ref-<nn>` numbers reference shots apart from findings, so a later finding citing one keeps the path it already has
@@ -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,6 +48,7 @@ Each frame carries its own label and follows the board theme, so the set reads a
48
48
  - Label each arm inside its frame with its id and its cost, since the composite capture draws no captions
49
49
  - Theme every arm off the `data-theme` attribute the board sets on each frame's root, so the theme toggle sets the whole set at once. A set spanning both themes cannot be compared.
50
50
  - Give no arm a script that stores a theme and reapplies it on load. It overwrites the toggle, and a fresh browser profile hides the fault.
51
+ - Write each frame's headings, labels, and captions by `${CLAUDE_SKILL_DIR}/../ui-craft/references/copy.md`, since a candidate's copy is often the first draft of the shipped page's
51
52
 
52
53
  ### Default path and live app
53
54
 
@@ -29,6 +29,19 @@ The verb resolves the board at the main worktree root in-process, the root `sess
29
29
  - A line already reading as a list of `#NNN` entries takes the new number appended, reported as `appended`, so a task shipped in slices keeps every pull request
30
30
  - The same write drops this branch from the `Pending branch:` line `canon tasks outcome` wrote, which lets the merge-time archive close the task
31
31
 
32
+ ## Record the session
33
+
34
+ Beside the number, name this session on the same task's `Sessions:` line. It is the one record that covers a hand-launched worker, which no dispatcher saw start. Read the id from the roster's own row for the caller, then hand it to the verb under the same plan:
35
+
36
+ ```bash
37
+ id=$(canon sessions list --self --json | jq -r '.sessions[0].sessionId // empty')
38
+ [ -n "$id" ] && canon tasks session "$id" --plan feature-<slug> --json
39
+ ```
40
+
41
+ - A dispatched worker is already listed, since its dispatcher recorded it at launch, and the verb reports `unchanged` rather than writing it twice
42
+ - An empty `id` means the roster could not name the caller, so skip the write and report that no session was recorded
43
+ - Skip the same three refusals as the number below, and report `bad-input` or `no-name`, since either is a defect in this call
44
+
32
45
  ## Refusals
33
46
 
34
47
  Skip silently when the record is `ok: false` and `reason` is `no-board`, `no-match`, or `ambiguous`, meaning no board, no task naming the plan, or more than one. A guessed write would compound each, since a wrong match archives the wrong task unattended once the branch merges. Report any other refusal rather than swallowing it.
@@ -134,6 +134,7 @@ A bullet's punctuation follows its sentence count, and a list opens unannounced.
134
134
 
135
135
  - Do not use em dashes (`—`) or semicolons (`;`). Rewrite or restructure the sentence to avoid them. A colon or a comma standing where the dash was is the same sentence, so split it or rewrite it.
136
136
  - Do not use a colon to join two clauses in the middle of a sentence. A colon belongs after a label or at the end of a line introducing a list.
137
+ - The check misses a clause colon in a list of colon items, but it is wrong.
137
138
  - Do not use parenthetical asides in prose (`the config (which is optional) controls...`). Split into its own sentence or drop it. Parentheses in rule definitions for grouping examples are fine.
138
139
 
139
140
  ## Language
@@ -86,6 +86,7 @@ The readout is the text `Created cloud session: <title>`, unanchored since a ter
86
86
  - On a failed create, report the typescript's last lines and fall back to the human-launch line in `orchestrator-dispatch.md`
87
87
  - The wrapper is a stopgap any change to the interactive create screen breaks, which is why the readout fails loudly instead of guessing
88
88
  - Record `session` beside the row's branch in this pass's launched record, since that and the pull request list are the only readings that know it exists
89
+ - Name it on the row's task with `canon tasks session "$session" <task> --name cloud-<project>-<slug> --json`, since a cloud worker has no board and the roster never lists it
89
90
  - Report the dispatch as the local shape does, naming the row, the plan, the repository, and the session id in place of a session name
90
91
 
91
92
  ## Recognize the pull request
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Orchestrator launch runbook
3
- description: The launch every dispatch kind shares, being the build, cloud build, review-address, planning, and talk templates, the session name and controller id each carries, why the command sits at position zero, and what the brief may carry
3
+ description: The launch every dispatch kind shares, being the build, cloud build, review-address, and planning templates with a pointer to the talk variant, the session name and controller id each carries, why the command sits at position zero, and what the brief may carry
4
4
  ---
5
5
 
6
6
  Run this once `orchestrator-dispatch.md` has cleared a row, or from its planning or review-address shape below when that runbook's checks do not bind. The model each template names comes from `## Pick the model` in that runbook.
@@ -79,6 +79,10 @@ The prompt carries pointers and standing context, and stops there. The branch an
79
79
 
80
80
  Report the dispatch as loudly as the human-launch line it replaces, naming the branch, the model, the task, and the session name, so a person reading the transcript can follow what fired without watching it happen.
81
81
 
82
+ ### Record the worker on its task
83
+
84
+ Once a build or review-address launch returns, run `canon tasks session <worker-id> <task> --json` with the sessionId the launch output carries. On `no-name`, the worker already exited, so rerun with `--name` and the name passed to `-n`.
85
+
82
86
  ## Dispatch to a cloud worker
83
87
 
84
88
  Read `${CLAUDE_SKILL_DIR}/references/orchestrator-cloud-launch.md` when `orchestrator-dispatch.md` picked cloud for the row. It holds the prompt that carries the plan as text and announces over GitHub, the create under `script`, and the readout that refuses to record a missing session id.
@@ -137,25 +141,7 @@ Hold all planning of a row any talk session has said by message it is planning,
137
141
 
138
142
  ## Dispatch a talk session
139
143
 
140
- A planner or worker the operator will talk with takes the same launch as its cold shape above, with a `-talk` suffix on its name and one sentence added to its brief. A cold session works alone and reports back, and a talk session stays open after its plan or pull request lands so the operator can keep shaping the row.
141
-
142
- ```bash
143
- claude --bg --model <model> -n "planner-<project>-<slug>-talk" "Run /canon:role-planner, then /canon:plan-feature <task>. This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
144
- claude --bg --model <model> -n "worker-<project>-<slug>-talk" "/canon:auto-ship <plan>
145
- This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
146
- ```
147
-
148
- The ellipsis stands for the rest of the cold template's message clauses, unchanged. The build variant keeps `/canon:auto-ship <plan>` at position zero with nothing before it, per the rule above.
149
-
150
- - Keep the role prefix and add the suffix, since `orchestrator-handoff.md` separates dispatched sessions by `worker-` and `planner-` and a new prefix reads as a hand launch
151
- - A talk session is retired only on the operator's word, stated once in `orchestrator-handoff.md`, so do not restate it in a launch report
152
- - Reviewers get no talk shape, since a reviewer's pass holds no operator dialogue
153
-
154
- ### Recording the talk session
155
-
156
- Read the session's `sessionId` off the launch output, carry it in this session's own context, and write it into the map's `## Talk sessions held open` at the next handoff. The client can rename a session and drop the suffix, so the id is the durable marker and the suffix is only for display.
157
-
158
- The map exists only once the handoff writes it, so this session's own launches, read with the prior map, are what the first wind-down reads talk sessions from.
144
+ Read `${CLAUDE_SKILL_DIR}/references/orchestrator-talk-launch.md` when the operator will talk with a planner or worker rather than leave it to report back. It states the `-talk` name suffix, the one sentence the brief adds, and where the session's id is kept for the handoff.
159
145
 
160
146
  ## Hand launch
161
147
 
@@ -21,6 +21,16 @@ claude --bg --model <model> -n "reviewer-<project>-<number>" "Run /canon:role-re
21
21
  - Append the cross-branch facts after the controller clause, per `### What the brief may carry` in `orchestrator-launch.md`
22
22
  - Check `canon sessions list --json` for a live `reviewer-<project>-<number>` before launching, and message it instead when one holds the pull request
23
23
 
24
+ ### Record the reviewer on the task
25
+
26
+ A reviewer writes no task file, so this session names it on the task the pull request closes, through the sessionId the launch output carries:
27
+
28
+ ```bash
29
+ canon tasks session <reviewer-id> <task> --json
30
+ ```
31
+
32
+ Record the UI reviewer below the same way after its launch. A `no-name` refusal means the reviewer exited before the read, so rerun with `--name` and the name the launch passed to `-n`.
33
+
24
34
  ### The channel clauses
25
35
 
26
36
  The channel clauses restate what `role-reviewer` holds, so a reviewer whose plugin cache predates that body still sends the dispatch itself. The worker reads the reviewer's sessionId off that message and sends its re-review request back to it, since a reviewer holds the trunk branch and no branch lookup finds it.
@@ -0,0 +1,30 @@
1
+ ---
2
+ title: Orchestrator talk launch
3
+ description: The talk variant of the planning and build launches, being the name suffix, the one added brief sentence, and where the talk session's id is recorded for the handoff
4
+ ---
5
+
6
+ Run this when the operator wants to talk with a planner or worker rather than leave it to report back. The rules every launch shares stay in `orchestrator-launch.md`.
7
+
8
+ # Talk launch
9
+
10
+ ## The launch
11
+
12
+ A planner or worker the operator will talk with takes the same launch as its cold shape in `orchestrator-launch.md`, with a `-talk` suffix on its name and one sentence added to its brief. A cold session works alone and reports back, and a talk session stays open after its plan or pull request lands so the operator can keep shaping the row.
13
+
14
+ ```bash
15
+ claude --bg --model <model> -n "planner-<project>-<slug>-talk" "Run /canon:role-planner, then /canon:plan-feature <task>. This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
16
+ claude --bg --model <model> -n "worker-<project>-<slug>-talk" "/canon:auto-ship <plan>
17
+ This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
18
+ ```
19
+
20
+ The ellipsis stands for the rest of the cold template's message clauses, unchanged. The build variant keeps `/canon:auto-ship <plan>` at position zero with nothing before it, per `### Position zero` in `orchestrator-launch.md`.
21
+
22
+ - Keep the role prefix and add the suffix, since `orchestrator-handoff.md` separates dispatched sessions by `worker-` and `planner-` and a new prefix reads as a hand launch
23
+ - A talk session is retired only on the operator's word, stated once in `orchestrator-handoff.md`, so do not restate it in a launch report
24
+ - Reviewers get no talk shape, since a reviewer's pass holds no operator dialogue
25
+
26
+ ## Recording the talk session
27
+
28
+ Read the session's `sessionId` off the launch output, carry it in this session's own context, and write it into the map's `## Talk sessions held open` at the next handoff. The client can rename a session and drop the suffix, so the id is the durable marker and the suffix is only for display.
29
+
30
+ The map exists only once the handoff writes it, so this session's own launches, read with the prior map, are what the first wind-down reads talk sessions from.
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: Task record lines reference
3
+ description: The lines a verb writes on a task below its origin lines, being the Pull request line that lets a merge close its task, the Pending branch marker that holds that merge back, and the Sessions line naming who worked it
4
+ ---
5
+
6
+ # Task record lines reference
7
+
8
+ Applies to the lines a task carries under its origin lines that no session writes by hand. Each one has a `canon tasks` verb as its writer, and this file fixes what each line means and who calls that verb.
9
+
10
+ This is an attribute standard. It governs lines inside a task file rather than a file of its own, so it carries no template.
11
+
12
+ ## Scope
13
+
14
+ Governs the `Pull request:`, `Pending branch:`, and `Sessions:` lines.
15
+
16
+ Does not govern:
17
+
18
+ - The task file's layout, filename, format, origin lines, and archiving: `tasks.md`
19
+ - The `Declined:` line: `tasks-decline.md`
20
+
21
+ ## The `Pull request:` line
22
+
23
+ `Pull request:` lists every pull request that shipped part of the task as bare numbers, oldest first and comma-separated, as in `Pull request: #NNN, #NNN`. It is not an origin, so a task without one is well-formed, and `git-pr` appends to it when a pull request opens.
24
+
25
+ The line lets a merge close its own task. `canon tasks archive --pull-request <n>` finds the task by any listed number and archives it only on the last.
26
+
27
+ - One pull request, one task. Two tasks naming the same number refuse to archive rather than both moving.
28
+ - `Pending branch: <branch>` holds that merge back while a branch that ticked an outcome waits on its own number
29
+ - `canon tasks outcome` writes that line, skipping it when the branch's pull request is already listed, and `canon tasks pull-request` clears it
30
+
31
+ ## The `Sessions:` line
32
+
33
+ `Sessions:` names each session that built or reviewed the task, by roster name and full sessionId, as in `Sessions: <name> (<sessionId>), <name> (<sessionId>)`. A retro or a regression hunt reaches each transcript through `canon sessions export <sessionId>`, which takes the full id alone. It is not an origin either.
34
+
35
+ - `canon tasks session <sessionId> <task>` writes it, or `--plan <slug>` in place of the stem, so it is never hand-edited
36
+ - The verb reads the name off the live roster. A session that already exited takes `--name`, and so does a cloud session's `session_` id, since the roster never lists one.
37
+ - The id is the key. A repeat call for a listed id keeps the name first recorded, so two callers recording one worker write it once.
38
+ - The dispatcher records each worker and reviewer it launches, and `git-pr` records the session opening the pull request, which covers a hand launch
39
+
40
+ The line sits below the origin, `Pull request:`, and `Pending branch:` lines. `canon tasks validate` reports a line that does not parse as name and id pairs as `sessions-misshapen`.