@erclx/canon 5.18.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.
- package/README.md +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/create-skill/SKILL.md +1 -0
- package/claude/skills/plan-feature/SKILL.md +1 -1
- package/claude/skills/plan-groundwork/SKILL.md +1 -1
- package/claude/skills/record-screencast/REQUIREMENT.md +2 -1
- package/claude/skills/record-screencast/SKILL.md +2 -2
- package/claude/skills/role-worker/REQUIREMENT.md +3 -1
- package/claude/skills/role-worker/SKILL.md +5 -3
- package/claude/skills/session-resume/SKILL.md +1 -1
- package/claude/skills/task-board/REQUIREMENT.md +1 -0
- package/claude/skills/task-board/SKILL.md +6 -0
- package/claude/skills/task-board/references/decline.md +2 -0
- package/claude/skills/video-craft/REQUIREMENT.md +48 -0
- package/claude/skills/video-craft/SKILL.md +80 -0
- package/claude/skills/video-craft/references/adopted.md +66 -0
- package/docs/agents/canvas.md +4 -0
- package/docs/agents/commands.md +1 -0
- package/docs/agents/demo.md +1 -1
- package/docs/agents/install-and-sync.md +17 -3
- package/docs/agents/rule-citations.md +4 -4
- package/docs/agents/sandbox.md +8 -7
- package/docs/agents/teach.md +7 -1
- package/docs/workflow/operating-model.md +9 -9
- package/docs/workflow/parallel-features.md +1 -1
- package/docs/workflow/skill-map.md +1 -0
- package/governance/renames.toml +24 -0
- package/governance/rules/{canon/640-architecture.md → standards/architecture.md} +3 -2
- package/governance/rules/standards/context.md +15 -0
- package/governance/rules/standards/design.md +13 -0
- package/governance/rules/standards/diagrams.md +17 -0
- package/governance/rules/standards/groundwork.md +13 -0
- package/governance/rules/standards/intake.md +12 -0
- package/governance/rules/standards/markdown.md +15 -0
- package/governance/rules/standards/memory.md +12 -0
- package/governance/rules/standards/mermaid.md +15 -0
- package/governance/rules/{canon/658-plan.md → standards/plan.md} +5 -9
- package/governance/rules/standards/readme.md +12 -0
- package/governance/rules/standards/ready.md +13 -0
- package/governance/rules/standards/requirements.md +13 -0
- package/governance/rules/standards/rule.md +13 -0
- package/governance/rules/standards/session.md +13 -0
- package/governance/rules/{claude/570-skill.md → standards/skill.md} +6 -10
- package/governance/rules/standards/standard.md +13 -0
- package/governance/rules/standards/tasks.md +15 -0
- package/governance/rules/{canon/661-teach.md → standards/teach.md} +3 -2
- package/governance/rules/standards/wiki.md +13 -0
- package/governance/rules/standards/wireframes.md +14 -0
- package/governance/rules/writing/800-prose.md +1 -1
- package/governance/stacks/base.toml +4 -2
- package/package.json +2 -1
- package/src/canvas/capture.ts +228 -15
- package/src/claude/cases/misc.ts +5 -0
- package/src/claude/routing.ts +1 -1
- package/src/commands/canvas.ts +76 -2
- package/src/commands/gov.ts +19 -4
- package/src/commands/sandbox.ts +7 -0
- package/src/commands/slides.ts +73 -4
- package/src/commands/teach.ts +112 -4
- package/src/gate/stages.ts +7 -1
- package/src/gov/citations.ts +1 -1
- package/src/gov/standard-rules.ts +179 -0
- package/src/sandbox/equivalence.ts +43 -14
- package/src/sandbox/stub-remote.ts +140 -0
- package/src/serve/live.ts +113 -0
- package/src/serve/static.ts +60 -2
- package/src/slides/convert/export.ts +323 -0
- package/src/slides/convert/shapes.ts +764 -0
- package/src/slides/convert/svg.ts +38 -0
- package/src/slides/convert/walk.ts +444 -0
- package/src/teach/browser/reload.ts +9 -0
- package/src/teach/nav.ts +7 -6
- package/src/teach/workspace.ts +2 -1
- package/src/teach/write-if-changed.ts +17 -0
- package/standards/architecture.md +5 -0
- package/standards/context.md +6 -0
- package/standards/design.md +3 -0
- package/standards/diagrams.md +8 -0
- package/standards/groundwork-spikes.md +66 -0
- package/standards/groundwork.md +5 -25
- package/standards/index.md +6 -2
- package/standards/intake.md +2 -0
- package/standards/markdown.md +6 -0
- package/standards/memory.md +2 -0
- package/standards/mermaid.md +6 -0
- package/standards/plan-lifecycle.md +36 -0
- package/standards/plan.md +13 -11
- package/standards/readme.md +2 -0
- package/standards/ready.md +4 -0
- package/standards/requirements.md +3 -0
- package/standards/rule.md +6 -1
- package/standards/session.md +4 -0
- package/standards/skill-paths.md +50 -0
- package/standards/skill.md +15 -23
- package/standards/standard.md +7 -1
- package/standards/tasks-decline.md +38 -0
- package/standards/tasks.md +8 -13
- package/standards/teach.md +5 -0
- package/standards/wiki.md +4 -0
- package/standards/wireframes.md +5 -0
- package/governance/rules/canon/610-context.md +0 -17
- package/governance/rules/canon/620-wireframes.md +0 -13
- package/governance/rules/canon/630-requirements.md +0 -12
- package/governance/rules/canon/650-design.md +0 -12
- package/governance/rules/canon/655-tasks.md +0 -13
- package/governance/rules/canon/656-groundwork.md +0 -11
- package/governance/rules/canon/657-intake.md +0 -11
- package/governance/rules/canon/659-memory.md +0 -11
- package/governance/rules/canon/660-diagrams.md +0 -19
- package/governance/rules/canon/662-session.md +0 -15
- package/governance/rules/canon/663-ready.md +0 -15
- package/governance/rules/claude/590-rule-authoring.md +0 -12
- package/governance/rules/writing/801-markdown.md +0 -14
- package/governance/rules/writing/802-mermaid.md +0 -14
- package/governance/rules/writing/880-readme.md +0 -11
- package/governance/rules/writing/891-standard-authoring.md +0 -12
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ Each domain has a canonical source in this repo and a thin install or sync CLI o
|
|
|
68
68
|
| Standards | Authoring conventions for commits, branches, plans, tasks, and markdown | Opened by name, read by name with `canon standards <name>` |
|
|
69
69
|
| Tooling stacks | Golden configs, seeds, and a reference per framework | Laid down by `canon init`, reconciled by `canon tooling sync` |
|
|
70
70
|
| Design system | Ships a `DESIGN.md` token format, a skill that drafts one from an existing project or from scratch, and a render command | `canon design render` |
|
|
71
|
-
| Slides | A `SLIDES.md` source format with a layout catalog
|
|
71
|
+
| Slides | A `SLIDES.md` source format with a layout catalog, or a folder of HTML slides rebuilt as editable shapes | `canon slides render` writes PowerPoint |
|
|
72
72
|
| Teach | Lessons, sources, and a glossary in one workspace, rendered to a small site | `canon teach` |
|
|
73
73
|
| Canvas | Pages of HTML frames on a local pan and zoom surface, each frame drawn with the project's tokens | `canon canvas serve` |
|
|
74
74
|
| Transcripts | A YouTube transcript with metadata frontmatter | `canon transcripts <url>` writes it into any repo |
|
|
@@ -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
|
|
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
|
|
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
|
|
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 `
|
|
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
|
|
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
|
-
-
|
|
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
|
|
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.
|
package/docs/agents/canvas.md
CHANGED
|
@@ -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.
|
package/docs/agents/commands.md
CHANGED
|
@@ -129,6 +129,7 @@ Subcommands no other page describes:
|
|
|
129
129
|
- `claude skills rank` scores either skill corpus's descriptions against a case corpus by TF-IDF cosine similarity, reporting rank-one and top-three (`--cases <path>`).
|
|
130
130
|
- `design regen` rewrites this repository's `canon/DESIGN.md` from `src/design/tokens.ts` and `src/design/base.css` from `src/design/neutral.ts`. `design css` emits the tokens and components as CSS on stdout, with `--no-components` for properties alone, and `design render` declares each vendored face the typography table names under `--embed-fonts`.
|
|
131
131
|
- `slides render` renders a `.claude/SLIDES.md` source into a PowerPoint deck and reports any unrecognized layout name on stderr, and `slides list --json` emits the layout catalog.
|
|
132
|
+
- `slides render --source <folder>` lays out each `.html` file in filename order in Chromium at 1280 by 720 and rebuilds it as editable shapes. Each element drawn as a picture prints one `✗` line on stderr naming the slide, the selector, and the properties that forced it. A link left out, being a `#slide-N` past the deck's end or any target that is neither that nor an absolute URL, prints one too, and the exit stays 0.
|
|
132
133
|
- `canvas`, with its verbs, content format, and write routes, is described in `canvas.md`.
|
|
133
134
|
- `labels scan` fails a pull request or a posted review whose title, body, or review comment carries a phase label, a label a code span quotes, a gitignored record path, a session link, a title word no dictionary holds, or a title breaking `standards/pr.md`'s format, casing, or length rule (`--event`, `--body-file`, `--json`).
|
|
134
135
|
- `repo metadata propose` compares a description, homepage, and topic set computed from the README and `package.json` against what the remote carries, writing nothing, and `repo metadata apply` writes an explicitly supplied set through `gh repo edit` (`--description`, `--homepage`, `--topics`).
|
package/docs/agents/demo.md
CHANGED
|
@@ -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.
|
|
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
|
|
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
|
|
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.
|
|
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 `
|
|
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/
|
|
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/
|
|
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
|
|
package/docs/agents/sandbox.md
CHANGED
|
@@ -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
|
-
| `--
|
|
64
|
-
| `--
|
|
65
|
-
| `--
|
|
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
|
|
package/docs/agents/teach.md
CHANGED
|
@@ -126,9 +126,15 @@ The link opens the named workspace's contents page, or the root listing when no
|
|
|
126
126
|
|
|
127
127
|
The JSON record is one line carrying the `nav` fields, then `served`, the absolute folder, and the server's `host`, `port`, `entry`, `url`, and `entryExists`. A lesson `nav` skips lands in `skipped` and the server still starts, since a partial refresh is still worth viewing. A `nav` refusal starts no server.
|
|
128
128
|
|
|
129
|
+
While it runs, `up` watches the teach root. A change there, such as a lesson, a workspace, a glossary term, or a reference page added by hand or by another `teach` verb, runs the `nav` pass again, and every open page reloads once that pass changes what is served. Passes run one at a time, so a burst of saves costs one more pass rather than several at once. A pass `nav` refuses, such as one over a workspace deleted while it was served, is reported on stderr, the server keeps running, and no page reloads.
|
|
130
|
+
|
|
131
|
+
Each refresh is logged to stderr, so stdout stays the one record line. Dotfiles and editor backups ending in `~` start no pass.
|
|
132
|
+
|
|
133
|
+
The reload script is added to each page as the server sends it and never written to disk, so a page saved from the browser, a promoted lesson, and a committed fixture carry no trace of it. The script listens on `/__live`, which answers only a request naming the server by its loopback address or `localhost`.
|
|
134
|
+
|
|
129
135
|
Viewing writes. Every page and generated stylesheet `nav` owns is rewritten first, which on a committed fixture shows as a diff. To serve without rewriting anything, `canon teach list <topic>` ends its human output with a `canon serve` line for that workspace, with the teach folder written relative to the cwd, or absolute when it sits outside it. The JSON record of `list` carries no such field.
|
|
130
136
|
|
|
131
|
-
`canon serve` itself stays general, since nothing about serving a directory is specific to a learning workspace and the same verb carries a slide render and a design preview. What `up` adds in front of it is the refresh,
|
|
137
|
+
`canon serve` itself stays general, since nothing about serving a directory is specific to a learning workspace and the same verb carries a slide render and a design preview. What `up` adds in front of it is the refresh and the watch that repeats it, both teach-specific, and it serves through the same server rather than a second one.
|
|
132
138
|
|
|
133
139
|
Read `url` off the record rather than building one from the port that was asked for. The verb walks forward past a port already in use, which is routine when a second workspace is already open, and the port it took is the one thing a composed URL gets wrong.
|
|
134
140
|
|
|
@@ -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
|
|
52
|
-
`.canon/tasks/priority.md
|
|
53
|
-
|
|
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,
|
|
120
|
-
|
|
121
|
-
each address-review pass with the new CI state, and
|
|
122
|
-
interactive prompt. Nothing is sent on progress. An
|
|
123
|
-
starts the controller's review poll, with a dispatch
|
|
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,
|
|
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
|
|