@erclx/canon 5.19.0 → 5.20.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 (101) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/create-skill/SKILL.md +1 -0
  3. package/claude/skills/plan-feature/SKILL.md +1 -1
  4. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  5. package/claude/skills/record-screencast/REQUIREMENT.md +2 -1
  6. package/claude/skills/record-screencast/SKILL.md +2 -2
  7. package/claude/skills/role-worker/REQUIREMENT.md +3 -1
  8. package/claude/skills/role-worker/SKILL.md +5 -3
  9. package/claude/skills/session-resume/SKILL.md +1 -1
  10. package/claude/skills/task-board/REQUIREMENT.md +1 -0
  11. package/claude/skills/task-board/SKILL.md +6 -0
  12. package/claude/skills/task-board/references/decline.md +2 -0
  13. package/claude/skills/video-craft/REQUIREMENT.md +48 -0
  14. package/claude/skills/video-craft/SKILL.md +80 -0
  15. package/claude/skills/video-craft/references/adopted.md +66 -0
  16. package/docs/agents/canvas.md +4 -0
  17. package/docs/agents/demo.md +1 -1
  18. package/docs/agents/install-and-sync.md +17 -3
  19. package/docs/agents/rule-citations.md +4 -4
  20. package/docs/agents/sandbox.md +8 -7
  21. package/docs/workflow/operating-model.md +9 -9
  22. package/docs/workflow/parallel-features.md +1 -1
  23. package/docs/workflow/skill-map.md +1 -0
  24. package/governance/renames.toml +24 -0
  25. package/governance/rules/{canon/640-architecture.md → standards/architecture.md} +3 -2
  26. package/governance/rules/standards/context.md +15 -0
  27. package/governance/rules/standards/design.md +13 -0
  28. package/governance/rules/standards/diagrams.md +17 -0
  29. package/governance/rules/standards/groundwork.md +13 -0
  30. package/governance/rules/standards/intake.md +12 -0
  31. package/governance/rules/standards/markdown.md +15 -0
  32. package/governance/rules/standards/memory.md +12 -0
  33. package/governance/rules/standards/mermaid.md +15 -0
  34. package/governance/rules/{canon/658-plan.md → standards/plan.md} +5 -9
  35. package/governance/rules/standards/readme.md +12 -0
  36. package/governance/rules/standards/ready.md +13 -0
  37. package/governance/rules/standards/requirements.md +13 -0
  38. package/governance/rules/standards/rule.md +13 -0
  39. package/governance/rules/standards/session.md +13 -0
  40. package/governance/rules/{claude/570-skill.md → standards/skill.md} +6 -10
  41. package/governance/rules/standards/standard.md +13 -0
  42. package/governance/rules/standards/tasks.md +15 -0
  43. package/governance/rules/{canon/661-teach.md → standards/teach.md} +3 -2
  44. package/governance/rules/standards/wiki.md +13 -0
  45. package/governance/rules/standards/wireframes.md +14 -0
  46. package/governance/rules/writing/800-prose.md +1 -1
  47. package/governance/stacks/base.toml +4 -2
  48. package/package.json +1 -1
  49. package/src/canvas/capture.ts +228 -15
  50. package/src/claude/cases/misc.ts +5 -0
  51. package/src/claude/routing.ts +1 -1
  52. package/src/commands/canvas.ts +76 -2
  53. package/src/commands/gov.ts +19 -4
  54. package/src/commands/sandbox.ts +7 -0
  55. package/src/gate/stages.ts +7 -1
  56. package/src/gov/citations.ts +1 -1
  57. package/src/gov/standard-rules.ts +179 -0
  58. package/src/sandbox/equivalence.ts +43 -14
  59. package/src/sandbox/stub-remote.ts +140 -0
  60. package/standards/architecture.md +5 -0
  61. package/standards/context.md +6 -0
  62. package/standards/design.md +3 -0
  63. package/standards/diagrams.md +8 -0
  64. package/standards/groundwork-spikes.md +66 -0
  65. package/standards/groundwork.md +5 -25
  66. package/standards/index.md +6 -2
  67. package/standards/intake.md +2 -0
  68. package/standards/markdown.md +6 -0
  69. package/standards/memory.md +2 -0
  70. package/standards/mermaid.md +6 -0
  71. package/standards/plan-lifecycle.md +36 -0
  72. package/standards/plan.md +13 -11
  73. package/standards/readme.md +2 -0
  74. package/standards/ready.md +4 -0
  75. package/standards/requirements.md +3 -0
  76. package/standards/rule.md +6 -1
  77. package/standards/session.md +4 -0
  78. package/standards/skill-paths.md +50 -0
  79. package/standards/skill.md +15 -23
  80. package/standards/standard.md +7 -1
  81. package/standards/tasks-decline.md +38 -0
  82. package/standards/tasks.md +8 -13
  83. package/standards/teach.md +5 -0
  84. package/standards/wiki.md +4 -0
  85. package/standards/wireframes.md +5 -0
  86. package/governance/rules/canon/610-context.md +0 -17
  87. package/governance/rules/canon/620-wireframes.md +0 -13
  88. package/governance/rules/canon/630-requirements.md +0 -12
  89. package/governance/rules/canon/650-design.md +0 -12
  90. package/governance/rules/canon/655-tasks.md +0 -13
  91. package/governance/rules/canon/656-groundwork.md +0 -11
  92. package/governance/rules/canon/657-intake.md +0 -11
  93. package/governance/rules/canon/659-memory.md +0 -11
  94. package/governance/rules/canon/660-diagrams.md +0 -19
  95. package/governance/rules/canon/662-session.md +0 -15
  96. package/governance/rules/canon/663-ready.md +0 -15
  97. package/governance/rules/claude/590-rule-authoring.md +0 -12
  98. package/governance/rules/writing/801-markdown.md +0 -14
  99. package/governance/rules/writing/802-mermaid.md +0 -14
  100. package/governance/rules/writing/880-readme.md +0 -11
  101. package/governance/rules/writing/891-standard-authoring.md +0 -12
@@ -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.19.0",
4
+ "version": "5.20.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -9,6 +9,7 @@ Read these files in parallel:
9
9
 
10
10
  - `${CLAUDE_SKILL_DIR}/../../standards/skill.md`: skill structure, skill types, frontmatter fields, invocation rules
11
11
  - `${CLAUDE_SKILL_DIR}/../../standards/skill-requirement.md`: what `REQUIREMENT.md` must answer, its sections, and its template
12
+ - `${CLAUDE_SKILL_DIR}/../../standards/skill-paths.md`: which root a path in the body resolves against, and how the body cites a standard
12
13
  - `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: punctuation and formatting for skill body text
13
14
  - The `write-human` skill: voice, rhythm, and sentence construction for skill body text
14
15
 
@@ -40,7 +40,7 @@ Open each file before describing what is in it. A count or a claim carried from
40
40
 
41
41
  ## Step 3: build the plan
42
42
 
43
- The section list, what each section holds, the suggested-and-answer contract, and the lifecycle are fixed by `${CLAUDE_SKILL_DIR}/../../standards/plan.md`. Read it before writing the file and follow it rather than working the shape from memory.
43
+ The section list, what each section holds, and the suggested-and-answer contract are fixed by `${CLAUDE_SKILL_DIR}/../../standards/plan.md`, and the lifecycle by `${CLAUDE_SKILL_DIR}/../../standards/plan-lifecycle.md`. Read it before writing the file and follow it rather than working the shape from memory.
44
44
 
45
45
  What this skill adds on top of the standard:
46
46
 
@@ -33,7 +33,7 @@ Read `${CLAUDE_SKILL_DIR}/../../standards/groundwork.md` before writing any file
33
33
  A track may run an experiment to settle an open question without stopping to ask. What it takes depends on what the experiment does.
34
34
 
35
35
  - Reading or computing: run it. Unrestricted reading already covers this, and it is what most spikes turn out to be.
36
- - Anything that processes an input: start against a sample and scale up after it works, per the sample rule in the standard's spikes section, which bounds it on size, duration, and spend.
36
+ - Anything that processes an input: start against a sample and scale up after it works, per the sample rule in `${CLAUDE_SKILL_DIR}/../../standards/groundwork-spikes.md`, which bounds it on size, duration, and spend.
37
37
  - Writing a fixture this session reads or provisions itself: run it, under the fixtures path above. Provisioning is the usual blocker rather than spend, and it costs nothing.
38
38
  - Spawning a billed headless session: run up to three, then ask before spawning more. The bound is a run count rather than a budget, because a headless run reports its total cost only after it finishes, so a dollar ceiling is reportable and not enforceable while a run count is checkable before spawning.
39
39
 
@@ -14,7 +14,8 @@ Without this skill, `draft-screencast` writes a draft and names `canon demo comp
14
14
  - Resolve the default plan path the same way `canon demo compile` does, so a caller passing only the draft path reaches the plan without naming it
15
15
  - Skip compiling when a plan already exists at that path, since its timing may be tuned by hand and a draft cannot reproduce that
16
16
  - Report every unresolved field from the compile or run record and stop rather than filling one in
17
- - Report every path a run wrote, video, mp4, gif, still, skipping any the record carries as null
17
+ - Report every path a run wrote, video, mp4, gif, still, and timeline, skipping any the record carries as null
18
+ - Load the video craft guidance before composing, so a composition applies sourced judgment on captions, zoom, pointer, and audio rather than the defaults an unguided session reaches for
18
19
  - Compose the take into a finished mp4 through HyperFrames when the draft's wrap section asks for anything, check the composition before rendering, and hand the render to `read-frames`
19
20
  - Stop at the take when the wrap section says `none` throughout, and stop with the install command when HyperFrames is absent
20
21
 
@@ -57,7 +57,7 @@ Read the draft's `## Wrap` section. When intro, outro, and music all say `none`,
57
57
 
58
58
  Otherwise confirm HyperFrames' `hyperframes` skill resolves. `bunx` would fetch the package on a machine without it, which installs by the back door, so the skill is the presence test. When it does not resolve, stop and report the install command, `bunx -y hyperframes init`, with the warning that init installs its skills machine-wide without asking, and report the take's paths as Step 6 does so the operator still holds the recording the run wrote. Never install it from here.
59
59
 
60
- When it resolves, load it and build `demos/<slug>/index.html` around the take, with the intro, outro, and music the wrap section names. That skill owns the composition rules, so this body states none of them. Then run both from `demos/<slug>/`:
60
+ When it resolves, load it, then load `canon:video-craft` for the captions, zoom, pointer, and audio judgment a video of software needs, reporting it rather than proceeding silently when it does not resolve. Build `demos/<slug>/index.html` around the take, with the intro, outro, and music the wrap section names, aiming each zoom from the timeline the run wrote beside the take. Those two skills own the composition rules, so this body states none of them. Then run both from `demos/<slug>/`:
61
61
 
62
62
  ```bash
63
63
  bunx -y hyperframes check
@@ -72,6 +72,6 @@ Hand the render to `read-frames` as its video path, so the composed result is ch
72
72
 
73
73
  ## Step 6: output
74
74
 
75
- The record carries `video`, `mp4`, `gif`, and `still`, each a path or `null`. Report each one that is not `null`, one per line, skipping the rest, and add the render path when Step 4 wrote one. Name the mp4 as the deliverable, the webm as the raw take, and the gif as the form for a host that strips video.
75
+ The record carries `video`, `mp4`, `gif`, `still`, and `timeline`, each a path or `null`. Report each one that is not `null`, one per line, skipping the rest, and add the render path when Step 4 wrote one. Name the mp4 as the deliverable, the webm as the raw take, the gif as the form for a host that strips video, and the timeline as the per-step timing a composition aims its zooms from.
76
76
 
77
77
  Say so plainly if `canon demo compile` or `canon demo run` is not available, rather than driving the application some other way. Both ship with the CLI and this skill ships with the plugin, so a project carrying one and not the other is a real state.
@@ -25,8 +25,9 @@ The draft mark fails from both ends. On 2026-08-31 four sessions re-drafted a pu
25
25
 
26
26
  - Assert what a building session is, what it may not do, and how long the role lasts, since the three step-owning skills each carry a procedure and none carries a role
27
27
  - State that session scratch resolves at the main worktree root, since a linked worktree holds none of those folders and their absence reads as a missing artifact rather than as a wrong vantage
28
- - State the shared board as read-only for a building session and name what it does instead when a row is owed, since a worker cannot pick a free label without reading every task file and every archive entry
28
+ - State the shared board as read-only for a building session and name what it does instead when a row is owed, since a task file with no row is a dropped task and placing the row is the controlling session's call
29
29
  - Owe an announcement the moment the pull request opens, carrying the number, the branch, and the task, since that transition is the one interval only the worker can observe
30
+ - Carry a row the build turned up in the pull request announcement, and send it alone only when the session ends before a pull request opens, since the worker files no task file of its own and the channel is the row's only route
30
31
  - Owe a message before a block becomes an interactive prompt, since a session already waiting on input never reaches the tool round an inbound message drains at
31
32
  - Defer the addressee resolution to `session-relay` and keep only the operator ask and the last-rung inference, which discriminates here because a worker holds a feature branch and a controller does not, and which falls back to the roster and says so, since an operator's own launch names nobody
32
33
  - Keep refusing a dispatcher a first-class move carrying its evidence, since the halts measured so far were correct and the cost of each fell where it belonged
@@ -39,6 +40,7 @@ The draft mark fails from both ends. On 2026-08-31 four sessions re-drafted a pu
39
40
  - Restate a boundary the orchestrator already states about itself
40
41
  - Report progress through the channel, which rebuilds on the sender's side the poll the announcement exists to retire
41
42
  - Write the priority board or the backlog, at any size
43
+ - Create a task file for work the build turns up, through `task-board` or by hand, since the file lands with no row and the placement is not the worker's to make
42
44
  - Be a skill nothing invokes but its author typing the name. `auto-ship` Step 0 invokes it on every build, dispatched or hand-launched, so a stretch where only a typed invocation reaches it is the signal that the role never took.
43
45
 
44
46
  ## Guards
@@ -37,16 +37,18 @@ which `auto-ship` Step 2 loads.
37
37
  ## The board is read-only
38
38
 
39
39
  - Never write `.canon/tasks/priority.md` or `.canon/tasks/backlog.md`. The controlling session is their only writer apart from `canon tasks archive`, and both are gitignored, so an overwrite drops a row with no history to recover it from.
40
- - Report a row this build turns up rather than adding it. Picking a free label means reading every task file and every archive entry, which this session has not done, so a label it invents collides with one already taken.
40
+ - Create no file under `.canon/tasks/`, including through `task-board`, when this build turns up new work. A task file with no row is a dropped task, and where the row lands is the controlling session's call, so a file this session writes is either orphaned or a placement it had no standing to make.
41
+ - Report the row upward instead, through the channel below.
41
42
  - Write the task file this build closes and the plan it ran under. The ban covers the shared board rather than the artifacts of the row in hand.
42
43
 
43
44
  ## The channel
44
45
 
45
- The controlling session cannot watch this one build, so three messages are owed
46
- and nothing else.
46
+ The controlling session cannot watch this one build, so the messages below are
47
+ owed and nothing else.
47
48
 
48
49
  - Announce the pull request as the ship chain's pull request step returns, carrying the number, the branch, and the task it closes. That transition is the one moment only this session knows, and the controller's review poll no longer starts on a dispatch because of it.
49
50
  - Carry the reach in that same message: the paths this branch wrote that another live plan or `## Run now` row holds, and who holds each, which `canon tasks plan-reach` reports as `claimed`. The gate cleared this branch against a prediction it has since outgrown, so the controller holds a disjointness reading that stopped being true hours ago and nothing else tells it. Say the reach was unread rather than clear when the installed binary carries no such subcommand, and leave the undeclared list to the pull request.
51
+ - Carry a row this build turned up in that same message, with its title, its origin, and the surface it would take. Send it as its own message only when the session will end before a pull request opens, since the row has no other way to reach the controller.
50
52
  - Announce when an address-review pass finishes, as `review-address` Step 8 returns, carrying what was addressed and the PR's new CI state. That transition is the other moment only this session knows, and it is what tells the controller to re-review rather than leaving it to poll for an answer nothing marks as landed.
51
53
  - Send a block out as a message before it becomes an interactive prompt.
52
54
  - Send nothing on progress. A worker reporting progress rebuilds, on this side of the channel, the poll the announcement retired on the other.
@@ -41,7 +41,7 @@ End with one line: `Start with: <first Up next item>` and note whether it has a
41
41
 
42
42
  When the board is empty and a handoff was found, name what the handoff leaves open instead: `Start with: <the open thread the handoff names>`. A recommendation slot filled with nothing reads as a failed run, and a handoff on an empty board is the shape a session leaves when it was reasoning rather than shipping.
43
43
 
44
- Do not offer to remove entries. A completed task is archived out of `.canon/tasks/` when work ships. The git log is the authoritative record of shipped work. Plan files are archived per the lifecycle rule in `${CLAUDE_SKILL_DIR}/../../standards/plan.md`.
44
+ Do not offer to remove entries. A completed task is archived out of `.canon/tasks/` when work ships. The git log is the authoritative record of shipped work. Plan files are archived per the lifecycle rule in `${CLAUDE_SKILL_DIR}/../../standards/plan-lifecycle.md`.
45
45
 
46
46
  Memory is updated only when a recorded fact becomes wrong, never on resume. A domain fact reaches a session through `canon/context/`, which `memory-capture` routes to and the three-tier model loads on demand, so the memory folder read here is the residue no context entry owns.
47
47
 
@@ -31,6 +31,7 @@ Placing a row without checking for another writer collides the same way. Two ses
31
31
  - Write a pull request line at creation, when any number is a guess at someone else's work
32
32
  - Archive around a refusal
33
33
  - Split the legacy single-file archive into per-task files nobody wrote
34
+ - Claim a label or write a task file for a session holding the worker role, since that role reports a row upward and the controlling session places it
34
35
  - Fall through to a direct write when no orchestrator is found and this session's own name starts with `worker-` or `planner-`, since those role bodies ban the write with no exception
35
36
 
36
37
  ## Guards
@@ -27,6 +27,12 @@ A task with no origin is either lost context or work nobody decided to do. This
27
27
 
28
28
  Accept work whose origin is the conversation itself only when the user says so explicitly, and record what it was in the intro paragraph instead of writing a link line to a file that does not exist.
29
29
 
30
+ ### Stop a worker before it claims a label
31
+
32
+ A session that asserted `canon:role-worker` this run, or whose own name in `canon sessions list --self --json` starts with `worker-`, stops here. It claims no label and writes no file. Report the row's title, its origin, and the surface it would take to the controlling session instead, since a task file with no row is a dropped task and placing the row is that session's call.
33
+
34
+ The guard sits ahead of Step 2 because `--claim` reserves a label on disk, so a stop after it leaves a reservation nothing uses. It names the worker role alone. A planner closing a groundwork track still writes its task file here and reaches Step 4's roster check as before.
35
+
30
36
  ### Step 2: allocate the phase label
31
37
 
32
38
  Run `canon tasks next-label --claim --json` and take its `label` field. The verb reads the live board and its `archive/` sibling together, so the label it returns accounts for what the board alone no longer shows, and `--claim` reserves it under `.canon/ordinal-locks/` so a second session filing at the same moment gets the next one. Branch on the record's `reason` rather than the exit: `label-contended` means re-run the claim, and a usage error from an unknown `--claim` means the installed binary predates the flag, so report the verb as unavailable rather than falling back to a bare read, which reopens the race.
@@ -7,6 +7,8 @@ description: How task-board gathers the reason a task is decided against, runs c
7
7
 
8
8
  The Decline mode of `task-board`. The session reads this file when the request names a task decided against.
9
9
 
10
+ Read `${CLAUDE_SKILL_DIR}/../../standards/tasks-decline.md` first. It holds the declined folder, the `Declined:` line, and what the move does to a plan and a board row.
11
+
10
12
  A task decided against carries no `post-merge` hook of its own, so every decline request arrives here directly rather than through work the hook already did.
11
13
 
12
14
  Do not move the file, edit `priority.md` or `backlog.md`, or regenerate the index by hand. `canon tasks decline` owns all three as one unit.
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: video-craft
3
+ description: Why a session composing a video of software needs sourced judgment on captions, zoom, pointer, and audio beyond what HyperFrames' own skills carry, and why every number in it has to trace to a source
4
+ ---
5
+
6
+ # Video craft requirement
7
+
8
+ ## Gap
9
+
10
+ Without this skill, a session composing a video applies no judgment specific to a video of software. HyperFrames' own skills carry general motion craft, being ease and speed variety, anchoring, and click timing, and nothing carries what a demo needs on top: what a caption says, which moment earns a zoom, how a recorded pointer behaves, and how far music sits under a voice.
11
+
12
+ The miss is measured. Two unguided renders of one demo in October 2026 pushed in over 2.2 and 1.4 seconds, used one ease on every move, centered the caption in a pill, and opened on a card holding the product name and a slogan over a gradient. The operator watched both and judged them generic, naming the zoom as too slow, and added that a caption has to name what the frame shows at that moment rather than narrate the whole flow. Rendering the first again with HyperFrames' creative and animation skills loaded fixed the general motion and left the four points above untouched.
13
+
14
+ Numbers from recall are the second gap. HyperFrames' zoom rule states 1.0 to 2.0 seconds with no source, and its default music bed sits about 18 dB under a voice where the accessibility guideline asks for 20. A session taking either as given reproduces the defaults the operator rejected.
15
+
16
+ ## Must
17
+
18
+ - State that a caption names only what its frame shows, with its on-screen time, line count, line length, and reading rate traced to published subtitle guidelines
19
+ - State which moment earns a zoom, aim it from the timeline `canon demo run` writes beside the take, and give a sourced duration for a push onto an action
20
+ - State how a recorded pointer behaves on a real interface: one pointer, and each click inside its recorded target. Smoothing and hiding the pointer are recorder settings a composition cannot change, so they stay out
21
+ - Cover choosing music or silence, the level music sits under a voice, and the pace of a captioned voiceover, each number sourced
22
+ - State that a checker finding is dismissed only after the frame it names is read
23
+ - Record the source behind every number in `references/adopted.md`, and name each conflict between sources with its pick rather than averaging
24
+ - Close with the practice skill's excuses, red flags, and closing checklist
25
+ - Be loaded by `record-screencast` before it composes, reporting when the skill does not resolve
26
+
27
+ ## Must not
28
+
29
+ - Restate a rule HyperFrames' own skills carry, such as ease variety, anchoring, click timing, the scale and dwell of a zoom, safe margins, or the carve that sits music under a voice. Point at the skill that owns it.
30
+ - State a number that `references/adopted.md` does not trace to a source
31
+ - Fetch, generate, or install a media file or HyperFrames itself
32
+ - Name this repository's demos, branches, or render files, since the body ships to targets holding none of them
33
+
34
+ ## Guards
35
+
36
+ - Two sources disagreeing on a number are named together with the side the body takes, never averaged
37
+
38
+ ## Out of scope
39
+
40
+ - General motion and composition rules: `hyperframes-animation` and `hyperframes-creative`
41
+ - Sourcing media: `media-use`
42
+ - Recording the take: `record-screencast`
43
+ - Vertical 9:16 framing, until a project asks for it
44
+ - Whether loading the skill improves a render, which needs a with-and-without comparison rather than a rule here
45
+
46
+ ## Measured
47
+
48
+ Not yet measured. The comparison owed is a demo composed with the skill loaded, judged by the operator against the unguided renders described under Gap. Whether the result reads designed is a taste call, so a pattern check cannot stand in for it.
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: video-craft
3
+ description: Carries what makes a composed video of software read as designed rather than generic, being captions that name only what the frame shows, which moment earns a zoom and how fast it lands, how a real pointer behaves on a real interface, music or silence and how far under a voice the music sits, and reading a frame before dismissing a checker finding. Every number traces to a source. Use before composing or judging any video, whether a product demo, an explainer, a pull request walkthrough, or a launch clip, when a render reads generic or slow, or when asked "make this video look designed", "is this zoom too slow", "what should this caption say", "should this have music", or "the checker flagged a frame, is it real". Do NOT use for general motion such as easing, speed variety, and click timing, which HyperFrames' `hyperframes-animation` and `hyperframes-creative` carry, to fetch or generate a media file, which is `media-use`, or to record the take, which is `record-screencast`.
4
+ ---
5
+
6
+ # Video craft
7
+
8
+ A session composing a video with no stated direction reaches for the defaults: a push-in of over two seconds, one ease on every move, a caption centered in a pill, and an intro card holding the product name and a slogan. Each default is reasonable alone, and together they read as generic. This skill carries the judgment specific to a video of software, which HyperFrames' own skills leave out.
9
+
10
+ Load `hyperframes-creative` and `hyperframes-animation` first. They own general motion, being ease and speed variety, anchoring, and click timing, and this body names none of their rules. Read `${CLAUDE_SKILL_DIR}/references/adopted.md` for the source behind every number below, and only when extending this guidance or arguing against a rule in it.
11
+
12
+ The guidance covers landscape 16:9 video. Vertical 9:16 framing is not covered yet.
13
+
14
+ ## Captions name what the frame shows
15
+
16
+ - Write each caption about the frame on screen while it shows, never about the step before or the one after. A caption narrating the whole flow describes a frame the viewer is not looking at.
17
+ - Name the visible change, such as the card landing or the field filling, rather than the feature's pitch. The pitch belongs in an intro card or the voiceover.
18
+ - Start a caption on the first frame of the action it names, and keep it on screen for at least 5/6 of a second and at most 7 seconds.
19
+ - Hold a caption to two lines of at most 42 characters, read at no more than 20 characters per second, or 17 for an audience of children. Cut words rather than shorten the hold.
20
+ - Place a caption where it covers nothing the frame is about. Move it off the element the step acts on, rather than centering it by default. HyperFrames' studio skill owns the title-safe margins.
21
+
22
+ ## A zoom is earned by an action
23
+
24
+ - Zoom only on a click, fill, or hover whose result is too small to read at full frame. A navigate, a wait, or a hold has nothing to aim at.
25
+ - Aim the zoom at the action's own place and moment. `canon demo run` writes a timeline beside the take carrying each step's start, end, and target box, so read the zoom's target and its start off that file rather than adding up holds by hand.
26
+ - Run a push that lands on an action no faster than the floor HyperFrames' `viewport-change` rule states, and never past 1 second. That rule's own range suits an ambient reveal with no action to land on, and reads slow on a push onto a click.
27
+ - Leave the scale and the dwell after a zoom settles to the `viewport-change` rule, which states both.
28
+
29
+ ## A real pointer on a real interface
30
+
31
+ - Keep the pointer the take recorded. Never draw a second, synthetic cursor over a real interface, since two pointers on one frame leave the viewer guessing which one acted.
32
+ - Check that each click lands inside the target box the timeline records for it. A pointer arriving beside the button it claims to press reads as a fake.
33
+
34
+ ## Music, silence, and a voice
35
+
36
+ - Choose silence over a music bed that competes with a voiceover. A bed earns its place on a video with no voice, where it carries the pacing between beats.
37
+ - Sit music at least 20 dB under the voice. Check `media-use`'s narrated bed default against that floor rather than take it as given, since it has sat short of it. The mechanism, a carve rather than a flat duck, is `hyperframes-audio`'s.
38
+ - Keep a captioned voiceover at or under 160 words a minute, since captions follow the voice and a faster voice forces captions past their reading limit. `hyperframes-creative`'s narration pace sits under that ceiling.
39
+
40
+ ## Read the frame before dismissing a finding
41
+
42
+ - Open the frame at the timestamp a checker names before calling its finding a false positive, whether the checker is `hyperframes check`, `canon demo frames`, or `read-frames`.
43
+ - Report what the frame shows beside the dismissal. A dismissal with no frame read is a guess about the render, and the viewer sees the render.
44
+
45
+ ## Excuses and rebuttals
46
+
47
+ | Excuse | Rebuttal |
48
+ | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
49
+ | A slow zoom feels cinematic | A push onto an action is interface motion. Past 1 second the viewer waits on the camera instead of watching the action land. |
50
+ | The caption explains the whole feature, so it is more useful | A caption about anything but the frame on screen makes the viewer read one thing and watch another. |
51
+ | The checker flagged a frame I already know is fine | Knowing is a memory of the composition, not of the render. Open the frame. |
52
+ | Music makes it feel finished | Music under a voice that is not 20 dB down masks the words, and the words carry the explanation. |
53
+ | A drawn cursor looks cleaner than the recorded one | The recorded pointer is the one that pressed the button. A drawn one is a claim about an action the take already shows. |
54
+
55
+ ## Red flags
56
+
57
+ - A push onto a click runs longer than 1 second.
58
+ - Every move in the composition shares one duration.
59
+ - A caption is centered on screen and covers the element the step acts on.
60
+ - A caption names a step the frame is not showing.
61
+ - The zoom's start time was added up by hand while a timeline file sits beside the take.
62
+ - Two pointers appear on one frame.
63
+ - A checker finding was dismissed and no frame was opened.
64
+
65
+ ## Before handing over
66
+
67
+ - Every caption names what its frame shows, starts on its action's first frame, and holds within its time and length limits.
68
+ - Every zoom aims at a click, fill, or hover read from the timeline, and lands within its duration.
69
+ - One pointer is on screen, and each click lands inside its recorded box.
70
+ - Music, when present, sits at least 20 dB under any voice, and a captioned voice stays at or under 160 words a minute.
71
+ - Every checker finding was either fixed or dismissed with the frame it names read and reported.
72
+
73
+ ## What this delegates
74
+
75
+ - Easing, speed variety, anchoring, click timing, and every other general motion rule: `hyperframes-animation` and `hyperframes-creative`
76
+ - Title-safe margins and timeline layout: `hyperframes-studio`
77
+ - The carve that sits music under a voice: `hyperframes-audio`
78
+ - Fetching or generating music, effects, voice, and imagery: `media-use`
79
+ - Recording the take and writing its timeline: `record-screencast` through `canon demo run`
80
+ - Reading a render frame by frame: `read-frames`
@@ -0,0 +1,66 @@
1
+ ---
2
+ title: Adopted and declined
3
+ description: The source behind every number in the video-craft body, by field, which conflicts between sources were picked and why, and what was declined
4
+ ---
5
+
6
+ # Adopted and declined
7
+
8
+ Each number in the body traces to a source here, read through the `search-craft` method: the field named first, its authorities derived from the kind of body it trusts, and each question searched scoped to those authorities and open beside it. A later session extending the skill adds to this file rather than re-arguing an item settled here.
9
+
10
+ ## Captions
11
+
12
+ Field: subtitling and captioning. Authorities: broadcasters' and streamers' published subtitle guidelines, and the captioning program that sets educational practice.
13
+
14
+ **On screen for 5/6 of a second to 7 seconds, two lines, 42 characters a line.** Netflix's [Timed Text Style Guide: General Requirements](https://partnerhelp.netflixstudios.com/hc/en-us/articles/215758617-Timed-Text-Style-Guide-General-Requirements) states a minimum of 5/6 of a second (20 frames at 24 fps) and a maximum of 7 seconds per event, and its [English (USA) guide](https://partnerhelp.netflixstudios.com/hc/en-us/articles/217350977-English-USA-Timed-Text-Style-Guide) states 42 characters a line and two lines at most.
15
+
16
+ **20 characters per second, 17 for children.** The same English (USA) guide, adult and children's programs respectively.
17
+
18
+ **Start on the first frame of the action.** Netflix's [Subtitle Timing Guidelines](https://partnerhelp.netflixstudios.com/hc/en-us/articles/360051554394-Timed-Text-Style-Guide-Subtitle-Timing-Guidelines) put a subtitle's in-time on the first frame of its audio. A software video's caption names an action rather than a line of speech, so the body keys the in-time on the action's first frame.
19
+
20
+ **Never over what the frame is about.** The DCMP [Captioning Tip Sheet](https://dcmp.org/learn/225-captioning-tip-sheet): "Placement must not interfere with existing visuals/graphics."
21
+
22
+ **Captions name what the frame shows.** No source states this for a software video. It is the operator's read of an unguided render whose caption narrated the whole flow, kept because the timing rules above already assume a caption tied to one moment.
23
+
24
+ ## Zoom
25
+
26
+ Fields: interface motion design, and screen recording practice. Authorities: design systems that publish motion specs, and the reference documentation of a screen recording tool.
27
+
28
+ **A push onto an action no faster than HyperFrames' floor, never past 1 second.** HyperFrames' `viewport-change` rule states a zoom of 1.0 to 2.0 seconds and gives its reason beside the value: "under 0.8s teleports, over 2.5s drags". The body keeps that floor by pointing at the rule rather than restating it. The 1 second ceiling has two grounds. Measured: an unguided render pushed in over 2.2 seconds and a second over 1.4 seconds, and the operator judged both slow, so the range's lower half already reads slow on a push onto a click. Published: Material Design 3's [easing and duration tokens](https://m3.material.io/styles/motion/easing-and-duration/tokens-specs) end their scale at 1000 ms, the top of the extra-long band they reserve for ambient transitions, so no input-driven transition in that system runs longer.
29
+
30
+ **Zoom on a click.** Screen Studio's [auto zoom guide](https://screen.studio/guide/auto-zoom) keys its zoom on click positions and zooms nowhere a click did not occur.
31
+
32
+ **Conflict, and the pick.** HyperFrames' range and the measured renders disagree on the push onto an action, and the body takes the overlap: HyperFrames' teleport floor below, and 1 second above, which sits inside HyperFrames' range at its fast end. HyperFrames' full range stays with an ambient reveal, which matches Material's own split between input-driven and ambient motion. A tighter band was considered and declined. Material puts large expressive transitions at 450 to 600 ms, and Nielsen Norman Group's [animation duration article](https://www.nngroup.com/articles/animation-duration/) calls 400 ms "very slow", but both write for an interface a user waits on, which a video viewer is not, and that band sits below HyperFrames' stated teleport floor with nothing measured to show it reads right. Narrow the band once a composed demo is compared against the unguided renders.
33
+
34
+ ## Pointer
35
+
36
+ The two pointer rules in the body carry no number. One pointer on a frame and a click landing inside its recorded box both follow from the take recording the real pointer and the timeline recording each target's box.
37
+
38
+ ## Audio
39
+
40
+ Fields: web accessibility, and audio post-production. Authorities: the W3C's accessibility guidelines, and the audio engineering society's streaming recommendation.
41
+
42
+ **Music at least 20 dB under the voice.** WCAG 2.1 [Success Criterion 1.4.7](https://www.w3.org/WAI/WCAG21/Understanding/low-or-no-background-audio.html): "The background sounds are at least 20 decibels lower than the foreground speech content, with the exception of occasional sounds that last for only one or two seconds."
43
+
44
+ **Conflict, and the pick.** HyperFrames' `media-use` sets its narrated bed at a volume of 0.12, about 18 dB under a voice at full scale. The body takes WCAG's 20 dB, since it is the published floor and the bed default sits 2 dB short of it.
45
+
46
+ **Overall loudness is delegated.** The AES [TD1008](https://aes.org/wp-content/uploads/2024/01/20210924_TD1008_v3.13.pdf) streaming recommendation normalizes speech to -18 LUFS with a true peak no higher than -1 dBTP, while `media-use` ships -14 and -16 LUFS targets for social and podcast delivery. The body states no overall target, since the right one depends on where the video is published and `media-use` owns that operation.
47
+
48
+ ## Voiceover
49
+
50
+ Field: captioning, for the reading ceiling a voiceover's captions inherit. Authority: the captioning program's presentation rate guidance.
51
+
52
+ **At or under 160 words a minute when captioned.** The DCMP [Captioning Key: Presentation Rate](https://dcmp.org/learn/601-captioning-key---presentation-rate) caps upper-level captions at 160 words a minute. `hyperframes-creative`'s narration reference states 2.5 words a second, 150 a minute, which sits under the ceiling, so the two do not conflict. An open search of voiceover practitioners put explainers at 140 to 160 words a minute, which agrees.
53
+
54
+ Narration has no standards body for pace, and the scoped search found none, so the body sets only the ceiling captions impose and points at HyperFrames for the pace itself.
55
+
56
+ ## Declined
57
+
58
+ **Restating HyperFrames' motion rules.** Ease variety, anchoring, click timing, the scale and dwell of a zoom, and title-safe margins are stated in HyperFrames' own skills, which update on their own cadence. A copy here goes stale on theirs.
59
+
60
+ **A loudness target in the body.** See Audio above.
61
+
62
+ **Pointer smoothing and hiding at rest.** Screen Studio's [cursor guide](https://screen.studio/guide/cursor) smooths the pointer and hides it when idle, and its [guide to disabling smooth movement](https://screen.studio/guide/disable-smooth-mouse-movement) turns smoothing off for a dropdown menu. Declined because both are recorder settings. A take is composed with its pointer already baked into the frames, so a session composing from it cannot change either. They belong to whatever records the take.
63
+
64
+ **Zoom out before a cut, and a sound effect only on a click that changes something.** Neither has a source, and no operator read stands behind either, so both stay out until one does.
65
+
66
+ **Vertical 9:16 framing.** Every video measured when this skill was written was landscape. Add it when a project asks for vertical video, with its safe areas sourced from the platform's own creator documentation.
@@ -46,3 +46,7 @@ The Theme tab in the shell lists what the token stylesheet defines, grouped as c
46
46
  `canvas capture <page>/<frame>` renders one frame as a PNG, and `canvas capture <page>` renders every frame on the page. Each goes through a server started for the call, so the injected tokens are in the image, and renders at the frame's own width from the layout, so a media query resolves there. It never captures the file on disk.
47
47
 
48
48
  `--out` is the PNG for a frame and a folder for a page, defaulting to session scratch. `--json` emits `{ ok, captures }` with the path and pixel size of each frame. Each PNG is the frame's whole document, so its height follows the document and not the frame's box. The font check `canon capture` makes applies, so a frame naming a font the machine lacks fails with that reason. A refused capture reports `no-page` or `no-frame` for a target that does not exist, `no-server` when the server for the call cannot start, and `capture-failed` for an error the engine throws, such as a browser that will not launch.
49
+
50
+ `canvas capture <page> --composite` renders the whole page as one PNG, with every frame at its layout position and its own width. The image is the union of the frame boxes with no padding, transparent where no frame sits, and frames that overlap paint in the board's order. It shows the frames only, with no captions and no selection outline. Each frame is clipped to its box as it is on the board, so its height can differ from the per-frame PNG, and each shows in its default theme, since the board's theme toggle is client state the capture never sees. The font check covers the composite page and not the documents inside its frames.
51
+
52
+ Under `--composite`, `--out` is the PNG itself, defaulting to `<page>.png` beside the per-frame folder in session scratch. `--json` emits `{ ok, composite }` carrying the page, the path, and the pixel size. The flag takes a page alone, and a `<page>/<frame>` target is refused as `invalid-name`. For the length of the call the generated page sits at `.canon/canvas/.composite/`, so it shares an origin with the frames, and the capture removes it after.
@@ -123,7 +123,7 @@ The cost is stated rather than hidden: the browser binary installs separately, s
123
123
 
124
124
  ## Composing the take into a finished video
125
125
 
126
- The take is raw. When the draft's `## Wrap` section asks for an intro, an outro, or music, `record-screencast` composes the take into `demos/<slug>/index.html` through [HyperFrames](https://hyperframes.heygen.com) and renders `renders/<slug>.mp4`, the deliverable. The skill loads HyperFrames' own `hyperframes` skill for the composition rules and runs `bunx -y hyperframes check` and `render`, then hands the render to `read-frames`. A wrap section reading `none` throughout stops at the take. The webm is only the raw take, and a gif is for a host that strips video.
126
+ The take is raw. When the draft's `## Wrap` section asks for an intro, an outro, or music, `record-screencast` composes the take into `demos/<slug>/index.html` through [HyperFrames](https://hyperframes.heygen.com) and renders `renders/<slug>.mp4`, the deliverable. The skill loads HyperFrames' own `hyperframes` skill for the composition rules and `canon:video-craft` for the captions, zoom, pointer, and audio judgment a video of software needs, aims each zoom from the take's timeline, and runs `bunx -y hyperframes check` and `render`, then hands the render to `read-frames`. A wrap section reading `none` throughout stops at the take. The webm is only the raw take, and a gif is for a host that strips video.
127
127
 
128
128
  Canon neither ships nor installs HyperFrames, and there is no `canon` verb for composing, since the render is one command already. The operator installs it once per machine:
129
129
 
@@ -25,7 +25,16 @@ installs the rule under its new name and deletes the old file, whether or not
25
25
  the target's stamp records a stack. Local edits to the old file are not
26
26
  carried, and the sync says so. The sync lists each change by path before it
27
27
  applies, and the target's git diff is the record afterwards. `canon sync
28
- --check` lists the same file as `retired` or `renamed` before any sync runs. A project's own rules belong under `.claude/rules/project/`, where
28
+ --check` lists the same file as `retired` or `renamed` before any sync runs.
29
+
30
+ The `standards` band is the largest such move. Each rule that only routed a
31
+ path to a standard now ships under that standard's name at
32
+ `.claude/rules/canon/standards/<standard>.md`, so a target holding
33
+ `canon/658-plan.md` or `writing/801-markdown.md` syncs onto `standards/plan.md`
34
+ and `standards/markdown.md`. Those rules carry no number, and their globs and
35
+ bullets come from the standard's own frontmatter.
36
+
37
+ A project's own rules belong under `.claude/rules/project/`, where
29
38
  `canon standards rule` reserves `900-999` for them, and a rule placed under
30
39
  `canon/` instead is lost on the next sync.
31
40
 
@@ -130,7 +139,12 @@ runs the verb again for that name.
130
139
 
131
140
  `canon gov regen` is the one governance verb that runs against the toolkit root,
132
141
  because the `.claude/rules/` it writes there is produced output rather than an
133
- operator's working copy. It reads the stack recorded in `internal/governance.toml`
142
+ operator's working copy. It first writes `governance/rules/standards/`, one rule
143
+ per standard under `standards/` whose frontmatter carries `paths:`, clearing the
144
+ folder so a standard that drops the field loses its rule. A standard named like
145
+ a band folder or an authored rule, or a `paths:` or `rule:` that is not a list
146
+ of strings, refuses the whole run before anything is written. It then reads the
147
+ stack recorded in `internal/governance.toml`
134
148
  into `.claude/rules/canon/`, installs anything under `internal/rules/` into a
135
149
  separate `.claude/rules/internal/`, and clears both destinations first so a
136
150
  rule the record stopped naming disappears. `internal/` is what this repository
@@ -140,7 +154,7 @@ since a target has no rule source of its own that ships nowhere.
140
154
  It takes `--root <path>` and defaults to the toolkit root, prints nothing on success, and
141
155
  reports the reason on stderr with exit 1 when the record names a stack or rule
142
156
  that does not resolve. The Consumed copies stage of `bun run check` calls it and
143
- asserts the result is committed.
157
+ asserts both the generated band and the consumed copy are committed.
144
158
 
145
159
  ## Whole-project sync
146
160
 
@@ -24,7 +24,7 @@ Under `--json` the record holds stdout alone and the frame still renders on stde
24
24
 
25
25
  ## What the drift check cannot see
26
26
 
27
- `bun run check` asserts that an authored rule and its consumed copy agree, and a dead citation passes that assertion because both copies carry it. `governance/rules/canon/661-teach.md` told its reader to open a `references/glossary.md` inside the teach skill that had never existed at that path. The rule shipped, survived a release, and fired during a real teach run before anyone noticed.
27
+ `bun run check` asserts that an authored rule and its consumed copy agree, and a dead citation passes that assertion because both copies carry it. The teach rule told its reader to open a `references/glossary.md` inside the teach skill that had never existed at that path. The rule shipped, survived a release, and fired during a real teach run before anyone noticed.
28
28
 
29
29
  Two files agreeing is what a drift check measures. Whether either one is right about the tree is a different question, and this is the stage that asks it.
30
30
 
@@ -49,7 +49,7 @@ A `path` is anchored on the whole backticked span rather than on a trailing patt
49
49
  A rule body is full of backticked spans carrying a slash, and almost none of them names a file in this tree. The stage declines four shapes outright.
50
50
 
51
51
  - A placeholder or glob segment describes a shape rather than naming a file: `canon/context/<domain>.md`, `standards/<name>.md`, `app/**/route.ts`, `${CLAUDE_SKILL_DIR}/../../standards/<name>.md`.
52
- - A bare filename names a convention: `route.ts`, `manifest.toml`, `components.json`, `playwright.config.ts`. A bare name is read as a citation only when it matches a rule filename, which is how `662-session.md` points at `655-tasks.md`.
52
+ - A bare filename names a convention: `route.ts`, `manifest.toml`, `components.json`, `playwright.config.ts`. A bare name is read as a citation only when it matches a rule filename, which is how one authored rule would point at a sibling such as `605-worktrees.md`. A generated rule under `governance/rules/standards/` carries no number, so a bare name citing one is not read as a citation, and those rules name each other in prose instead.
53
53
  - A span carrying no file extension is a folder or a module specifier: `src/pages/`, `next/font`, `try/except`, `react-hooks/set-state-in-effect`, `oven-sh/setup-bun@v2`, `@/lib/utils`.
54
54
  - A fenced block displays a path rather than pointing at one.
55
55
 
@@ -59,11 +59,11 @@ The extension test is what carries most of the separation, and it costs one real
59
59
 
60
60
  Two classes resolve to nothing and are right to. Both are reported by name rather than dropped, so a reader can see what the verdict declined to judge.
61
61
 
62
- **Governed.** A rule spelling a path in its own frontmatter `paths:` is naming an artifact a target holds rather than a file here. `governance/rules/canon/660-diagrams.md` declares `.claude/DIAGRAMS.md` and then tells its reader to convert one an older install left behind, so the file is correctly absent from this tree and correctly named in the rule.
62
+ **Governed.** A rule spelling a path in its own frontmatter `paths:` is naming an artifact a target holds rather than a file here. `governance/rules/standards/diagrams.md` declares `.claude/DIAGRAMS.md` and then tells its reader to convert one an older install left behind, so the file is correctly absent from this tree and correctly named in the rule.
63
63
 
64
64
  Only an exact declaration exempts, never a glob match against one. A glob declares a shape, so a body path sitting inside it is still a citation and a stale one is still a defect. A rule scoped at `docs/**` citing a `docs/agents/renamed.md` that moved is exactly the class this stage exists to catch, and matching the glob would excuse it.
65
65
 
66
- **Ignored.** A path git ignores is session scratch no clone is expected to hold. `governance/rules/canon/655-tasks.md` cites `.canon/tasks/index.md`, which is real in a live project and absent from a fresh clone and from every linked worktree. Resolving against the filesystem alone would make the verdict depend on which tree the stage ran in, so the unresolved paths go to one batched `git check-ignore` and an ignored one is excused. A read git cannot answer refuses rather than reporting those paths dead.
66
+ **Ignored.** A path git ignores is session scratch no clone is expected to hold. `governance/rules/standards/tasks.md` cites `.canon/tasks/index.md`, which is real in a live project and absent from a fresh clone and from every linked worktree. Resolving against the filesystem alone would make the verdict depend on which tree the stage ran in, so the unresolved paths go to one batched `git check-ignore` and an ignored one is excused. A read git cannot answer refuses rather than reporting those paths dead.
67
67
 
68
68
  ## Why the glob half reads one corpus
69
69
 
@@ -56,13 +56,14 @@ canon sandbox equivalence claude:plan-feature/full --base HEAD
56
56
 
57
57
  A target is `<category>`, `<category>:<command>`, or `<category>:<command>/<arm>`, defaulting to every category.
58
58
 
59
- | Flag | Effect |
60
- | ------------------ | ------------------------------------------------------------------------------------------- |
61
- | `--base <ref>` | Ref the baseline is provisioned from, `main` by default |
62
- | `--include-anchor` | Also run the arms that push to the shared GitHub anchor, one at a time, for an attended run |
63
- | `--out <dir>` | Keep the provisioned trees, logs, and per-side manifests in this folder |
64
- | `--no-masks` | Compare every path, which lists what each mask would hide |
65
- | `--json` | Emit the record on stdout |
59
+ | Flag | Effect |
60
+ | ------------------ | -------------------------------------------------------------------------------------------------- |
61
+ | `--base <ref>` | Ref the baseline is provisioned from, `main` by default |
62
+ | `--include-anchor` | Also run the arms that push to the shared GitHub anchor, one at a time, for an attended run |
63
+ | `--stub-remote` | Run the anchor arms against a local bare repository and a stub `gh`, writing nothing to the anchor |
64
+ | `--out <dir>` | Keep the provisioned trees, logs, and per-side manifests in this folder |
65
+ | `--no-masks` | Compare every path, which lists what each mask would hide |
66
+ | `--json` | Emit the record on stdout |
66
67
 
67
68
  The baseline is a detached worktree with full history, removed on exit including after `SIGINT`. Each arm provisions on the base side, is read into a manifest, is deleted, then provisions on the head side at the same path with the run id pinned. A manifest holds every file's mode and hash, every symlink's target, the exit status, the narration, and for the outer repository and each nested one the commit subjects, the staged index, and the branch.
68
69
 
@@ -48,9 +48,9 @@ or a path that no longer resolves is reported rather than repaired, since the
48
48
  task file and the board stay the orchestrator's to write.
49
49
 
50
50
  A worker that halts on a plan question it may not answer, or argues back against
51
- an instruction the tree contradicts, is working correctly. It never writes
52
- `.canon/tasks/priority.md` or the backlog beside it, and reports the row it
53
- needs for the orchestrator to write. `role-worker` carries the reason for each.
51
+ an instruction the tree contradicts, is working correctly. It writes neither
52
+ `.canon/tasks/priority.md`, the backlog, nor a task file for work it turns up,
53
+ and hands the row to the orchestrator. `role-worker` gives the reason for each.
54
54
 
55
55
  The orchestrator's cell reads every tracked file rather than every feature, and
56
56
  it offers no exception for a small one. A correction found while orchestrating
@@ -116,12 +116,12 @@ delta against, and `canon pr checks` reports the runs belonging to that tip, so
116
116
  follow-up push cannot be read as green off the predecessor's completed run. See
117
117
  [Head-sensitive pull request reads](../agents/pr-reads.md).
118
118
 
119
- Three messages travel from the worker to its controller, and `role-worker`
120
- states each with its reason: the worker's pull request as it opens, the end of
121
- each address-review pass with the new CI state, and a block before it becomes an
122
- interactive prompt. Nothing is sent on progress. An open pull request is what
123
- starts the controller's review poll, with a dispatch still silent after thirty
124
- minutes kept as a fallback.
119
+ Three messages travel from the worker to its controller, each stated with its
120
+ reason in `role-worker`: the pull request as it opens, carrying any row the
121
+ build turned up, the end of each address-review pass with the new CI state, and
122
+ a block before it becomes an interactive prompt. Nothing is sent on progress. An
123
+ open pull request is what starts the controller's review poll, with a dispatch
124
+ still silent after thirty minutes kept as a fallback.
125
125
 
126
126
  What the session channel carries is the handback instruction and the worker's
127
127
  reply to it, which is a notification layer over a record that stays on the PR. A
@@ -34,7 +34,7 @@ A constraint naming a track in flight carries the same problem past the handoff,
34
34
 
35
35
  `.canon/plans/`, `.canon/review/`, and `.canon/memory/` all resolve at the main worktree root, so artifacts created in any session are visible from any sibling worktree. A session inside a worktree reads them directly, since the file-editing tools refuse a main-root path but `Read` resolves normally. It writes a whole file through the shell and makes a change inside an existing file through a `canon` verb, which resolves the main root in-process. See [Claude Code and git worktrees](../../wiki/claude/worktrees.md) for the full rule and the domain-level fan-out guidance.
36
36
 
37
- The plan's shape is fixed by `standards/plan.md`: the section list, the filename, the lifecycle, and the contract its questions keep. Every question carries a `- Suggested:` line and an empty `- Answer:` slot, and a blank answer accepts the suggestion at execution time. That default is what makes a plan decision-ready in one pass, and it is the opposite of the contract an intake folder keeps, where an empty slot means nobody reached the item.
37
+ The plan's shape is fixed by `standards/plan.md`: the section list, the filename, and the contract its questions keep. Its lifecycle, from the session that writes it to the archive, is `standards/plan-lifecycle.md`. Every question carries a `- Suggested:` line and an empty `- Answer:` slot, and a blank answer accepts the suggestion at execution time. That default is what makes a plan decision-ready in one pass, and it is the opposite of the contract an intake folder keeps, where an empty slot means nobody reached the item.
38
38
 
39
39
  An execution that picks other than the suggestion rewrites the `- Suggested:` line as `overridden at execution to <pick>,` followed by the measurement that moved it, and leaves the slot blank. That fixed phrase is how a reader of the archived plan tells an override from a suggestion the execution accepted, since an authored suggestion often carries a number of its own. The same deviation takes one line in the open task's `## Findings`, which is the register that survives the plan being archived. A deviation from a question somebody already answered goes back to whoever answered it instead, since a filled slot is a decision already made.
40
40
 
@@ -53,6 +53,7 @@ This page is the corpus the coverage claim is measured against: every name `cano
53
53
  | `canon:search-craft` | Before searching outside the project, to derive where the field's authorities publish and search there too |
54
54
  | `canon:systematic-debugging` | When a test fails or a bug surfaces, to force root cause first |
55
55
  | `canon:design-taste` | When drafting or judging an interface, or when output reads generic, to settle which decision comes first |
56
+ | `canon:video-craft` | Before composing or judging a video, for sourced captions, zoom, pointer, and audio judgment |
56
57
  | `canon:ui-checklist` | After a UI change, to write what to look at and name what ships untested |
57
58
 
58
59
  ## Check the work before it leaves the branch
@@ -13,6 +13,10 @@
13
13
  # resolves A only while both links stay. A key must name no live rule and every
14
14
  # chain must end on one, which `src/gov/renames.test.ts` checks against this
15
15
  # file.
16
+ #
17
+ # A numbered rule replaced by the rule `canon gov regen` generates from its
18
+ # standard is a rename too: the generated rule keeps every glob and bullet, so
19
+ # the pair is one-to-one identity under the standard's name.
16
20
  [renamed]
17
21
  "005-behavior" = "565-behavior"
18
22
  "015-output" = "566-output"
@@ -47,3 +51,23 @@
47
51
  "075-dependencies" = "775-dependencies"
48
52
  "080-config-comments" = "780-config-comments"
49
53
  "090-code-comments" = "790-code-comments"
54
+ "658-plan" = "plan"
55
+ "610-context" = "context"
56
+ "620-wireframes" = "wireframes"
57
+ "630-requirements" = "requirements"
58
+ "640-architecture" = "architecture"
59
+ "650-design" = "design"
60
+ "655-tasks" = "tasks"
61
+ "656-groundwork" = "groundwork"
62
+ "657-intake" = "intake"
63
+ "659-memory" = "memory"
64
+ "660-diagrams" = "diagrams"
65
+ "661-teach" = "teach"
66
+ "662-session" = "session"
67
+ "663-ready" = "ready"
68
+ "570-skill" = "skill"
69
+ "590-rule-authoring" = "rule"
70
+ "801-markdown" = "markdown"
71
+ "802-mermaid" = "mermaid"
72
+ "880-readme" = "readme"
73
+ "891-standard-authoring" = "standard"