@erclx/canon 5.38.0 → 5.40.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 +5 -5
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +12 -9
- package/claude/skills/auto-ship/SKILL.md +43 -23
- package/claude/skills/backlog-triage/SKILL.md +62 -53
- package/claude/skills/backlog-triage/references/apply.md +69 -0
- package/claude/skills/build-in-slices/SKILL.md +8 -4
- package/claude/skills/canon-cli/SKILL.md +5 -1
- package/claude/skills/canon-feedback/SKILL.md +18 -8
- package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
- package/claude/skills/canvas-board/SKILL.md +37 -18
- package/claude/skills/ci-workflow/SKILL.md +5 -4
- package/claude/skills/code-craft/SKILL.md +10 -6
- package/claude/skills/codebase-layout/SKILL.md +3 -5
- package/claude/skills/context-fold/REQUIREMENT.md +4 -4
- package/claude/skills/context-fold/SKILL.md +42 -23
- package/claude/skills/context-fold/references/context-refresh.md +4 -3
- package/claude/skills/context-fold/references/context.md +79 -64
- package/claude/skills/create-rule/SKILL.md +7 -3
- package/claude/skills/create-skill/SKILL.md +27 -7
- package/claude/skills/create-skill/references/skill-reference.md +41 -17
- package/claude/skills/decision-escalate/SKILL.md +8 -5
- package/claude/skills/deploy-app/SKILL.md +1 -1
- package/claude/skills/deprecation-migration/SKILL.md +12 -4
- package/claude/skills/design-taste/SKILL.md +17 -11
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
- package/claude/skills/docs-sync/SKILL.md +17 -6
- package/claude/skills/docs-sync/references/docs.md +54 -21
- package/claude/skills/docs-sync/references/readme.md +32 -8
- package/claude/skills/document-health/SKILL.md +3 -4
- package/claude/skills/draft-and-pick/SKILL.md +73 -47
- package/claude/skills/draft-doc/SKILL.md +9 -4
- package/claude/skills/draft-doc/references/context.md +4 -4
- package/claude/skills/draft-doc/references/docs.md +1 -0
- package/claude/skills/draft-doc/references/wiki.md +3 -2
- package/claude/skills/draft-figure/SKILL.md +9 -7
- package/claude/skills/draft-identity/SKILL.md +24 -52
- package/claude/skills/draft-identity/references/card-route.md +46 -0
- package/claude/skills/draft-ready/SKILL.md +19 -7
- package/claude/skills/draft-screencast/SKILL.md +6 -112
- package/claude/skills/draft-screencast/references/beats-template.md +119 -0
- package/claude/skills/draft-slides/SKILL.md +9 -7
- package/claude/skills/draft-slides/references/deck.md +183 -0
- package/claude/skills/git-branch/SKILL.md +3 -3
- package/claude/skills/git-commit/SKILL.md +5 -3
- package/claude/skills/git-followup/SKILL.md +16 -9
- package/claude/skills/git-issue/SKILL.md +6 -5
- package/claude/skills/git-pr/SKILL.md +56 -44
- package/claude/skills/git-pr/references/evidence.md +2 -2
- package/claude/skills/git-pr/references/final-command.md +1 -1
- package/claude/skills/git-pr/references/labels.md +1 -1
- package/claude/skills/git-pr/references/publish.md +1 -1
- package/claude/skills/git-ship/SKILL.md +43 -34
- package/claude/skills/git-ship/references/ci-watch.md +31 -0
- package/claude/skills/git-split/SKILL.md +28 -100
- package/claude/skills/git-split/references/independent.md +40 -0
- package/claude/skills/git-split/references/stacked.md +73 -0
- package/claude/skills/git-stage/SKILL.md +9 -7
- package/claude/skills/git-worktree/SKILL.md +27 -49
- package/claude/skills/git-worktree/references/cleanup.md +55 -0
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/markdown-craft/references/markdown.md +82 -53
- package/claude/skills/plan-feature/SKILL.md +52 -46
- package/claude/skills/plan-feature/references/batches.md +46 -0
- package/claude/skills/plan-groundwork/SKILL.md +60 -74
- package/claude/skills/plan-groundwork/references/output.md +48 -0
- package/claude/skills/plan-intake/SKILL.md +28 -21
- package/claude/skills/plan-intake-answer/SKILL.md +14 -13
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +31 -11
- package/claude/skills/review-address/SKILL.md +76 -158
- package/claude/skills/review-address/references/rebase-only.md +34 -0
- package/claude/skills/review-craft/SKILL.md +27 -11
- package/claude/skills/review-pr/SKILL.md +91 -40
- package/claude/skills/review-ui/SKILL.md +63 -37
- package/claude/skills/review-ui/references/hosted-preview.md +30 -0
- package/claude/skills/role-orchestrator/SKILL.md +105 -74
- package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-planner/SKILL.md +66 -64
- package/claude/skills/role-reviewer/SKILL.md +57 -46
- package/claude/skills/role-worker/SKILL.md +68 -63
- package/claude/skills/search-craft/SKILL.md +7 -5
- package/claude/skills/session-compact/SKILL.md +16 -11
- package/claude/skills/session-map/SKILL.md +31 -10
- package/claude/skills/session-relay/SKILL.md +32 -65
- package/claude/skills/session-resume/SKILL.md +18 -13
- package/claude/skills/session-worktree/SKILL.md +70 -42
- package/claude/skills/systematic-debugging/SKILL.md +6 -1
- package/claude/skills/target-check/SKILL.md +13 -6
- package/claude/skills/target-setup/SKILL.md +39 -27
- package/claude/skills/task-board/SKILL.md +68 -60
- package/claude/skills/task-board/references/board.md +1 -1
- package/claude/skills/task-board/references/create-report.md +36 -0
- package/claude/skills/task-board/references/tasks.md +1 -1
- package/claude/skills/task-complete/SKILL.md +20 -18
- package/claude/skills/teach-workspace/SKILL.md +61 -33
- package/claude/skills/test-craft/SKILL.md +2 -1
- package/claude/skills/test-first/SKILL.md +15 -9
- package/claude/skills/ui-checklist/SKILL.md +18 -16
- package/claude/skills/ux-audit/SKILL.md +9 -10
- package/claude/skills/ux-measure/SKILL.md +23 -19
- package/claude/skills/video-craft/SKILL.md +15 -7
- package/claude/skills/write-human/SKILL.md +9 -1
- package/claude/skills/youtube-transcripts/SKILL.md +2 -1
- package/docs/agents/audits.md +61 -60
- package/docs/agents/context-audit.md +40 -58
- package/docs/agents/index.md +11 -61
- package/docs/agents/indexes.md +25 -29
- package/docs/agents/install-and-sync.md +125 -235
- package/docs/agents/markdown-audit.md +54 -96
- package/docs/agents/migrate.md +41 -16
- package/docs/agents/output-shape.md +60 -45
- package/docs/agents/overview.md +36 -12
- package/docs/agents/records.md +37 -79
- package/docs/agents/sessions-transfer.md +26 -70
- package/docs/agents/targets.md +25 -77
- package/docs/target/index.md +0 -1
- package/docs/target/migrations.md +57 -66
- package/docs/target/projects.md +36 -78
- package/docs/target/scenarios.md +9 -19
- package/docs/target/sync.md +27 -68
- package/docs/workflow/ai-workflow.md +22 -68
- package/docs/workflow/operating-model.md +32 -186
- package/docs/workflow/parallel-features.md +29 -66
- package/docs/workflow/skill-map-on-request.md +22 -24
- package/docs/workflow/skill-map.md +72 -76
- package/docs/workflow/visual-design-workflow.md +25 -118
- package/docs/workflow/zshrc-aliases.md +18 -37
- package/package.json +1 -1
- package/src/canvas/client/inspector/fields.css +4 -0
- package/src/canvas/index.html +6 -0
- package/src/claude/skills-reach.ts +2 -2
- package/src/cli/ui.ts +3 -1
- package/src/commands/canvas.ts +23 -0
- package/src/commands/capture.ts +14 -0
- package/src/commands/claude.ts +14 -1
- package/src/commands/context.ts +106 -7
- package/src/commands/demo.ts +22 -0
- package/src/commands/deps.ts +6 -0
- package/src/commands/driver.ts +28 -2
- package/src/commands/gov.ts +52 -18
- package/src/commands/hooks.ts +63 -0
- package/src/commands/intake.ts +17 -0
- package/src/commands/labels.ts +38 -5
- package/src/commands/markdown.ts +169 -32
- package/src/commands/pr.ts +160 -43
- package/src/commands/records.ts +8 -0
- package/src/commands/secrets.ts +6 -0
- package/src/commands/sessions.ts +8 -0
- package/src/commands/tasks.ts +52 -0
- package/src/commands/teach.ts +13 -0
- package/src/commands/upstream.ts +25 -1
- package/src/commands/worktrees.ts +5 -0
- package/src/context/audit.ts +274 -5
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/folders.ts +1 -1
- package/src/context/gate.ts +23 -7
- package/src/context/shape-gated.ts +30 -0
- package/src/counts/scan.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/gate/boundaries.ts +4 -1
- package/src/gate/measures.ts +16 -191
- package/src/gate/stages.ts +14 -30
- package/src/git/env.ts +6 -0
- package/src/hooks/reply-links.ts +110 -0
- package/src/markdown/density.ts +258 -0
- package/src/markdown/gate.ts +57 -18
- package/src/markdown/reference-shape.ts +103 -0
- package/src/markdown/scope.ts +162 -0
- package/src/markdown/structure.ts +9 -59
- package/src/pr/lift.ts +153 -19
- package/src/pr/painted.ts +87 -0
- package/src/roots/record.ts +18 -1
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/headless/run.ts +3 -2
- package/src/sandbox/headless/watch.ts +3 -4
- package/src/shipped/references.ts +1 -1
- package/src/slides/convert/master.ts +3 -0
- package/src/sync/format.ts +46 -0
- package/src/sync/stamp.ts +6 -0
- package/tooling/astro/reference.md +2 -2
- package/tooling/base/reference.md +1 -1
- package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/tooling/go/reference.md +1 -1
- package/tooling/nextjs/reference.md +1 -1
- package/tooling/php/reference.md +1 -1
- package/tooling/python/reference.md +1 -1
- package/tooling/vite-react/reference.md +1 -1
- package/tooling/web/reference.md +1 -1
- package/docs/agents/canvas.md +0 -86
- package/docs/agents/capture.md +0 -65
- package/docs/agents/census.md +0 -23
- package/docs/agents/commands.md +0 -154
- package/docs/agents/comments.md +0 -34
- package/docs/agents/context-audit-checks.md +0 -90
- package/docs/agents/context-classify.md +0 -101
- package/docs/agents/counts.md +0 -74
- package/docs/agents/demo.md +0 -140
- package/docs/agents/docs.md +0 -27
- package/docs/agents/drift-surfaces.md +0 -201
- package/docs/agents/driver.md +0 -103
- package/docs/agents/gate.md +0 -90
- package/docs/agents/gov-detect.md +0 -47
- package/docs/agents/hooks.md +0 -58
- package/docs/agents/intake.md +0 -81
- package/docs/agents/key-changes.md +0 -116
- package/docs/agents/label-coverage.md +0 -86
- package/docs/agents/markdown-audit-weight.md +0 -81
- package/docs/agents/pr-evidence-layout.md +0 -70
- package/docs/agents/pr-evidence.md +0 -273
- package/docs/agents/pr-frames.md +0 -131
- package/docs/agents/pr-lift.md +0 -132
- package/docs/agents/pr-local.md +0 -111
- package/docs/agents/pr-preview.md +0 -155
- package/docs/agents/pr-reads.md +0 -111
- package/docs/agents/pr-tick.md +0 -72
- package/docs/agents/records-push.md +0 -61
- package/docs/agents/records-stale.md +0 -40
- package/docs/agents/records-validate.md +0 -57
- package/docs/agents/restated.md +0 -83
- package/docs/agents/routing.md +0 -61
- package/docs/agents/rule-citations.md +0 -90
- package/docs/agents/sandbox.md +0 -126
- package/docs/agents/scripting.md +0 -142
- package/docs/agents/sessions.md +0 -128
- package/docs/agents/skills-audit.md +0 -120
- package/docs/agents/skills-reach.md +0 -64
- package/docs/agents/slides.md +0 -176
- package/docs/agents/state-scoped-risk.md +0 -105
- package/docs/agents/superseded.md +0 -85
- package/docs/agents/tasks-archive.md +0 -83
- package/docs/agents/tasks-plans.md +0 -152
- package/docs/agents/tasks-validate.md +0 -133
- package/docs/agents/tasks.md +0 -123
- package/docs/agents/teach-authoring.md +0 -118
- package/docs/agents/teach.md +0 -157
- package/docs/agents/test-order.md +0 -58
- package/docs/agents/upstream.md +0 -94
- package/docs/agents/worktrees.md +0 -118
- package/docs/target/standards-moved.md +0 -34
- package/src/markdown/growth.ts +0 -43
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Context audit checks
|
|
3
|
-
description: What each non-gating check reports, the unit each checkpoint is measured in, the requirements record's word cap, which folders each check reaches, and what moved to the attribute tier
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Context audit checks
|
|
7
|
-
|
|
8
|
-
What each finding from `canon context audit` means. The command surface, its flags, and the two gating checks are in `context-audit.md`.
|
|
9
|
-
|
|
10
|
-
## Required sections
|
|
11
|
-
|
|
12
|
-
The required-section check reports what does not declare the sections its folder's standard requires. A context entry owes `## Overview` and `## Layout`, the two sections `claude/skills/context-fold/references/context.md` marks required. The lists are held in code beside the numeric checkpoints rather than parsed out of the standard, so it fails on a defect rather than on a rewrite of the wording around it. A heading at any level counts, because a domain that split into a folder carries its overview in a sibling named `overview.md` where the section is the `#` title and an `##` beneath it would repeat the filename. Matching exactly is what keeps `## Layout catalog` from satisfying `Layout`.
|
|
13
|
-
|
|
14
|
-
Which unit answers depends on the folder. Entries of the folder named under `.claude/` are one domain each, so each answers for itself and a finding names the entry. Entries of a folder a domain split into describe that one domain between them, so any sibling answers and a finding names the folder. Holding a split folder to the rule per file would report every child beside its `overview.md`, and rolling the named folder up would let one conforming entry stand in for every other domain sitting next to it.
|
|
15
|
-
|
|
16
|
-
It reports rather than gates by default, the closer call because a missing section reads more like a fact than the other judgments. What settles it is that the standard sanctions omitting `## Layout` from a domain owning no paths in the repo, and no measure separates that from an entry that forgot it. A domain covering only external tools is that case, and it reports on every run. The JSON record carries the findings as `missingSections`, the lists per folder name as `checkpoints.requiredSectionsByFolder`, and the context list alone as `checkpoints.requiredSections`, the flat key it carried first.
|
|
17
|
-
|
|
18
|
-
`--gate` promotes the finding to a failing exit code, which the seed stage runs and no other caller does. That mode needs an answer to the sanctioned omission above, so a file declaring `stub: true` in its frontmatter is dropped before the check and reported nowhere. Both are described in `context-audit.md`.
|
|
19
|
-
|
|
20
|
-
### The closed set
|
|
21
|
-
|
|
22
|
-
The same section also reports an H2 outside the folder's closed set. A context entry allows `Overview`, `Layout`, `Decisions`, and `Gotchas` and no other H2, so a topic of the domain's own sits one level down as an H3. The finding is per entry rather than per folder, since an extra heading is a fact about the file carrying it. Fenced blocks are skipped, a stub seed is skipped, and only H2 is read, so where an H3 sits is not audited. It gates under `--gate` alone, like a missing section.
|
|
23
|
-
|
|
24
|
-
The record carries it as a top-level `extraSections` array of `{ rel, headings }`, and the set itself as `checkpoints.allowedSectionsByFolder`, keyed on the folder name the way `requiredSectionsByFolder` is. Both are additive.
|
|
25
|
-
|
|
26
|
-
## Reference form
|
|
27
|
-
|
|
28
|
-
The reference-form check reports an entry naming a sibling entry by bare filename where `claude/skills/context-fold/references/context.md` asks for the path it sits at. A bare name resolves against whichever folder its reader is already in, so a domain that splits into subfolders strands every inbound reference and the break surfaces nowhere. A path is checkable, which is what makes the form rule worth measuring at all: once a reference spells its path, the citation gate resolves it and a split that moves the file fails the push.
|
|
29
|
-
|
|
30
|
-
A finding is a backticked filename carrying no folder, matched against the entries beside the one that wrote it. The backticks are required, since a filename in running prose is not a reference a reader follows.
|
|
31
|
-
|
|
32
|
-
A name matching no sibling is left alone, which is the measure reaching less than the rule does rather than the rule stopping there. The standard governs a reference to any other entry, so a split entry naming one that sits in a different folder is a violation this check never sees. What the sibling set buys is that a name resolving inside the folder is a reference by construction, where a bare filename matched anywhere would report every sentence that happens to name a file.
|
|
33
|
-
|
|
34
|
-
An entry naming itself is left alone on separate grounds, since no split can strand it. Fenced blocks are excluded with the scans above, and a line carrying the citation ignore marker is excluded because that marker already means the line displays a name rather than pointing at one.
|
|
35
|
-
|
|
36
|
-
The check covers the folders a domain split into and stops at the flat folder above them. A split folder's entries are named for sub-areas of one domain, so a bare name matching one of them points at it. The flat folder's entries are named for whole domains, and a domain name is a common noun that a seed or another tree spells the same way, which is where both false positives measured against this corpus sat. What the exemption costs is the references a future split of the flat folder would strand, and it is taken because a report firing on correct prose teaches a reader to stop reading the section.
|
|
37
|
-
|
|
38
|
-
It reports and never gates, which is the split the citation check already draws. An unresolved path is a fact and a form violation is a judgment with a measured false-positive rate, the same line `canon markdown audit` draws between a ban and a weight checkpoint. The JSON record carries the findings per entry as `entries[].bareReferences`.
|
|
39
|
-
|
|
40
|
-
## Length
|
|
41
|
-
|
|
42
|
-
Length quotes its checkpoint from `claude/skills/context-fold/references/context.md`: roughly 150 rendered lines for an entry, applied to each of the 60 entries the audit measures, 51 of them under `canon/context/` and 9 diagram files beside them. It counts rendered lines rather than source lines, wrapping each line at 80 columns and summing the heights.
|
|
43
|
-
|
|
44
|
-
A line is wrapped at the width it renders at, so a link counts as its anchor text and a backticked path counts whole, which parts the rendered count from a source count wherever an entry cites a path in backticks rather than as a link. Entries here are authored one line per bullet, so a block of fifteen paragraph-bullets occupies fifteen source lines and renders past sixty, which source counting cannot see.
|
|
45
|
-
|
|
46
|
-
The measure counts fenced blocks and frontmatter, so a reference-heavy entry ranks by its examples, which the legend states on every run alongside the width, since a number in rendered lines cannot be reproduced without it.
|
|
47
|
-
|
|
48
|
-
Every entry past the checkpoint carries the three questions the standard asks of it rather than a count alone: whether it still covers one domain, whether it has filled with content `ls` or `--help` reproduces, and whether it has accumulated the history of its own changes. The checkpoint is not a cap, so the count is not the finding. What a reader acts on is which question came back true, and the standard directs the fix at that rather than at the number.
|
|
49
|
-
|
|
50
|
-
Only the third is mechanical, and it is the provenance check already reported below, so the length finding cites that count rather than measuring it again. What it cites is a count of change markers, which is why an entry recording what its own runs cost answers `no` there while carrying dates throughout. An entry outside the governed folder reads open there too, since provenance is scoped to the standard stating it and a clean list there is a scan that never ran. The other two stay open beside every entry, because whether a domain is still one domain is a judgment about its subject and recognizing reproduced content needs a reader who knows what those commands emit. Omitting them would read as an entry nothing found rather than one nothing checked.
|
|
51
|
-
|
|
52
|
-
It reports and never gates, which the standard settles rather than the usual judgment-against-fact line: the 150 checkpoint is diagnostic, so an entry that answers all three and is still long is a correct outcome. The one hard cap is the 300-line whole-document ceiling, which `canon markdown audit` and the Document ceiling gate stage read rather than this check. The JSON record carries the joined findings as `length`, each with a `causes` array in the standard's order, and the jurisdiction the join reads as `entries[].governed`. That flag is what parts a provenance list measured and empty from one never scanned, which the count alone cannot say. The join is published rather than left to a consumer, since deriving it means restating which question the provenance count answers.
|
|
53
|
-
|
|
54
|
-
Depth and bullet weight are quoted from `claude/skills/markdown-craft/references/markdown.md`, which states both over every markdown file rather than over a context entry, so `canon markdown audit` measures them and this command no longer does. They share `renderedHeight` with the length measure, since the two checkpoints sit in one section of that standard and a reader compares them. What the split costs is that a session wanting both numbers for one entry runs two commands, and what it buys is that either number can be had for a file in a folder this audit refuses to resolve.
|
|
55
|
-
|
|
56
|
-
## Tables
|
|
57
|
-
|
|
58
|
-
The table check reports a catalog that grows a row per shipped thing, not a table count. A fixed comparison table never reflows, so its size costs nothing. A table qualifies at six or more body rows whose first column mostly carries a path, command, or link, which is what separates a catalog from a comparison without reading the prose. It stays here rather than moving with depth, because the shape it routes a catalog into is a judgment the context standard makes about an entry.
|
|
59
|
-
|
|
60
|
-
## Provenance
|
|
61
|
-
|
|
62
|
-
The provenance check reports the markers narrating how a domain reached its shape rather than describing what it is: a date, a change number, or a release label. The standard admits a rejected alternative and the reasoning that killed it while refusing the provenance attached to it, so a marker names a line to read rather than a line to delete. Findings group by entry and sort left to right within a line, since what a reader acts on is which file to open.
|
|
63
|
-
|
|
64
|
-
A change number matches at any digit count, so `PR #7` and `#49` report alongside a four-digit number. Displayed spans are masked before the match runs, which is what keeps a heading's own auto-derived link destination, `(#7-open-questions)`, and a hex color in a code span, `` `#000` ``, from reading as a change reference: both are text an entry shows rather than a claim it makes. <!-- canon-allow-reference: illustrates the input shape the rule reads -->
|
|
65
|
-
|
|
66
|
-
A date stamping a measurement is excluded, because the standard cuts a date attached to a change and permits one dating a figure. The check reads the clause in front of the date, back to the nearest sentence boundary, for one of five verbs: measured, verified, driven, passed, and fired. The noun `run` counts only where it sits against the date, so `A run on 2026-08-14` is excluded and `Runs on erclx/canon#632 and erclx/canon#634 landed 2026-08-02` reports. The set is closed, and a date it cannot place reports as a change marker rather than as a state of its own, which names one date too many rather than clearing one the rule cuts. <!-- canon-allow-reference: illustrates the input shape the rule reads -->
|
|
67
|
-
|
|
68
|
-
A release label reports with or without its leading `v` at three segments, since the rule cuts the label rather than a spelling of it. Two segments still need the `v`, which keeps a dollar cost and a duration out. Another tool's version reports too, and the check cannot tell one from a release, so treat a version beside a tool name as a line to read rather than one to cut.
|
|
69
|
-
|
|
70
|
-
Fenced blocks are excluded, which keeps a pinned version in an install command from reading as a claim the entry makes. Frontmatter is excluded with them, since the content checks read the body alone, and that is what keeps a diagram entry's dated `verified` stamp a record of its last check rather than a marker to settle. Length is the exception, counting the whole file, so a reader applying the 150-rendered-line checkpoint against the body alone lands a few lines under what the tool reports.
|
|
71
|
-
|
|
72
|
-
## The requirements record
|
|
73
|
-
|
|
74
|
-
The audit reads `canon/REQUIREMENTS.md` under its own step rather than as a folder, and counts every word below the frontmatter against the cap the record states in a clause of the form `This record holds at most 600 words.` The cap is the record's own, so a record stating none is measured and never gated, and a project with no record is reported as out of scope. The seeded record states the 600-word cap. The JSON record carries the reading as `requirements`, null where the project carries no record and absent under `--citations-only`, and the audit catalog counts a record past its cap as `requirementsOverWords`.
|
|
75
|
-
|
|
76
|
-
## Which folders each check reaches
|
|
77
|
-
|
|
78
|
-
The provenance check covers `canon/context/` alone, the reference-form check covers the split folders inside it, the required-section check covers `canon/context/` alone, and length and the table finding reach every audited folder.
|
|
79
|
-
|
|
80
|
-
What narrows the provenance check is stated in `claude/skills/context-fold/references/context.md`, which opens its scope by handing figures to the `draft-figure` skill, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder, and what decides it is which tier states the rule rather than what the check measures.
|
|
81
|
-
|
|
82
|
-
Length and the table finding generalize as judgments about how far a reader travels, so both reach wherever the audit is pointed. Required sections narrow for a plainer reason: each list is one standard's own, so it reaches the folder that standard governs. The context standard states a set, and an older install's diagrams folder has no standard to state one.
|
|
83
|
-
|
|
84
|
-
The same test is what moved depth and bullet weight out of this command entirely. A rule stated at the attribute tier reaches every markdown file, and a check reaching every markdown file has no reason to require a folder that resolves.
|
|
85
|
-
|
|
86
|
-
The scoping key is the folder an entry was audited under, so `--folder` still reaches a folder the default list does not carry, and a domain split into `context/<sub-area>/` is governed as `context`. Every run states the reach, including a run where no audited folder is the governed one. The JSON record carries it as `checkpoints.provenanceFolder` and a per-folder `governsContent`.
|
|
87
|
-
|
|
88
|
-
## Index drift
|
|
89
|
-
|
|
90
|
-
Index drift compares an index against its siblings in both directions. An entry the index does not link is invisible to a session choosing what to open, and a linked name resolving to nothing sends one to a path that opens nothing.
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Doc classifier
|
|
3
|
-
description: Classifying canonical-doc content as keep, replace/rewrite, history, or move in diff and sweep mode, the classifier setting pair, the record shape, and the exit codes
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Doc classifier
|
|
7
|
-
|
|
8
|
-
`canon context classify` reads content from the three canonical doc types (`context/<domain>.md`, `DESIGN.md`, `REQUIREMENTS.md`) and reports whether each piece states the project as it stands or should be rewritten, narrated elsewhere, or moved to another surface. It reports and never gates: a finding is a judgment for a writer to act on, not a fact a push fails over. The `context-fold` skill calls this verb in diff mode over its own diff baseline. Wiring it into the merge gate or `canon context audit` is separate work this verb does not do.
|
|
9
|
-
|
|
10
|
-
Two modes read different units. Diff mode reads the chunks a git range changed, each with the section it landed in, which is what a session checks right after an edit. Sweep mode reads every section of the four doc types, split at H3, which is what a cleanup pass or a periodic re-scan runs over a whole corpus.
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
canon context classify diff
|
|
14
|
-
canon context classify diff --base origin/main --json
|
|
15
|
-
canon context classify diff --doc-types context,design
|
|
16
|
-
canon context classify sweep
|
|
17
|
-
canon context classify sweep --doc-types design,requirements --json
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
| Option | Behavior |
|
|
21
|
-
| -------------------- | -------------------------------------------------------------- |
|
|
22
|
-
| `--base <ref>` | Diff mode only. Far side of the range, defaulting to the trunk |
|
|
23
|
-
| `--doc-types <list>` | Comma-separated canonical doc types (default: all four) |
|
|
24
|
-
| `--backend <name>` | Override the resolved model backend for this run |
|
|
25
|
-
| `--model <name>` | Override the resolved model name for this run |
|
|
26
|
-
| `--json` | Add a machine-readable record on stdout |
|
|
27
|
-
|
|
28
|
-
## Two layers
|
|
29
|
-
|
|
30
|
-
The regex layer always runs. It is free, needs nothing installed, and catches narration (a branch name, "closed on", "did not survive"). It never answers REPLACE in diff mode, since telling a restated figure from a genuinely new one needs the section a hunk landed in, which the model layer reads and the regex layer does not.
|
|
31
|
-
|
|
32
|
-
The local Ollama layer runs only when configured, through `canon context classifier`. When it runs, its call is one chunk or section per request, never batched: the groundwork measurement behind this verb found that batching 16 hunks into one call returned KEEP for every one of them. Thinking is always off, since it was measured to catch nothing thinking-off missed while running roughly five times slower and, in sweep mode, losing three real flags by reasoning past them.
|
|
33
|
-
|
|
34
|
-
Sweep mode reads decision rationale as current. A reason naming why an alternative was left out, what an earlier approach got wrong, what a measurement caught, or what a past run cost is KEEP even told in the past tense. Only a superseded figure kept beside its replacement, a "now" or "no longer" marking a change, branch or PR narration, or rounds of candidates is REWRITE.
|
|
35
|
-
|
|
36
|
-
A finding carries both layers' readings when the model ran. The `verdict` field takes the model's reading when it ran and parsed, and falls back to the regex reading otherwise, since the model catches shapes the regex layer cannot reach structurally. `decidedBy` names which one won.
|
|
37
|
-
|
|
38
|
-
A configured-but-unreachable backend warns on stderr and falls back to the regex layer alone. The run still exits clean: the record's `modelLayer` field names why the model layer did not run (`off`, `skipped-no-model`, `skipped-unreachable`, or `ran`), so a clean regex-only report never reads as a clean model pass.
|
|
39
|
-
|
|
40
|
-
## The classifier setting
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
canon context classifier show
|
|
44
|
-
canon context classifier show --json
|
|
45
|
-
canon context classifier set --backend ollama --model qwen3.8:27b
|
|
46
|
-
canon context classifier set --backend off
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
The backend and model resolve independently through the same four-tier precedence: a flag on the verb, then `CANON_CLASSIFIER_BACKEND` / `CANON_CLASSIFIER_MODEL`, then `canon/config/classifier.toml`, then off. `classifier show` reports the resolved backend and model and which tier decided them, without running a classification. There is no default model name: a model that resolves on one machine means nothing on another, so a backend configured with no model reports `no-model` from `show` and runs the regex layer alone from `classify`.
|
|
50
|
-
|
|
51
|
-
`classifier set` writes `canon/config/classifier.toml`, creating `canon/config/` when a project does not carry it yet:
|
|
52
|
-
|
|
53
|
-
```toml
|
|
54
|
-
[classifier]
|
|
55
|
-
backend = "ollama"
|
|
56
|
-
model = "qwen3.8:27b"
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
`--backend off` writes a file with no `model` line, which reads back as `off` at the same tier a missing file would default to, but with a source line saying the file decided it rather than the default.
|
|
60
|
-
|
|
61
|
-
## The record
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{
|
|
65
|
-
"decision": "ok",
|
|
66
|
-
"mode": "diff",
|
|
67
|
-
"backend": "ollama",
|
|
68
|
-
"model": "qwen3.8:27b",
|
|
69
|
-
"modelLayer": "ran",
|
|
70
|
-
"settingsSource": "file",
|
|
71
|
-
"findings": [
|
|
72
|
-
{
|
|
73
|
-
"file": "canon/context/retrieval.md",
|
|
74
|
-
"docType": "context",
|
|
75
|
-
"regex": {
|
|
76
|
-
"verdict": "KEEP",
|
|
77
|
-
"quote": "",
|
|
78
|
-
"reason": "no narration or wrong-surface pattern"
|
|
79
|
-
},
|
|
80
|
-
"model": {
|
|
81
|
-
"verdict": "REPLACE",
|
|
82
|
-
"quote": "the count moved",
|
|
83
|
-
"reason": "restates a figure the section already carries"
|
|
84
|
-
},
|
|
85
|
-
"verdict": "REPLACE",
|
|
86
|
-
"decidedBy": "model"
|
|
87
|
-
}
|
|
88
|
-
]
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Sweep mode's findings carry a `heading` field alongside `file` and use the sweep vocabulary (KEEP, REWRITE, MOVE) rather than diff mode's four (KEEP, REPLACE, HISTORY, MOVE). REWRITE stands in for both REPLACE and HISTORY, matching the sweep prompt's own three-verdict vocabulary: a whole section already shows its own history in view, so there is no diff-mode split left to make.
|
|
93
|
-
|
|
94
|
-
## Exit codes
|
|
95
|
-
|
|
96
|
-
| Code | Meaning |
|
|
97
|
-
| ---- | ------------------------------------------------------------- |
|
|
98
|
-
| `0` | the run completed, whatever the findings say |
|
|
99
|
-
| `1` | refused: a bad range, an unreadable file, or a malformed flag |
|
|
100
|
-
|
|
101
|
-
Findings never set a failing exit code, in either mode. `canon audits run` carries sweep mode as its placement entry for the same reason, pinned to `--backend off` so the tally it retains is the regex layer's on every machine. `docs/agents/audits.md` states why. Diff mode refuses on a git range it cannot resolve. Both modes refuse on a file the run could not read.
|
package/docs/agents/counts.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Self-stated counts
|
|
3
|
-
description: Reading a sentence that asserts a closed catalog's size, how a match is decided, the plausibility filter that keeps a generic word from matching a subset, and why the sweep reports rather than gates
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Self-stated counts
|
|
7
|
-
|
|
8
|
-
`canon gov counts` reports a sentence stating how many members a closed catalog holds where the stated figure disagrees with what the tree actually counts. A document that reports its own catalog size carries a number nothing else compares against the tree, so it goes stale on the edit that moves the catalog and reads as current until a reviewer happens to recompute it.
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
canon gov counts
|
|
12
|
-
canon gov counts --json
|
|
13
|
-
canon gov counts --root ../my-app
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
| Option | Behavior |
|
|
17
|
-
| --------------- | ---------------------------------------------------------- |
|
|
18
|
-
| `--root <path>` | Tree to read, defaulting to the current directory |
|
|
19
|
-
| `--json` | Add a machine-readable record on stdout, keeping the frame |
|
|
20
|
-
|
|
21
|
-
Under `--json` the record holds stdout alone and the frame still renders on stderr, refusals included, which is the split `output-shape.md` fixes for every mode.
|
|
22
|
-
|
|
23
|
-
## The catalogs it reads
|
|
24
|
-
|
|
25
|
-
A closed set of four, each with a filesystem reader behind it rather than every list command this CLI ships:
|
|
26
|
-
|
|
27
|
-
- `skills`: shipped plugin skills, a folder per `claude/skills/*/SKILL.md`
|
|
28
|
-
- `rules`: authored governance rules, a file per `governance/rules/**/*.md`
|
|
29
|
-
- `commands`: top-level `canon` commands, read off `src/cli.ts`'s registration imports
|
|
30
|
-
- `audits`: the registered set in `src/audits/catalog.ts`, this entry included
|
|
31
|
-
|
|
32
|
-
The set is closed rather than derived, so widening it is a deliberate change to this file rather than a side effect of a new list command shipping elsewhere. `commands` is the one catalog with no meaning outside this repository: a project installing this CLI carries no `src/cli.ts` of its own, and that catalog reads as not applicable there rather than as zero, since zero would report a finding against any such project stating its command count as anything but zero, forever.
|
|
33
|
-
|
|
34
|
-
## How a match is decided
|
|
35
|
-
|
|
36
|
-
A sentence has to carry an assertion verb (`loads`, `ships`, `carries`, `holds`, `counts`, `totals`, `documents`, `declares`, `installs`, `lists`, `contains`, `comprises`, `authors`), the quantifier `all`, or an article (`the`, `a`, `an`) immediately ahead of the number, which is immediately ahead of the catalog noun, with one optional qualifying word between the number and the noun (`sixty-one shipped skills`). The number reads either as digits or as a spelled-out cardinal through ninety-nine, since this corpus states a catalog size in words as often as in digits.
|
|
37
|
-
|
|
38
|
-
Nothing stands between the trigger and the number, which is the rule an author writing a new count has to know. It separates `the toolkit authors 49 rules` and `took all 49 rules`, both read, from `a domain of 55 skills` and `denominator of sixty-one shipped skills`, neither of them read. A figure meant as a past state takes a date in the same sentence instead, which reads the sentence past whatever its shape.
|
|
39
|
-
|
|
40
|
-
## How the trigger set grew
|
|
41
|
-
|
|
42
|
-
The verb gate is not the first design tried. A bare number next to a catalog noun anywhere in the tracked corpus returned 290 findings against a repository whose actionable instance count was one. Reading that run showed why: `18 rules citing a standard`, `21 skill bodies`, and `eight internal skills` all pair a number with a catalog noun while naming a subset, an example, or a different catalog than the one matched, and that shape dominates ordinary prose. Every instance this sweep was written against reads the number as the direct object of a verb asserting the catalog's own total, and gating on that verb is what took the false-positive count from 290 to five on the same tree.
|
|
43
|
-
|
|
44
|
-
The article half was added after a first review of the shipped design found a live miss: the development domain's gating-stages entry stated a stale audit total while the tree held 20, and the verb gate never reached it, since that sentence puts its verb after the noun rather than ahead of the number. Widening the trigger set to admit an article ahead of the number closed that gap.
|
|
45
|
-
|
|
46
|
-
The quantifier `all` and the verb `authors` joined on the same evidence, two more live misses failing only the trigger test. Allowing words to stand between the trigger and the number was the other candidate, measured and declined: at widths of one, two, and three it reached 77, 104, and 132 sentences against a baseline of 65, missed `took all 49 rules` at every width, and reached `the toolkit authors 49 rules` only at a width admitting the indirect-noun shape below. The two words reach both at 75 sentences and no false positive.
|
|
47
|
-
|
|
48
|
-
## The plausibility filter
|
|
49
|
-
|
|
50
|
-
The verb gate alone still left four false positives standing: `carries two rules about a standard's own lifecycle`, `holds one rule or one fact` (twice, once per mirrored copy), and `documents two similar commands`. Each pairs an assertion verb with a catalog noun used for something the `rules` or `commands` catalog does not mean, and what tells those apart from the one live finding is magnitude: a catalog this sweep tracks drifts by a few members between the day a sentence was written and the day it is read, so a genuine staleness claim sits near the true count. `2` beside a true count of `59` is not a catalog that shrank, it is a different `rules` entirely.
|
|
51
|
-
|
|
52
|
-
A stated figure is read only when it sits within a factor of two of the true count, in either direction. That bound is tuned against the run this sweep was written against rather than reasoned to from first principles, the way `restated.ts` tunes its own document-frequency ceiling, and it is a property of the scale every catalog here sits at (the tens) rather than a universal rule.
|
|
53
|
-
|
|
54
|
-
The article gate is looser than the verb list and carries a real cost. Re-running against the tree once it widened caught the live miss above and also misread a passage in the standards destinations entry, since retired, naming a real subset, a standard outside the retired bundled fan-out, as a claim about the whole standards catalog. The qualifying adjective there fills the same optional-word slot `sixty-one shipped skills` needs to match at all, and no syntactic rule tells a qualifier that narrows a catalog from one that only restates it. The finding could not be closed by correcting a figure, since the sentence was true when the corpus held it, only unmarked as a past state, which is the class the date exclusion already reads past. Naming the moment, the same way a context entry dates its own figures, closed it with no change to the matcher.
|
|
55
|
-
|
|
56
|
-
## What it does not measure
|
|
57
|
-
|
|
58
|
-
A delta phrased as a transition (`from fourteen to fifteen`), a fraction (`thirteen of sixteen`), and a total reached through an indirect noun (`denominator of sixty-one shipped skills`) are all catalog-size claims this corpus carries, and none matches the trigger shape this reads. Each stays a known gap. The false-positive rate that gated closing them has a measurement behind it now, and what it showed is that the widening these three need is the one that costs a false positive rather than the one that does not.
|
|
59
|
-
|
|
60
|
-
A second figure in a sentence whose first figure already matched is a fourth gap and a structural one, since one match is taken per catalog per sentence. `authors 49 rules under governance/rules/ and consumes 31 into .claude/rules/` is read for its 49 alone, which is correct here because the two figures name different populations, and a sentence stating one catalog twice would go unread the same way.
|
|
61
|
-
|
|
62
|
-
A calendar date (`2026-08-21`) or a backticked commit reference in the same sentence reads the whole sentence past, since that is how this corpus already marks a figure as a historical record rather than a live claim. The context entries carry a figure this way deliberately, and every one of them stays correct forever.
|
|
63
|
-
|
|
64
|
-
The wider check over prose restatements is deliberately out of reach here. `canon gov restated` already records a parser over prose as rejected, and this sweep reaches a number with a command behind it rather than two sentences a reader has to judge as agreeing.
|
|
65
|
-
|
|
66
|
-
## Exit codes
|
|
67
|
-
|
|
68
|
-
Exit codes are `0` when no stated figure disagrees with the tree, `1` for a refusal, and `2` for at least one disagreement.
|
|
69
|
-
|
|
70
|
-
Nothing wires this into `bun run check` or into a hook. The false-positive rate is read off the first real run rather than assumed ahead of it, and gating a measure with an unmeasured rate is what teaches a contributor to route around the stage. `canon gov restated` and `canon gov test-order` are the siblings this reasoning already governs.
|
|
71
|
-
|
|
72
|
-
Both refusals are breaks rather than absences. A tree with no git history or no markdown file at all is a broken checkout, matching what `canon markdown audit` already reads `no-git` and `no-markdown` as, since this sweep shares that corpus.
|
|
73
|
-
|
|
74
|
-
An exit code says nothing about a call made from a session, since a shell profile may wrap the binary in a function taking its status from a later command. Read the record's `findings` rather than the exit when a skill consumes this.
|
package/docs/agents/demo.md
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Demo
|
|
3
|
-
description: Compiling a screencast draft into a runnable plan, driving a served application to a recording and a still, reading numbered frames back out of a recording, the pointer the recording paints, and what each refusal reports
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Demo
|
|
7
|
-
|
|
8
|
-
`canon demo` drives a project's running application and writes a recording of what it did, plus a still frame of the same run. It exists so a project card and a short demo stop depending on someone sitting down to record one by hand.
|
|
9
|
-
|
|
10
|
-
Two verbs, and they are separate because the artifact between them is edited.
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
canon demo compile demos/inline-edit/beats.md --slug inline-edit
|
|
14
|
-
canon demo run demos/inline-edit/plan.json
|
|
15
|
-
canon demo run demos/inline-edit/plan.json --cursor ~/cursors/theme --out assets
|
|
16
|
-
canon demo frames demos/inline-edit/take/inline-edit.webm --fps 2
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## One folder per demo
|
|
20
|
-
|
|
21
|
-
Each demo owns a folder, `demos/<slug>/`, and `compile` writes the plan into it.
|
|
22
|
-
|
|
23
|
-
| Path | Committed | Holds |
|
|
24
|
-
| ------------ | --------- | ----------------------------------------------------- |
|
|
25
|
-
| `beats.md` | yes | The draft `draft-screencast` wrote |
|
|
26
|
-
| `plan.json` | yes | The compiled plan, with its hand-tuned timing |
|
|
27
|
-
| `index.html` | yes | The HyperFrames composition, when the demo is wrapped |
|
|
28
|
-
| `demo.gif` | yes | The one deliverable a README embeds |
|
|
29
|
-
| `take/` | no | The raw recording, its still, and its timeline |
|
|
30
|
-
| `renders/` | no | The composed mp4, written by the render |
|
|
31
|
-
|
|
32
|
-
A project carries `demos/*/take/` and `demos/*/renders/` in its `.gitignore`, since both are one command away and a webm is large. A plan compiled before this layout, at `demos/<slug>.json`, still runs by path, because only the default moved.
|
|
33
|
-
|
|
34
|
-
## The draft and the plan are different files
|
|
35
|
-
|
|
36
|
-
`draft-screencast` drafts beats for a person. A beat carries what is on screen, one verb, what to watch for, an emphasis, and a caption, and none of that names a selector, a URL, a wait condition, or a timing. Those four are what an executor needs and what would ruin the draft, since the format is pre-seeded so the operator edits down rather than fills blanks.
|
|
37
|
-
|
|
38
|
-
So `canon demo compile` writes a second artifact rather than adding fields to a beat. It maps each beat's verb to a step, seeds the timing, marks which beat the still comes from, and leaves the target and the URL empty for a person to fill. The report names every field it could not supply.
|
|
39
|
-
|
|
40
|
-
The plan is committed, not scratch. Its timing is a starting point tuned by watching a recording, and the draft cannot reproduce a tuned value, so a recompile over an existing plan refuses and names `--force`.
|
|
41
|
-
|
|
42
|
-
A plan can carry an optional `colorScheme` of `light` or `dark`, which the recording context starts in so a page following the system preference paints that scheme with no click beat of its own. An absent field keeps the engine's default, which is light, and `compile` never seeds it. Any other value makes the plan unreadable. A page keyed on a stored theme rather than the preference ignores the field.
|
|
43
|
-
|
|
44
|
-
A recording that has to match both themes takes one plan per scheme, committed side by side, rather than one plan run twice. The pair shares its beats and differs in `colorScheme`, `slug`, and the `output` paths. Neither plan clicks a theme toggle, since a stored theme overrides the preference. Nothing checks that the two plans keep the same beats, so an edit to one is made to both.
|
|
45
|
-
|
|
46
|
-
`record-screencast` is the routed way to run both verbs from a draft path: it compiles only when no plan exists yet, then runs, stopping to report any field still unresolved rather than guessing one.
|
|
47
|
-
|
|
48
|
-
| Option | Behavior |
|
|
49
|
-
| --------------- | ----------------------------------------------------------------- |
|
|
50
|
-
| `--out <dir>` | Directory the plan and its output paths point at, default `demos` |
|
|
51
|
-
| `--slug <slug>` | Demo folder name, defaulting to the draft filename |
|
|
52
|
-
| `--force` | Overwrite an existing plan, losing any field set by hand |
|
|
53
|
-
| `--json` | Add a record on stdout carrying the beats and what is unfilled |
|
|
54
|
-
|
|
55
|
-
## What a run does
|
|
56
|
-
|
|
57
|
-
`canon demo run` reads the plan, refuses if a field is still empty, and drives the application the plan's URL names. It records the whole run to `webm` and writes the still from the beat the draft calls the hero, falling back to the last beat, since a demo's final state is the payoff and a cold open is usually an empty screen.
|
|
58
|
-
|
|
59
|
-
A step's caption from the draft renders as an overlay while its hold plays, so the narration a person wrote is what shows on screen rather than the name of the action the engine performed.
|
|
60
|
-
|
|
61
|
-
Beside the webm, the run writes `<video-basename>.timeline.json`, so a composition can aim a zoom at the moment and the place of an action rather than adding up holds by hand. It holds an `entries` array with one entry per step, each carrying the step's `index`, its `kind`, and `startMs` and `endMs` counted from the recording's first frame. A step ends once its hold has played. A click, fill, or hover entry also carries `box`, the target's `x`, `y`, `width`, and `height` in viewport pixels, which are the video frame's own coordinates. A navigate, scroll, wait, or hold entry carries no `box`, and the file is still written. A run under `--no-video` writes no timeline, since there is no video for it to sit beside. The `--json` record names the file under `timeline`, and `null` when none was written.
|
|
62
|
-
|
|
63
|
-
When `ffmpeg` is on PATH, the run also writes an mp4 beside the webm, since webm plays in a `<video>` tag but nothing else accepts it. A target without `ffmpeg` still gets the webm and a line naming what to install, and the run does not fail over the missing converter.
|
|
64
|
-
|
|
65
|
-
`--gif` adds a third file from the same converter, and it is opt-in where the mp4 is not. A gif runs several times the size of the webm it derives from, and the destination that needs one is a README on a host that strips `<video>`, which GitHub does. The filter generates a palette from the source and then applies it, rather than quantizing per frame, since a per-frame palette is what makes a recording of flat interface colors band and shimmer. It applies that palette without dithering, because the command records applications rather than photographs and the dither writes noise the encoder then stores. One recording measured 3,193,715 bytes dithered against 2,701,941 without, with the same text region cropped from both and read as identical. A missing converter is reported the same way it is for the mp4, so an absent `ffmpeg` costs the gif and not the run.
|
|
66
|
-
|
|
67
|
-
| Option | Behavior |
|
|
68
|
-
| ---------------- | ------------------------------------------------------------------- |
|
|
69
|
-
| `--out <dir>` | Directory to write into, overriding what the plan names |
|
|
70
|
-
| `--cursor <dir>` | Cursor theme folder to draw the pointer from |
|
|
71
|
-
| `--no-video` | Write only the still |
|
|
72
|
-
| `--no-still` | Write only the recording |
|
|
73
|
-
| `--gif` | Also write a gif, for a host that strips video |
|
|
74
|
-
| `--json` | Add a record on stdout carrying every path written and the duration |
|
|
75
|
-
|
|
76
|
-
A step waits on its `waitFor` selector becoming visible and then holds for its own `holdMs`, which is what puts a finished state on screen long enough to read. `navigate` uses the plan's URL unless the step names its own.
|
|
77
|
-
|
|
78
|
-
## What frames does
|
|
79
|
-
|
|
80
|
-
`canon demo frames` pulls numbered PNG stills back out of a recorded video through the same `ffmpeg` binary the mp4 and gif conversion already shells to. Nothing reads a recording back today, so a broken one ships until a person opens it, and this verb is what a skill calls to read one instead. It writes one frame a second by default, sampling at a rate matched to how long a tuned recording runs rather than at a rate tuned for any one clip. Frames land beside the video by default, named `<video-basename>-frame-<NNN>.png`, so they fall under the same `take/` ignore entry the still already uses.
|
|
81
|
-
|
|
82
|
-
| Option | Behavior |
|
|
83
|
-
| ----------------- | -------------------------------------------------------- |
|
|
84
|
-
| `-o, --out <dir>` | Directory to write frames into, default beside the video |
|
|
85
|
-
| `--fps <n>` | Frames extracted per second of video, default `1` |
|
|
86
|
-
| `--json` | Add a record on stdout carrying every frame path written |
|
|
87
|
-
|
|
88
|
-
`read-frames` is the routed way to call this verb and read the frames back: it runs the verb, reads each returned frame with the Read tool, and reports one plain description per frame. It never renders a verdict, since a frame read is evidence a person weighs rather than a pass or fail this toolkit states on their behalf.
|
|
89
|
-
|
|
90
|
-
## The pointer is painted inside the page
|
|
91
|
-
|
|
92
|
-
The browser engine offers an annotation of its own that draws a dot on the interacted element and a title naming the API call it made, and this recorder does not turn it on. It paints no cursor, so a run relying on it looks like the pointer teleports between targets, and the two overlays below supersede it: a real cursor where the dot is a marker, and the beat's narration where the title reads `Mouse move`. Running both put four overlays on the frame, and the two the engine drew were the two a viewer reads as noise.
|
|
93
|
-
|
|
94
|
-
The recorder injects a pointer element before navigation and moves it through the engine's pointer with interpolated steps rather than through the element-clicking helper, which resolves a target and jumps to it. The step count is the whole difference between a cursor that travels and one that appears, and how many steps a move takes is derived from the machine's own round-trip cost rather than fixed, so the same plan glides at roughly the same pace on a loaded machine as an idle one. It also reads the element under it on every move and switches between an arrow, a hand, and a text beam, so it reflects the page the way a real cursor does.
|
|
95
|
-
|
|
96
|
-
`--cursor` points at a folder of Windows cursor resources and the browser decodes them directly, with no conversion step and no image tooling. Each resource carries a hotspot per size, and the largest entry's hotspot scaled to the drawn size is what puts the artwork's tip where the click lands. A theme contributes per state, so a folder holding an arrow and no hand still supplies its arrow and the bundled artwork covers the rest.
|
|
97
|
-
|
|
98
|
-
Three of the nineteen states a theme carries are read. A drag, a resize, or a wait shows the arrow where a real session would show something else, and the two animated states have no still frame to draw.
|
|
99
|
-
|
|
100
|
-
## What the refusals report
|
|
101
|
-
|
|
102
|
-
Every refusal exits 1 and names its reason in the `--json` record, so a skill branches on `reason` rather than on the exit code.
|
|
103
|
-
|
|
104
|
-
| Reason | What happened |
|
|
105
|
-
| --------------------- | ----------------------------------------------------------------------------------- |
|
|
106
|
-
| `draft-missing` | No file at the path given to `compile` |
|
|
107
|
-
| `draft-unreadable` | The draft carries no beat sheet, or a sheet with no beats |
|
|
108
|
-
| `plan-exists` | A plan is already there and `--force` was not passed |
|
|
109
|
-
| `plan-unresolved` | A URL or a target is still empty, named field by field |
|
|
110
|
-
| `no-output-requested` | `--no-video` and `--no-still` together, which would drive the app and write nothing |
|
|
111
|
-
| `plan-unreadable` | The plan is not JSON, or a step names a kind nothing drives |
|
|
112
|
-
| `browser-missing` | The browser binary is not installed, with `install` carrying the command |
|
|
113
|
-
| `engine-missing` | The browser package itself did not resolve |
|
|
114
|
-
| `video-missing` | No file at the path given to `frames` |
|
|
115
|
-
| `converter-missing` | `ffmpeg` is not on PATH, so `frames` extracted nothing |
|
|
116
|
-
| `extraction-failed` | `ffmpeg` exited non-zero, with `message` carrying its stderr |
|
|
117
|
-
|
|
118
|
-
## The browser reaches every target
|
|
119
|
-
|
|
120
|
-
This command was the first browser command to ship, and `canon capture` has since joined it. Capture was held back because its only caller was this repository regenerating its own committed images, which was a fact about that caller rather than about the render.
|
|
121
|
-
|
|
122
|
-
The cost is stated rather than hidden: the browser binary installs separately, so a target runs `bunx playwright install chromium` once before a recording works at all. A run that cannot launch reports that command inside the frame and exits 1.
|
|
123
|
-
|
|
124
|
-
## Composing the take into a finished video
|
|
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 `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
|
-
|
|
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
|
-
|
|
130
|
-
```bash
|
|
131
|
-
bunx -y hyperframes init
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
`hyperframes init` installs its skills machine-wide without asking, so run it knowing that. A machine without it stops the skill with this command and nothing else.
|
|
135
|
-
|
|
136
|
-
## What it does not do
|
|
137
|
-
|
|
138
|
-
Nothing in `canon demo` itself trims a take or scores it beyond the caption each beat already carries. Composing is the skill's step and HyperFrames' work.
|
|
139
|
-
|
|
140
|
-
It also does not replace a narrated screencast. That has a hero moment, a cut list, and a voice, none of which survives being generated. This answers the case where the alternative is recording nothing.
|
package/docs/agents/docs.md
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Docs
|
|
3
|
-
description: How canon docs resolves the toolkit's own reference surface from an install root, and how a split domain is named
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Docs
|
|
7
|
-
|
|
8
|
-
`canon docs` emits the toolkit's own reference docs so an agent in a target project can orient without the toolkit source checked out. The CLI resolves `docs/` and `canon/context/` from its install root, and which of the two it finds depends on how the CLI was installed. A registry install carries `docs/` alone, since `.claude/` is not published. A clone or a linked worktree carries both.
|
|
9
|
-
|
|
10
|
-
- `canon docs list [--json]` lists the downstream catalog: the consumer-facing `docs/` surface plus per-domain narrative from `canon/context/` when that root is present. Toolkit-internal context entries (`ci`, `development`, `sandbox`) are dropped. From a registry install the context section is absent rather than empty.
|
|
11
|
-
- `canon docs <topic>` prints one doc to stdout, resolved by exact name from `docs/` first, then `canon/context/`. Any doc the install carries is reachable by name, including the toolkit-internal topics the list omits.
|
|
12
|
-
|
|
13
|
-
## How a name resolves
|
|
14
|
-
|
|
15
|
-
A domain too large for one file splits into `<domain>/` with a generated `index.md`, and both verbs name it by the folder. `canon docs <domain>` prints that index, which is the catalog routing to the sub-area files, and the listing describes it from the index's `subtitle` where a sibling file supplies `description`. A folder carrying no `index.md` is absent from both, since a catalog is what makes the sub-areas reachable, and so are the files inside it.
|
|
16
|
-
|
|
17
|
-
A sub-area file resolves by its bare name too, so `canon docs operating-model` reaches `docs/workflow/operating-model.md`. Three spellings are tried in order, being a sibling file, a folder of that name, then a sub-area file one level down, and each spelling is tried across both roots before the next one runs. A sibling file therefore wins over a folder of the same name, and both win over a sub-area file. Reading the folder last is what keeps the sub-area spelling from changing any name that resolved before it existed.
|
|
18
|
-
|
|
19
|
-
The sub-area spelling keeps the root order too. The first root whose folders carry the name answers, so `canon docs indexes` reaches `docs/agents/indexes.md` even though a context folder holds an entry of the same name. A bare name carried by two folders of that one root resolves to neither, which names the available topics and exits 1 rather than answering with whichever folder sorts first.
|
|
20
|
-
|
|
21
|
-
`canon docs list` stops at the folder where `canon docs <topic>` goes on to name each file inside it. The listing is the downstream catalog rather than the index of what a name reaches, so a sub-area file appears there only where it declares a target-facing `category` of its own, and no sub-area file of the context root appears at all. A name that resolves and does not list is the divergence the toolkit-internal topics already carry.
|
|
22
|
-
|
|
23
|
-
## Output
|
|
24
|
-
|
|
25
|
-
Data prints to stdout and the frame to stderr, so `canon docs <topic> > out.md` captures clean markdown. With no topic and no verb, `canon docs` runs `list`. An unknown topic names the available topics on stderr and exits 1.
|
|
26
|
-
|
|
27
|
-
Only a `---` block opening on the first line counts as frontmatter, so a document body carrying horizontal rules emits whole.
|