@erclx/canon 5.51.0 → 5.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -4
  3. package/claude/.claude-plugin/plugin.json +1 -1
  4. package/claude/skills/canon-cli/SKILL.md +0 -3
  5. package/claude/skills/context-fold/REQUIREMENT.md +0 -1
  6. package/claude/skills/design-taste/references/kinds.md +0 -1
  7. package/claude/skills/draw-figure/REQUIREMENT.md +2 -3
  8. package/claude/skills/draw-figure/SKILL.md +4 -5
  9. package/claude/skills/draw-figure/references/figures.md +0 -1
  10. package/claude/skills/draw-figure/references/hand-drawn.md +1 -1
  11. package/claude/skills/git-pr/references/pr.md +1 -1
  12. package/claude/skills/pick-by-eye/REQUIREMENT.md +0 -1
  13. package/claude/skills/pick-by-eye/SKILL.md +1 -1
  14. package/claude/skills/review-address/SKILL.md +1 -1
  15. package/claude/skills/review-address/references/post-review-findings.md +1 -1
  16. package/claude/skills/review-pr/references/post.md +2 -2
  17. package/claude/skills/target-check/SKILL.md +2 -0
  18. package/claude/skills/target-setup/SKILL.md +1 -1
  19. package/claude/skills/target-update/REQUIREMENT.md +33 -0
  20. package/claude/skills/target-update/SKILL.md +136 -0
  21. package/claude/skills/teach-craft/REQUIREMENT.md +30 -0
  22. package/claude/skills/teach-craft/SKILL.md +39 -0
  23. package/claude/skills/teach-craft/references/lesson-craft.md +52 -0
  24. package/claude/skills/{teach-workspace → teach-craft}/references/pedagogy.md +12 -4
  25. package/docs/agents/audits.md +0 -1
  26. package/docs/agents/migrate.md +2 -1
  27. package/docs/target/migrations.md +12 -1
  28. package/docs/target/projects.md +1 -1
  29. package/docs/target/sync.md +1 -1
  30. package/docs/workflow/parallel-features.md +1 -1
  31. package/docs/workflow/skill-map-on-request.md +10 -22
  32. package/docs/workflow/skill-map.md +13 -14
  33. package/package.json +1 -4
  34. package/scripts/core/regen-web-previews.ts +2 -67
  35. package/src/audits/catalog.ts +0 -1
  36. package/src/browser/engine.ts +3 -6
  37. package/src/capture/render.ts +1 -1
  38. package/src/claude/cases/authoring.ts +0 -12
  39. package/src/claude/cases/misc.ts +0 -17
  40. package/src/claude/cases/setup.ts +7 -0
  41. package/src/claude/cases/workflow.ts +2 -38
  42. package/src/claude/skills-audit.ts +0 -1
  43. package/src/cli/help.ts +0 -7
  44. package/src/cli.ts +0 -6
  45. package/src/commands/labels.ts +9 -7
  46. package/src/commands/records.ts +0 -1
  47. package/src/commands/serve.ts +2 -2
  48. package/src/design/components.ts +8 -1514
  49. package/src/design/css.ts +5 -6
  50. package/src/design/fonts.ts +3 -5
  51. package/src/driver/drive.ts +3 -4
  52. package/src/driver/steps.ts +2 -5
  53. package/src/inventory/walk.ts +1 -1
  54. package/src/markdown/scope.ts +4 -31
  55. package/src/migrate/status.ts +5 -1
  56. package/src/records/validate.ts +4 -176
  57. package/src/sandbox/equivalence.ts +0 -5
  58. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +1 -1
  59. package/claude/skills/draft-and-pick/REQUIREMENT.md +0 -26
  60. package/claude/skills/draft-and-pick/SKILL.md +0 -11
  61. package/claude/skills/draft-doc/REQUIREMENT.md +0 -26
  62. package/claude/skills/draft-doc/SKILL.md +0 -11
  63. package/claude/skills/draft-figure/REQUIREMENT.md +0 -26
  64. package/claude/skills/draft-figure/SKILL.md +0 -11
  65. package/claude/skills/draft-identity/REQUIREMENT.md +0 -26
  66. package/claude/skills/draft-identity/SKILL.md +0 -11
  67. package/claude/skills/draft-ready/REQUIREMENT.md +0 -26
  68. package/claude/skills/draft-ready/SKILL.md +0 -11
  69. package/claude/skills/draft-screencast/REQUIREMENT.md +0 -26
  70. package/claude/skills/draft-screencast/SKILL.md +0 -11
  71. package/claude/skills/draft-slides/REQUIREMENT.md +0 -26
  72. package/claude/skills/draft-slides/SKILL.md +0 -11
  73. package/claude/skills/make-deck/REQUIREMENT.md +0 -36
  74. package/claude/skills/make-deck/SKILL.md +0 -80
  75. package/claude/skills/make-deck/references/deck.md +0 -183
  76. package/claude/skills/read-frames/REQUIREMENT.md +0 -30
  77. package/claude/skills/read-frames/SKILL.md +0 -55
  78. package/claude/skills/record-screencast/REQUIREMENT.md +0 -35
  79. package/claude/skills/record-screencast/SKILL.md +0 -99
  80. package/claude/skills/script-screencast/REQUIREMENT.md +0 -34
  81. package/claude/skills/script-screencast/SKILL.md +0 -70
  82. package/claude/skills/script-screencast/references/beats-template.md +0 -119
  83. package/claude/skills/teach-workspace/REQUIREMENT.md +0 -34
  84. package/claude/skills/teach-workspace/SKILL.md +0 -196
  85. package/claude/skills/teach-workspace/references/glossary.md +0 -90
  86. package/claude/skills/teach-workspace/references/lesson-build.md +0 -106
  87. package/claude/skills/teach-workspace/references/lesson-craft.md +0 -135
  88. package/claude/skills/teach-workspace/references/promotion-fold.md +0 -35
  89. package/claude/skills/teach-workspace/references/promotion.md +0 -116
  90. package/claude/skills/teach-workspace/references/revisit.md +0 -28
  91. package/claude/skills/teach-workspace/references/teach.md +0 -211
  92. package/claude/skills/video-craft/REQUIREMENT.md +0 -35
  93. package/claude/skills/video-craft/SKILL.md +0 -96
  94. package/claude/skills/video-craft/references/adopted.md +0 -110
  95. package/src/commands/demo.ts +0 -542
  96. package/src/commands/slides.ts +0 -184
  97. package/src/commands/teach.ts +0 -1401
  98. package/src/demo/beats.ts +0 -135
  99. package/src/demo/compile.ts +0 -350
  100. package/src/demo/container.ts +0 -219
  101. package/src/demo/cursors.ts +0 -55
  102. package/src/demo/drive.ts +0 -442
  103. package/src/demo/pointer.ts +0 -178
  104. package/src/demo/theme.ts +0 -112
  105. package/src/demo/timeline.ts +0 -64
  106. package/src/slides/convert/chart.ts +0 -165
  107. package/src/slides/convert/deck.ts +0 -244
  108. package/src/slides/convert/export.ts +0 -567
  109. package/src/slides/convert/master.ts +0 -198
  110. package/src/slides/convert/shapes.ts +0 -804
  111. package/src/slides/convert/svg.ts +0 -38
  112. package/src/slides/convert/walk.ts +0 -671
  113. package/src/slides/decks.ts +0 -110
  114. package/src/slides/open.ts +0 -18
  115. package/src/slides/package/fonts.ts +0 -301
  116. package/src/slides/package/motion.ts +0 -316
  117. package/src/slides/package/test-face.ts +0 -113
  118. package/src/teach/browser/compile.ts +0 -44
  119. package/src/teach/browser/dismiss.ts +0 -76
  120. package/src/teach/browser/focus-line.ts +0 -19
  121. package/src/teach/browser/glossary-filter.ts +0 -44
  122. package/src/teach/browser/head.ts +0 -30
  123. package/src/teach/browser/quiz.ts +0 -19
  124. package/src/teach/browser/reload.ts +0 -9
  125. package/src/teach/browser/sidebar.ts +0 -233
  126. package/src/teach/browser/theme.ts +0 -18
  127. package/src/teach/components/code.tsx +0 -24
  128. package/src/teach/components/heading.tsx +0 -11
  129. package/src/teach/components/list.tsx +0 -17
  130. package/src/teach/components/paragraph.tsx +0 -29
  131. package/src/teach/components/refs.tsx +0 -28
  132. package/src/teach/cross-references.ts +0 -78
  133. package/src/teach/fonts.ts +0 -16
  134. package/src/teach/highlight.ts +0 -71
  135. package/src/teach/html/jsx-dev-runtime.ts +0 -13
  136. package/src/teach/html/jsx-runtime.ts +0 -113
  137. package/src/teach/html/raw.ts +0 -28
  138. package/src/teach/lesson.ts +0 -178
  139. package/src/teach/nav.ts +0 -1337
  140. package/src/teach/render.ts +0 -240
  141. package/src/teach/workspace.ts +0 -1164
  142. package/src/teach/write-if-changed.ts +0 -17
@@ -8,6 +8,8 @@ category: Agent surface
8
8
 
9
9
  Each section is a move a project runs once, when it was scaffolded before the change it names. Run `canon upgrade` first, then `canon migrate status --json` to list the moves a project still needs in the order to run them. The recurring sync that follows is in [target sync](sync.md).
10
10
 
11
+ `canon:target-update` is the guided path through both. It runs the moves in that order once you approve its preview.
12
+
11
13
  ## Move the records first, once
12
14
 
13
15
  Gitignored session records, being the task board, plans, review reports, and scratch, moved from `.claude/` to `.canon/`. Run these from inside the project, and read the `ok` field of the `--json` record rather than the exit code.
@@ -128,7 +130,7 @@ From the registry the walk reports `historyUnavailable`, so check both paths by
128
130
  | `git-commit` | `commit`, `versioning` |
129
131
  | `git-pr` | `pr`, `publish` |
130
132
  | `markdown-craft` | `markdown` |
131
- | `teach-workspace` | `glossary`, `teach` |
133
+ | `teach-workspace` | `glossary`, `teach` <!-- canon-keep-retired --> |
132
134
  | `plan-groundwork` | `groundwork`, `groundwork-spikes` |
133
135
  | `plan-intake` | `intake` |
134
136
  | `plan-feature` | `plan`, `plan-lifecycle` |
@@ -146,6 +148,15 @@ The wireframes record is retired, and nothing deletes what a project holds.
146
148
  - Delete the `@canon/wireframes/index.md` line in your `CLAUDE.md` with the folder. `canon claude sync` does not rewrite it.
147
149
  - `canon gov sync` removes `.claude/rules/canon/standards/wireframes.md`
148
150
 
151
+ ## Keep or delete the retired product files, your call
152
+
153
+ The learning workspace, the deck renderer, and the app recorder are retired with their verbs and skills, and nothing deletes what a project holds.
154
+
155
+ - `.canon/teach/` holds rendered HTML that opens as it is, so it needs nothing <!-- canon-keep-retired -->
156
+ - `.canon/slides/` and a `demos/` folder hold sources nothing renders any more, so delete them once nothing cites them <!-- canon-keep-retired -->
157
+ - Replace a `canon:teach-workspace` reference with `canon:teach-craft` by hand, since `canon migrate skill-names` does not rewrite it <!-- canon-keep-retired -->
158
+ - Delete a `canon:make-deck`, `canon:script-screencast`, `canon:record-screencast`, `canon:read-frames`, or `canon:video-craft` reference, since none has a successor <!-- canon-keep-retired -->
159
+
149
160
  ## Move decisions out of a held architecture record, once
150
161
 
151
162
  The toolkit no longer seeds `canon/ARCHITECTURE.md`, and a held file and its `CLAUDE.md` import stay. Move a trap a session would hit into that domain's `## Gotchas`, then delete the file and its `@canon/ARCHITECTURE.md` line.
@@ -47,7 +47,7 @@ The chain runs these phases:
47
47
  - The `verify` phase runs the installed `package.json` scripts and reports pass or fail
48
48
  - The `indexes` phase bootstraps `index.md` over the project's documentation folders, confirming candidates with you
49
49
 
50
- An existing project goes to `canon:target-check` first. For the Claude layer alone, run `canon claude init` and then `canon:target-setup indexes`. Run `canon:target-setup verify deep` by hand for the heavier smoke and screenshot pass.
50
+ An existing project goes to `canon:target-check` first, then to `canon:target-update` to apply the catch-up. For the Claude layer alone, run `canon claude init` and then `canon:target-setup indexes`. Run `canon:target-setup verify deep` by hand for the heavier smoke and screenshot pass.
51
51
 
52
52
  Keep the `## Scripts` table in `canon/context/development/local-loop.md` current as scripts are added. A split entry keeps it in any entry directly under `development/`, grouping a long set into short tables under lead sentences. <!-- audit-ignore-citations: canon/context/development/local-loop.md -->
53
53
 
@@ -10,7 +10,7 @@ A target pulls toolkit changes per domain, through one catch-all and several tar
10
10
 
11
11
  ## Check first
12
12
 
13
- `canon sync --check <path>` reports drift without writing, split by cause. `canon:target-check` groups the same state by domain and repairs nothing.
13
+ `canon sync --check <path>` reports drift without writing, split by cause. `canon:target-check` groups the same state by domain and repairs nothing. `canon:target-update` is the guided path, previewing the drift and then applying it on your go-ahead.
14
14
 
15
15
  The report opens with the binary version against the newest published one, and a version behind means run `canon upgrade` first.
16
16
 
@@ -32,7 +32,7 @@ Assert the orchestrator role in one warm session with `canon:role-orchestrator`.
32
32
 
33
33
  - To pick otherwise, rewrite that line as `overridden at execution to <pick>,` plus the measurement, and add one line to the open task's `## Findings`
34
34
 
35
- - `canon records validate plans [plan]` reports a plan breaking its standard, plus `structure` misses that never set the exit, and takes `groundwork`, `intake`, and `teach`
35
+ - `canon records validate plans [plan]` reports a plan breaking its standard, plus `structure` misses that never set the exit, and takes `groundwork` and `intake`
36
36
  - `canon records push` and `canon records pull` carry `.canon/` to and from a private repository. See [records](../agents/records.md).
37
37
  - `canon records size`, `canon records prune-tmp`, and `canon records stale canonical` report folder size, idle scratch, and releases since the requirements review
38
38
  - `canon tasks archive` moves a shipped plan to `.canon/plans/archive/` and retargets the task's `Plan:` line
@@ -10,24 +10,15 @@ These skills serve a request rather than a moment. With the [skill map](skill-ma
10
10
 
11
11
  ## Generate an artifact on demand
12
12
 
13
- | Skill | When to use |
14
- | ------------------------- | ---------------------------------------------------------------------------------- |
15
- | `canon:create-rule` | A project rule the toolkit does not ship |
16
- | `canon:create-skill` | A new `SKILL.md` |
17
- | `canon:write-doc` | A new `docs/` page, context entry, or `README.md` |
18
- | `canon:draft-doc` | Never on purpose. A pointer naming `write-doc` <!-- canon-keep-retired --> |
19
- | `canon:plan-ready` | Finished files a worker should copy |
20
- | `canon:draft-ready` | Never on purpose. A pointer naming `plan-ready` <!-- canon-keep-retired --> |
21
- | `canon:draw-figure` | A figure or architecture view inside a doc |
22
- | `canon:draft-figure` | Never on purpose. A pointer naming `draw-figure` <!-- canon-keep-retired --> |
23
- | `canon:ci-workflow` | A GitHub Actions workflow file |
24
- | `canon:make-deck` | A deck rendered to editable PowerPoint |
25
- | `canon:draft-slides` | Never on purpose. A pointer naming `make-deck` <!-- canon-keep-retired --> |
26
- | `canon:script-screencast` | A recording script with beats seeded |
27
- | `canon:draft-screencast` | Never on purpose. A pointer naming `script-screencast` <!-- canon-keep-retired --> |
28
- | `canon:record-screencast` | Recording a screencast draft into a finished mp4 |
29
- | `canon:design-identity` | A logo mark and social card |
30
- | `canon:draft-identity` | Never on purpose. A pointer naming `design-identity` <!-- canon-keep-retired --> |
13
+ | Skill | When to use |
14
+ | ----------------------- | ------------------------------------------------- |
15
+ | `canon:create-rule` | A project rule the toolkit does not ship |
16
+ | `canon:create-skill` | A new `SKILL.md` |
17
+ | `canon:write-doc` | A new `docs/` page, context entry, or `README.md` |
18
+ | `canon:plan-ready` | Finished files a worker should copy |
19
+ | `canon:draw-figure` | A figure or architecture view inside a doc |
20
+ | `canon:ci-workflow` | A GitHub Actions workflow file |
21
+ | `canon:design-identity` | A logo mark and social card |
31
22
 
32
23
  ## Answer a question at any point
33
24
 
@@ -35,9 +26,6 @@ These skills serve a request rather than a moment. With the [skill map](skill-ma
35
26
  | --------------------------- | ----------------------------------------------------- |
36
27
  | `canon:canon-cli` | To pick a `canon` verb, or learn which can lose edits |
37
28
  | `canon:youtube-transcripts` | A video transcript wanted as context |
38
- | `canon:read-frames` | To read a recorded demo back frame by frame |
39
- | `canon:teach-workspace` | To learn a subject across sessions |
29
+ | `canon:teach-craft` | To teach a subject so it sticks |
40
30
  | `canon:markdown-craft` | Before a substantial markdown edit |
41
31
  | `canon:write-human` | Before drafting or revising prose |
42
-
43
- Ask `canon:teach-workspace` to promote a learning workspace's reference pages and glossaries. It proposes a destination per page and waits. An Anthropic-owned subject goes to the wiki, an internal one to the matching context entry, and the rest to the public docs. A project with no wiki folder gets a refusal naming the folder to create.
@@ -17,19 +17,18 @@ Groups run in the order a project meets them. Every name `canon claude skills li
17
17
 
18
18
  ## Decide what to build
19
19
 
20
- | Skill | When to use |
21
- | -------------------------- | ---------------------------------------------------------------------------- |
22
- | `canon:plan-intake` | The input is a pile of findings |
23
- | `canon:plan-intake-answer` | An intake folder holds unread slots |
24
- | `canon:backlog-triage` | The backlog needs pruning |
25
- | `canon:plan-groundwork` | The state is unmeasured and approaches compete |
26
- | `canon:decision-escalate` | Open decisions turn on your preference |
27
- | `canon:pick-by-eye` | The call is taste, wanting candidates side by side |
28
- | `canon:draft-and-pick` | Never on purpose. A pointer naming `pick-by-eye` <!-- canon-keep-retired --> |
29
- | `canon:canvas-board` | A direction should be drawn as editable frames |
30
- | `canon:task-board` | A decided item needs a file on the board |
31
- | `canon:plan-feature` | The approach is settled and needs a plan |
32
- | `canon:codebase-layout` | A change adds a file and needs a folder |
20
+ | Skill | When to use |
21
+ | -------------------------- | -------------------------------------------------- |
22
+ | `canon:plan-intake` | The input is a pile of findings |
23
+ | `canon:plan-intake-answer` | An intake folder holds unread slots |
24
+ | `canon:backlog-triage` | The backlog needs pruning |
25
+ | `canon:plan-groundwork` | The state is unmeasured and approaches compete |
26
+ | `canon:decision-escalate` | Open decisions turn on your preference |
27
+ | `canon:pick-by-eye` | The call is taste, wanting candidates side by side |
28
+ | `canon:canvas-board` | A direction should be drawn as editable frames |
29
+ | `canon:task-board` | A decided item needs a file on the board |
30
+ | `canon:plan-feature` | The approach is settled and needs a plan |
31
+ | `canon:codebase-layout` | A change adds a file and needs a folder |
33
32
 
34
33
  ## Build the feature
35
34
 
@@ -47,7 +46,6 @@ Groups run in the order a project meets them. Every name `canon claude skills li
47
46
  | `canon:search-craft` | Before searching outside the project |
48
47
  | `canon:systematic-debugging` | A test fails or a bug surfaces |
49
48
  | `canon:design-taste` | Drafting or judging an interface |
50
- | `canon:video-craft` | Before composing or judging a video |
51
49
  | `canon:ui-checklist` | After a UI change, to list what to check |
52
50
 
53
51
  ## Check the work before it leaves the branch
@@ -103,6 +101,7 @@ Groups run in the order a project meets them. Every name `canon claude skills li
103
101
  | Skill | When to use |
104
102
  | ----------------------------- | ------------------------------------------------------- |
105
103
  | `canon:target-check` | In a target, to compare each domain with the toolkit |
104
+ | `canon:target-update` | After a release, to catch a target up to the toolkit |
106
105
  | `canon:document-repair` | Rewrite a failing docs folder to the limits and gate it |
107
106
  | `canon:canon-feedback` | The toolkit is broken, missing, or off |
108
107
  | `canon:canon-feedback-triage` | In the toolkit repo, to file feedback issues |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/canon",
3
3
  "type": "module",
4
- "version": "5.51.0",
4
+ "version": "5.53.0",
5
5
  "description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -54,10 +54,7 @@
54
54
  "@preact/signals": "^2.11.3",
55
55
  "commander": "^13.1.0",
56
56
  "execa": "^9.5.2",
57
- "highlight.js": "^11.12.0",
58
- "jszip": "^3.10.1",
59
57
  "playwright-core": "1.64.1",
60
- "pptxgenjs": "^4.0.1",
61
58
  "preact": "^11.0.0"
62
59
  },
63
60
  "devDependencies": {
@@ -2,19 +2,14 @@
2
2
  * Writes `web/public/previews/design-tokens/index.html` and `design.css` by
3
3
  * calling `renderDesignDoc` directly, the in-process pattern
4
4
  * `regen-web-favicon.ts` already takes rather than spawning a subprocess.
5
- * Writes `web/public/previews/teach-workspace/` the same way, calling
6
- * `generateNav` over an isolated copy of one workspace.
7
5
  *
8
- * Both are embedded live in a landing section as an `<iframe>` rather than a
6
+ * It is embedded live in a landing section as an `<iframe>` rather than a
9
7
  * screenshot, since `web/e2e/home.spec.ts` asserts no `<img>` renders inside
10
8
  * `<main>`.
11
9
  */
12
- import { cpSync, existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'
13
- import { tmpdir } from 'node:os'
14
- import { join } from 'node:path'
10
+ import { readFileSync } from 'node:fs'
15
11
  import { DESIGN_DOCUMENT } from '@/design/regen'
16
12
  import { renderDesignDoc } from '@/design/render'
17
- import { generateNav } from '@/teach/nav'
18
13
 
19
14
  const root = new URL('../..', import.meta.url).pathname
20
15
 
@@ -33,63 +28,3 @@ if (!/--(color|space|type|radius)-/.test(css)) {
33
28
  }
34
29
 
35
30
  console.log('regen-web-previews: wrote web/public/previews/design-tokens/')
36
-
37
- /**
38
- * The workspace ships alone, on its own isolated nav tree, rather than
39
- * copied straight out of `.canon/teach/`. That folder cross-links every
40
- * sibling workspace by relative path, including the operator's own personal
41
- * study notes, so a copy carrying its live chrome would ship either dead
42
- * links or a path into content never meant to be public. Regenerating the
43
- * chrome over a scratch copy holding this one workspace alone is what keeps
44
- * the jump menus from naming anything else.
45
- *
46
- * `.canon/teach/` is gitignored session scratch, per `claude/skills/teach-workspace/references/teach.md`, so
47
- * it exists on the machine that authored the lesson and nowhere else,
48
- * including CI. `web/public/previews/teach-workspace/` is therefore the
49
- * durable copy: committed once the workspace exists, regenerated here as a
50
- * local convenience when authoring continues, and left untouched by a build
51
- * that cannot see the source, the same way a target without Playwright still
52
- * builds against a committed capture.
53
- */
54
- const TEACH_SLUG = '04-governance-rule-loading'
55
- const teachSource = `${root}.canon/teach/${TEACH_SLUG}`
56
-
57
- if (!existsSync(teachSource)) {
58
- console.log(
59
- `regen-web-previews: no workspace at .canon/teach/${TEACH_SLUG} on this machine, leaving the committed web/public/previews/teach-workspace/ as is`,
60
- )
61
- } else {
62
- const scratchRoot = mkdtempSync(join(tmpdir(), 'canon-teach-preview-'))
63
- try {
64
- cpSync(teachSource, join(scratchRoot, '.canon', 'teach', TEACH_SLUG), {
65
- recursive: true,
66
- })
67
-
68
- const nav = await generateNav(scratchRoot)
69
- if (!nav.ok) {
70
- console.error(`regen-web-previews: ${nav.message}`)
71
- process.exit(1)
72
- }
73
- if (nav.lessons === 0) {
74
- console.error(
75
- 'regen-web-previews: teach-workspace render carries no lesson, refusing an empty preview',
76
- )
77
- process.exit(1)
78
- }
79
-
80
- const dest = `${root}web/public/previews/teach-workspace`
81
- rmSync(dest, { recursive: true, force: true })
82
- cpSync(join(scratchRoot, '.canon', 'teach'), dest, {
83
- recursive: true,
84
- // Only the rendered chrome ships. MISSION.md, RESOURCES.md, and
85
- // GLOSSARY.md carry links relative to `.canon/teach/`, which resolve to
86
- // nothing once copied under `web/public/`, and nothing links to them
87
- // from the rendered pages anyway.
88
- filter: (path) => !path.endsWith('.md'),
89
- })
90
- } finally {
91
- rmSync(scratchRoot, { recursive: true, force: true })
92
- }
93
-
94
- console.log('regen-web-previews: wrote web/public/previews/teach-workspace/')
95
- }
@@ -496,7 +496,6 @@ const RECORD_KINDS: readonly (readonly [string, Corpus])[] = [
496
496
  ['plans', 'per-machine'],
497
497
  ['groundwork', 'per-machine'],
498
498
  ['intake', 'per-machine'],
499
- ['teach', 'per-machine'],
500
499
  ]
501
500
 
502
501
  /**
@@ -7,9 +7,8 @@
7
7
  * The two absences are different states with different remedies. A package that
8
8
  * never resolved means the target installed the CLI without the engine, and a
9
9
  * binary that was never downloaded means the engine is present and its browser
10
- * is not. Both were spelled inside `src/demo/` when `demo` was the only command
11
- * driving a browser, and a second command is what makes them shared rather than
12
- * local.
10
+ * is not. Every command driving a browser reads both, so they sit here rather
11
+ * than beside one caller.
13
12
  */
14
13
 
15
14
  /** Fetches the browser revision the pinned engine expects. */
@@ -72,9 +71,7 @@ export interface KeyboardPage {
72
71
  * browser in pointer modality, where that rule does not match, so a reader
73
72
  * calling it alone reports every correctly styled element as unstyled.
74
73
  *
75
- * It moved here when `@/driver/probes/focus` became the second call site,
76
- * matching how the launch-failure split moved out of `src/demo/` once
77
- * `canon inventory` became the second command driving a browser. One press
74
+ * It moved here when `@/driver/probes/focus` became the second call site. One press
78
75
  * covers the page rather than the element that happens to hold focus, so it
79
76
  * survives the blur every reader takes next.
80
77
  */
@@ -16,7 +16,7 @@ import { formatStamp, hashSource, stampPath } from '@/capture/stamp'
16
16
  * `src/commands/capture.ts` reaches it through a dynamic import so `src/cli.ts`
17
17
  * never resolves the engine at startup.
18
18
  *
19
- * It ships, like `@/demo/drive`, `@/inventory/walk`, and `@/driver/drive`.
19
+ * It ships, like `@/inventory/walk` and `@/driver/drive`.
20
20
  * Regenerating this repository's own committed images was the reason it stayed
21
21
  * behind, and it was a reason about one caller rather than about the mechanism:
22
22
  * a target renders its own generated pages and proves its own fonts resolved,
@@ -24,23 +24,11 @@ export const AUTHORING_CASES: readonly SkillCase[] = [
24
24
  'Write a brand-new docs page for the capture command, nothing under docs/ covers it yet.',
25
25
  expect: 'write-doc',
26
26
  },
27
- {
28
- prompt:
29
- 'I typed draft-doc and it said the doc skill was renamed to write-doc.', // canon-keep-retired
30
- // The pointer answers under its old name on purpose. canon-keep-retired
31
- expect: 'draft-doc',
32
- },
33
27
  {
34
28
  prompt:
35
29
  'I already wrote the finished skill files, package them as a ready folder with a plan and a task for a worker to copy.',
36
30
  expect: 'plan-ready',
37
31
  },
38
- {
39
- prompt:
40
- 'I typed draft-ready and it said the ready skill was renamed to plan-ready.', // canon-keep-retired
41
- // The pointer answers under its old name on purpose. canon-keep-retired
42
- expect: 'draft-ready',
43
- },
44
32
  {
45
33
  prompt: 'This project has no README.md at all, write one from scratch.',
46
34
  expect: 'write-doc',
@@ -12,12 +12,6 @@ export const MISC_CASES: readonly SkillCase[] = [
12
12
  'Show me a few different treatments for this callout so I can pick one by looking.',
13
13
  expect: 'pick-by-eye',
14
14
  },
15
- {
16
- prompt:
17
- 'I typed draft-and-pick and it said the pick skill was renamed to pick-by-eye.', // canon-keep-retired
18
- // The pointer answers under its old name on purpose. canon-keep-retired
19
- expect: 'draft-and-pick',
20
- },
21
15
  {
22
16
  prompt:
23
17
  'Which layer of this landing page should I settle first, and what has to stay constant across it?',
@@ -28,12 +22,6 @@ export const MISC_CASES: readonly SkillCase[] = [
28
22
  'This project has no logo yet. Draft one and give me a social card to go with it.',
29
23
  expect: 'design-identity',
30
24
  },
31
- {
32
- prompt:
33
- 'I typed draft-identity and it said the identity skill was renamed to design-identity.', // canon-keep-retired
34
- // The pointer answers under its old name on purpose. canon-keep-retired
35
- expect: 'draft-identity',
36
- },
37
25
  {
38
26
  prompt:
39
27
  'Draw the signup screen as a frame on the canvas, then restyle the element I just selected there.',
@@ -97,11 +85,6 @@ export const MISC_CASES: readonly SkillCase[] = [
97
85
  'Find me the strongest evidence on whether rent control reduces housing supply. Where should I look?',
98
86
  expect: 'search-craft',
99
87
  },
100
- {
101
- prompt:
102
- 'The composed demo video looks generic and the zoom drags. What should the captions say, and how fast should the push-in be?',
103
- expect: 'video-craft',
104
- },
105
88
  {
106
89
  prompt:
107
90
  "I've got the plan approved and it touches the parser, the command, and the docs. How should I build it so I don't end up with one giant diff?",
@@ -66,6 +66,13 @@ export const SETUP_CASES: readonly SkillCase[] = [
66
66
  'Report what this project has fallen behind the toolkit on, domain by domain, and fix nothing.',
67
67
  expect: 'target-check',
68
68
  },
69
+ // The applying half of the same moment. It previews what the check would
70
+ // report and then writes, which is the line between the two.
71
+ {
72
+ prompt:
73
+ 'A new toolkit release is out, bring this project up to it and run whatever migrations it needs.',
74
+ expect: 'target-update',
75
+ },
69
76
  {
70
77
  prompt:
71
78
  "This project needs its own coding rule that the toolkit doesn't ship.",
@@ -24,12 +24,6 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
24
24
  prompt: 'Draw me a diagram of how the pieces of this system connect.',
25
25
  expect: 'draw-figure',
26
26
  },
27
- {
28
- prompt:
29
- 'I typed draft-figure and it said the figure skill was renamed to draw-figure.', // canon-keep-retired
30
- // The pointer answers under its old name on purpose. canon-keep-retired
31
- expect: 'draft-figure',
32
- },
33
27
  {
34
28
  prompt:
35
29
  'This onboarding doc needs a hand-drawn picture of the signup-to-active path, sketch it in and make sure it actually renders correctly.',
@@ -45,11 +39,6 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
45
39
  'Sketch out a plan for adding this new capability before we touch any code.',
46
40
  expect: 'plan-feature',
47
41
  },
48
- {
49
- prompt:
50
- 'The video just finished recording. Read it back and tell me what each part shows.',
51
- expect: 'read-frames',
52
- },
53
42
  {
54
43
  prompt:
55
44
  'We need to measure this properly before committing to an approach.',
@@ -92,11 +81,6 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
92
81
  'I pushed another commit to the open PR. Update the screenshot comparison on it so the reviewer sees the current head.',
93
82
  expect: 'pr-evidence',
94
83
  },
95
- {
96
- prompt:
97
- 'The screencast draft is finished. Turn it into an actual video now.',
98
- expect: 'record-screencast',
99
- },
100
84
  {
101
85
  prompt:
102
86
  'What should a review of a change look for beyond bugs, and how much evidence does a finding need?',
@@ -112,26 +96,6 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
112
96
  'Our backlog only ever grows, measure each row and suggest which to decline.',
113
97
  expect: 'backlog-triage',
114
98
  },
115
- {
116
- prompt: 'Draft me a script with beats for a screencast recording.',
117
- expect: 'script-screencast',
118
- },
119
- {
120
- prompt:
121
- 'I typed draft-screencast and it said the screencast skill was renamed to script-screencast.', // canon-keep-retired
122
- // The pointer answers under its old name on purpose. canon-keep-retired
123
- expect: 'draft-screencast',
124
- },
125
- {
126
- prompt: 'Turn this topic into a slide deck I can render.',
127
- expect: 'make-deck',
128
- },
129
- {
130
- prompt:
131
- 'I typed draft-slides and it said the slides skill was renamed to make-deck.', // canon-keep-retired
132
- // The pointer answers under its old name on purpose. canon-keep-retired
133
- expect: 'draft-slides',
134
- },
135
99
  // Rot across documents nobody changed is what this reads, rather than a
136
100
  // stated rule broken on a given line. It is also not `target-check`, which
137
101
  // asks whether a document exists and holds its sections rather than whether
@@ -168,8 +132,8 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
168
132
  expect: 'task-complete',
169
133
  },
170
134
  {
171
- prompt: 'Open a learning workspace so I can study this topic properly.',
172
- expect: 'teach-workspace',
135
+ prompt: 'Quiz me on what we covered about regular expressions yesterday.',
136
+ expect: 'teach-craft',
173
137
  },
174
138
  {
175
139
  prompt:
@@ -55,7 +55,6 @@ export const PRACTICE_SKILLS: readonly string[] = [
55
55
  join(SHIPPED_CORPUS, 'build-in-slices'),
56
56
  join(SHIPPED_CORPUS, 'deprecation-migration'),
57
57
  join(SHIPPED_CORPUS, 'search-craft'),
58
- join(SHIPPED_CORPUS, 'video-craft'),
59
58
  ]
60
59
 
61
60
  /**
package/src/cli/help.ts CHANGED
@@ -38,14 +38,11 @@ export const COMMAND_GROUPS: { title: string; rows: CommandRow[] }[] = [
38
38
  title: 'Author and render',
39
39
  rows: [
40
40
  ['design [cmd]', 'Design system'],
41
- ['slides [cmd]', 'Slide decks'],
42
41
  ['capture [source]', 'Render HTML capture sources to PNG'],
43
42
  ['serve [dir]', 'Serve a directory on localhost, print the link'],
44
- ['demo [cmd]', 'Record a running app'],
45
43
  ['inventory [subj]', 'Report one computed property across every route'],
46
44
  ['drive <url> <run>', 'Walk a page through interactions, measure each'],
47
45
  ['transcripts <url>', 'Fetch a YouTube transcript with frontmatter'],
48
- ['teach [cmd]', 'Learning workspaces'],
49
46
  ['canvas [cmd]', 'Local canvas of pages and frames'],
50
47
  ],
51
48
  },
@@ -103,10 +100,7 @@ const EXAMPLES = [
103
100
  'canon docs agents',
104
101
  'canon design render',
105
102
  'canon canvas list --json',
106
- 'canon slides render',
107
- 'canon slides list --json',
108
103
  'canon capture assets/captures/install.html --selector .window --out assets/frames',
109
- 'canon serve .canon/teach',
110
104
  'canon inventory focus --json',
111
105
  'canon drive http://localhost:4173 run.json --json',
112
106
  'pbpaste | canon feedback',
@@ -114,7 +108,6 @@ const EXAMPLES = [
114
108
  'canon tasks --help --all',
115
109
  'canon tasks archive --pull-request 673 --json',
116
110
  'canon intake list toolkit-overview --unread --json',
117
- 'canon teach list --json',
118
111
  'canon comments scan src --json',
119
112
  'canon context audit --json',
120
113
  'canon markdown audit .claude/rules --json',
package/src/cli.ts CHANGED
@@ -10,17 +10,14 @@ import { register as claude } from '@/commands/claude'
10
10
  import { register as indexes } from '@/commands/indexes'
11
11
  import { register as docs } from '@/commands/docs'
12
12
  import { register as design } from '@/commands/design'
13
- import { register as slides } from '@/commands/slides'
14
13
  import { register as capture } from '@/commands/capture'
15
14
  import { register as serve } from '@/commands/serve'
16
- import { register as demo } from '@/commands/demo'
17
15
  import { register as inventory } from '@/commands/inventory'
18
16
  import { register as driver } from '@/commands/driver'
19
17
  import { register as feedback } from '@/commands/feedback'
20
18
  import { register as transcripts } from '@/commands/transcripts'
21
19
  import { register as tasks } from '@/commands/tasks'
22
20
  import { register as intake } from '@/commands/intake'
23
- import { register as teach } from '@/commands/teach'
24
21
  import { register as canvas } from '@/commands/canvas'
25
22
  import { register as comments } from '@/commands/comments'
26
23
  import { register as context } from '@/commands/context'
@@ -71,17 +68,14 @@ claude(program)
71
68
  indexes(program)
72
69
  docs(program)
73
70
  design(program)
74
- slides(program)
75
71
  capture(program)
76
72
  serve(program)
77
- demo(program)
78
73
  inventory(program)
79
74
  driver(program)
80
75
  feedback(program)
81
76
  transcripts(program)
82
77
  tasks(program)
83
78
  intake(program)
84
- teach(program)
85
79
  canvas(program)
86
80
  comments(program)
87
81
  context(program)
@@ -249,8 +249,8 @@ export function register(program: Command): void {
249
249
  '## Summary or ## Key changes, fails. A review, a release-please body,',
250
250
  'and a scan carrying no title skip this check.',
251
251
  '',
252
- 'It reports the density of that same body per section under `density`,',
253
- 'without failing on it: a bullet past 200 characters, more than 5 plain',
252
+ 'It fails the density of that same body, reported per section under',
253
+ '`density`: a bullet past 200 characters, more than 5 plain',
254
254
  'bullets or 2 paragraphs in a row, a paragraph past 350 characters, any',
255
255
  'H3 or deeper heading, and Technical context mixing bullets with',
256
256
  'paragraphs. A bold label alone on a line splits a Key changes run, a',
@@ -279,11 +279,12 @@ export function register(program: Command): void {
279
279
  'not read, as GitHub does not read it.',
280
280
  '',
281
281
  'Exit codes:',
282
- ' 0 none of the eight found',
282
+ ' 0 none of the nine found',
283
283
  ' 1 refused, with the reason on stderr or in the JSON record',
284
284
  ' 2 the title or body carries a phase label, a board identifier, a',
285
285
  ' session link, a banned character, a heading outside the closed',
286
- ' list or a required one missing, a missing or stray closing line',
286
+ ' list or a required one missing, a density finding in the body, a',
287
+ ' missing or stray closing line',
287
288
  ' under --closes, or a title',
288
289
  " breaking claude/skills/git-pr/references/pr.md's format, casing, or length",
289
290
  '',
@@ -718,9 +719,9 @@ async function runScan(opts: ScanOptions): Promise<number> {
718
719
  }
719
720
  }
720
721
 
721
- // Reported and never gated yet. New bodies come back clean under the
722
- // shape in pr.md first, so an older open pull request fails no edit event.
723
- // A post is never gated, since CI reads one only after it is published.
722
+ // A body's density fails the scan. A post's never does, since the review
723
+ // post hook denies on exit 2 and scans with no title, so a post-density
724
+ // fail would block every dense review or reply post.
724
725
  const post = !sectionsChecked && isPost(resolved.body)
725
726
  const density = sectionsChecked
726
727
  ? bodyDensity(resolved.body)
@@ -859,6 +860,7 @@ async function runScan(opts: ScanOptions): Promise<number> {
859
860
  titleFormatIssues.length === 0 &&
860
861
  sections.outside.length === 0 &&
861
862
  sections.missing.length === 0 &&
863
+ !(sectionsChecked && density.length > 0) &&
862
864
  banFindings.length === 0 &&
863
865
  closing.missing.length === 0 &&
864
866
  closing.stray.length === 0
@@ -127,7 +127,6 @@ export function register(program: Command): void {
127
127
  'Examples:',
128
128
  ' canon records validate plans',
129
129
  ' canon records validate plans feature-records-by-heading',
130
- ' canon records validate teach',
131
130
  ' canon records validate intake --json',
132
131
  '',
133
132
  ].join('\n'),
@@ -40,8 +40,8 @@ export function register(program: Command): void {
40
40
  'starts it in the background and reads the record off stdout.',
41
41
  '',
42
42
  'Examples:',
43
- ' canon serve .canon/teach',
44
- ' canon serve .canon/teach --entry 03-fde-system-design/index.html',
43
+ ' canon serve site',
44
+ ' canon serve site --entry guide/index.html',
45
45
  ' canon serve dist --port 4000 --json',
46
46
  ' canon serve .canon/groundwork --index',
47
47
  '',