@erclx/canon 4.119.0 → 4.121.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 +2 -2
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/SKILL.md +29 -115
- package/claude/skills/auto-ship/references/draft-mark.md +30 -0
- package/claude/skills/auto-ship/references/failure-recovery.md +27 -0
- package/claude/skills/auto-ship/references/tier-failures.md +26 -0
- package/claude/skills/auto-ship/references/verb-absent.md +37 -0
- package/claude/skills/auto-ship/references/worktree-name.md +22 -0
- package/claude/skills/bash-script/SKILL.md +1 -1
- package/claude/skills/bash-script/references/patterns.md +0 -99
- package/claude/skills/bash-script/references/prompts.md +100 -0
- package/claude/skills/create-skill/SKILL.md +3 -2
- package/claude/skills/create-snippet/SKILL.md +1 -1
- package/claude/skills/create-standard/SKILL.md +1 -1
- package/claude/skills/design-extract/SKILL.md +1 -1
- package/claude/skills/design-taste/REQUIREMENT.md +2 -2
- package/claude/skills/docs-sync/SKILL.md +1 -1
- package/claude/skills/draft-context/SKILL.md +1 -1
- package/claude/skills/draft-docs/SKILL.md +1 -1
- package/claude/skills/draft-figure/SKILL.md +1 -1
- package/claude/skills/draft-readme/SKILL.md +1 -1
- package/claude/skills/draft-wiki/SKILL.md +1 -1
- package/claude/skills/draft-wireframes/SKILL.md +1 -1
- package/claude/skills/git-issue/SKILL.md +1 -1
- package/claude/skills/git-issue/references/issue.md +1 -1
- package/claude/skills/git-pr/REQUIREMENT.md +1 -0
- package/claude/skills/git-pr/SKILL.md +35 -5
- package/claude/skills/git-stage/SKILL.md +1 -1
- package/claude/skills/memory-capture/SKILL.md +1 -1
- package/claude/skills/restate-plainly/REQUIREMENT.md +1 -1
- package/claude/skills/review-address/SKILL.md +4 -3
- package/claude/skills/review-branch/REQUIREMENT.md +1 -0
- package/claude/skills/review-branch/SKILL.md +5 -6
- package/claude/skills/review-craft/REQUIREMENT.md +43 -0
- package/claude/skills/review-craft/SKILL.md +50 -0
- package/claude/skills/review-craft/references/security.md +21 -0
- package/claude/skills/review-craft/references/ui.md +72 -0
- package/claude/skills/review-pr/REQUIREMENT.md +1 -0
- package/claude/skills/review-pr/SKILL.md +14 -243
- package/claude/skills/review-pr/references/close-out.md +30 -0
- package/claude/skills/review-pr/references/post.md +145 -0
- package/claude/skills/review-pr/references/scope.md +82 -0
- package/claude/skills/role-orchestrator/REQUIREMENT.md +9 -16
- package/claude/skills/role-orchestrator/SKILL.md +9 -153
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +4 -193
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +22 -0
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +85 -0
- package/claude/skills/role-orchestrator/references/orchestrator-output.md +61 -0
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +56 -0
- package/claude/skills/role-orchestrator/references/orchestrator-review-fallback.md +18 -0
- package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +1 -1
- package/claude/skills/role-planner/REQUIREMENT.md +2 -2
- package/claude/skills/standards-audit/SKILL.md +1 -1
- package/claude/skills/write-human/REQUIREMENT.md +7 -4
- package/claude/skills/write-human/SKILL.md +4 -2
- package/claude/skills/write-human/references/machine-tells.md +1 -1
- package/claude/skills/write-human/references/source-material.md +5 -2
- package/docs/agents/audits.md +1 -1
- package/docs/agents/commands.md +3 -2
- package/docs/agents/counts.md +1 -1
- package/docs/agents/index.md +8 -3
- package/docs/agents/markdown-audit.md +13 -19
- package/docs/agents/pr-evidence.md +19 -3
- package/docs/agents/pr-local.md +105 -0
- package/docs/agents/pr-preview.md +2 -2
- package/docs/agents/records-push.md +61 -0
- package/docs/agents/records-validate.md +73 -0
- package/docs/agents/records.md +3 -119
- package/docs/agents/sessions-transfer.md +91 -0
- package/docs/agents/sessions.md +3 -82
- package/docs/agents/skills-audit.md +2 -2
- package/docs/agents/teach-authoring.md +112 -0
- package/docs/agents/teach.md +3 -103
- package/docs/target-projects.md +2 -2
- package/docs/workflow/ai-workflow.md +2 -1
- package/docs/workflow/visual-design-workflow.md +1 -1
- package/governance/rules/claude/500-prose.md +1 -1
- package/governance/rules/claude/501-markdown.md +3 -3
- package/governance/rules/claude/570-skill.md +2 -1
- package/package.json +1 -1
- package/scripts/core/check-ignore-parity.sh +1 -1
- package/scripts/lib/sandbox-git.sh +1 -1
- package/src/autoship/paths.ts +3 -2
- package/src/claude/cases/workflow.ts +5 -0
- package/src/commands/audits.ts +2 -2
- package/src/commands/markdown.ts +7 -9
- package/src/commands/pr.ts +331 -2
- package/src/context/classify/extract.ts +2 -2
- package/src/counts/scan.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/gate/measures.ts +4 -4
- package/src/gate/stages.ts +2 -3
- package/src/markdown/bans.ts +11 -68
- package/src/markdown/gate.ts +1 -1
- package/src/markdown/scan.ts +7 -88
- package/src/pr/evidence.ts +42 -2
- package/src/pr/local.ts +125 -0
- package/standards/docs.md +1 -1
- package/standards/index.md +2 -1
- package/standards/markdown.md +5 -7
- package/standards/pr.md +1 -1
- package/standards/publish.md +1 -1
- package/standards/readme.md +2 -2
- package/standards/skill-requirement.md +72 -0
- package/standards/skill.md +34 -152
- package/tooling/astro/reference.md +1 -1
- package/tooling/base/configs/.github/workflows/pr-local-preview.yml +32 -0
- package/tooling/base/configs/scripts/verify.sh +2 -2
- package/tooling/base/seeds/canon/context/development.md +1 -1
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +5 -6
package/docs/agents/teach.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Teach
|
|
3
|
-
description: Listing learning workspaces with what their records schedule next, opening one with its required files, recording sources and glossary terms,
|
|
3
|
+
description: Listing learning workspaces with what their records schedule next, opening one with its required files, recording sources and glossary terms, where the lesson authoring verbs are described, the refusal reasons, and why every write here runs through a verb
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Teach
|
|
@@ -110,109 +110,9 @@ A term already defined is refused rather than replaced. A definition the subject
|
|
|
110
110
|
|
|
111
111
|
The entry lands as the standard's shape, leading with the term as a bolded span. A definition not ending in sentence punctuation is terminated before the citation is appended, so a bare phrase does not run into the sentence naming where the term first appears.
|
|
112
112
|
|
|
113
|
-
## Lesson
|
|
113
|
+
## Lesson, render, and nav
|
|
114
114
|
|
|
115
|
-
`canon teach lesson`
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
canon teach lesson regular-expressions \
|
|
119
|
-
--slug capture-groups \
|
|
120
|
-
--questions 3 \
|
|
121
|
-
--options 4
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
| Option | Behavior |
|
|
125
|
-
| ----------------- | --------------------------------------------------------- |
|
|
126
|
-
| `--slug <kebab>` | The lesson's own topic, required |
|
|
127
|
-
| `--questions <n>` | How many questions the quiz carries, required |
|
|
128
|
-
| `--options <n>` | How many options each question carries, defaulting to `4` |
|
|
129
|
-
| `--json` | Emit a machine-readable record on stdout |
|
|
130
|
-
| `--root <path>` | Teach root, defaulting to the main worktree |
|
|
131
|
-
|
|
132
|
-
It reports three things. `lesson` is the numbered path the lesson takes, derived from the highest ordinal already in `lessons/` the way an open derives a workspace ordinal. `success` carries the mission's success lines, so a session reports progress against the exit criteria without a second read of `MISSION.md`. `quiz` carries one entry per question.
|
|
133
|
-
|
|
134
|
-
A lesson written against this record carries its chrome as four empty marker pairs rather than hand-composed markup: `canon:teach:style`, `canon:teach:header`, `canon:teach:footnav`, and `canon:teach:scripts`. `canon teach nav`, below, fills them from what the workspace holds on disk.
|
|
135
|
-
|
|
136
|
-
`canon teach stylesheet <topic>` writes the pair every lesson in the workspace renders through, seeded from the design source so a workspace renders in the system every other surface does. The two halves are written on different terms. `assets/base.css` holds the generated design layer and is rewritten on every run, which is the only way a change to the shared chrome reaches a workspace that already exists. `assets/course.css` is the half a workspace owns, so it refuses to overwrite, reporting `written` as false where the workspace already carries one, and `--force` takes the seed back over it. Each workspace used to carry a hand-authored palette, which is how the course styling forked once per workspace, so a lesson adds its own rules under the seed and reaches a value through its custom property rather than restating the hex.
|
|
137
|
-
|
|
138
|
-
Each `quiz` entry carries `order`, the authored option indices in presentation order where index `0` is the correct answer, and `answer`, the one-based position that answer lands in. Both travel together because a caller deriving the position itself is a caller that can derive it wrongly.
|
|
139
|
-
|
|
140
|
-
The order is drawn here rather than instructed, and that is the point of the verb. An author told to vary the position still varies it by judgment, and the judgment settles on the first slot, which is the defect this design departs from. The draw is uniform over the options, so the position carries no information about which answer is correct.
|
|
141
|
-
|
|
142
|
-
## Render
|
|
143
|
-
|
|
144
|
-
`canon teach render` renders a lesson body's structural blocks to HTML, through the four lesson components. It takes no topic and no `--root`, since the verb is a stateless transform reading nothing off a workspace on disk.
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
echo '[{"type":"heading","level":1,"text":"Compass bearings"}]' | canon teach render --json
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
| Option | Behavior |
|
|
151
|
-
| -------- | ---------------------------------------- |
|
|
152
|
-
| `--json` | Emit a machine-readable record on stdout |
|
|
153
|
-
|
|
154
|
-
It reads a JSON array of blocks from stdin, each a `heading`, `paragraph`, `list`, `refs`, or `raw` block, and reports `{ ok: true, html }` on `--json` or the bare rendered HTML on stdout otherwise. Content none of the components can express takes a `raw` block, carrying its own HTML verbatim and unescaped, which is the shape the quiz and the teach-back block travel in.
|
|
155
|
-
|
|
156
|
-
A citation takes two shapes. A `paragraph` carries an optional `cites` array of reference numbers, rendered as `sup.cite` markers after its text. The one `refs` block carries `items` of `{ title, url?, note? }`, rendered as `ol.refs` and numbered from 1, so cite `1` links to the first item.
|
|
157
|
-
|
|
158
|
-
```json
|
|
159
|
-
[
|
|
160
|
-
{ "type": "paragraph", "text": "North is fixed.", "cites": [1] },
|
|
161
|
-
{
|
|
162
|
-
"type": "refs",
|
|
163
|
-
"items": [{ "title": "Compass manual", "url": "https://example.com" }]
|
|
164
|
-
}
|
|
165
|
-
]
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
It refuses `bad-input` on empty stdin, on malformed JSON, on stdin that does not parse to an array, and on a block carrying an unrecognized `type` or a field of the wrong shape for its type, naming the block's index in the message. Citations add four refusals, each naming the offending block: a cite that resolves to no reference, `cites` on a lede paragraph, a second `refs` block, and a reference `url` that is not `http` or `https`.
|
|
169
|
-
|
|
170
|
-
## Nav
|
|
171
|
-
|
|
172
|
-
`canon teach nav` rewrites the teach-root listing, a workspace's contents page, and each of its lessons' chrome, from what the workspace holds on disk.
|
|
173
|
-
|
|
174
|
-
```bash
|
|
175
|
-
canon teach nav
|
|
176
|
-
canon teach nav regular-expressions --json
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
| Option | Behavior |
|
|
180
|
-
| --------------- | ------------------------------------------------- |
|
|
181
|
-
| `[topic]` | Workspace folder or topic, scoping the run to one |
|
|
182
|
-
| `--json` | Emit a machine-readable record on stdout |
|
|
183
|
-
| `--root <path>` | Teach root, defaulting to the main worktree |
|
|
184
|
-
|
|
185
|
-
With no topic it rewrites every workspace. The teach-root listing is always rewritten regardless, since it reports on every workspace and a scoped run leaving it stale would be a second kind of drift this verb exists to end.
|
|
186
|
-
|
|
187
|
-
A lesson carries its chrome as four marker pairs the authoring skill writes empty: `canon:teach:style`, `canon:teach:header`, `canon:teach:footnav`, and `canon:teach:scripts`. This verb splices each one from the current workspace state, embedding the toolkit's favicon, the shared stylesheet, and the script that settles the course panel before the page paints, rebuilding the course sidebar, the breadcrumb and jump menus, the prev/next footer nav, and the behavior scripts. It leaves the authored `<h1>`, lede, body, and quiz between the header and the footnav as written, with two exceptions. It wraps them in `<main>` when the lesson holds none, since the column width hangs off that element, and a lesson that already carries a `<main>` keeps its own.
|
|
188
|
-
|
|
189
|
-
It also links each "lesson NNNN" mention in that region to the lesson file in the same workspace carrying that number, skipping text inside `a`, `code`, `pre`, `script`, `style`, `label`, `summary`, and comments. A link the verb writes carries `data-lesson-ref`, and it is the only kind the verb rewrites: every run points one at the current filename for its number, or unwraps it to plain text once that number names no lesson. A link an author wrote is never touched.
|
|
190
|
-
|
|
191
|
-
Every workspace label in that chrome, being the breadcrumb, the sidebar heading, the workspace switcher, and the root listing's row, reads the mission's `title` and falls back to the folder topic in sentence case where the mission names none.
|
|
192
|
-
|
|
193
|
-
It also deletes two links a session used to write by hand into a lesson's `<head>`, each matched as its exact string: the old icon link and `<link rel="stylesheet" href="../assets/course.css" />`. The page keeps only the icon and the stylesheets the `style` region carries. Any other link an author wrote stays.
|
|
194
|
-
|
|
195
|
-
A workspace carrying no `course.css` gets its stylesheet pair seeded first, so the contents page it links is never unstyled, and an existing `course.css` is never overwritten. The `style` region links `assets/base.css` ahead of an embedded copy of `course.css`, so the workspace's own rules still win the cascade. The embedded copy drops the seed's `@import` line, which resolved against the lesson's own folder and never loaded anything, and the link is what reaches the base sheet in its place. A workspace with no `assets/base.css`, one holding a hand-authored `course.css` from before the seed, gets no link rather than one pointing at a missing file.
|
|
196
|
-
|
|
197
|
-
That seeding fires on the absent file alone, so a workspace already holding a `course.css` has neither half rewritten here. A change to the shared chrome therefore takes `canon teach stylesheet <topic>` per workspace, which rewrites `assets/base.css`, and every lesson picks it up through its link with no run of this verb. Running this one alone leaves every lesson on the `base.css` the workspace already holds, and nothing reports it. Only an edit to a workspace's own `course.css` needs this verb, since that half is embedded.
|
|
198
|
-
|
|
199
|
-
A lesson missing one of the four marker pairs is refused by name rather than rewritten, and every other lesson in the run still rewrites. The record's `skipped` list carries the refused files and which marker each is missing.
|
|
200
|
-
|
|
201
|
-
A mention whose number names no lesson in its workspace stays plain text and lands in the record's `unresolved` list, one `{ file, lesson }` entry per distinct number per lesson, with `file` relative to the root the way a `skipped` entry is. The lesson still rewrites and counts toward `lessons`, and the exit stays 0. A mention of the lesson's own number stays plain and is not reported, and a refused lesson reports nothing.
|
|
202
|
-
|
|
203
|
-
The `style` region carries the quiz stepper after the workspace stylesheet, for every lesson but the one shape named three paragraphs down, so it wins the cascade at equal specificity and reaches a workspace seeded before it existed. The stepper is CSS over the radio inputs a quiz is written from: it hides every question that follows one holding no checked input, and hides a question's feedback until that question does. The general sibling combinator is what keeps that from depending on the markup contract holding, since it selects the same questions as the adjacent one for a quiz written correctly and goes on gating when anything sits between two of them, where the adjacent one matches nothing and shows them all at once. Gating there rather than in a script is what keeps a later stem from answering an earlier question with nothing to bind, and the whole block sits inside `@supports selector(:has(*))`, so an engine without `:has()` renders every question rather than a stepper showing nothing. Feedback there follows the workspace stylesheet, shown by one that says nothing about `.fb` and hidden by one grown under the retired script.
|
|
204
|
-
|
|
205
|
-
The block hides and shows and sets nothing else, which leaves a workspace's own layout for a question and its own appearance for an option and a feedback panel. The one value it names is `display: block` on revealed feedback, since every stylesheet grown under the retired script carries `.fb { display: none }` and nothing adds the class that used to reveal it.
|
|
206
|
-
|
|
207
|
-
One detector decides both regions. A lesson carrying `<button class="opt"`, the shape written before the stepper, takes the feedback script and no stepper, and every other lesson takes the stepper and no script. That is a detector rather than a mode, since a lesson has one shape or the other, and removing the script outright would leave the lessons already written showing no feedback at all.
|
|
208
|
-
|
|
209
|
-
Splicing the stepper into a lesson of either shape was measured against a browser and reverted. Its rules match a button question, which can never hold a checked radio, so a lesson given both hides every question past the first for good and outranks the class the script reveals feedback with. Nothing else caught that: the markup is valid, the splice succeeds, and the page renders.
|
|
210
|
-
|
|
211
|
-
### Reference pages
|
|
212
|
-
|
|
213
|
-
Each reference page is rendered to a `reference/<slug>.html` sibling carrying the same chrome, and the contents page links that sibling rather than the markdown, which `canon serve` hands over as plain text. The render drops the frontmatter, turns tables into `<table>` markup, and escapes raw HTML written in the markdown rather than passing it through. A body with no H1 gets one from the frontmatter `title`. A relative link to another reference page's markdown points at that page's `.html` sibling, and one to the workspace `GLOSSARY.md` points at the glossary on the contents page, `../index.html#gloss`. Every other link, such as `../RESOURCES.md`, stays as written. The markdown file is never touched.
|
|
214
|
-
|
|
215
|
-
Every rendered page carries a `<meta name="generator" content="canon teach nav">` tag. A `.html` file under `reference/` whose markdown is gone is deleted when it carries that tag, and a hand-written HTML file there, carrying none, is left alone. The record's `reference` field counts the pages rendered. On a Bun with no `Bun.markdown`, each reference page lands in `skipped` with `Bun.markdown` as what is missing, and the rest of the run goes on.
|
|
115
|
+
`canon teach lesson`, `canon teach render`, and `canon teach nav` build and splice a lesson rather than editing a workspace's records. They are in `teach-authoring.md`.
|
|
216
116
|
|
|
217
117
|
## Opening a workspace
|
|
218
118
|
|
package/docs/target-projects.md
CHANGED
|
@@ -102,7 +102,7 @@ Run `canon tooling list --json` and `canon gov list --json` to see the current c
|
|
|
102
102
|
|
|
103
103
|
`canon init` installs base tooling, Claude workflow, and governance, and scaffolds `.claude/wiki/`. Governance defaults to the `base` stack, so a bare init carries the rules that route a project. Pass `--stack <name>` to install a framework stack instead.
|
|
104
104
|
|
|
105
|
-
No standard is written into the project. Each governance rule's authority line names `canon standards <name>`, which answers from the corpus inside the CLI's own package, and every toolkit skill names the copy in its own plugin root. `canon markdown audit` needs no standard at all, its ban
|
|
105
|
+
No standard is written into the project. Each governance rule's authority line names `canon standards <name>`, which answers from the corpus inside the CLI's own package, and every toolkit skill names the copy in its own plugin root. `canon markdown audit` needs no standard at all, its ban set and checkpoints shipping with the package as data.
|
|
106
106
|
|
|
107
107
|
No snippet is written into the project either. `claude/snippets` in the plugin cache symlinks to the toolkit's own `snippets/`, so a session reaches one at its `@` reference with no install step, the same live resolution `claude/standards` gives a rule's authority line.
|
|
108
108
|
|
|
@@ -350,5 +350,5 @@ Sync also refuses a target whose working tree is dirty, so commit or stash befor
|
|
|
350
350
|
|
|
351
351
|
- [agents](agents/index.md): CLI flags, exit codes, and JSON output shapes
|
|
352
352
|
- [AI workflow](workflow/ai-workflow.md): feature-development loop inside a toolkit-managed project
|
|
353
|
-
- [tooling](../canon/context/tooling.md), [governance](../canon/context/governance/index.md), [claude plugin](../canon/context/claude-plugin/index.md), [indexes](../canon/context/indexes.md), [snippets](../canon/context/snippets.md), [standards](../canon/context/standards/index.md): per-domain mechanics
|
|
353
|
+
- [tooling](../canon/context/tooling/index.md), [governance](../canon/context/governance/index.md), [claude plugin](../canon/context/claude-plugin/index.md), [indexes](../canon/context/indexes.md), [snippets](../canon/context/snippets.md), [standards](../canon/context/standards/index.md): per-domain mechanics
|
|
354
354
|
- [sandbox](../canon/context/sandbox/index.md): scenario catalog for verifying domain flows
|
|
@@ -109,7 +109,7 @@ An execution that picks other than the suggestion rewrites the `- Suggested:` li
|
|
|
109
109
|
|
|
110
110
|
`canon records push` carries these folders off the disk they live on, and `canon records pull` brings them back. Every top-level entry under `.canon/` is backed except `tmp`, `ordinal-locks`, and `.records.git`, so a folder added later enters the payload on its own rather than waiting on a name written into a list. Push names each folder it carries the first time it sees it, which is what keeps a stray folder visible instead of silently entering the payload. It refuses the whole push, naming each path, when a new or changed file is over 25 MB or carries a credential `canon secrets scan` would report. The history lives in a second git directory at `.canon/.records.git` with `.canon/` as its work tree, so every path a task file cites stays where it is.
|
|
111
111
|
|
|
112
|
-
A person points it at a private repository once and both verbs refuse until they have, and `push` refuses when that origin is also a remote of the project, since the payload is the memory pen and the groundwork trails. `.husky/post-merge` runs the push after its archive loop, on every merge rather than only on one that closed a task. See [records](../agents/records.md) for the refusal table.
|
|
112
|
+
A person points it at a private repository once and both verbs refuse until they have, and `push` refuses when that origin is also a remote of the project, since the payload is the memory pen and the groundwork trails. `.husky/post-merge` runs the push after its archive loop, on every merge rather than only on one that closed a task. See [records push](../agents/records-push.md) for the refusal table.
|
|
113
113
|
|
|
114
114
|
`canon records size` reports what each of these folders holds, heaviest first, along with `.canon/tmp`. Each row carries the file count, the bytes, how many files were written in the last 7 and 30 days, and the dates of the least and most recently written one. Nothing fails on a number, because a record folder has no correct size. What the verb replaces is a reading somebody had to remember to take: the memory pen went from 44 entries to 236 between two counts made by hand a fortnight apart, and nothing reported the rate in between.
|
|
115
115
|
|
|
@@ -231,6 +231,7 @@ This section is the corpus the coverage claim is measured against: every name `c
|
|
|
231
231
|
| `canon:project-commands` | When the project's own command needs running |
|
|
232
232
|
| `canon:test-first` | Before implementing a planned change, to run its test red, green, then refactor |
|
|
233
233
|
| `canon:test-craft` | When writing or changing any test, to pick its layer and filter what it asserts |
|
|
234
|
+
| `canon:review-craft` | When reviewing a change, for what to look for and how much evidence a finding needs |
|
|
234
235
|
| `canon:systematic-debugging` | When a test fails or a bug surfaces, to force root cause first |
|
|
235
236
|
| `canon:ui-checklist` | After a UI change, to write what to look at and name what ships untested |
|
|
236
237
|
|
|
@@ -22,7 +22,7 @@ Claude Code reads both and writes the implementation. Works for CLI tools, inter
|
|
|
22
22
|
|
|
23
23
|
The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table template with a starting set of roles, and `standards/design.md` carries the same tables under `## Template` with placeholder rows. The column headers are what the renderer parses, so they stay verbatim in either, while the rows and values are the project's own.
|
|
24
24
|
|
|
25
|
-
The `canon:design-extract` skill drafts the file, sourcing tokens from a project's existing prose and CLI UI surfaces, or proposing them from `canon/REQUIREMENTS.md` and a `## Personality` paragraph when no UI code exists yet. `canon design render` writes an HTML plus CSS preview to `.canon/tmp/render/design/` for eyeballing the current system without leaving Claude Code. See `canon/context/design.md`.
|
|
25
|
+
The `canon:design-extract` skill drafts the file, sourcing tokens from a project's existing prose and CLI UI surfaces, or proposing them from `canon/REQUIREMENTS.md` and a `## Personality` paragraph when no UI code exists yet. `canon design render` writes an HTML plus CSS preview to `.canon/tmp/render/design/` for eyeballing the current system without leaving Claude Code. See `canon/context/design/index.md`.
|
|
26
26
|
|
|
27
27
|
A project wanting a neutral starting point to override runs `canon design install`, which copies one stylesheet to `.claude/design/base.css` carrying an achromatic token set as custom properties and two components built on them. Greys run from near-black to near-white and the accent is monochrome, so the only palette the project renders is one it writes itself. That file is toolkit-owned and `canon design sync` refreshes it, so a project overrides a value in `.claude/design/project/` instead, which sync never touches. Nothing arrives without that install, and the two channels are independent: a record drafted by the extract skill is the project's own, and the installed stylesheet is the toolkit's.
|
|
28
28
|
|
|
@@ -12,4 +12,4 @@ paths:
|
|
|
12
12
|
- Load it before drafting a passage, not after revising one.
|
|
13
13
|
- Report it rather than proceeding silently when the skill does not resolve.
|
|
14
14
|
- Do not work these rules from memory.
|
|
15
|
-
-
|
|
15
|
+
- Punctuation, formatting, and file references are a separate topic. `501-markdown` routes them.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Route markdown edits to the markdown standard for headings, lists, punctuation,
|
|
2
|
+
description: Route markdown edits to the markdown standard for headings, lists, punctuation, and frontmatter wording
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.md'
|
|
5
5
|
---
|
|
@@ -8,7 +8,7 @@ paths:
|
|
|
8
8
|
|
|
9
9
|
## Authority
|
|
10
10
|
|
|
11
|
-
- Follow the markdown standard for headings, paragraph and list structure, code spans, punctuation, emphasis, file references,
|
|
12
|
-
- Read it before a substantial markdown edit. Do not work the banned
|
|
11
|
+
- Follow the markdown standard for headings, paragraph and list structure, code spans, punctuation, emphasis, file references, and the wording of a `title` or `description`. It is the single source. Read it with `canon standards markdown`.
|
|
12
|
+
- Read it before a substantial markdown edit. Do not work the banned characters from memory.
|
|
13
13
|
- Run `canon markdown audit <path>` after the edit, and rewrite the sentence carrying a hit rather than swapping the token for a near-synonym.
|
|
14
14
|
- Voice, rhythm, and sentence construction are a separate topic. `500-prose` routes them.
|
|
@@ -21,4 +21,5 @@ paths:
|
|
|
21
21
|
|
|
22
22
|
## Authority
|
|
23
23
|
|
|
24
|
-
- Follow the skill standard for skill structure, frontmatter fields, invocation rules
|
|
24
|
+
- Follow the skill standard for skill structure, frontmatter fields, and invocation rules. It is the single source. Read it with `canon standards skill`.
|
|
25
|
+
- Follow the skill requirement standard for the shape a `REQUIREMENT.md` states. Read it with `canon standards skill-requirement`.
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@ SECTION="# Claude"
|
|
|
19
19
|
# The diagrams divergence is the one that cost something. A target used to track
|
|
20
20
|
# its diagrams and keep the context audit's default coverage of them, and it now
|
|
21
21
|
# ignores them with the rest of its records, so that coverage is gone unless the
|
|
22
|
-
# project names the folder itself. `canon/context/tooling.md` carries the
|
|
22
|
+
# project names the folder itself. `canon/context/tooling/manifests.md` carries the
|
|
23
23
|
# narrative.
|
|
24
24
|
#
|
|
25
25
|
# An exception mechanism is not kept against a future divergence, because an
|
|
@@ -95,7 +95,7 @@ ensure_sandbox_anchor_repo() {
|
|
|
95
95
|
# nine to a pass against something that is not the anchor. Refusing is the safe
|
|
96
96
|
# default and creating is the opt-in, the shape `canon tooling sync --write`
|
|
97
97
|
# already sets. `canon records push` refuses outright for the reason
|
|
98
|
-
# `canon/context/development/
|
|
98
|
+
# `canon/context/development/records.md` records, so the two still differ.
|
|
99
99
|
# The sibling SANDBOX_ flags are presence tests, so any non-empty value turns
|
|
100
100
|
# them on. This one allowlists instead, because a presence test would have
|
|
101
101
|
# SANDBOX_ANCHOR_CREATE=false provisioning a repository. Both spellings are
|
package/src/autoship/paths.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* The surfaces where markdown states what an agent does, and the extensions
|
|
3
3
|
* that read as prose, held as data one command parses.
|
|
4
4
|
*
|
|
5
|
-
* Lifted verbatim in content from the list `auto-ship
|
|
6
|
-
*
|
|
5
|
+
* Lifted verbatim in content from the list `auto-ship` Step 6 carried, whose
|
|
6
|
+
* written fallback copy now sits in `auto-ship/references/verb-absent.md`,
|
|
7
|
+
* which a session was asked to apply by hand. It failed that
|
|
7
8
|
* application three times, so the set moved here and the body now calls a verb
|
|
8
9
|
* that reads it. Being machine-parsed makes it permanently exempt from any
|
|
9
10
|
* later design that folds a standard back into the surface citing it, per the
|
|
@@ -99,6 +99,11 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
|
|
|
99
99
|
'Look over everything that changed on this branch for bugs and edge cases.',
|
|
100
100
|
expect: 'review-branch',
|
|
101
101
|
},
|
|
102
|
+
{
|
|
103
|
+
prompt:
|
|
104
|
+
'What should a review of a change look for beyond bugs, and how much evidence does a finding need?',
|
|
105
|
+
expect: 'review-craft',
|
|
106
|
+
},
|
|
102
107
|
{
|
|
103
108
|
prompt: 'Draft me a script with beats for a screencast recording.',
|
|
104
109
|
expect: 'draft-screencast',
|
package/src/commands/audits.ts
CHANGED
|
@@ -76,8 +76,8 @@ export function register(program: Command): void {
|
|
|
76
76
|
' 3 an audit did not report, so the run measured less than the set',
|
|
77
77
|
'',
|
|
78
78
|
'It gates on exactly what already gates a push and on nothing new:',
|
|
79
|
-
'an unresolved context citation, a banned character,
|
|
80
|
-
'
|
|
79
|
+
'an unresolved context citation, a banned character, and a skill folder',
|
|
80
|
+
'carrying no REQUIREMENT.md. Every other measure is a',
|
|
81
81
|
'judgment a reader settles, and failing a push on one teaches',
|
|
82
82
|
'contributors to route around the stage.',
|
|
83
83
|
'',
|
package/src/commands/markdown.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function register(program: Command): void {
|
|
|
67
67
|
markdown
|
|
68
68
|
.command('audit')
|
|
69
69
|
.description(
|
|
70
|
-
'Fail on a banned character,
|
|
70
|
+
'Fail on a banned character, and report bullet, paragraph, cadence, depth, and length',
|
|
71
71
|
)
|
|
72
72
|
.argument(
|
|
73
73
|
'[path...]',
|
|
@@ -82,8 +82,8 @@ export function register(program: Command): void {
|
|
|
82
82
|
'Exit codes:',
|
|
83
83
|
' 0 the audit completed with no gating finding',
|
|
84
84
|
' 1 refused, with the reason on stderr',
|
|
85
|
-
' 2 a banned character
|
|
86
|
-
'
|
|
85
|
+
' 2 a banned character is present, or a relative link resolves',
|
|
86
|
+
' to nothing on disk',
|
|
87
87
|
' 3 a shipped ban set is empty, so the run measured nothing',
|
|
88
88
|
'',
|
|
89
89
|
'A ban hit and a dead link are each a fact and gate unconditionally.',
|
|
@@ -192,8 +192,6 @@ async function runAudit(
|
|
|
192
192
|
unmatchedPaths: scope.unmatched,
|
|
193
193
|
bans: {
|
|
194
194
|
characters: bans.characters,
|
|
195
|
-
words: bans.words,
|
|
196
|
-
spellings: bans.spellings,
|
|
197
195
|
emptySets: empty,
|
|
198
196
|
},
|
|
199
197
|
checkpoints: {
|
|
@@ -284,19 +282,19 @@ function reportBans(
|
|
|
284
282
|
|
|
285
283
|
if (empty.length > 0) {
|
|
286
284
|
logWarn(
|
|
287
|
-
`Not measured. The shipped set is empty for: ${empty.join(', ')}. The
|
|
285
|
+
`Not measured. The shipped set is empty for: ${empty.join(', ')}. The set ships with the canon package, so an empty set is a defect in the build rather than a missing install.`,
|
|
288
286
|
)
|
|
289
287
|
return
|
|
290
288
|
}
|
|
291
289
|
|
|
292
290
|
logInfo(
|
|
293
|
-
`${plural(bans.characters.length, 'character')}
|
|
291
|
+
`${plural(bans.characters.length, 'character')} shipped with the canon package`,
|
|
294
292
|
)
|
|
295
293
|
logInfo(
|
|
296
294
|
'Frontmatter, fenced blocks, code spans, and link destinations are excluded.',
|
|
297
295
|
)
|
|
298
296
|
logInfo(
|
|
299
|
-
'
|
|
297
|
+
'Word bans, phrase bans, and every voice rule are guidance for the reader',
|
|
300
298
|
)
|
|
301
299
|
|
|
302
300
|
const carrying = reports
|
|
@@ -304,7 +302,7 @@ function reportBans(
|
|
|
304
302
|
.sort((a, b) => b.bans.length - a.bans.length)
|
|
305
303
|
|
|
306
304
|
if (carrying.length === 0) {
|
|
307
|
-
logInfo('No banned character
|
|
305
|
+
logInfo('No banned character.')
|
|
308
306
|
return
|
|
309
307
|
}
|
|
310
308
|
|