@erclx/canon 5.20.0 → 5.22.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/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/SKILL.md +1 -1
- package/claude/skills/auto-ship/references/draft-mark.md +8 -6
- package/claude/skills/auto-ship/references/verb-absent.md +1 -1
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -1
- package/claude/skills/document-health/REQUIREMENT.md +1 -1
- package/claude/skills/draft-doc/REQUIREMENT.md +45 -0
- package/claude/skills/draft-doc/SKILL.md +77 -0
- package/claude/skills/draft-doc/references/context.md +31 -0
- package/claude/skills/draft-doc/references/docs.md +33 -0
- package/claude/skills/draft-doc/references/readme.md +58 -0
- package/claude/skills/draft-doc/references/wiki.md +53 -0
- package/claude/skills/draft-doc/references/wireframes.md +48 -0
- package/claude/skills/draft-figure/REQUIREMENT.md +1 -1
- package/claude/skills/draft-figure/SKILL.md +1 -1
- package/claude/skills/draft-ready/REQUIREMENT.md +2 -1
- package/claude/skills/draft-ready/SKILL.md +6 -4
- package/claude/skills/git-pr/SKILL.md +5 -46
- package/claude/skills/git-pr/references/final-command.md +75 -0
- package/claude/skills/git-pr/references/labels.md +2 -2
- package/claude/skills/markdown-propose/REQUIREMENT.md +3 -3
- package/claude/skills/markdown-propose/SKILL.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +76 -0
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +11 -1
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +5 -1
- package/claude/skills/search-craft/REQUIREMENT.md +4 -4
- package/claude/skills/search-craft/SKILL.md +1 -1
- package/docs/agents/commands.md +1 -0
- package/docs/agents/drift-surfaces.md +20 -9
- package/docs/agents/index.md +2 -1
- package/docs/agents/install-and-sync.md +3 -3
- package/docs/agents/markdown-audit.md +1 -3
- package/docs/agents/migrate.md +1 -1
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/slides.md +164 -0
- package/docs/agents/tasks-validate.md +1 -1
- package/docs/agents/tasks.md +2 -2
- package/docs/target/migrations.md +4 -2
- package/docs/target/sync.md +1 -1
- package/docs/workflow/ai-workflow.md +1 -1
- package/docs/workflow/skill-map.md +25 -31
- package/governance/rules/canon/604-scratch.md +0 -1
- package/governance/rules/claude/575-hooks.md +1 -2
- package/governance/rules/claude/576-settings.md +1 -2
- package/governance/rules/lib/330-testing-py.md +1 -1
- package/governance/rules/lib/336-testing-php.md +1 -1
- package/governance/rules/standards/architecture.md +0 -1
- package/governance/rules/standards/context.md +0 -1
- package/governance/rules/standards/design.md +0 -1
- package/governance/rules/standards/diagrams.md +0 -3
- package/governance/rules/standards/requirements.md +0 -1
- package/governance/rules/standards/wireframes.md +0 -1
- package/package.json +1 -1
- package/scripts/manage-sandbox.sh +7 -8
- package/src/claude/cases/authoring.ts +5 -5
- package/src/claude/cases/workflow.ts +4 -20
- package/src/commands/slides.ts +23 -3
- package/src/commands/sync.ts +10 -0
- package/src/commands/tasks.ts +46 -2
- package/src/gov/citations.ts +1 -2
- package/src/migrate/skill-names.ts +12 -7
- package/src/slides/convert/chart.ts +165 -0
- package/src/slides/convert/deck.ts +244 -0
- package/src/slides/convert/export.ts +281 -23
- package/src/slides/convert/master.ts +195 -0
- package/src/slides/convert/shapes.ts +44 -4
- package/src/slides/convert/walk.ts +229 -2
- package/src/slides/package/fonts.ts +297 -0
- package/src/slides/package/motion.ts +316 -0
- package/src/slides/package/test-face.ts +113 -0
- package/src/sync/check.ts +9 -0
- package/src/sync/layout.ts +27 -1
- package/src/tasks/record.ts +11 -1
- package/src/tasks/validate.ts +14 -0
- package/standards/architecture.md +0 -1
- package/standards/context.md +0 -1
- package/standards/design.md +0 -1
- package/standards/diagrams.md +0 -3
- package/standards/requirements.md +0 -1
- package/standards/rule.md +1 -0
- package/standards/tasks.md +1 -1
- package/standards/wireframes.md +0 -1
- package/tooling/astro/configs/card-src/pages/og-card.astro +2 -2
- package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +8 -3
- package/claude/skills/docs-fold/REQUIREMENT.md +0 -25
- package/claude/skills/docs-fold/SKILL.md +0 -9
- package/claude/skills/draft-context/REQUIREMENT.md +0 -37
- package/claude/skills/draft-context/SKILL.md +0 -61
- package/claude/skills/draft-docs/REQUIREMENT.md +0 -35
- package/claude/skills/draft-docs/SKILL.md +0 -59
- package/claude/skills/draft-readme/REQUIREMENT.md +0 -38
- package/claude/skills/draft-readme/SKILL.md +0 -73
- package/claude/skills/draft-wiki/REQUIREMENT.md +0 -42
- package/claude/skills/draft-wiki/SKILL.md +0 -83
- package/claude/skills/draft-wireframes/REQUIREMENT.md +0 -38
- package/claude/skills/draft-wireframes/SKILL.md +0 -69
- package/claude/skills/standards-audit/REQUIREMENT.md +0 -33
- package/claude/skills/standards-audit/SKILL.md +0 -99
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Slides
|
|
3
|
+
description: What a folder of HTML slides declares for the whole deck in deck.json, the faces it embeds, what each slide declares on its own body, transitions and entrances, the master built from the project's tokens, speaker notes, charts, and what each refusal reports
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Slides
|
|
7
|
+
|
|
8
|
+
`canon slides render --source <folder>` turns a folder of `.html` slides into an editable PowerPoint deck. Each slide describes its own shapes. What belongs to the whole deck, being the bands, the numbers, and the mark, sits in one file beside them, and the master that carries it takes the project's own colors and face.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
canon slides render --source slides/q3-review
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## The deck file
|
|
15
|
+
|
|
16
|
+
`deck.json` beside the slides is optional. Without it the deck gets its defaults.
|
|
17
|
+
|
|
18
|
+
| Field | Default | What it sets |
|
|
19
|
+
| -------------- | ------------------------------ | ------------------------------------------------- |
|
|
20
|
+
| `title` | the folder name | the file's title and the default footer text |
|
|
21
|
+
| `header` | off | a band at the top, with `left`, `center`, `right` |
|
|
22
|
+
| `footer` | on, with the title on the left | a band at the bottom, with the same three slots |
|
|
23
|
+
| `slideNumbers` | `true` | the number at the right of the footer |
|
|
24
|
+
| `mark` | none | an image path, relative to the folder, top right |
|
|
25
|
+
| `fonts` | none | faces to embed in the file, described below |
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"title": "Q3 review",
|
|
30
|
+
"header": { "left": "Acme" },
|
|
31
|
+
"footer": { "center": "Internal" },
|
|
32
|
+
"mark": "assets/mark.png",
|
|
33
|
+
"fonts": [
|
|
34
|
+
{ "family": "Inter", "path": "fonts/Inter-Regular.ttf" },
|
|
35
|
+
{ "family": "Inter", "weight": 700, "path": "fonts/Inter-Bold.ttf" }
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
A band takes `show` and the three slots. A declared band merges over its default, so `"footer": { "center": "Internal" }` keeps the title on the left. Declaring any slot turns a band on unless it also says `"show": false`. Set a slot to `""` to empty it.
|
|
41
|
+
|
|
42
|
+
Slide numbers belong to the footer and hold its right slot. They show only where the footer does, and `footer.right` needs `slideNumbers` set to `false`.
|
|
43
|
+
|
|
44
|
+
Prefer a raster mark. An SVG mark lands as a vector, and its fallback for a viewer that cannot draw SVG comes out broken.
|
|
45
|
+
|
|
46
|
+
### Embedded faces
|
|
47
|
+
|
|
48
|
+
Each entry in `fonts` names one TrueType or OpenType file inside the deck folder, and the deck carries it so it renders in its own face on a machine without the font installed.
|
|
49
|
+
|
|
50
|
+
- `family` is required and should match the family the slides set, since that is the name PowerPoint looks the face up by.
|
|
51
|
+
- `weight` defaults to `400`. PowerPoint holds four faces a family, so `600` and above fills the bold slot and anything lighter fills regular.
|
|
52
|
+
- `style` is `normal` or `italic`, defaulting to `normal`.
|
|
53
|
+
- `path` is relative to the folder and has to stay inside it.
|
|
54
|
+
|
|
55
|
+
A face is refused, and the deck still written without it, when its license forbids embedding or allows a bitmap only, when it is a variable font, when it is a `woff` or `woff2` file, or when a second face lands in a slot one already fills. Supply static instances, one per weight, in place of a variable face. For `woff2`, supply the TrueType or OpenType file it was compressed from, which most font downloads ship beside it.
|
|
56
|
+
|
|
57
|
+
## What each slide declares
|
|
58
|
+
|
|
59
|
+
A slide sets its own place in the deck through attributes on `<body>`.
|
|
60
|
+
|
|
61
|
+
| Attribute | Effect |
|
|
62
|
+
| --------------------------------------- | --------------------------------------------- |
|
|
63
|
+
| `data-section="Results"` | opens a section the slides after it stay in |
|
|
64
|
+
| `data-hidden` | hides the slide in the show |
|
|
65
|
+
| `data-header="off"` | drops the header on this slide |
|
|
66
|
+
| `data-footer="off"` | drops the footer and its number on this slide |
|
|
67
|
+
| `data-footer-left`, `-center`, `-right` | replaces that footer slot on this slide alone |
|
|
68
|
+
| `data-header-left`, `-center`, `-right` | replaces that header slot on this slide alone |
|
|
69
|
+
|
|
70
|
+
Once any slide opens a section, slides ahead of the first one sit in a section named after the deck, since PowerPoint wants every slide in one. A title the deck returns to after another section opens a new section numbered `Intro (2)`, so each section stays one run of slides.
|
|
71
|
+
|
|
72
|
+
A slide dropping one band keeps the other from the master. A slide replacing a slot draws its band as its own text, so editing that band once in PowerPoint's master view reaches every slide except the ones that replaced it.
|
|
73
|
+
|
|
74
|
+
## Motion
|
|
75
|
+
|
|
76
|
+
A slide declares how it arrives on `<body>`, and an element declares how it comes in on its own tag.
|
|
77
|
+
|
|
78
|
+
| Attribute | Takes | Effect |
|
|
79
|
+
| -------------------------- | ------------------------------- | -------------------------------------- |
|
|
80
|
+
| `data-transition` | `fade`, `push`, `wipe`, `cover` | the transition into this slide |
|
|
81
|
+
| `data-transition-duration` | `500`, `500ms`, or `0.5s` | rounded to 0.5, 0.75, or 1 second |
|
|
82
|
+
| `data-enter` | `fade`, `fly`, `wipe`, `zoom` | an entrance played on a click |
|
|
83
|
+
| `data-enter-order` | a number | the click it plays on, lowest first |
|
|
84
|
+
| `data-enter-duration` | `500`, `500ms`, or `0.5s` | the entrance length, 500 ms by default |
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<body data-transition="fade">
|
|
88
|
+
<h1>Results</h1>
|
|
89
|
+
<div class="card" data-enter="fly" data-enter-order="1">…</div>
|
|
90
|
+
<div class="card" data-enter="fly" data-enter-order="2">…</div>
|
|
91
|
+
</body>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Each entrance is its own click. Entrances without an order play after the ordered ones, in page order. An entrance brings in every shape drawn from its element and the elements inside it together, so a card's box and its text arrive on one click, and an element drawn as a picture brings in that picture. An element inside it with its own `data-enter` waits for its own click. Fly comes in from the bottom and wipe from the left.
|
|
95
|
+
|
|
96
|
+
A transition length rounds to the nearest of the three speeds PowerPoint's file format names, since a length in milliseconds needs an extension the deck does not write.
|
|
97
|
+
|
|
98
|
+
## The master
|
|
99
|
+
|
|
100
|
+
The master takes its colors from the `<html>` element of the first slide as Chromium laid it out with the project's token stylesheet injected, so a theme switched on one slide's `<body>`, such as a dark cover, stays on that slide:
|
|
101
|
+
|
|
102
|
+
- `--color-background`: the slide ground
|
|
103
|
+
- `--color-text`: the header text
|
|
104
|
+
- `--color-muted`: the footer text
|
|
105
|
+
- `--color-accent`: the slide number
|
|
106
|
+
- the `<body>` font family, first name with a ` Variable` suffix dropped: the theme face
|
|
107
|
+
|
|
108
|
+
A role the project declares no token for falls back to the slide body's own color and prints one `✗` line naming it. It never falls back to the toolkit's palette.
|
|
109
|
+
|
|
110
|
+
A slide whose `<body>` background differs from the master's keeps its own. A slide whose `<body>` computes a `--color-text` apart from the master's prints one `✗` line naming it, since its bands keep the master's colors and may not read against its ground.
|
|
111
|
+
|
|
112
|
+
## Speaker notes
|
|
113
|
+
|
|
114
|
+
`<aside class="notes">` becomes the slide's notes and is never drawn. Each paragraph or list item becomes its own line, and markup is dropped.
|
|
115
|
+
|
|
116
|
+
## Charts
|
|
117
|
+
|
|
118
|
+
A `<figure data-chart="...">` holding a `<table>` becomes a native, editable chart placed where the figure was laid out. The table stays the page's accessible source and is not drawn as well.
|
|
119
|
+
|
|
120
|
+
```html
|
|
121
|
+
<figure data-chart="bar" data-labels>
|
|
122
|
+
<figcaption>Revenue by region</figcaption>
|
|
123
|
+
<table>
|
|
124
|
+
<tr>
|
|
125
|
+
<th>Region</th>
|
|
126
|
+
<th>Q1</th>
|
|
127
|
+
<th>Q2</th>
|
|
128
|
+
</tr>
|
|
129
|
+
<tr>
|
|
130
|
+
<td>North</td>
|
|
131
|
+
<td>12</td>
|
|
132
|
+
<td>16</td>
|
|
133
|
+
</tr>
|
|
134
|
+
<tr>
|
|
135
|
+
<td>South</td>
|
|
136
|
+
<td></td>
|
|
137
|
+
<td>11</td>
|
|
138
|
+
</tr>
|
|
139
|
+
</table>
|
|
140
|
+
</figure>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- `data-chart` takes `bar`, `line`, `area`, `pie`, or `doughnut`.
|
|
144
|
+
- The header row names the series and the first column names the categories.
|
|
145
|
+
- An empty cell is a gap, not a zero. A comma is a thousands separator only where it groups in threes, as in `12,345.5`, so a comma-decimal `3,5` refuses rather than reading as 35.
|
|
146
|
+
- `data-labels` shows each value. A `<figcaption>` becomes the chart title.
|
|
147
|
+
- Series take the accent first, then every other declared `--color-*` role in sheet order except the background and surface, repeating past the last.
|
|
148
|
+
|
|
149
|
+
## Refusals
|
|
150
|
+
|
|
151
|
+
| Case | Report | Exit |
|
|
152
|
+
| -------------------------------------- | ---------------------------------------------- | ---- |
|
|
153
|
+
| `deck.json` field malformed or unknown | `✗` naming the file and the field | 1 |
|
|
154
|
+
| `mark` path missing | `✗` naming the resolved path | 1 |
|
|
155
|
+
| `fonts` path missing or outside folder | `✗` naming the field and the path | 1 |
|
|
156
|
+
| face not embeddable | `✗` naming the path and the reason | 0 |
|
|
157
|
+
| unknown transition or entrance name | `✗` naming the slide, the element, the effect | 0 |
|
|
158
|
+
| entrance on an element that draws none | `✗` naming the slide and the element | 0 |
|
|
159
|
+
| chart cell not a number | `✗` naming the slide, the figure, and the cell | 0 |
|
|
160
|
+
| `data-chart` outside the five types | `✗` naming the value | 0 |
|
|
161
|
+
| token role not declared | `✗` naming the role | 0 |
|
|
162
|
+
| slide body sets its own `--color-text` | `✗` naming the slides | 0 |
|
|
163
|
+
|
|
164
|
+
A refused chart, effect, or face is left out and the rest of the deck is written.
|
|
@@ -61,7 +61,7 @@ The blocker check re-takes a measurement the board records once and never repeat
|
|
|
61
61
|
}
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
A closed outcome is not the fact the dependency half needs. The ship chain marks outcomes as its first step and opens the pull request several steps later, so a check reading the checkbox reports the row settled while the branch is still in review. A live task therefore settles the row only once it closed every outcome and carries a `Pull request:` line the trunk holds. One that names no pull request, and one whose number no trunk ref could answer for, land in the untested array below rather than being settled or left silent.
|
|
64
|
+
A closed outcome is not the fact the dependency half needs. The ship chain marks outcomes as its first step and opens the pull request several steps later, so a check reading the checkbox reports the row settled while the branch is still in review. A live task therefore settles the row only once it closed every outcome and carries a `Pull request:` line the trunk holds. One that carries a `Pending branch:` line, one that names no pull request, and one whose number no trunk ref could answer for, land in the untested array below rather than being settled or left silent.
|
|
65
65
|
|
|
66
66
|
The trunk is read as the clone already holds it, `origin/main` first and local `main` behind it, and no run fetches. A validate runs several times a sweep and a fetch per run is a cost this command does not carry, so a clone behind its remote under-reports rather than claiming work landed.
|
|
67
67
|
|
package/docs/agents/tasks.md
CHANGED
|
@@ -64,7 +64,7 @@ Run from a branch other than `main` or `master`, the verb also drops that branch
|
|
|
64
64
|
|
|
65
65
|
Exit codes: `0` recorded, `1` refused. The `reason` field carries `no-board`, `no-match`, or `ambiguous`. `git-pr` skips silently on those three, because each is a case where a guessed write would archive the wrong task once the branch merges.
|
|
66
66
|
|
|
67
|
-
A malformed argument refuses as `bad-input` instead, which sits outside that set on purpose. `git-pr` derives the number by slicing
|
|
67
|
+
A malformed argument refuses as `bad-input` instead, which sits outside that set on purpose. `git-pr` derives the number by slicing the address the create call returned, so a non-numeric value is reachable, and folding it into the swallowed set would lose the number with nothing reporting it.
|
|
68
68
|
|
|
69
69
|
## Outcome
|
|
70
70
|
|
|
@@ -84,7 +84,7 @@ canon tasks outcome --plan worktree-scratch-routing --close 2 --json
|
|
|
84
84
|
|
|
85
85
|
An outcome already closed comes back under `alreadyClosed` rather than refusing, so a rerun against the same positions changes nothing. A position past the end of the list refuses as `out-of-range`, since a caller counting wrong should hear about it rather than mark a neighbor.
|
|
86
86
|
|
|
87
|
-
A close that ticks at least one box from a branch other than `main` or `master` names that branch on a `Pending branch:` line, read from `git branch --show-current` in the working directory. The line holds the task against `canon tasks archive --pull-request` until `canon tasks pull-request` records that branch's own number. A detached HEAD, a trunk checkout, or a failed git read writes no line and refuses nothing. The `pending` field lists the branches on the line after the write.
|
|
87
|
+
A close that ticks at least one box from a branch other than `main` or `master` names that branch on a `Pending branch:` line, read from `git branch --show-current` in the working directory. The line holds the task against `canon tasks archive --pull-request` until `canon tasks pull-request` records that branch's own number. A detached HEAD, a trunk checkout, or a failed git read writes no line and refuses nothing. The line is also skipped when `gh pr list --head <branch> --state all` lists a number already on the task's `Pull request:` line, since that branch has recorded itself and a marker would outlive it, as in a review-address pass. A failed, offline, or unreadable `gh` lookup counts as no listing and writes the line. The `pending` field lists the branches on the line after the write.
|
|
88
88
|
|
|
89
89
|
Positions skip fenced blocks. A checkbox inside a sample a task displays is not an outcome the task claims, and counting one would shift every position after it. `canon tasks archive` reads the list through the same walker, so the two verbs cannot disagree about which checkboxes are outcomes.
|
|
90
90
|
|
|
@@ -60,9 +60,11 @@ The first line reports the plan and the second applies it, relocating each rule
|
|
|
60
60
|
|
|
61
61
|
## Rename the skill citations, once
|
|
62
62
|
|
|
63
|
-
Twenty-five plugin skills dropped their `claude-` prefix for two-word names, so `canon:claude-docs` answers as `canon:context-fold` and `canon:claude-tasks` as `canon:task-board`. A project that installed governance or tooling before that release holds files naming the old ones, and the plugin answers to none of them. A later release renamed `docs-fold` to `context-fold`, since the skill folds a session into the context entries and the task board rather than into `docs/`, and the same sweep carries a project across that rename too. <!-- canon-keep-retired -->
|
|
63
|
+
Twenty-five plugin skills dropped their `claude-` prefix for two-word names, so `canon:claude-docs` answers as `canon:context-fold` and `canon:claude-tasks` as `canon:task-board`. A project that installed governance or tooling before that release holds files naming the old ones, and the plugin answers to none of them. A later release renamed `docs-fold` to `context-fold`, since the skill folds a session into the context entries and the task board rather than into `docs/`, and the same sweep carries a project across that rename too. The pointer that answered under the old name no longer ships, so a citation the sweep has not reached names nothing. <!-- canon-keep-retired -->
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
The same sweep carries the merge of the five per-kind document drafters into `draft-doc`, so a citation of any one of them lands on `canon:draft-doc`.
|
|
66
|
+
|
|
67
|
+
Two of those files run rather than sit there. `.husky/post-merge` runs the `canon hooks post-merge` verb, so a stale copy of the hook calls a binary that may lack it, and `.claude/hooks/pr-create-log.sh` hands a session a message naming a skill, so a stale copy tells someone to invoke something that no longer exists. A copy older than `git-pr`'s move to REST also matches only `gh pr create`, so it stays silent on every pull request `git-pr` opens. A rule under `.claude/rules/canon/core/` names skills too, though a rule is read rather than run.
|
|
66
68
|
|
|
67
69
|
Resync what the toolkit owns, then sweep what the project wrote:
|
|
68
70
|
|
package/docs/target/sync.md
CHANGED
|
@@ -28,7 +28,7 @@ Each domain holds its own toolkit commit, so syncing governance today does not m
|
|
|
28
28
|
|
|
29
29
|
A project that has never synced under a toolkit new enough to write a stamp falls back to the toolkit's own git history. Installed content matching any version that history published proves the file untouched, so it reports `stale` naming the commit it came from, and content matching no published version stays `drifted`. That fallback needs the toolkit as a git checkout. Installed from the registry it ships source without history, and the report says attribution was unavailable rather than reading every file as a local edit.
|
|
30
30
|
|
|
31
|
-
Further causes sit outside the per-domain scan, each naming something that walk cannot see. A seed the project edited is reported under `seeds` and reconciled with `canon:seed-sync`, since no sync command touches a seed. A file a newer seed folder replaced is reported under `superseded`, such as `.claude/TASKS.md` against the `.canon/tasks/` that now ships, and nothing moves it because the content is the project's own. A domain sitting at the root layout with nothing under `.claude/` is reported under `unmigrated`, and no command moves it either. The project moves the content itself.
|
|
31
|
+
Further causes sit outside the per-domain scan, each naming something that walk cannot see. A seed the project edited is reported under `seeds` and reconciled with `canon:seed-sync`, since no sync command touches a seed. A file a newer seed folder replaced is reported under `superseded`, such as `.claude/TASKS.md` against the `.canon/tasks/` that now ships, and nothing moves it because the content is the project's own. A domain sitting at the root layout with nothing under `.claude/` is reported under `unmigrated`, and no command moves it either. The project moves the content itself. A surface still at its `.claude/` spelling with nothing under `canon/`, such as `.claude/REQUIREMENTS.md`, is reported under `unmovedSurfaces`, since rules glob the `canon/` spelling alone, and `canon migrate surface-roots` moves it. <!-- canon-keep-surface-root -->
|
|
32
32
|
|
|
33
33
|
`unmigrated` currently names no domain, since standards and snippets are the two the toolkit ever installed at the project root, standards closed its install channel, and snippets retired outright. A target still holding a root `standards/` folder from an older toolkit is carrying its own authoring surface now, not an unfinished install, and nothing proposes moving it. A leftover `.claude/snippets/` reports under `reverse` below instead.
|
|
34
34
|
|
|
@@ -97,7 +97,7 @@ Review findings split by origin before severity is read. One the branch inherite
|
|
|
97
97
|
|
|
98
98
|
Review is skipped when the diff is prose that only informs: every changed file matches `*.md` or `*.txt`, and none sits under a behavior path. Behavior paths cover skills and rules in both the authoring and the installed spelling, so the list matches whether a repository authors those surfaces or consumed them from the toolkit. Standards, `internal/`, and `tooling/` carry the authoring spelling alone, since none of the three reaches a session through a `.claude/` copy, and root `CLAUDE.md` is named as a file because a path prefix reaches nothing sitting in no folder.
|
|
99
99
|
|
|
100
|
-
Markdown under one states what an agent does, so a branch touching it reaches review while `docs/` and `wiki/` still skip and stay gated by `docs-sync`, `
|
|
100
|
+
Markdown under one states what an agent does, so a branch touching it reaches review while `docs/` and `wiki/` still skip and stay gated by `docs-sync`, `canon markdown audit`, and pre-push hooks.
|
|
101
101
|
|
|
102
102
|
An empty changed-file list stops the chain rather than counting as prose-only. The filename test passes vacuously on an empty set, which routed a branch past review instead of through it.
|
|
103
103
|
|
|
@@ -61,7 +61,6 @@ This page is the corpus the coverage claim is measured against: every name `cano
|
|
|
61
61
|
| Skill | When to use |
|
|
62
62
|
| ------------------------ | --------------------------------------------------------------------------------------- |
|
|
63
63
|
| `canon:review-branch` | On the local branch diff, before anything is pushed |
|
|
64
|
-
| `canon:standards-audit` | When changed markdown has to answer to the authoring standards |
|
|
65
64
|
| `canon:document-health` | When the documents themselves have to answer for length, placement, and staleness |
|
|
66
65
|
| `canon:markdown-propose` | When a markdown claim needs rewriting and the change should wait for an answer per file |
|
|
67
66
|
| `canon:ux-audit` | To read UI source for missing states, edge cases, and inconsistencies |
|
|
@@ -70,18 +69,17 @@ This page is the corpus the coverage claim is measured against: every name `cano
|
|
|
70
69
|
|
|
71
70
|
## Ship it
|
|
72
71
|
|
|
73
|
-
| Skill | When to use
|
|
74
|
-
| ---------------------- |
|
|
75
|
-
| `canon:git-ship` | To run the whole post-feature chain from the verify gate through open PR
|
|
76
|
-
| `canon:memory-capture` | First skill in that chain, to route what the session learned to the surface owning it
|
|
77
|
-
| `canon:context-fold` | When decisions diverged from the plan, or a shipped task needs its outcomes marked
|
|
78
|
-
| `canon:docs-
|
|
79
|
-
| `canon:
|
|
80
|
-
| `canon:git-
|
|
81
|
-
| `canon:git-
|
|
82
|
-
| `canon:git-
|
|
83
|
-
| `canon:
|
|
84
|
-
| `canon:memory-review` | When the pen has grown, to propose where each entry belongs |
|
|
72
|
+
| Skill | When to use |
|
|
73
|
+
| ---------------------- | ------------------------------------------------------------------------------------- |
|
|
74
|
+
| `canon:git-ship` | To run the whole post-feature chain from the verify gate through open PR |
|
|
75
|
+
| `canon:memory-capture` | First skill in that chain, to route what the session learned to the surface owning it |
|
|
76
|
+
| `canon:context-fold` | When decisions diverged from the plan, or a shipped task needs its outcomes marked |
|
|
77
|
+
| `canon:docs-sync` | When a change since main left `README.md` or `docs/` stale |
|
|
78
|
+
| `canon:git-stage` | When the staged set spans several concerns and wants one commit each |
|
|
79
|
+
| `canon:git-commit` | When the staged set is one concern, or was staged hunk by hand |
|
|
80
|
+
| `canon:git-branch` | When a branch name needs generating or renaming to conventional form |
|
|
81
|
+
| `canon:git-pr` | When a pull request needs a title and body written from the diff |
|
|
82
|
+
| `canon:memory-review` | When the pen has grown, to propose where each entry belongs |
|
|
85
83
|
|
|
86
84
|
## After the pull request opens
|
|
87
85
|
|
|
@@ -120,24 +118,20 @@ This page is the corpus the coverage claim is measured against: every name `cano
|
|
|
120
118
|
|
|
121
119
|
## Generate an artifact on demand
|
|
122
120
|
|
|
123
|
-
| Skill | When to use
|
|
124
|
-
| ------------------------- |
|
|
125
|
-
| `canon:create-rule` | For a project-specific governance rule the toolkit does not ship
|
|
126
|
-
| `canon:create-skill` | For a new `SKILL.md`
|
|
127
|
-
| `canon:create-standard` | For a new authoring convention
|
|
128
|
-
| `canon:draft-
|
|
129
|
-
| `canon:draft-ready` | For finished files a worker should copy, written as a ready folder with its overview, thin plan, and task
|
|
130
|
-
| `canon:draft-
|
|
131
|
-
| `canon:
|
|
132
|
-
| `canon:
|
|
133
|
-
| `canon:draft-
|
|
134
|
-
| `canon:draft-
|
|
135
|
-
| `canon:
|
|
136
|
-
| `canon:
|
|
137
|
-
| `canon:draft-slides` | For a deck, drafted as `.claude/SLIDES.md` and rendered to PowerPoint |
|
|
138
|
-
| `canon:draft-screencast` | For a recording script with beats and defaults already seeded |
|
|
139
|
-
| `canon:record-screencast` | For recording a screencast draft, then composing the take into a finished mp4 when the draft asks for a wrap |
|
|
140
|
-
| `canon:draft-identity` | For a project's logo mark and its social card, drafted through `draft-and-pick`'s pick loop |
|
|
121
|
+
| Skill | When to use |
|
|
122
|
+
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
|
+
| `canon:create-rule` | For a project-specific governance rule the toolkit does not ship |
|
|
124
|
+
| `canon:create-skill` | For a new `SKILL.md` |
|
|
125
|
+
| `canon:create-standard` | For a new authoring convention |
|
|
126
|
+
| `canon:draft-doc` | For a brand-new `docs/` page, context entry, wireframe surface, wiki reference page, or `README.md`, drafted against the standard for its kind |
|
|
127
|
+
| `canon:draft-ready` | For finished files a worker should copy, written as a ready folder with its overview, thin plan, and task |
|
|
128
|
+
| `canon:draft-figure` | For a hand-drawn figure inside an existing doc, drafted against `standards/figures.md` in Mermaid or freehand SVG |
|
|
129
|
+
| `canon:bash-cli-script` | For a small non-interactive shell wrapper, stopping at 100 lines in favor of TypeScript on Bun |
|
|
130
|
+
| `canon:ci-workflow` | For a GitHub Actions workflow file |
|
|
131
|
+
| `canon:draft-slides` | For a deck, drafted as `.claude/SLIDES.md` and rendered to PowerPoint |
|
|
132
|
+
| `canon:draft-screencast` | For a recording script with beats and defaults already seeded |
|
|
133
|
+
| `canon:record-screencast` | For recording a screencast draft, then composing the take into a finished mp4 when the draft asks for a wrap |
|
|
134
|
+
| `canon:draft-identity` | For a project's logo mark and its social card, drafted through `draft-and-pick`'s pick loop |
|
|
141
135
|
|
|
142
136
|
## Answer a question at any point
|
|
143
137
|
|
|
@@ -7,4 +7,3 @@ description: Write temporary files to the scratch folder structure
|
|
|
7
7
|
## Temporary files
|
|
8
8
|
|
|
9
9
|
- Write temporary files to `.canon/tmp/<slug>/<file>.md` at the current worktree's root, a nested folder with a kebab-slug tied to the topic rather than a flat `<slug>-<file>.md`. The slug must not take one of the five reserved names `runs`, `hooks`, `handoff`, `pr`, and `render`. A skill that resolves a write at the main root instead states so in its own body.
|
|
10
|
-
- Write to `.claude/.tmp/<slug>/` instead in a project that carries no `.canon/` root, and `canon migrate records` moves it to the first spelling. <!-- canon-keep-record-root -->
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: State the hook stdin guard and the silencing rule for .claude/hooks scripts
|
|
2
|
+
description: State the hook stdin guard and the silencing rule for .claude/hooks scripts
|
|
3
3
|
paths:
|
|
4
4
|
- '.claude/hooks/**/*.sh'
|
|
5
|
-
- 'tooling/claude/seeds/.claude/hooks/**/*.sh'
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# Hook standards
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: State the autoContinueAtUsageLimit inversion and the autoCompactWindow cap for .claude/settings.json
|
|
2
|
+
description: State the autoContinueAtUsageLimit inversion and the autoCompactWindow cap for .claude/settings.json
|
|
3
3
|
paths:
|
|
4
4
|
- '.claude/settings.json'
|
|
5
|
-
- 'tooling/claude/seeds/.claude/settings.json'
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# Settings standards
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
description: Shape and content rules for .canon/diagrams/<kind>.md files
|
|
4
4
|
paths:
|
|
5
5
|
- '.canon/diagrams/**'
|
|
6
|
-
- '.claude/DIAGRAMS.md'
|
|
7
6
|
---
|
|
8
7
|
|
|
9
8
|
# Diagram standards
|
|
@@ -13,5 +12,3 @@ paths:
|
|
|
13
12
|
- Follow the diagrams standard for shape and content rules for .canon/diagrams/<kind>.md files. It is the single source. Read it with `canon standards diagrams`.
|
|
14
13
|
- Layout, budgets, accessibility, labels, and render verification inside the fence are a separate topic. The mermaid standard routes them.
|
|
15
14
|
- A diagram entry carries structure and flow, not implementation. Read the standard before adding or revising a kind.
|
|
16
|
-
- Write a new diagram to `.canon/diagrams/<kind>.md`, never to `.claude/DIAGRAMS.md`
|
|
17
|
-
- Convert a `.claude/DIAGRAMS.md` left by an older install into per-kind entries before editing it
|
package/package.json
CHANGED
|
@@ -190,10 +190,10 @@ provision_sandbox() {
|
|
|
190
190
|
(cd "$SANDBOX" && configure_sandbox_git_credentials)
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
# Runs the real installer rather than copying the source tree. The
|
|
194
|
-
#
|
|
195
|
-
# to what install produces left the sandbox
|
|
196
|
-
# scenario could observe the difference.
|
|
193
|
+
# Runs the real installer rather than copying the source tree. The copies these
|
|
194
|
+
# replaced, for gov rules and for seeds, each reimplemented an installer's
|
|
195
|
+
# selection rules, so a change to what install produces left the sandbox
|
|
196
|
+
# provisioning the old shape and no scenario could observe the difference.
|
|
197
197
|
run_sandbox_install() {
|
|
198
198
|
local label="$1"
|
|
199
199
|
shift
|
|
@@ -223,10 +223,9 @@ inject_gov_rules() {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
inject_seeds() {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
fi
|
|
226
|
+
[ ! -d "$PROJECT_ROOT/tooling/claude/seeds" ] && return
|
|
227
|
+
|
|
228
|
+
run_sandbox_install "seeds" claude init "$SANDBOX"
|
|
230
229
|
}
|
|
231
230
|
|
|
232
231
|
commit_environment_setup() {
|
|
@@ -31,7 +31,7 @@ export const AUTHORING_CASES: readonly SkillCase[] = [
|
|
|
31
31
|
{
|
|
32
32
|
prompt:
|
|
33
33
|
'Write a brand-new docs page for the capture command, nothing under docs/ covers it yet.',
|
|
34
|
-
expect: 'draft-
|
|
34
|
+
expect: 'draft-doc',
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
prompt:
|
|
@@ -40,22 +40,22 @@ export const AUTHORING_CASES: readonly SkillCase[] = [
|
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
prompt: 'This project has no README.md at all, write one from scratch.',
|
|
43
|
-
expect: 'draft-
|
|
43
|
+
expect: 'draft-doc',
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
prompt:
|
|
47
47
|
'Write a context entry for the payments domain, there is no canon/context page for it yet.',
|
|
48
|
-
expect: 'draft-
|
|
48
|
+
expect: 'draft-doc',
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
prompt:
|
|
52
52
|
'Draft a wireframe for the settings panel, nothing under canon/wireframes covers that surface yet.',
|
|
53
|
-
expect: 'draft-
|
|
53
|
+
expect: 'draft-doc',
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
prompt:
|
|
57
57
|
'Write a wiki reference page for Claude Code output styles, no page covers that subject yet.',
|
|
58
|
-
expect: 'draft-
|
|
58
|
+
expect: 'draft-doc',
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
prompt: 'Say what that dense answer actually means in plain terms.',
|
|
@@ -38,12 +38,6 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
|
|
|
38
38
|
'Fold what we decided this session into the context entries and mark off what shipped on the task board.',
|
|
39
39
|
expect: 'context-fold',
|
|
40
40
|
},
|
|
41
|
-
{
|
|
42
|
-
prompt:
|
|
43
|
-
'I typed the old fold skill name and it says it was renamed, where did it go?',
|
|
44
|
-
// The pointer answers under its old name on purpose. canon-keep-retired
|
|
45
|
-
expect: 'docs-fold',
|
|
46
|
-
},
|
|
47
41
|
{
|
|
48
42
|
prompt:
|
|
49
43
|
'Sketch out a plan for adding this new capability before we touch any code.',
|
|
@@ -143,16 +137,10 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
|
|
|
143
137
|
prompt: 'Turn this topic into a slide deck I can render.',
|
|
144
138
|
expect: 'draft-slides',
|
|
145
139
|
},
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
},
|
|
151
|
-
// Rot across documents nobody changed is what separates this from
|
|
152
|
-
// `standards-audit`, which is diff-scoped and reports a stated rule broken on
|
|
153
|
-
// a given line. It is also not `target-check`, which asks whether a document
|
|
154
|
-
// exists and holds its sections rather than whether it still describes the
|
|
155
|
-
// tree.
|
|
140
|
+
// Rot across documents nobody changed is what this reads, rather than a
|
|
141
|
+
// stated rule broken on a given line. It is also not `target-check`, which
|
|
142
|
+
// asks whether a document exists and holds its sections rather than whether
|
|
143
|
+
// it still describes the tree.
|
|
156
144
|
{
|
|
157
145
|
prompt:
|
|
158
146
|
'Which of our docs have gone stale, grown too long, or ended up in the wrong file?',
|
|
@@ -230,10 +218,6 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
|
|
|
230
218
|
"Go through what's still unanswered in the intake folder and decide.",
|
|
231
219
|
expect: 'plan-intake-answer',
|
|
232
220
|
},
|
|
233
|
-
{
|
|
234
|
-
prompt: 'Check this markdown against the house style rules.',
|
|
235
|
-
expect: 'standards-audit',
|
|
236
|
-
},
|
|
237
221
|
{
|
|
238
222
|
prompt: 'Find the rough, unfinished-feeling spots in this interface.',
|
|
239
223
|
expect: 'ux-audit',
|
package/src/commands/slides.ts
CHANGED
|
@@ -119,9 +119,11 @@ export function register(program: Command): void {
|
|
|
119
119
|
|
|
120
120
|
/**
|
|
121
121
|
* The converter loads on demand, so no other command resolves pptxgenjs,
|
|
122
|
-
* jszip, or the token module at startup. A fallback
|
|
123
|
-
*
|
|
124
|
-
*
|
|
122
|
+
* jszip, or the token module at startup. A fallback, a refused link, chart, or
|
|
123
|
+
* effect, or a token the master fell back on reports one line each and keeps
|
|
124
|
+
* the exit at 0, as an unrecognized layout does on the markdown path, since the
|
|
125
|
+
* deck is written either way. A malformed `deck.json` refuses before any slide is laid
|
|
126
|
+
* out and exits 1.
|
|
125
127
|
*/
|
|
126
128
|
async function renderHtmlFolder(
|
|
127
129
|
sourceDir: string,
|
|
@@ -156,6 +158,24 @@ async function renderHtmlFolder(
|
|
|
156
158
|
`${GREY}│${NC} ${RED}✗${NC} slide ${slide} ${selector} link "${href}" left out: ${reason}\n`,
|
|
157
159
|
)
|
|
158
160
|
}
|
|
161
|
+
for (const { slide, selector, message } of result.refusedCharts) {
|
|
162
|
+
process.stderr.write(
|
|
163
|
+
`${GREY}│${NC} ${RED}✗${NC} slide ${slide} ${selector} chart left out: ${message}\n`,
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
for (const { slide, message } of result.refusedMotion) {
|
|
167
|
+
process.stderr.write(
|
|
168
|
+
`${GREY}│${NC} ${RED}✗${NC} slide ${slide} motion left out: ${message}\n`,
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
for (const { path, message } of result.refusedFonts) {
|
|
172
|
+
process.stderr.write(
|
|
173
|
+
`${GREY}│${NC} ${RED}✗${NC} font ${path} not embedded: ${message}\n`,
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
for (const notice of result.notices) {
|
|
177
|
+
process.stderr.write(`${GREY}│${NC} ${RED}✗${NC} ${notice}\n`)
|
|
178
|
+
}
|
|
159
179
|
if (result.mirrorPath) {
|
|
160
180
|
process.stderr.write(
|
|
161
181
|
`${GREY}│${NC} ${GREEN}✓${NC} mirrored to ${result.mirrorPath}\n`,
|
package/src/commands/sync.ts
CHANGED
|
@@ -168,6 +168,16 @@ function renderCheck(report: CheckReport): void {
|
|
|
168
168
|
logInfo('Move the content yourself. No sync command touches these.')
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
if (report.unmovedSurfaces.length > 0) {
|
|
172
|
+
logStep('Surfaces at the old .claude/ root')
|
|
173
|
+
for (const entry of report.unmovedSurfaces) {
|
|
174
|
+
logWarn(`${entry.rel} (moves to ${entry.movesTo})`)
|
|
175
|
+
}
|
|
176
|
+
logInfo(
|
|
177
|
+
'Rules glob the canon/ spelling only. Run `canon migrate surface-roots` to move these.',
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
171
181
|
renderSeeds(report)
|
|
172
182
|
|
|
173
183
|
if (report.superseded.length > 0) {
|