@erclx/canon 4.102.0 → 4.104.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/canon-cli/SKILL.md +3 -74
- package/claude/skills/canon-operator/REQUIREMENT.md +2 -2
- package/claude/skills/canon-operator/SKILL.md +5 -5
- package/claude/skills/canon-rollout/SKILL.md +7 -6
- package/claude/skills/design-taste/references/craft.md +1 -1
- package/claude/skills/design-taste/references/preflight.md +2 -2
- package/claude/skills/design-taste/references/tells.md +1 -1
- package/claude/skills/draft-readme/REQUIREMENT.md +2 -0
- package/claude/skills/draft-readme/SKILL.md +9 -1
- package/claude/skills/git-followup/SKILL.md +1 -1
- package/claude/skills/git-issue/SKILL.md +2 -2
- package/{standards → claude/skills/git-issue/references}/issue.md +3 -8
- package/claude/skills/git-pr/SKILL.md +2 -2
- package/claude/skills/index-lookup/REQUIREMENT.md +2 -2
- package/claude/skills/project-commands/REQUIREMENT.md +1 -1
- package/claude/skills/seed-sync/REQUIREMENT.md +1 -1
- package/claude/skills/target-check/REQUIREMENT.md +42 -0
- package/claude/skills/target-check/SKILL.md +91 -0
- package/claude/skills/target-check/references/domains.md +88 -0
- package/claude/skills/target-setup/REQUIREMENT.md +56 -0
- package/claude/skills/target-setup/SKILL.md +163 -0
- package/claude/skills/target-setup/references/detect.md +80 -0
- package/claude/skills/{setup-indexes/SKILL.md → target-setup/references/indexes.md} +59 -23
- package/claude/skills/target-setup/references/verify.md +95 -0
- package/claude/skills/ui-checklist/SKILL.md +17 -0
- package/docs/agents/commands.md +1 -1
- package/docs/agents/sandbox.md +1 -1
- package/docs/agents/scripting.md +3 -2
- package/docs/target-projects.md +13 -11
- package/docs/workflow/ai-workflow.md +19 -23
- package/governance/rules/ci/700-ci-workflow.md +11 -0
- package/governance/rules/ui/400-ui.md +0 -5
- package/governance/rules/ui/460-design-taste.md +1 -1
- package/governance/rules/ui/465-interface-casing.md +31 -0
- package/governance/stacks/astro.toml +1 -1
- package/governance/stacks/react.toml +1 -1
- package/package.json +1 -1
- package/scripts/core/regen-hero.sh +1 -1
- package/scripts/core/regen-web-previews.ts +1 -0
- package/src/claude/cases/setup.ts +20 -11
- package/src/commands/design.ts +8 -2
- package/src/commands/sync.ts +1 -1
- package/src/design/css.ts +5 -2
- package/src/design/render.ts +46 -6
- package/src/gate/measures.ts +57 -0
- package/src/gate/stages.ts +10 -14
- package/src/gov/list.ts +1 -1
- package/src/sandbox/census.ts +3 -3
- package/src/shipped/references.ts +1 -1
- package/standards/index.md +0 -1
- package/standards/readme.md +22 -3
- package/tooling/astro/manifest.toml +1 -0
- package/tooling/nextjs/manifest.toml +1 -0
- package/tooling/web/configs/.github/workflows/readme-screenshot.yml +110 -0
- package/tooling/web/configs/e2e/screenshot.ts +69 -15
- package/tooling/web/configs/scripts/lib/preview-server.sh +31 -0
- package/tooling/web/configs/scripts/readme-screenshot.sh +26 -0
- package/tooling/web/configs/scripts/screenshot.sh +1 -24
- package/tooling/web/manifest.toml +1 -0
- package/tooling/web/reference.md +6 -1
- package/claude/skills/setup-gov/REQUIREMENT.md +0 -37
- package/claude/skills/setup-gov/SKILL.md +0 -77
- package/claude/skills/setup-indexes/REQUIREMENT.md +0 -48
- package/claude/skills/setup-init/REQUIREMENT.md +0 -46
- package/claude/skills/setup-init/SKILL.md +0 -133
- package/claude/skills/setup-plugins/REQUIREMENT.md +0 -42
- package/claude/skills/setup-plugins/SKILL.md +0 -81
- package/claude/skills/setup-plugins/references/plugin-catalog.md +0 -53
- package/claude/skills/setup-smoke/REQUIREMENT.md +0 -38
- package/claude/skills/setup-smoke/SKILL.md +0 -53
- package/claude/skills/setup-verify/REQUIREMENT.md +0 -39
- package/claude/skills/setup-verify/SKILL.md +0 -51
- package/scripts/core/regen-tooling-paths.sh +0 -61
|
@@ -17,7 +17,7 @@ Consult before running an unfamiliar `canon` verb, before a sync or install, or
|
|
|
17
17
|
|
|
18
18
|
| Surface | Command | Effect on existing files |
|
|
19
19
|
| -------------------------------------------------------- | -------------------- | --------------------------------------------------------------------------- |
|
|
20
|
-
| Golden configs
|
|
20
|
+
| Golden configs | `canon tooling sync` | Overwritten once `--write` is passed. Local edits are lost. |
|
|
21
21
|
| Dictionary seeds (`.cspell/*.txt`) | `canon tooling sync` | Merged and sorted. Existing terms preserved. |
|
|
22
22
|
| Other seeds (`cspell.json`, `.lintstagedrc`, state docs) | `canon tooling sync` | Copy-once. Dropped on first install, untouched after. |
|
|
23
23
|
| Standards | none | Nothing installs. `canon standards <name>` reads and never writes. |
|
|
@@ -31,83 +31,12 @@ Consult before running an unfamiliar `canon` verb, before a sync or install, or
|
|
|
31
31
|
|
|
32
32
|
A golden config is any file a stack ships under `configs/`, and the category is wider than its name suggests. It carries the CI workflow, the git hooks, the end-to-end harness, the shell scripts under `scripts/`, and the editor settings, alongside the linters and compilers a reader expects. A stack inherits its parent's configs, so syncing `astro` also writes everything `web` and `base` hold.
|
|
33
33
|
|
|
34
|
-
Run `canon tooling diff <stack> <target>` for the list resolved against a real target. It reports every path, writes nothing, and exits 1 when any differs.
|
|
35
|
-
|
|
36
|
-
<!-- generated:tooling-paths -->
|
|
37
|
-
|
|
38
|
-
### astro
|
|
39
|
-
|
|
40
|
-
- `astro.config.mjs`
|
|
41
|
-
- `eslint.config.js`
|
|
42
|
-
- `playwright.config.ts`
|
|
43
|
-
- `src/components/dev/scenarios.astro`
|
|
44
|
-
- `tsconfig.json`
|
|
45
|
-
- `vitest.config.ts`
|
|
46
|
-
|
|
47
|
-
### base
|
|
48
|
-
|
|
49
|
-
- `.editorconfig`
|
|
50
|
-
- `.github/pull_request_template.md`
|
|
51
|
-
- `.github/workflows/phase-label-gate.yml`
|
|
52
|
-
- `.github/workflows/verify.yml`
|
|
53
|
-
- `.husky/commit-msg`
|
|
54
|
-
- `.husky/post-merge`
|
|
55
|
-
- `.husky/post-rewrite`
|
|
56
|
-
- `.husky/pre-commit`
|
|
57
|
-
- `.husky/pre-push`
|
|
58
|
-
- `.prettierrc`
|
|
59
|
-
- `.shellcheckrc`
|
|
60
|
-
- `.vscode/extensions.json`
|
|
61
|
-
- `.vscode/settings.json`
|
|
62
|
-
- `commitlint.config.js`
|
|
63
|
-
- `scripts/verify.sh`
|
|
64
|
-
|
|
65
|
-
### cloudflare
|
|
66
|
-
|
|
67
|
-
- `.github/workflows/deploy.yml`
|
|
68
|
-
|
|
69
|
-
### nextjs
|
|
70
|
-
|
|
71
|
-
- `eslint.config.js`
|
|
72
|
-
- `next.config.ts`
|
|
73
|
-
- `playwright.config.ts`
|
|
74
|
-
- `vitest.config.ts`
|
|
75
|
-
|
|
76
|
-
### python
|
|
77
|
-
|
|
78
|
-
- `.coveragerc`
|
|
79
|
-
- `.python-version`
|
|
80
|
-
- `mypy.ini`
|
|
81
|
-
- `pytest.ini`
|
|
82
|
-
- `ruff.toml`
|
|
83
|
-
- `scripts/verify.sh`
|
|
84
|
-
|
|
85
|
-
### vite-react
|
|
86
|
-
|
|
87
|
-
- `playwright.config.ts`
|
|
88
|
-
- `tsconfig.json`
|
|
89
|
-
- `vite.config.ts`
|
|
90
|
-
- `vitest.config.ts`
|
|
91
|
-
|
|
92
|
-
### web
|
|
93
|
-
|
|
94
|
-
- `.github/workflows/verify.yml`
|
|
95
|
-
- `.vscode/extensions.json`
|
|
96
|
-
- `.vscode/settings.json`
|
|
97
|
-
- `e2e/home.spec.ts`
|
|
98
|
-
- `e2e/screenshot.ts`
|
|
99
|
-
- `eslint.config.js`
|
|
100
|
-
- `scripts/screenshot.sh`
|
|
101
|
-
- `scripts/verify.sh`
|
|
102
|
-
- `scripts/worktree-port.sh`
|
|
103
|
-
- `src/test/setup.ts`
|
|
104
|
-
|
|
105
|
-
<!-- /generated:tooling-paths -->
|
|
34
|
+
No list of those paths ships in this body, since a copy would go stale on a different cadence than the stacks. Run `canon tooling diff <stack> <target>` for the list resolved against a real target. It reports every path, writes nothing, and exits 1 when any differs. A binary older than that verb answers the same question through `canon tooling sync <stack> <target> --check`, which names each file it would replace.
|
|
106
35
|
|
|
107
36
|
## Rules
|
|
108
37
|
|
|
109
38
|
- `canon tooling sync` writes nothing until `--write` is passed. A headless run without it reports and exits 1, so a script that forgets the flag fails rather than silently skipping the sync.
|
|
110
|
-
- Run `--check` first when the project carries local edits to
|
|
39
|
+
- Run `--check` first when the project carries local edits to a config the stack ships. The report names each file it would replace, which is the warning the user needs before the write.
|
|
111
40
|
- An interactive run still prompts. `--write` skips the prompt, and `--check` refuses to write even with a TTY.
|
|
112
41
|
- Seeds are user-owned. Dictionary `.txt` files merge and sort. Other seeds are copy-once, so re-seeding a structured file means deleting it and syncing again.
|
|
113
42
|
- No command writes a standard into a project. A `.claude/standards/` folder from an older toolkit is inert, and deleting it costs nothing.
|
|
@@ -53,9 +53,9 @@ The last failure is a section no route reaches. `## Route` maps an intent or a d
|
|
|
53
53
|
|
|
54
54
|
## Out of scope
|
|
55
55
|
|
|
56
|
-
- First-time scaffold of a fresh project: `setup
|
|
56
|
+
- First-time scaffold of a fresh project: `target-setup`
|
|
57
57
|
- Seed and preamble drift in installed files: `seed-sync`
|
|
58
|
-
- Governance rule install and index bootstrap: `setup
|
|
58
|
+
- Governance rule install and index bootstrap: `target-setup`, on its `gov` and `indexes` phases
|
|
59
59
|
- What a given sync overwrites once it runs: `canon-cli`
|
|
60
60
|
|
|
61
61
|
That last contract carries no row for the governance install this skill routes to, so the overwrite `Must` above reads nothing at one of its own destinations. The row belongs to the skill owning the table. This file records the silence rather than answering it, since a rule written here for a silent contract teaches a session that silence means safe.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: canon-operator
|
|
3
|
-
description: Front door to the toolkit in a target project. Orients on the toolkit's own docs and live `canon` catalogs, then runs or routes any toolkit operation from a plain-language intent. Use when you want one entry point instead of picking a specific setup or sync skill, or when asked to "use the toolkit", "what can the toolkit do", "sync my standards", "install rules", or "help me set up this project". User-invoked only. Defers first-time scaffold to setup
|
|
3
|
+
description: Front door to the toolkit in a target project. Orients on the toolkit's own docs and live `canon` catalogs, then runs or routes any toolkit operation from a plain-language intent. Use when you want one entry point instead of picking a specific setup or sync skill, or when asked to "use the toolkit", "what can the toolkit do", "sync my standards", "install rules", or "help me set up this project". User-invoked only. Defers first-time scaffold to setup and seed drift to seed-sync.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -47,9 +47,9 @@ The two can name different rows, and a reply answers both rather than picking on
|
|
|
47
47
|
- Anything in `superseded`: name which files and what replaced them, then hand off to `migration-superseded`. Both skills propose, so neither moves nor deletes the file
|
|
48
48
|
- A folder in `unclaimed`: name it and the attribution it carries. No command moves it and the content may be the project's own, so the decision is the user's
|
|
49
49
|
|
|
50
|
-
- First-time scaffold of a fresh project: hand off to `setup
|
|
51
|
-
- Governance rules for the project stack: hand off to `setup
|
|
52
|
-
- Bootstrap the `index.md` system: hand off to `setup
|
|
50
|
+
- First-time scaffold of a fresh project: hand off to `target-setup`
|
|
51
|
+
- Governance rules for the project stack: hand off to `target-setup`, which installs them alone on its `gov` phase
|
|
52
|
+
- Bootstrap the `index.md` system: hand off to `target-setup`, which bootstraps it on its `indexes` phase
|
|
53
53
|
- Seed or standards drift in `CLAUDE.md` or `.claude/` preambles: hand off to `seed-sync`
|
|
54
54
|
- Install one snippet, standard, or rule: run the domain `install` command
|
|
55
55
|
- Sync one domain or every installed domain: run `canon <domain> sync` or `canon sync`
|
|
@@ -104,5 +104,5 @@ The comparison needs the earlier report. When `## Diagnose` was skipped because
|
|
|
104
104
|
## Boundaries
|
|
105
105
|
|
|
106
106
|
- Run `canon`. Never reimplement its install or sync logic, and never edit managed files like rules, configs, or seeds by hand.
|
|
107
|
-
- Hand off the deep flows. Do not duplicate `setup
|
|
107
|
+
- Hand off the deep flows. Do not duplicate `target-setup` detection or `seed-sync` part-diffing inline.
|
|
108
108
|
- Resolve names from catalogs at runtime. A hardcoded name is a bug.
|
|
@@ -88,7 +88,7 @@ Report each dispatch by naming the target, the clone, the branch, the model, and
|
|
|
88
88
|
|
|
89
89
|
1. Address every finding whatever its severity. A minor is a finding, and a reviewer calling one non-blocking does not close the pass that raised it.
|
|
90
90
|
2. Resolve who holds the branch before dispatching anybody. Run `canon sessions list --branch chore/agents --repository <clone> --json` and read the count rather than the first row.
|
|
91
|
-
- A live session holds it: send that session the findings and name `canon:review-address` for it to run, which is step
|
|
91
|
+
- A live session holds it: send that session the findings and name `canon:review-address` for it to run, which is step 7 of `## The worker role` and the step that session already stands at. Never name this skill in that message. This body carries `disable-model-invocation: true`, which blocks the `Skill` tool rather than only suppressing an auto-trigger, and a session acting on an inbound message reaches a skill that way and no other, so a message naming this one halts the address leg with the branch built and the findings unread. A launch prompt is the one route to a flagged body, which is why the dispatch above names this skill and this message must not. Assuming the worker was gone is what one hand-driven pass got wrong. All four sessions that opened those pull requests were still alive holding their worktrees hours later, and of two fresh addressers sent over them, one refused on the worktree lock and one cut a second worktree on the same branch, which would have put two sessions pushing to one ref.
|
|
92
92
|
- No live session holds it: dispatch a fresh worker into that clone and brief it with the findings, since it holds none of the reasoning behind the diff.
|
|
93
93
|
- More than one row: report the ambiguity and stop rather than picking among candidates.
|
|
94
94
|
3. Re-review when the answer lands, scoped to the commits added since. A worker's reply never closes a target. One fix for two minor findings closed both and introduced four more, every one of them in prose that fix added, and a loop trusting the reply merges that.
|
|
@@ -101,11 +101,12 @@ One session, one target, from the worktree entry to the merge of the branch it o
|
|
|
101
101
|
|
|
102
102
|
1. Confirm the clone is current. Fetch, then compare against the origin's default branch. Report a checkout that is behind and stop, rather than branching from a stale base.
|
|
103
103
|
2. Enter a worktree. Invoke `canon:session-worktree chore/agents`, which takes the branch as its tier 0 argument and enters a linked worktree inside this target. Branching in the checkout itself is what this avoids, since the operator may be working in it.
|
|
104
|
-
3.
|
|
105
|
-
4.
|
|
106
|
-
5.
|
|
107
|
-
6.
|
|
108
|
-
7.
|
|
104
|
+
3. Check what this target holds. Invoke `canon:target-check`, which reports per domain what the target carries against what the toolkit ships and repairs nothing. It runs before any repair so the wave reads one stated set of domains per target rather than whatever each session decided to examine.
|
|
105
|
+
4. Diagnose and repair. Invoke `canon:canon-operator`, which reads `canon sync --check . --json` and routes each finding to the command or the skill that owns it. Do not restate that routing here and do not edit a managed file by hand.
|
|
106
|
+
5. Commit and open the pull request through `canon:git-commit` and `canon:git-pr`, handing each the fixed shape above rather than taking the title the generator derives from the diff.
|
|
107
|
+
6. Announce as the pull request opens, carrying its URL, its number, and the branch, to whoever dispatched this session. That transition is the one moment only this session can observe.
|
|
108
|
+
7. Answer the review. Invoke `canon:review-address`, which pulls the findings and the CI state on this branch's open pull request, fixes each in the working tree, replies, and pushes. Answer every finding whatever its severity.
|
|
109
|
+
8. Stop there. Do not mark the pull request ready, do not merge, and do not declare the review closed. A narrow re-review posts `## Review closed`.
|
|
109
110
|
|
|
110
111
|
Send a block out as a message before it becomes an interactive prompt. A session already waiting on input never reaches the tool round an inbound message drains at, so an answer relayed afterwards arrives under the open question and changes nothing.
|
|
111
112
|
|
|
@@ -39,7 +39,7 @@ Reaching for size is the first instinct and the weakest tool.
|
|
|
39
39
|
- **Measure.** Body text running the full width of a wide container is unreadable however good the type is.
|
|
40
40
|
- **Figures in columns.** Numbers that change, in a table, a price or a timer, need tabular figures or the column jitters.
|
|
41
41
|
- **Tracking by size.** Large type wants tighter letter spacing, small uppercase labels want looser. Body text wants whatever the face was drawn with.
|
|
42
|
-
- **Casing.** Sentence case for headings and labels.
|
|
42
|
+
- **Casing.** Sentence case for headings and labels. `465-interface-casing` states the rule and its exceptions.
|
|
43
43
|
|
|
44
44
|
## Depth and texture
|
|
45
45
|
|
|
@@ -28,7 +28,7 @@ Skip nothing on the ground that it is obviously fine. A rule is on this list bec
|
|
|
28
28
|
|
|
29
29
|
- [ ] No layout family used twice. Eight sections carry at least four families
|
|
30
30
|
- [ ] No three consecutive sections sharing the image-and-text split
|
|
31
|
-
- [ ] Small uppercase labels above headings number no more than one per three sections
|
|
31
|
+
- [ ] Small uppercase labels above headings number no more than one per three sections, per `465-interface-casing`
|
|
32
32
|
- [ ] At most one horizontal marquee
|
|
33
33
|
- [ ] Grid cells equal content items, with no blank tile filling a gap
|
|
34
34
|
- [ ] Lists over five items use something other than a longer list
|
|
@@ -62,7 +62,7 @@ Skip this group where the surface draws on a system already settled.
|
|
|
62
62
|
- [ ] Every number either real, labeled as sample, or removed
|
|
63
63
|
- [ ] No placeholder that reads as placeholder: generic names, generic company names, reused portraits, identical dates
|
|
64
64
|
- [ ] No filler verbs
|
|
65
|
-
- [ ] Sentence case throughout
|
|
65
|
+
- [ ] Sentence case throughout, with exceptions per `465-interface-casing`
|
|
66
66
|
- [ ] Every claim about what the product does is a thing it does
|
|
67
67
|
|
|
68
68
|
## Motion
|
|
@@ -61,7 +61,7 @@ These are the rules with numbers, so they are checked by counting rather than by
|
|
|
61
61
|
|
|
62
62
|
- **A layout family appears once.** Once a section uses a shape, no other section on the surface uses it. Eight sections need at least four distinct families.
|
|
63
63
|
- **Two consecutive splits, never three.** Alternating image-left and image-right reads as considered twice and as filler by the third. Break it with a full-width section, a vertical stack, a grid, or anything else.
|
|
64
|
-
- **One small uppercase label per three sections.** The tiny wide-tracked line above a heading is the single most over-reached default in model output.
|
|
64
|
+
- **One small uppercase label per three sections.** The tiny wide-tracked line above a heading is the single most over-reached default in model output. `465-interface-casing` carries the count. The fix is usually to delete it, since a section's position already says what it is.
|
|
65
65
|
- **One marquee.** Two sliding strips on one surface read as filler rather than as a device.
|
|
66
66
|
- **Cells equal items.** A grid with a hole in it, or a blank tile at the end, means the grid was shaped before the content was counted. Reshape it.
|
|
67
67
|
- **Over five items wants a different component.** A longer list is the lazy answer. Group into clusters, split into columns, give each item a card, make them scrollable, or collapse the tail behind a disclosure.
|
|
@@ -16,6 +16,7 @@ A README whose real documentation lives in `canon/context/` or `docs/` was a sec
|
|
|
16
16
|
- Read `standards/readme.md` before drafting, since its `## Voice` section is scoped to a repository-root README and yields to `write-human`'s reference voice everywhere else
|
|
17
17
|
- Detect every project type the standard's `## Content` list applies to, from the manifest and the tree, rather than drafting against the closest single type
|
|
18
18
|
- Treat an existing README with no H1, or with headings that name only the scaffold that wrote it, as unedited generator output to draft over rather than a page to sync section by section
|
|
19
|
+
- Read the header block's slots off the repository, being the mark, the claim, the live link, and the product screenshot, and skip the link and the screenshot for a project with no page, so every element traces to a file or field the project holds
|
|
19
20
|
- Verify a candidate badge by the value it would render rather than by a fetch's status code, since a badge service answers 200 for a query it cannot satisfy
|
|
20
21
|
- Confirm the resolved path, the detected types, the badge candidates, and the full content with the user before writing, since project-type detection and badge selection are judgment calls with no diff to preview them against
|
|
21
22
|
|
|
@@ -23,6 +24,7 @@ A README whose real documentation lives in `canon/context/` or `docs/` was a sec
|
|
|
23
24
|
|
|
24
25
|
- Rewrite an authored README. One carrying an H1 that names the project refuses toward `docs-sync`.
|
|
25
26
|
- Offer to overwrite an authored README on the refusal path, or propose conforming it to what this skill would have drafted. A target project's own citations into its README are invisible from here, so the refusal reports rather than proposes.
|
|
27
|
+
- Invent a screenshot or a mark the project does not hold, or write a placeholder path for one. An omitted slot is a correct page and an invented image is the failure.
|
|
26
28
|
- Assume this skill's own invocation frequency needs no check. Whether anything reaches for it beyond an author typing its name has no answer at creation time, so a review pass some months in should read that back rather than take the assumption on faith.
|
|
27
29
|
|
|
28
30
|
## Guards
|
|
@@ -27,10 +27,16 @@ Read these files in parallel:
|
|
|
27
27
|
- Read the project's manifest (`package.json`, `pyproject.toml`, `Cargo.toml`, or equivalent) for a `bin` field or CLI entry point, an installable package name, and its declared dependencies.
|
|
28
28
|
- Check for a `claude/skills/` or `.claude/skills/` folder, a `plugin.json`, or a marketplace manifest, each naming an agent-facing or marketplace-distributed surface.
|
|
29
29
|
- A project is often several of these at once. Note every type that applies rather than stopping at the first match, since the Draft step covers each one the project actually is.
|
|
30
|
+
- Check for a page. A dependency on a site framework or a site config file in the manifest or the tree marks a project as having one. Read a live URL separately, from a `homepage` field or a deploy config, since a project can have a page and no known URL.
|
|
31
|
+
- A monorepo can carry a page in one package and a CLI in another, so both signals may fire. Report each rather than picking one.
|
|
32
|
+
- Look for the mark and the screenshot among images the project already commits: scan the existing README for image references, then the asset and public folders.
|
|
30
33
|
|
|
31
34
|
## Draft
|
|
32
35
|
|
|
33
36
|
- Draft the page against `${CLAUDE_SKILL_DIR}/../../standards/readme.md`: H1, a 2-3 sentence description in plain text, then the required sections, then whichever optional sections and per-type content the Detect step found.
|
|
37
|
+
- Open the page with the standard's header block, filling each slot from what Detect found: mark, title, badges, a one-line claim from the manifest description, the live link, then the product screenshot.
|
|
38
|
+
- Fill the screenshot slot only with an image the project already commits, referenced with alt text naming what it depicts. This skill cannot capture one. Omit the slot when no such image exists and say so in the preview. Never write a placeholder path.
|
|
39
|
+
- Omit the link and the screenshot for a project with no page, and the mark for a project with none, without a note in the drafted page. A project with a page and no known URL gets the screenshot slot, and the Confirm step asks for the link.
|
|
34
40
|
- Cover every applicable project type from the standard's `## Content` list rather than picking the closest one.
|
|
35
41
|
- Candidate badges: check for a published package (a registry field in the manifest), a CI workflow, and a `LICENSE` file.
|
|
36
42
|
- State each candidate's rendered value in the preview rather than trusting a fetch's status code, since a badge service answers 200 for a query it cannot satisfy.
|
|
@@ -38,7 +44,8 @@ Read these files in parallel:
|
|
|
38
44
|
|
|
39
45
|
## Confirm
|
|
40
46
|
|
|
41
|
-
- Show the resolved path, the detected project types, the badge candidates and what backs each one, and the full drafted content before writing.
|
|
47
|
+
- Show the resolved path, the detected project types, the header slots filled or skipped with the reason for each, the badge candidates and what backs each one, and the full drafted content before writing.
|
|
48
|
+
- The skill can confirm that an image file exists and is referenced, and it cannot verify the picture shows the product. Ask the user to look at it in the preview.
|
|
42
49
|
- Confirm with the user. This skill waits for that answer rather than treating the tool permission dialog as the gate, since project-type detection and badge selection are judgment calls with no diff to preview them against.
|
|
43
50
|
|
|
44
51
|
## Write
|
|
@@ -52,6 +59,7 @@ Read these files in parallel:
|
|
|
52
59
|
|
|
53
60
|
**Target:** `<path>` (root | nested)
|
|
54
61
|
**Detected:** `<project types>`
|
|
62
|
+
**Header:** `<each slot as filled (source) or skipped (reason)>`
|
|
55
63
|
**Badges:** `<candidates, or none>`
|
|
56
64
|
|
|
57
65
|
```markdown
|
|
@@ -31,7 +31,7 @@ A missing tracking ref is no longer a guard. An open pull request proves the bra
|
|
|
31
31
|
|
|
32
32
|
5. Post the evidence comparison, on every invocation including `reply-owned`, since this comment is not the reply step 8 owns. Run `canon pr evidence <number> --json`, resolving `<number>` from `gh pr view --json number`, and read `reason` on the record rather than the exit code.
|
|
33
33
|
- `no-evidence`: nothing changed under an `evidence/` segment this push. Say nothing and move on.
|
|
34
|
-
- `ok`: write `body` to `.canon/tmp/pr/evidence/body-<number>.md` at the main worktree root (resolved the way `session-worktree` does), then post the comment with `gh pr comment <number> --body-file <main-root>/.canon/tmp/pr/evidence/body-<number>.md` when the record carries no `commentId`, or edit the existing one in place with `gh api -X PATCH repos/{owner}/{repo}/issues/comments/<commentId> -
|
|
34
|
+
- `ok`: write `body` to `.canon/tmp/pr/evidence/body-<number>.md` at the main worktree root (resolved the way `session-worktree` does), then post the comment with `gh pr comment <number> --body-file <main-root>/.canon/tmp/pr/evidence/body-<number>.md` when the record carries no `commentId`, or edit the existing one in place with `gh api -X PATCH repos/{owner}/{repo}/issues/comments/<commentId> -F body=@<main-root>/.canon/tmp/pr/evidence/body-<number>.md` when it does. Clean up the tmp file only after the call reports success.
|
|
35
35
|
- Any other reason is one of the mirrored git refusals (`gh-missing`, `gh-failed`, `no-base`, `unreadable-tree`, `unreadable-changes`). Report it and continue without stopping the chain.
|
|
36
36
|
6. Check for existing review comments: `gh api 'repos/{owner}/{repo}/pulls/<number>/comments' --jq 'length'`, resolving `<number>` from `gh pr view --json number`.
|
|
37
37
|
7. Sync the body and title on every invocation, before the routing below decides on the reply.
|
|
@@ -11,7 +11,7 @@ Format an issue from session context following the issue standard, then file it
|
|
|
11
11
|
|
|
12
12
|
Read these in parallel:
|
|
13
13
|
|
|
14
|
-
- `${CLAUDE_SKILL_DIR}
|
|
14
|
+
- `${CLAUDE_SKILL_DIR}/references/issue.md`: issue title, labels, body sections, and banned phrases
|
|
15
15
|
- `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: banned words, punctuation, and formatting for all generated text
|
|
16
16
|
- The `write-human` skill: voice, rhythm, and sentence construction for all generated text
|
|
17
17
|
|
|
@@ -39,7 +39,7 @@ After outputting the preview, execute the final command immediately. Claude Code
|
|
|
39
39
|
|
|
40
40
|
### Pre-publish scan
|
|
41
41
|
|
|
42
|
-
Before running the final command, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the title and body. The title and body go straight to the remote with nothing checking them on the way, so this scan is the only gate. It covers the phase-label check as well as the characters, since both go to a reader who has no task board. It applies on top of the banned phrases in `${CLAUDE_SKILL_DIR}
|
|
42
|
+
Before running the final command, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the title and body. The title and body go straight to the remote with nothing checking them on the way, so this scan is the only gate. It covers the phase-label check as well as the characters, since both go to a reader who has no task board. It applies on top of the banned phrases in `${CLAUDE_SKILL_DIR}/references/issue.md`.
|
|
43
43
|
|
|
44
44
|
The `pull_request` check the git-pr surface carries reads a pull request's own title and body alone, so an issue reaches no check behind this scan either.
|
|
45
45
|
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Issue reference
|
|
3
|
-
description: GitHub issue title, labels, and body conventions
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
# Issue reference
|
|
7
2
|
|
|
8
3
|
## Scope
|
|
@@ -11,10 +6,10 @@ Governs a tracker issue: its title, its labels, and the sections its body carrie
|
|
|
11
6
|
|
|
12
7
|
Does not govern:
|
|
13
8
|
|
|
14
|
-
- Pull request title and body:
|
|
15
|
-
- Whether a phase label may appear in issue text:
|
|
9
|
+
- Pull request title and body: the pull request standard
|
|
10
|
+
- Whether a phase label may appear in issue text: the versioning standard
|
|
16
11
|
- Voice, rhythm, and sentence construction in issue prose: the `write-human` skill
|
|
17
|
-
- Punctuation, formatting, and banned words in issue prose:
|
|
12
|
+
- Punctuation, formatting, and banned words in issue prose: the markdown standard
|
|
18
13
|
|
|
19
14
|
## Title
|
|
20
15
|
|
|
@@ -181,10 +181,10 @@ Read `reason` on the record rather than the exit code.
|
|
|
181
181
|
gh pr comment <number> --body-file <main-root>/.canon/tmp/pr/evidence/body-<number>.md
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
When the record carries a `commentId`, edit that comment in place instead of posting a second one, reading the body field from the tmp file with
|
|
184
|
+
When the record carries a `commentId`, edit that comment in place instead of posting a second one, reading the body field from the tmp file with `@`, which needs the typed-field flag `-F` because the raw-string flag `-f` posts the path itself as the body:
|
|
185
185
|
|
|
186
186
|
```bash
|
|
187
|
-
gh api -X PATCH repos/{owner}/{repo}/issues/comments/<commentId> -
|
|
187
|
+
gh api -X PATCH repos/{owner}/{repo}/issues/comments/<commentId> -F body=@<main-root>/.canon/tmp/pr/evidence/body-<number>.md
|
|
188
188
|
```
|
|
189
189
|
|
|
190
190
|
Delete the handoff file once that call reports success, per the cleanup below, since the checklist now lives on the pull request. Clean up the tmp body file the same way.
|
|
@@ -30,6 +30,6 @@ Without this skill, `canon indexes list --json` exists as a verb with nobody wra
|
|
|
30
30
|
|
|
31
31
|
## Out of scope
|
|
32
32
|
|
|
33
|
-
- Regenerating or scaffolding an index, which `canon indexes regen` and the `setup
|
|
33
|
+
- Regenerating or scaffolding an index, which `canon indexes regen` and the `target-setup` skill's `indexes` phase own
|
|
34
34
|
- Reading a folder's contents once a hit names it, which is an ordinary file read rather than part of the lookup
|
|
35
|
-
- Chaining this skill into `setup
|
|
35
|
+
- Chaining this skill into the `target-setup` skill's `indexes` phase as a verification step. Left independent: that phase already validates through `canon indexes regen --dry-run`, and a second skill call inside a bootstrap flow duplicates a check that already runs.
|
|
@@ -38,5 +38,5 @@ Two more failures are mechanical. A command that stays up run in the foreground
|
|
|
38
38
|
|
|
39
39
|
- Confirming a change works in the running app, which is a verification request and needs the steps this skill refuses
|
|
40
40
|
- Deploying, publishing, releasing, migrating, and resetting
|
|
41
|
-
- Running the scaffold verification chain against `package.json` scripts: `setup
|
|
41
|
+
- Running the scaffold verification chain against `package.json` scripts: the `target-setup` skill's `verify` phase
|
|
42
42
|
- Writing the entry it reads, which belongs to the project's own development docs
|
|
@@ -41,5 +41,5 @@ Two failures belong to the audit rather than to the diff. A decision taken in ch
|
|
|
41
41
|
- Bulk install and sync of a whole domain, which `canon <domain> install` and `canon <domain> sync` own and `canon-cli` documents. Reach for this skill when the target holds edits worth keeping, and for those commands when it does not.
|
|
42
42
|
- Golden configs, which overwrite by design and carry no section structure to diff
|
|
43
43
|
- Governance rules: `canon gov sync`
|
|
44
|
-
- First-time scaffold of a project that has installed nothing yet: `setup
|
|
44
|
+
- First-time scaffold of a project that has installed nothing yet: `target-setup`
|
|
45
45
|
- Public `README.md` and `docs/` prose: `docs-sync`
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: target-check
|
|
3
|
+
description: What the target check is for, the gap it closes, and the repairing it refuses
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Target check requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, a session landing in a target project decides for itself what to look at. `canon-rollout` dispatches a worker into each target and gets a pull request out, and nothing told that worker what a target holds against what the toolkit ships, so a wave is only as good as whatever each session happened to examine. Four hand-driven repairs across two waves examined four different sets of surfaces and none of them read the same domain twice.
|
|
11
|
+
|
|
12
|
+
The second half of the gap is silence. A session that runs a verb the target's binary does not carry, or reads a report key that is absent, has no instruction telling it apart from a clean answer, so an unexamined domain reaches the reader as a domain that passed.
|
|
13
|
+
|
|
14
|
+
## Must
|
|
15
|
+
|
|
16
|
+
- Report one section per domain, so a reader can tell which surface a finding came from
|
|
17
|
+
- Read each domain through the verb that already owns that comparison, rather than inspecting the same files by hand, since the verb is the surface under test
|
|
18
|
+
- Take the installed domains from the catalog the report returns rather than from a list in the body, so a domain the toolkit adds later needs no edit here
|
|
19
|
+
- Report a refusal, an absent key, and a missing subcommand as unread, naming the cause, so an unexamined domain never reads as a passing one
|
|
20
|
+
- Report the Claude harness as unchecked on every run while no verb answers for it, as a row rather than an omission
|
|
21
|
+
- Report the toolkit version first, since a target behind on the binary explains every unread section under it
|
|
22
|
+
- Run every read non-interactively by default, because every caller in the near term is a dispatched worker with nobody present to answer a prompt
|
|
23
|
+
|
|
24
|
+
## Must not
|
|
25
|
+
|
|
26
|
+
- Repair a finding, write a file in the target, or open a pull request. A check that repaired as it read leaves the reader unable to tell a finding from a fix, and the wave decides what to fix.
|
|
27
|
+
- Emit a verdict across the domains. Five answer from verbs and one answers from nothing, so any roll-up is a figure that lies about the sixth.
|
|
28
|
+
- Answer the harness domain by file inspection. A section reaching a verdict from a hand-rolled read is exactly what the other five sections avoid, and a hole a reader can see is worth more than a number nobody can trace.
|
|
29
|
+
- Hardcode a stack, rule, or domain name. A name written into the body goes stale on its own cadence.
|
|
30
|
+
|
|
31
|
+
## Guards
|
|
32
|
+
|
|
33
|
+
- `canon` absent from the path: stop, since no domain can be read
|
|
34
|
+
- No `.claude/` at the working root: stop and name the scaffold command, since nothing is installed to check
|
|
35
|
+
- The working root is the toolkit itself: stop and name `canon-rollout`, since this skill reads what the toolkit installed into rather than the source
|
|
36
|
+
|
|
37
|
+
## Out of scope
|
|
38
|
+
|
|
39
|
+
- Document health, which asks a content question rather than a structural one and takes its own surface
|
|
40
|
+
- Repairing anything a section names. Each routes to the command or skill that owns it.
|
|
41
|
+
- A target's own routes, which `canon inventory` reports as a listing rather than a verdict and which is a fact about the project rather than about what the toolkit ships
|
|
42
|
+
- First-time scaffold, which is `target-setup`, and per-intent routing of a single toolkit operation, which is `canon-operator`
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: target-check
|
|
3
|
+
description: Reports what a target project holds against what the toolkit currently ships, one section per domain, reading through `canon` verbs rather than inspecting files. Use when asked to "check this target", "what has this project fallen behind on", "is this project current with the toolkit", "run the target check", or as the first thing a rollout worker runs after entering a target. Do NOT use to repair a finding, which the owning command or skill does, and do NOT use in the toolkit repository itself.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Target check
|
|
7
|
+
|
|
8
|
+
Reports, per domain, what this target holds against what the toolkit currently ships. It reports and never repairs, so whoever read the report decides what to fix.
|
|
9
|
+
|
|
10
|
+
Six domains carry the report. Five answer from a verb that already exists and the sixth answers from nothing, which it says rather than omitting. `${CLAUDE_SKILL_DIR}/references/domains.md` holds what each one reads, what current looks like, and where a finding routes. This body holds the order, the guards, and the report shape.
|
|
11
|
+
|
|
12
|
+
## Guards
|
|
13
|
+
|
|
14
|
+
- `canon` absent from the path: stop. `❌ canon is not on PATH, so no domain can be read.`
|
|
15
|
+
- No `.claude/` directory at the working root: stop. `❌ No .claude/ here, so nothing is installed to check. Run canon init first.`
|
|
16
|
+
- A `claude/skills/` folder at the working root, with no leading dot: stop. `❌ This is the toolkit itself rather than a target. canon-rollout takes a change out to the targets.` A target receives skills at `.claude/skills/` and authors none, so the spelling without the dot separates the source from what it installs into.
|
|
17
|
+
- Run every command under `CANON_NON_INTERACTIVE=1` and prompt at no point. Every caller in the near term is a worker a wave dispatched, with nobody present to answer, so the non-interactive path is the only path rather than a flag a caller remembers.
|
|
18
|
+
- Branch on each record's own fields rather than on an exit status. An operator's shell profile may wrap `canon` in a function whose status comes from a trailing command, which reports every refusal as success.
|
|
19
|
+
|
|
20
|
+
## Step 1: read the reports
|
|
21
|
+
|
|
22
|
+
Run these from the target root, in parallel:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
CANON_NON_INTERACTIVE=1 canon sync --check . --json
|
|
26
|
+
CANON_NON_INTERACTIVE=1 canon context audit --json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The first answers five domains from one read, being `skew`, `domains`, `seeds`, `tooling`, and the layout fields `unmigrated`, `superseded`, and `reverse`. The second deepens a domain that first read only counts.
|
|
30
|
+
|
|
31
|
+
Then run `CANON_NON_INTERACTIVE=1 canon records validate <kind> --json` once per record folder the target carries, taking `<kind>` from what is present under the record root rather than from a list held here.
|
|
32
|
+
|
|
33
|
+
### The tooling read takes a stack, always
|
|
34
|
+
|
|
35
|
+
The tooling comparison runs last, because it needs a value the first read returns. Take `<stack>` from the first name in the report's `tooling.chain`, which records the stack nearest the target, and pass it:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
CANON_NON_INTERACTIVE=1 canon tooling sync --check <stack>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Refuse the domain and report it unread when `chain` names nothing, rather than running the command bare. A bare call reaches the stack prompt, and the non-interactive variable this skill's Guards make mandatory resolves that prompt to the first option in the catalog instead of refusing it. The domain would then compare every target against whichever stack sorts first, and report drift that is an artifact of the wrong comparison rather than anything the target did. It would fire on every run rather than on an edge, since nothing about the target is read on the way to that default.
|
|
42
|
+
|
|
43
|
+
Read every installed domain from the catalog the report returns rather than from a name written into this body. `domains` enumerates what the target actually stamped, so a domain the toolkit adds later reaches this report with no edit here, and a name hardcoded here is a bug.
|
|
44
|
+
|
|
45
|
+
## Step 2: report each domain
|
|
46
|
+
|
|
47
|
+
Report the six in this order, one section each, per `${CLAUDE_SKILL_DIR}/references/domains.md`:
|
|
48
|
+
|
|
49
|
+
1. Toolkit version
|
|
50
|
+
2. The `canon/` folder
|
|
51
|
+
3. Governance rules
|
|
52
|
+
4. Tooling
|
|
53
|
+
5. Seeds
|
|
54
|
+
6. The Claude harness
|
|
55
|
+
|
|
56
|
+
Give each section three things and nothing else: the state, the evidence the state was read from, and the command or skill that repairs it. Naming the repair is not running it.
|
|
57
|
+
|
|
58
|
+
### Unread is not current
|
|
59
|
+
|
|
60
|
+
A refused command, an absent key, or a subcommand the target's binary does not carry leaves a domain unread. Report it as unread, name which read could not be taken, and name the cause. Reading an absent key as an empty answer reports a clean target to a project nothing looked at, which is the failure this report exists to replace.
|
|
61
|
+
|
|
62
|
+
The version domain is what makes that case legible rather than mysterious. A target a release behind is missing verbs the other five sections call, so the version section is read first and its state explains every unread section under it.
|
|
63
|
+
|
|
64
|
+
### No verdict across the six
|
|
65
|
+
|
|
66
|
+
Report a state per domain and no number over them. Five sections answer from verbs and the sixth answers from nothing, so any roll-up is a figure that lies about the sixth. `canon inventory` reports a listing rather than a verdict for the same reason, and it is absent from the six here because its subject is a target's own routes rather than what the toolkit ships.
|
|
67
|
+
|
|
68
|
+
## Step 3: stop at the report
|
|
69
|
+
|
|
70
|
+
Repair nothing, write no file in the target, and open no pull request. A wave decides what to fix after reading this, and a check that repaired as it read would leave the reader unable to tell a finding from a fix.
|
|
71
|
+
|
|
72
|
+
## Output
|
|
73
|
+
|
|
74
|
+
Lead with the table, then one detail block per domain that is not current:
|
|
75
|
+
|
|
76
|
+
```markdown
|
|
77
|
+
Target check: `<path>`, against canon `<version>`.
|
|
78
|
+
|
|
79
|
+
| Domain | State | Evidence |
|
|
80
|
+
| ---------------- | ------------------------- | --------------------------------- |
|
|
81
|
+
| Toolkit version | current / behind / unread | `skew.installed` against `latest` |
|
|
82
|
+
| `canon/` folder | current / behind / unread | what the layout fields named |
|
|
83
|
+
| Governance rules | current / behind / unread | the per-state counts |
|
|
84
|
+
| Tooling | current / behind / unread | what a sync would change |
|
|
85
|
+
| Seeds | current / behind / unread | the per-state counts |
|
|
86
|
+
| Claude harness | unchecked | no verb reads it |
|
|
87
|
+
|
|
88
|
+
No overall verdict. The harness row is unchecked rather than passing.
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Keep the harness row `unchecked` on every run until a verb reads it. A domain left out of the table reads as a domain that passed, which is the one shape the row exists to prevent.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Target check domains
|
|
3
|
+
description: What each of the six domains reads, what counts as current, and where a finding routes
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Target check domains
|
|
7
|
+
|
|
8
|
+
One section per domain, in the order the body reports them. Each names the read, what current looks like, what the states mean, and the command or skill a finding routes to. Naming a repair is not running one.
|
|
9
|
+
|
|
10
|
+
## 1. Toolkit version
|
|
11
|
+
|
|
12
|
+
Read `skew` off `canon sync --check . --json`. It carries `state`, `installed`, and `latest`.
|
|
13
|
+
|
|
14
|
+
- Current: `state` reads `current`, or `installed` equals `latest`.
|
|
15
|
+
- Behind: `installed` trails `latest`. Name both versions.
|
|
16
|
+
- Unread: no `skew` key, or the whole report refused. Say the version could not be read and treat every section under it as read against an unknown binary.
|
|
17
|
+
|
|
18
|
+
Routes to `canon upgrade`, which reinstalls with the manager that installed it.
|
|
19
|
+
|
|
20
|
+
This domain is first because it conditions the other five. A target a release behind carries an older verb surface, so a section reporting unread below may be reporting a missing subcommand rather than a missing surface, and the version state is what separates those two readings.
|
|
21
|
+
|
|
22
|
+
## 2. The `canon/` folder
|
|
23
|
+
|
|
24
|
+
Read three fields off the same report, then two verbs:
|
|
25
|
+
|
|
26
|
+
- `unmigrated`: a domain still at the root layout with nothing under `.claude/`. The most urgent finding, because such a domain reports no drift of its own while being entirely behind.
|
|
27
|
+
- `superseded`: a file a newer seed folder replaced. No command moves it, since the content is the project's own.
|
|
28
|
+
- `reverse`: `unclaimed` names folders at roots the toolkit stopped shipping, each with an `attribution` of `dropped`, `unattributed`, or `project`. `migrations` names a proposal-only skill with a live case here and the `reason` behind it.
|
|
29
|
+
- `canon context audit --json`: required sections, entry length, citations, and index drift across the context folder.
|
|
30
|
+
- `canon records validate <kind> --json`, once per record folder the target carries.
|
|
31
|
+
|
|
32
|
+
- Current: `unmigrated` and `superseded` both empty, `reverse.unclaimed` carrying nothing outside `project` attribution, and both verbs finding nothing.
|
|
33
|
+
- Behind: any of those carrying an entry. Name the entry and its attribution.
|
|
34
|
+
- Unread: `historyUnavailable` set on `reverse`, a `reverse` key the report does not carry at all, or either verb refusing. A missing `reverse` key is a binary predating the field rather than a target with nothing unclaimed.
|
|
35
|
+
|
|
36
|
+
Routes by finding. `unmigrated` routes to a relocation the user runs, since no command moves it. `superseded` routes to `migration-superseded`. A `migrations` entry routes to the skill its `skill` field names, spelled as the report spells it. An `unclaimed` folder carrying `project` attribution routes nowhere, since history proved the project owns it.
|
|
37
|
+
|
|
38
|
+
## 3. Governance rules
|
|
39
|
+
|
|
40
|
+
Read `domains` off the report and take every entry it carries rather than naming governance here. Each entry carries `stamped`, per-state `counts`, and `entries` with a `state` and a `rel` path.
|
|
41
|
+
|
|
42
|
+
The states are `matching`, `stale`, `customized`, `drifted`, `orphaned`, `stranded`, and `missing`.
|
|
43
|
+
|
|
44
|
+
- Current: every count but `matching` reads zero.
|
|
45
|
+
- Behind: any other count is non-zero. Report the counts and name the paths behind `stale` and `missing`, which a sync repairs, separately from `customized` and `drifted`, which the project wrote and a sync would overwrite.
|
|
46
|
+
- Unread: `stamped` false with no entries, or the domain absent from the array while the target carries installed rules.
|
|
47
|
+
|
|
48
|
+
Routes to `canon <domain> sync`, or to `canon sync` for every installed domain at once. Read the `canon-cli` skill before naming either, since a command name says nothing about what it does to a file already there, and a `customized` entry is exactly the file a sync takes back.
|
|
49
|
+
|
|
50
|
+
## 4. Tooling
|
|
51
|
+
|
|
52
|
+
Read the `tooling` block off the report first, because the comparison command needs a value it carries.
|
|
53
|
+
|
|
54
|
+
Read `measured` before anything under it. Every count is zero when `measured` is false, which is an absence of measurement rather than a measured zero.
|
|
55
|
+
|
|
56
|
+
On a measured report, take `<stack>` from the first name in `chain` and run `canon tooling sync --check <stack>`. Never run it bare. The stack argument is what the target carries, and omitting it reaches a prompt that the non-interactive variable resolves to the catalog's first entry rather than refusing, which compares the target against a stack it does not use and reports the difference as drift.
|
|
57
|
+
|
|
58
|
+
- Current: `measured` true, `chain` naming stacks the toolkit still ships, and `--check` reporting nothing it would change.
|
|
59
|
+
- Behind: `--check` naming files it would replace, or `counts.gitignore` carrying missing managed entries.
|
|
60
|
+
- Unread: `measured` false. It splits three ways, and each is reported as unmeasured with its cause named rather than as clean. An empty `chain` at a workspace root is by design, since a chain there would guess at what the packages hold. An empty `chain` anywhere else means no tooling install is recorded. A `chain` carrying names the toolkit no longer ships means injecting would write against a retired name.
|
|
61
|
+
|
|
62
|
+
Routes to `canon tooling sync <stack>`, or to `canon tooling inject --gitignore <stack>` for ignore entries alone, taking `<stack>` the same way the comparison above does. An unmeasured report names no stack, so it routes to neither.
|
|
63
|
+
|
|
64
|
+
`canon tooling diff` is the verb this section wants and it does not exist yet. `--check` answers the same question today and stays working as an alias by design, so the retarget when that verb lands is a change of name rather than of behavior.
|
|
65
|
+
|
|
66
|
+
## 5. Seeds
|
|
67
|
+
|
|
68
|
+
Read `seeds.entries` off the report. Each entry is `matching`, `stale`, `drifted`, or `missing`, and the set spans `CLAUDE.md`, the `canon/` records, the generated indexes, `.claude/settings.json`, and the hook scripts under `.claude/hooks/`.
|
|
69
|
+
|
|
70
|
+
- Current: every entry reads `matching`.
|
|
71
|
+
- Behind: anything else. Report `stale` and `missing` separately from `drifted`, which means the content matches no version the toolkit ever published, so the project wrote it.
|
|
72
|
+
- Unread: `historyUnavailable` set on `seeds`, which leaves every difference unattributed. Say so rather than reporting a file as untouched.
|
|
73
|
+
|
|
74
|
+
Routes to `seed-sync`, which proposes per-section edits without overwriting a customization. It is a proposal rather than a write, which is why a `drifted` `CLAUDE.md` routes there rather than to a sync.
|
|
75
|
+
|
|
76
|
+
A seed entry matching says the file's bytes match the shipped seed. It says nothing about whether the harness those files configure is wired, which is the next domain.
|
|
77
|
+
|
|
78
|
+
## 6. The Claude harness
|
|
79
|
+
|
|
80
|
+
No verb reads this domain. Report it `unchecked` on every run and report it as a row rather than omitting it.
|
|
81
|
+
|
|
82
|
+
What goes unread is whether the target's hooks fire, whether `.claude/settings.json` registers them, which plugin version the target's sessions actually load, and whether the marketplace cache matches what the toolkit ships.
|
|
83
|
+
|
|
84
|
+
Confirm the gap against the live surface rather than against a list held here, by reading `canon claude --help` and the help of any subcommand under it that sounds like an answer. A list written into this file freezes on the day it was written and would report a gap a later release had closed. `canon claude skills drift` is the verb that comes nearest, and it reads the toolkit's own history against a ref, which says what moved upstream rather than what this target holds. Report the domain checked, with what the verb answered, on the run where a verb does answer one of the four questions above.
|
|
85
|
+
|
|
86
|
+
Reading it by file inspection is the alternative and it is refused. Every other section here answers from the verb under test, and a section answering from a hand-rolled read of the same files reaches a verdict nothing else in the report is entitled to make. A hole a reader can see is worth more than a number nobody can trace.
|
|
87
|
+
|
|
88
|
+
`canon claude plugin-update` is what an operator runs to bring a cache forward. Name it as the action available rather than as a repair for a finding, since no finding was taken.
|