@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
@@ -29,6 +29,7 @@ Governs the task files under `.canon/tasks/`: folder layout, filenames, frontmat
29
29
  Does not govern:
30
30
 
31
31
  - **`tasks-decline.md`**: the declined folder, the `Declined:` line, and what declining does to a plan and a board row
32
+ - **`tasks-record-lines.md`**: the `Pull request:`, `Pending branch:`, and `Sessions:` lines a verb writes below the origin lines
32
33
  - **`board.md`**: execution order, readiness groups, the backlog, and the generated index beside the tasks
33
34
  - **`plan.md`**: the plan file a task cites, its sections, and its answer contract
34
35
  - **`versioning.md`**: phase-label format and which surfaces a label may appear on
@@ -112,6 +113,7 @@ Groundwork: [<slug>](../groundwork/<slug>/)
112
113
  Intake: [<slug>](../intake/<slug>/)
113
114
  Issue: #NNN
114
115
  Pull request: #NNN
116
+ Sessions: <name> (<sessionId>)
115
117
 
116
118
  Why this task exists and what it depends on.
117
119
 
@@ -165,15 +167,9 @@ Three rules cover the line itself:
165
167
  - Use `Intake:` rather than `Groundwork:` for an intake pass, so the line records which kind of pass produced the task
166
168
  - `Intake:` names the folder rather than an item, and item numbers belong in the task's `## Findings`
167
169
 
168
- ### The `Pull request:` line
170
+ ### The lines a verb writes
169
171
 
170
- `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.
171
-
172
- 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.
173
-
174
- - One pull request, one task. Two tasks naming the same number refuse to archive rather than both moving.
175
- - `Pending branch: <branch>` holds that merge back while a branch that ticked an outcome waits on its own number
176
- - `canon tasks outcome` writes that line, skipping it when the branch's pull request is already listed, and `canon tasks pull-request` clears it
172
+ `Pull request:` and `Sessions:` are not origins, so a task without them is well-formed. A verb writes each, and `${CLAUDE_SKILL_DIR}/references/tasks-record-lines.md` fixes what they mean and who calls the verb.
177
173
 
178
174
  ## What goes in
179
175
 
@@ -3,7 +3,10 @@
3
3
  ## Punctuation
4
4
 
5
5
  - Write no em dash (`—`) or semicolon in rendered copy. Use a comma or a period, or restructure the sentence.
6
- - Add no trailing punctuation to a button label or a short action string.
6
+ - Add no trailing period, colon, or exclamation mark to a heading, label, link, button, nav item, caption, status, or one-sentence tagline. Keep the question mark a question needs.
7
+ - Rewrite a two-sentence tagline as one sentence rather than keeping a period inside it.
8
+ - End a one-sentence error or validation message with no period, such as `Enter an email address`.
9
+ - Keep end punctuation on body copy, multi-sentence messages, and quoted text, which a reader reads as prose.
7
10
 
8
11
  ## Button copy
9
12
 
@@ -19,13 +19,15 @@ A session that does reach `canon take` writes the plan from its own reading of t
19
19
  - The session looks at a still of each take before handing it off or posting it as a pull request reel, and names a beat that fell back to the real-time route
20
20
  - HyperFrames receives the takes with what it needs to apply the camera and draw the cursor
21
21
 
22
- One video keeps its plan, takes, and composition in one workspace the operator can find, backed up without its media.
22
+ One video keeps its plan, takes, and composition in one workspace the operator can find, backed up without its media. A README there records how to re-film the takes, and the composing session adds how to re-render.
23
+
24
+ A session composing the takes finds the footage guidance HyperFrames lacks, being captions over app UI, other shapes, a README loop, and sped-up clips.
23
25
 
24
26
  ## Must not
25
27
 
26
28
  - Film before the operator approves, or with nobody there to approve, unless `pr-evidence` named pull request mode, whose still check stands in for the approval
27
29
  - Write a tracked file, the config included
28
- - Compose, caption, or render the video
30
+ - Run the composition or render the video, or write any composition file
29
31
  - Trigger on anything but a request to record or film the app
30
32
  - Stay when no caller besides the operator reaches it, such as a pull request clip through `pr-evidence`, which a review checks
31
33
 
@@ -71,12 +71,15 @@ canon take <url> .canon/video/<slug>/plan.json --out .canon/video/<slug>/takes -
71
71
 
72
72
  Branch on the record's `reason`, never on the exit code, which a shell function wrapping `canon` can flatten to zero.
73
73
 
74
- | Record | Route |
75
- | -------------------- | --------------------------------------------------------------------------------------- |
76
- | No `reason` | Continue to the stills |
77
- | `target-missing` | Find the target the record's `beat` names on the page, fix the plan, and film once more |
78
- | `server-unreachable` | Restart the server from Step 1 and film once more |
79
- | Any other `reason` | Report the `reason` and `message` to the operator and stop, since each is a setup step |
74
+ | Record | Route |
75
+ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
76
+ | No `reason` | Continue to the stills |
77
+ | `target-missing` with `fallback` | Check the access before the selector, per the note below the table |
78
+ | `target-missing` | Open the record's `still`, find the target the record's `beat` names on the page, fix the plan, and film once more |
79
+ | `server-unreachable` | Restart the server from Step 1 and film once more |
80
+ | Any other `reason` | Report the `reason` and `message` to the operator and stop, since each is a setup step |
81
+
82
+ A refusal carrying `fallback` means the screencast opened the address a second time, so a single-use link was spent before the step ran. Read `${CLAUDE_SKILL_DIR}/references/config.md` for the access the take opens with, and fix that before touching the target.
80
83
 
81
84
  A second refusal of the same kind stops the run and reports both records.
82
85
 
@@ -85,30 +88,40 @@ A second refusal of the same kind stops the run and reports both records.
85
88
  Open each beat's `takes/<dir>/still.jpg` before handing off, since a clip can film the wrong state cleanly. The verb writes it from the clip's closing frame, where the action's result shows.
86
89
 
87
90
  - Say what each still shows beside the beat it belongs to
88
- - Report a beat the record marks with `fallback` as filmed in real time at 1080p, which goes soft under a zoom, and offer to re-film it with the beat's input simplified
91
+ - Report a beat the record marks with `fallback` as filmed in real time at 1080p, whose zoom stops near 1.35x rather than 1.8x, and offer to re-film it with the beat's input simplified
89
92
 
90
93
  ## Step 5: hand off
91
94
 
92
- Read `${CLAUDE_SKILL_DIR}/references/handoff.md` on reaching this step. It sets what HyperFrames receives and how a composition applies the camera track and draws the cursor.
95
+ Read `${CLAUDE_SKILL_DIR}/references/handoff.md` on reaching this step, for what HyperFrames receives, where each composition lives, and how one applies the camera track and draws the cursor. Read `${CLAUDE_SKILL_DIR}/references/compose-craft.md` beside it, for the footage rules the HyperFrames skills lack.
93
96
 
94
97
  Close the throwaway copy per `isolate.md` when Step 1 built one, after the stills are read.
95
98
 
99
+ ### Write the workspace README
100
+
101
+ Write the filming half of `.canon/video/<slug>/README.md`, so a later session can re-film without this one. The composing session adds the re-render half under its own heading, as `compose-craft.md` states.
102
+
103
+ - Name what was filmed, beat by beat, and how to re-film each one with `canon take`
104
+ - Say where each folder came from, being the plan, the takes, and the config keys the take read, with `access` described rather than copied when it carries a token
105
+ - Write the file whole through the main-root route when none exists, with the filming half under a `## Filming` heading
106
+ - Add a `## Filming` section when a README is already there, reading the file and writing it back whole, and never overwrite what another session wrote
107
+ - Replace an existing `## Filming` section in place on a re-film, since the commands in it changed
108
+
96
109
  ## Output
97
110
 
98
111
  Emit the takes folder, one line per beat, and the next step.
99
112
 
100
113
  ```plaintext
101
- 🎬 Filmed .canon/video/<slug>/takes/
114
+ 🎬 Filmed .canon/video/<slug>/takes/, re-film notes in .canon/video/<slug>/README.md
102
115
 
103
116
  01-open-the-kit step 4.2 s the board's first page with its frames filled in
104
117
  02-search-for-color screencast (fallback) 3.8 s the page list narrowed to two results
105
118
 
106
- Next: load hyperframes to compose, reading takes/take.json and the handoff notes
119
+ Next: load hyperframes to compose, reading takes/take.json, handoff.md, and compose-craft.md
107
120
  ```
108
121
 
109
122
  ## What this delegates
110
123
 
111
124
  - `app-drive`'s `isolate.md` owns the throwaway copy and its close
112
125
  - `hyperframes-creative`'s story spine owns what a beat says to a viewer
113
- - `hyperframes` and its sibling skills own composing, captioning, and rendering the video
126
+ - `hyperframes` and its sibling skills own composing, captioning, and rendering the video, and `compose-craft.md` adds only what app footage changes about their advice
114
127
  - `review-ui` owns driving a pull request's checklist
@@ -0,0 +1,81 @@
1
+ ---
2
+ title: Compose craft
3
+ description: The footage rules a session composing ui-film takes follows where the HyperFrames skills say nothing, being captions over app UI, other shapes, the README loop, sped-up clips, storyboard headings, and the workspace README
4
+ ---
5
+
6
+ # Compose craft
7
+
8
+ Read at Step 5 of `ui-film`, and by the session that composes the takes, which the handoff's next line points here. HyperFrames owns composing, captioning, and rendering, so this file carries only what app footage changes about its advice and restates none of it.
9
+
10
+ Each rule states the principle. Where a number appears, it is the case measured on one app's launch film, not a law for the next app.
11
+
12
+ ## Contents
13
+
14
+ - [Captions over app footage](#captions-over-app-footage)
15
+ - [Other shapes](#other-shapes)
16
+ - [The README loop](#the-readme-loop)
17
+ - [Sped-up clips](#sped-up-clips)
18
+ - [Storyboard headings](#storyboard-headings)
19
+ - [The workspace README](#the-workspace-readme)
20
+ - [Sources](#sources)
21
+
22
+ ## Captions over app footage
23
+
24
+ HyperFrames' caption guide places a landscape caption 80 to 120 px from the bottom and keeps it off a speaker's face. App footage has no speaker, and its bottom edge is often a toolbar where the beat's click lands.
25
+
26
+ - Pick one caption position for the whole film, clear of the app's chrome where actions land, and keep every caption there, since a caption that moves between beats makes the viewer hunt for it
27
+ - Back a caption over bright UI with the scrim HyperFrames' caption guide sizes to the text
28
+ - Snapshot each caption's moment, and move a caption only when it covers its own beat's action
29
+ - Write caption text by the interface copy rules in `ui-craft`'s `copy.md`, so a caption ends with no period
30
+
31
+ ## Other shapes
32
+
33
+ Cut a square or vertical version only when the operator asks for one. A film with one shape needs nothing from this section, and the vertical caption band and safe boxes stay with HyperFrames' frame presets.
34
+
35
+ - Start each shape as its own HyperFrames project, as `hyperframes-studio` states for a different aspect, in the workspace folder `handoff.md` names for it
36
+ - Frame the shape by cropping a window of the page at 1x, never by scaling the 16:9 frame into it, since a page shrunk into a square leaves the action too small to read
37
+ - Pan the window along the camera track's view center, so it follows the action the zoom would have aimed at. Frameboard's square cut used a 1080x1080 window.
38
+ - Expect a screencast take to hold at 1x from a softer 1080p source, while a stepped take gives the same window two clip pixels per page pixel
39
+
40
+ ## The README loop
41
+
42
+ Cut a README loop only when the operator asks for one. A README hero plays inline and silently, so it is a short loop rather than a cut of the film.
43
+
44
+ - Cut it from the raw take showing the app's core action, rather than from a render, in the workspace folder `handoff.md` names for it
45
+ - Crop it to the canvas, so no browser margin or page chrome outside the app shows
46
+ - End it on the finished state, held long enough to read before the loop restarts
47
+ - Export an animated WebP under about 2 MB, since a README renders one inline where a video needs a player. Frameboard's loop played inline at 1.72 MB.
48
+
49
+ ## Sped-up clips
50
+
51
+ A clip the edit plays faster runs its zoom faster too, so a push that settled in real time pumps several times a beat.
52
+
53
+ - Rebuild the beat's track for the playback rate with `canon take camera <dir>/log.json --rate <n> --out <file>`, and drive the wrapper from that file rather than from `camera.json`
54
+ - Never scale `camera.json`'s times by hand, since the rebuilt track also keeps each push inside the 1 s ceiling at the new speed
55
+ - Keep a typing beat at a rate where each word still reads, since a viewer cannot read a fill that finishes in a few frames
56
+
57
+ ## Storyboard headings
58
+
59
+ - Write each frame heading as `## Frame N: title`, since the dash form in HyperFrames' `storyboard-format.md` example fails the markdown audit
60
+ - Treat the parser's read of the colon form as assumed, since its lenient parse was not confirmed against its source
61
+ - Title each frame as the beat the operator approved, so the frame, the take's folder, and the caption share one name a reader can follow across all three
62
+
63
+ ## The workspace README
64
+
65
+ Step 5 writes the filming half of `.canon/video/<slug>/README.md`. The composing session adds its own half under its own heading.
66
+
67
+ - Add how to re-render each project the workspace holds, naming its folder and the render command it runs
68
+ - Name any track rebuilt with `--rate`, with the command that rebuilt it, since a re-film overwrites `camera.json` and leaves a rebuilt track stale
69
+ - Leave the filming half as Step 5 wrote it, so the next session can re-film without reading the composition
70
+
71
+ ## Sources
72
+
73
+ | Rule | Source |
74
+ | --------------------------- | -------------------------------------------------------------------------------------------------------- |
75
+ | Caption placement and scrim | HyperFrames' `captions.md`, adjusted for footage with chrome along its bottom edge |
76
+ | A new project per shape | `hyperframes-studio`'s brief step, which starts a new project for a different aspect |
77
+ | The 1080x1080 window | Frameboard's launch film, cut square from stepped takes |
78
+ | The 2 MB WebP loop | Frameboard's README hero, an animated WebP cut from a raw take, which played inline at 1.72 MB |
79
+ | Rebuilding a sped-up track | `canon take camera --help`, whose `--rate` divides every time in the log |
80
+ | Storyboard heading form | HyperFrames' `storyboard-format.md` and the markdown audit's character bans, with the colon read assumed |
81
+ | The README's two halves | Frameboard's workspace, whose README recorded how to re-film and re-render after a session ended |
@@ -28,7 +28,12 @@ access = "/write?token=demo"
28
28
  - An absent `access` opens the served root
29
29
  - `personas` and `proposals` belong to `app-drive`, and a take reads neither
30
30
 
31
- Every beat opens the address fresh in its own browser, so a link the app honors once, such as a single-use edit ticket, serves one beat alone. Mint a fresh link and run `canon take` once per beat for such an app, or a later beat opens the page without the access the first one spent.
31
+ ### Single-use access
32
+
33
+ Every beat opens the address fresh in its own browser, so a link the app honors once, such as a single-use edit ticket, serves one beat alone. A beat that falls back to the screencast opens the address a second time, so the fallback spends the link too, even within one beat.
34
+
35
+ - Point `access` at a local redirect minting a fresh link per request, so each open gets its own, the one pattern that held across beats and fallbacks alike
36
+ - Run `canon take` once per beat with a freshly minted link only where no redirect can be served, with `"route": "screencast"` on each so no fallback reopens it
32
37
 
33
38
  ## When the file is absent
34
39
 
@@ -14,7 +14,7 @@ Read at Step 5 of `ui-film`. Canon stops at the clip, and a HyperFrames composit
14
14
  | File | Holds |
15
15
  | ------------- | ---------------------------------------------------------------------------- |
16
16
  | `clip.mp4` | H.264 at 60 fps, 3840x2160 when frame stepped, 1920x1080 when screencast |
17
- | `log.json` | Every move, click, typing burst, and scroll, with each target's box |
17
+ | `log.json` | Every move, click, drag, key press, typing burst, and scroll, with its boxes |
18
18
  | `camera.json` | One camera per frame of the clip, with the cursor and the click ring |
19
19
  | `still.jpg` | The clip's closing frame, the check on each take, which no composition needs |
20
20
 
@@ -24,10 +24,10 @@ Every coordinate in the log and the track is in CSS pixels of a 1920x1080 page,
24
24
 
25
25
  Each frame carries `scale`, the view's top-left `x` and `y`, the `cursor`, and `ring`.
26
26
 
27
- - `scale` is 1 for the whole page and 1.8 at the deepest zoom
27
+ - `scale` is 1 for the whole page and 1.8 at the deepest zoom, or about 1.35 on a screencast beat, and holds at 1 on a beat whose plan set `push: false`
28
28
  - `x` and `y` place the view's corner on the page, so the view spans `1920 / scale` by `1080 / scale` from there
29
29
  - `cursor` is the pointer's position on the page
30
- - `ring` runs from 0 to 1 across the 450 ms after a click and is `null` otherwise
30
+ - `ring` runs from 0 to 1 across the 450 ms after a click and is `null` otherwise. On a drag it grows to 0.3, holds there from press to release, and runs on to 1 from the release.
31
31
 
32
32
  The track is final. It already carries the easing, the spring, and the hold, so a composition sets each frame's values and never tweens between them.
33
33
 
@@ -45,6 +45,14 @@ bunx -y hyperframes init .canon/video/<slug>/composition
45
45
  - Leave renders in the project's `renders/` folder, which `canon records push` skips along with `takes/`, `snapshots/`, `node_modules/`, and any video file
46
46
  - An image the composition adds under `assets/`, such as a logo, is backed up with the project's source
47
47
 
48
+ A cut in another shape and the README loop are each a project of their own beside `composition/`, so one shape's edit never reflows another's. Each reads the takes from `../takes/` the same way.
49
+
50
+ | Project | Holds |
51
+ | ---------------------- | ------------------------------------------------ |
52
+ | `composition/` | The main cut, in the takes' 16:9 shape |
53
+ | `composition-<shape>/` | One other shape, such as `composition-square/` |
54
+ | `readme-loop/` | The short silent loop a README plays as its hero |
55
+
48
56
  Compose from a session started at the main worktree root. From a linked worktree or an isolated background session, `Write` and `Edit` refuse every file in `composition/` and redirect to a worktree copy no later session reads, so never take that redirect.
49
57
 
50
58
  Where composing from the main root is not possible, write each file whole through the route `${CLAUDE_SKILL_DIR}/../session-worktree/references/main-root-writes.md` states.
@@ -62,6 +70,8 @@ The cursor stays outside the wrapper because a cursor inside it would scale with
62
70
 
63
71
  ## What the composition still owns
64
72
 
73
+ Read `${CLAUDE_SKILL_DIR}/references/compose-craft.md` for the captions, the other shapes, the loop, and a sped-up clip, where app footage changes what HyperFrames advises.
74
+
65
75
  - The order and the cuts between takes, the captions, and any music or voice
66
76
  - Whether a take plays whole or trimmed. A trim keeps the track aligned only when it shifts the track by the same frames.
67
77
  - Motion blur stays off, by the operator's call on these takes
@@ -15,6 +15,7 @@ Read at Step 3 of `ui-film`, before writing the first beat. `canon take --help`
15
15
  - [Targets](#targets)
16
16
  - [The pointer](#the-pointer)
17
17
  - [The zoom](#the-zoom)
18
+ - [The harness route](#the-harness-route)
18
19
  - [Sources](#sources)
19
20
 
20
21
  ## The plan
@@ -44,6 +45,13 @@ A plan holds the approved beats in order. Each beat names its setup, which runs
44
45
  - Reach the beat's start state through `setup`, since every beat opens the page fresh and nothing a setup step does is filmed
45
46
  - Write the beat's `name` as the operator approved it, since it names the clip's folder
46
47
 
48
+ ### Server state
49
+
50
+ Every beat reloads the page, never the server. An app holding its state in server memory keeps a change one beat made, so the next beat opens on it.
51
+
52
+ - Undo the change in the next beat's `setup`, or order the beats so each one's result is the next one's start
53
+ - Restart the server between beats only when neither works, since a restart costs the served address its warm start
54
+
47
55
  ## Frame-stepping limits
48
56
 
49
57
  A step beat runs the page on a virtual clock, one frame per step. Most pages film this way, and some inputs are known to stall it.
@@ -52,10 +60,11 @@ A step beat runs the page on a virtual clock, one frame per step. Most pages fil
52
60
  - A scroll has not been proven under frame stepping, and a smooth scroll can jump. Give a scroll its own beat so a fallback costs that beat alone.
53
61
  - An animated GIF can freeze, so expect one to hold its first frame
54
62
  - Set `"route": "screencast"` on a beat known to stall, rather than paying for the stall before the fallback
63
+ - Set a top-level `"route": "screencast"` on a plan whose page stalls on every beat, and a beat naming its own `route` keeps it
55
64
 
56
65
  A fallback films the beat again from a fresh load, replaying its setup and the steps the stepper already ran. A beat whose steps persist in the app, such as a fill that renames something, would then start from the changed state, so set `"route": "screencast"` on it when it risks a stall.
57
66
 
58
- A screencast beat films in real time at 1920x1080, which goes soft at the 1.8x zoom. Tell the operator which beats ran that way.
67
+ A screencast beat films in real time at 1920x1080, so its camera zooms only to about 1.35x before it would go soft. Tell the operator which beats ran that way.
59
68
 
60
69
  ### Reading a take back
61
70
 
@@ -68,6 +77,7 @@ Two rules hold once a beat is filmed.
68
77
 
69
78
  - Prefer a stable attribute, such as an `aria-label`, a `data-testid`, or an `id`, over a position like `:nth-child`
70
79
  - Use `text=<words>` for a control whose only stable handle is its label
80
+ - Target a control with no visible text, such as an icon button, by its `aria-label`, since `text=` finds nothing on it
71
81
  - Use a `move` to a point only for a target the page reveals on hover, and follow it with the click
72
82
  - Read each target off the served page before writing it. The verb refuses `target-missing` rather than filming a guess, and a refusal costs a reload.
73
83
 
@@ -86,6 +96,22 @@ The camera track already carries the zoom, so these rules decide what to film fo
86
96
  - Expect a target filling most of the view to get less zoom, and one filling the page to get none
87
97
  - The push reaches 90% of its depth in about 633 ms, inside the 1 s ceiling a push onto an action keeps
88
98
 
99
+ ### Depth, opt-out, and speed
100
+
101
+ Three controls change the push itself.
102
+
103
+ - Expect a screencast beat's zoom to stop near 1.35x, since its clip has one pixel per page pixel, and a stepped beat's to reach 1.8x
104
+ - Set `"push": false` on a beat the edit holds wide, such as one showing a whole layout change. Its track keeps the cursor and the click ring and drops the zoom.
105
+ - Rebuild a beat's track with `canon take camera <dir>/log.json --rate <n> --out <file>` for a clip the edit plays `n` times faster, so the zoom settles on the clock a viewer sees
106
+
107
+ ## The harness route
108
+
109
+ A beat driven from outside the page, such as a drag between two windows or an input the step kinds lack, cannot run as `canon take` steps. Until the verb can run an outside script itself, film it through a harness.
110
+
111
+ - Drive the beat from a Playwright script that records the page and writes a log in the shape of a take's `log.json`
112
+ - Build its camera track from that log with `canon take camera <log> --out <file>`, so the composition applies it like any other take
113
+ - Tell the operator which beats ran this way, since their clips carry the harness's resolution rather than the stepper's
114
+
89
115
  ## Sources
90
116
 
91
117
  | Rule | Source |
package/docs/index.md CHANGED
@@ -8,5 +8,6 @@ subtitle: One-line reference for each doc in this folder.
8
8
  One-line reference for each doc in this folder.
9
9
 
10
10
  - [Agents](agents/index.md): CLI catalog and invocation rules for agents, split by command domain. Start with overview.
11
+ - [Target migrations](migrations/index.md): One-time moves a project scaffolded under an older toolkit makes before its next sync, split by whether a canon migrate verb runs them or a person makes them by hand.
11
12
  - [Target](target/index.md): Scaffold, sync, and migrate a toolkit-managed project, with worked setups for three project shapes.
12
13
  - [Workflow](workflow/index.md): How a person and their agents run a feature, from the design loop through the parallel-session loop to the shell that launches them.
@@ -0,0 +1,107 @@
1
+ ---
2
+ title: Target migrations by hand
3
+ description: One-time moves and keep-or-delete calls a person makes by hand, which no canon migrate verb runs or detects
4
+ category: Agent surface
5
+ ---
6
+
7
+ # Target migrations by hand
8
+
9
+ Each section is a move a project scaffolded before the change it names makes by hand, since no `canon migrate` verb runs it and `canon migrate status` never lists it. The moves a verb runs, and the order to run them in, are in [target migrations by verb](by-verb.md).
10
+
11
+ ## Back records up off this machine, once
12
+
13
+ Run `canon records push` once a private repository exists. It prints the one-time setup command when it finds none, and `canon init` prints the same reminder.
14
+
15
+ ## Rename the pull request template headings, once
16
+
17
+ The template headings are now `## Key changes` and `## Technical context`, and `canon labels scan` compares case exactly. Rename them in `.github/pull_request_template.md`, or delete it and run `canon tooling sync base . --write`.
18
+
19
+ ## Delete the retired snippets, once
20
+
21
+ A project scaffolded while snippets installed may hold `.claude/snippets/` or a root `snippets/`.
22
+
23
+ ```bash
24
+ canon sync --check . --json | jq '.reverse'
25
+ ```
26
+
27
+ - `dropped` is the toolkit's copy, unchanged, so delete it
28
+ - `unattributed` is often an edited copy, so read what changed first
29
+ - `project` is the project's own content, so leave it
30
+
31
+ From the registry the walk reports `historyUnavailable`, so check both paths by hand.
32
+
33
+ ## Stop calling the standards verb, once
34
+
35
+ `canon standards <name>` is gone, and a call now fails with a too-many-arguments error. Replace each call with the skill that owns the standard, at `references/<name>.md`. <!-- canon-allow-reference: verb retired -->
36
+
37
+ | Skill | Standards |
38
+ | ----------------- | ------------------------------------------------------------- |
39
+ | `task-board` | `board`, `tasks`, `tasks-decline` |
40
+ | `context-fold` | `context` |
41
+ | `canvas-board` | `canvas`, `design` <!-- canon-keep-retired --> |
42
+ | `docs-sync` | `docs`, `readme` |
43
+ | `draw-figure` | `figures`, `mermaid` |
44
+ | `create-rule` | `rule` |
45
+ | `create-skill` | `skill`, `skill-paths`, `skill-practice`, `skill-requirement` |
46
+ | `git-branch` | `branch`, `slug` |
47
+ | `git-commit` | `commit`, `versioning` |
48
+ | `git-pr` | `pr`, `publish` |
49
+ | `markdown-craft` | `markdown` |
50
+ | `teach-workspace` | `glossary`, `teach` <!-- canon-keep-retired --> |
51
+ | `plan-groundwork` | `groundwork`, `groundwork-spikes` |
52
+ | `plan-intake` | `intake` |
53
+ | `plan-feature` | `plan`, `plan-lifecycle` |
54
+ | `plan-ready` | `ready` <!-- canon-keep-retired --> |
55
+ | `write-doc` | `requirements`, `wiki` |
56
+ | `session-map` | `session` |
57
+
58
+ The `standard` name became `skill-reference.md` in `create-skill`.
59
+
60
+ ## Keep or delete the wireframes folder, your call
61
+
62
+ The wireframes record is retired, and nothing deletes what a project holds.
63
+
64
+ - `canon/wireframes/` stays yours and unaudited. Keep it as notes or delete it.
65
+ - Delete the `@canon/wireframes/index.md` line in your `CLAUDE.md` with the folder. `canon claude sync` does not rewrite it.
66
+ - `canon gov sync` removes `.claude/rules/canon/standards/wireframes.md`
67
+
68
+ ## Keep or delete the retired product files, your call
69
+
70
+ The learning workspace, deck renderer, app recorder, canvas, and design install are retired with their verbs, and nothing deletes what a project holds.
71
+
72
+ - `.canon/teach/` holds HTML that opens as it is <!-- canon-keep-retired -->
73
+ - `.canon/slides/` and a `demos/` folder hold sources nothing renders any more, so delete them once nothing cites them <!-- canon-keep-retired -->
74
+ - Move the `.claude/design/project/` values, `fonts/`, and `fonts.css` to the stylesheet your `canon/DESIGN.md` lead names, then delete `.claude/design/`
75
+
76
+ A reference to a retired skill takes a hand edit.
77
+
78
+ - Replace a `canon:teach-workspace` reference with `canon:teach-craft` by hand, since `canon migrate skill-names` does not rewrite it <!-- canon-keep-retired -->
79
+ - Delete a `canon:make-deck`, `canon:script-screencast`, `canon:record-screencast`, `canon:read-frames`, or `canon:video-craft` reference, since none has a successor <!-- canon-keep-retired -->
80
+ - Delete a `canon:canvas-board` reference too. Frameboard, which `canon:design-pick` drives, reads each `.canon/canvas/` folder as a project, so move a kept page under one <!-- canon-keep-retired -->
81
+
82
+ ## Move decisions out of a held architecture record, once
83
+
84
+ The toolkit no longer seeds `canon/ARCHITECTURE.md`, and a held file and its `CLAUDE.md` import stay. Move a trap a session would hit into that domain's `## Gotchas`, then delete the file and its `@canon/ARCHITECTURE.md` line.
85
+
86
+ ## Move the capture cases out of the harness, once
87
+
88
+ A web project's `e2e/screenshot.ts` is a config. It now loads `CASES` from a seeded `e2e/capture/cases.ts` that sync copies once and never overwrites. A harness you edited is held on `--write`, so the new one lands only once you pass `--replace e2e/screenshot.ts`.
89
+
90
+ - Copy your cases from the old `e2e/screenshot.ts` into `e2e/capture/cases.ts`, then sync with `--replace e2e/screenshot.ts`.
91
+ - Evidence now defaults to `e2e/evidence/`. Set `export const EVIDENCE_ROOT = 'evidence'` in `e2e/capture/cases.ts` to keep a committed baseline at the old path.
92
+ - A run from a folder with no `e2e/capture/cases.ts` exits 1 and names the file.
93
+
94
+ ## Fold the ui rules onto one pointer, once
95
+
96
+ Eleven ui rules moved unchanged into the `ui-craft` skill, being `a11y`, `keyboard`, `pointer`, `forms`, `motion`, `ux-controls`, `ux-completeness`, `surface-capture`, `copy`, `interface-casing`, and `link-behavior`. Update the plugin, then sync, which folds each one you hold and `design-taste.md` onto one `craft.md` pointer without local edits.
97
+
98
+ ```bash
99
+ canon gov sync .
100
+ ```
101
+
102
+ ## Group a long paths section in `CLAUDE.md`, once
103
+
104
+ The `## Key paths` section of `CLAUDE.md` now keeps to 5 bullets in a row, and every other section stays exempt. `canon claude sync` never rewrites a `CLAUDE.md` you hold, so it warns with the line of each longer run.
105
+
106
+ - Regroup the section by hand under H3s, each opening on a one-sentence lead.
107
+ - List `CLAUDE.md` in `canon/config/markdown.toml` to gate it from then on.
@@ -0,0 +1,118 @@
1
+ ---
2
+ title: Target migrations by verb
3
+ description: One-time moves a canon migrate verb runs, for a project scaffolded under an older toolkit, in the order canon migrate status lists them
4
+ category: Agent surface
5
+ ---
6
+
7
+ # Target migrations by verb
8
+
9
+ Each section is a move a `canon migrate` verb runs once, for a project scaffolded before the change it names. Run `canon upgrade` first, then `canon migrate status --json` to list the moves still pending in the order to run them. A pending verb with no section here, such as `scratch-evidence` or `rename`, is in [migrate](../agents/migrate.md).
10
+
11
+ `canon:target-update` is the guided path through both, running the moves in that order once you approve its preview. The moves no verb runs are in [target migrations by hand](by-hand.md), and the recurring sync that follows is in [target sync](../target/sync.md).
12
+
13
+ ## Move the records first, once
14
+
15
+ Gitignored session records, being the task board, plans, review reports, and scratch, moved from `.claude/` to `.canon/`. Run these from inside the project, and read the `ok` field of the `--json` record rather than the exit code.
16
+
17
+ ```bash
18
+ canon tooling sync claude . --write
19
+ canon migrate records --json
20
+ canon migrate records --write --json
21
+ ```
22
+
23
+ The first line takes the `.canon/` ignore entry. The second reports and the third applies, repointing files that cite a moved folder and deleting a `.gitignore` line `.canon/` covers, as `dropped`. A line naming an old path keeps it via `canon-keep-record-root` on that line or the nearest non-blank one above.
24
+
25
+ Then sweep the citations inside the records, which the verb above never reaches.
26
+
27
+ ```bash
28
+ canon migrate record-tree --json
29
+ canon migrate record-tree --write --json
30
+ ```
31
+
32
+ It covers `diagrams`, `memory`, `plans`, `proposals`, `review`, `tasks`, and `teach`. Read the report before `--write`. The record tree is untracked, and a wrong rewrite has no undo.
33
+
34
+ ## Move the design board to `board/`, once
35
+
36
+ A pick round with no board named now drafts in `.canon/board/`, the folder Frameboard reads, rather than `.canon/canvas/`. Stop any `frameboard serve` on the old folder first.
37
+
38
+ ```bash
39
+ canon migrate record-layout --json
40
+ canon migrate record-layout --write --json
41
+ ```
42
+
43
+ A project holding both folders gets a collision, and neither moves. A `board` key in `design.toml` naming `.canon/canvas` stays as written, so update it by hand.
44
+
45
+ ## Move rules off the flat layout, once
46
+
47
+ Installed rules moved from `.claude/rules/<subdir>/` to `.claude/rules/canon/<subdir>/`. On the flat layout `canon gov sync` exits 0 reporting `No governance surfaces found in target`, and `canon gov install` lands a second copy.
48
+
49
+ ```bash
50
+ canon migrate rule-layout --json
51
+ canon migrate rule-layout --write --json
52
+ ```
53
+
54
+ Run it once, ahead of `canon gov sync` or `canon gov install`.
55
+
56
+ ## Rename the skill citations, once
57
+
58
+ Plugin skills dropped their `claude-` prefix, so `canon:claude-docs` is now `canon:context-fold`. Five drafters merged into `write-doc`, seven `draft-` skills took verb-first names, and four joined their family. No old name keeps a pointer, and `canon migrate skill-names --write` moves a project. <!-- canon-keep-retired -->
59
+
60
+ | Old name | New name |
61
+ | ------------------ | ----------------------------------------------- |
62
+ | `draft-doc` | `write-doc` <!-- canon-keep-retired --> |
63
+ | `draft-figure` | `draw-figure` <!-- canon-keep-retired --> |
64
+ | `draft-identity` | `design-identity` <!-- canon-keep-retired --> |
65
+ | `draft-slides` | `make-deck` <!-- canon-keep-retired --> |
66
+ | `draft-and-pick` | `design-pick` <!-- canon-keep-retired --> |
67
+ | `draft-ready` | `plan-ready` <!-- canon-keep-retired --> |
68
+ | `draft-screencast` | `script-screencast` <!-- canon-keep-retired --> |
69
+ | `pick-by-eye` | `design-pick` <!-- canon-keep-retired --> |
70
+ | `ui-record` | `ui-film` <!-- canon-keep-retired --> |
71
+ | `ux-audit` | `ui-audit` <!-- canon-keep-retired --> |
72
+ | `ux-measure` | `ui-measure` <!-- canon-keep-retired --> |
73
+
74
+ Replace a citation of a skill with no successor by hand, or delete the sentence.
75
+
76
+ - `canvas` is now `canvas-board`. The sweep rewrites only `canon:canvas` and `skills/canvas`, so replace a bare mention by hand. <!-- canon-keep-retired -->
77
+ - `draft-ready` is rewritten only as `canon:draft-ready` and `skills/draft-ready`, since bare it also describes a pull request, so replace a bare mention by hand. <!-- canon-keep-retired -->
78
+ - `design-extract` and `sketch-design` are replaced by `canon:canvas-board`. <!-- canon-keep-retired -->
79
+ - `review-branch`, `seed-sync`, `restate-plainly`, `bash-cli-script`, `canon-operator`, `canon-rollout`, and `canon-feedback-triage` have no successor <!-- canon-keep-retired -->
80
+ - `create-standard`, `markdown-propose`, `memory-review`, `project-commands`, `repo-metadata`, `ux-walkthrough`, and `plan-ready` have no successor <!-- canon-keep-retired -->
81
+
82
+ The `memory` record kind left `canon records`, so `canon records validate memory` refuses as an unknown kind and `canon records migrate` is gone.
83
+
84
+ - `canon repo metadata`, `canon autoship`, and the `120-bash` rule are gone, and `canon gov sync` removes the rule <!-- canon-keep-retired -->
85
+ - `memory-capture`, the `603-memory` rule, and the `memory` standard are gone, so send a lesson to the context entry that owns the fact <!-- canon-keep-retired -->
86
+
87
+ Two held files run, `.husky/post-merge` and `.claude/hooks/pr-create-log.sh`, and a stale copy calls a missing binary or names a removed skill. Resync what the toolkit owns before sweeping what the project wrote, and run the second line once per stack, naming a held hook with `--replace`.
88
+
89
+ ```bash
90
+ canon gov sync
91
+ canon tooling sync <stack> . --write
92
+ canon migrate skill-names --json
93
+ canon migrate skill-names --write --json
94
+ ```
95
+
96
+ ## Move the surfaces off `.claude/`, once
97
+
98
+ `context/`, `wireframes/`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`, and the install stamp folder, now `canon/config/`, moved under `canon/`. `rules/`, `skills/`, `hooks/`, and `settings.json` stay where Claude Code reads them.
99
+
100
+ ```bash
101
+ canon migrate surface-roots --json
102
+ canon migrate surface-roots --write --json
103
+ ```
104
+
105
+ It moves each surface with `git mv` and repoints every tracked citation. No other command notices a surface left at `.claude/`.
106
+
107
+ ## Deny subagents and merges, and turn auto memory off, once
108
+
109
+ The seeded `.claude/settings.json` now denies the `Agent` and `Task` tools and both merge commands, and sets `autoMemoryEnabled` to `false`. `canon claude sync` never rewrites a settings file you hold, so it warns while the file holds no default or lacks a merge entry. Removing `Agent` and `Task` later draws no warning.
110
+
111
+ ```bash
112
+ canon migrate session-defaults --json
113
+ canon migrate session-defaults --write --json
114
+ ```
115
+
116
+ The verb only adds a key that is absent. A person who wants auto memory back sets it in their own `.claude/settings.local.json`.
117
+
118
+ The verb adds `Bash(canon pr merge:*)` and `Bash(gh pr merge:*)` so a session cannot merge. A project migrated before them runs `--write` once more, which also restores `Agent` and `Task` for a person who removed them to allow subagents, so remove them again after.
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Target migrations
3
+ subtitle: One-time moves a project scaffolded under an older toolkit makes before its next sync, split by whether a canon migrate verb runs them or a person makes them by hand.
4
+ category: Agent surface
5
+ ---
6
+
7
+ # Target migrations
8
+
9
+ One-time moves a project scaffolded under an older toolkit makes before its next sync, split by whether a canon migrate verb runs them or a person makes them by hand.
10
+
11
+ ## Agent surface
12
+
13
+ - [Target migrations by hand](by-hand.md): One-time moves and keep-or-delete calls a person makes by hand, which no canon migrate verb runs or detects
14
+ - [Target migrations by verb](by-verb.md): One-time moves a canon migrate verb runs, for a project scaffolded under an older toolkit, in the order canon migrate status lists them
@@ -10,7 +10,6 @@ Scaffold, sync, and migrate a toolkit-managed project, with worked setups for th
10
10
 
11
11
  ## Agent surface
12
12
 
13
- - [Target migrations](migrations.md): One-time moves a project scaffolded under an older toolkit runs before its next sync
14
13
  - [Target projects](projects.md): Scaffold, add domains later, and sync upstream drift in a toolkit-managed project
15
14
  - [Target scenarios](scenarios.md): Worked setups for a markdown-heavy project, a web application, and a monorepo
16
- - [Target sync](sync.md): Check what drifted in a toolkit-managed project and pull it in, per domain or all at once
15
+ - [Target sync](sync.md): Check what drifted in a toolkit-managed project and pull it in, per domain or all at once, and update canon itself
@@ -84,11 +84,11 @@ Install one domain without re-running `canon init`.
84
84
  - A project-specific rule: invoke `canon:create-rule`, which writes into `.claude/rules/project/`. A rule under `.claude/rules/canon/` is deleted on the next sync.
85
85
  - An `index.md` system for a markdown-heavy folder: invoke `canon:target-setup indexes`
86
86
 
87
- For a leftover `.claude/snippets/` see [target migrations](migrations.md).
87
+ For a leftover `.claude/snippets/` see [target migrations by hand](../migrations/by-hand.md).
88
88
 
89
89
  ## Sync upstream drift
90
90
 
91
- A project scaffolded before a layout move runs the one-time moves in [target migrations](migrations.md) first. [Target sync](sync.md) covers reading drift and running a sync. [Target scenarios](scenarios.md) walks three worked setups.
91
+ A project scaffolded before a layout move runs the one-time moves in [target migrations](../migrations/index.md) first. [Target sync](sync.md) covers reading drift and running a sync. [Target scenarios](scenarios.md) walks three worked setups.
92
92
 
93
93
  ## Related
94
94