@erclx/canon 5.38.0 → 5.39.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 +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +12 -9
- package/claude/skills/auto-ship/SKILL.md +43 -23
- package/claude/skills/backlog-triage/SKILL.md +62 -53
- package/claude/skills/backlog-triage/references/apply.md +69 -0
- package/claude/skills/build-in-slices/SKILL.md +8 -4
- package/claude/skills/canon-cli/SKILL.md +5 -1
- package/claude/skills/canon-feedback/SKILL.md +18 -8
- package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
- package/claude/skills/canvas-board/SKILL.md +36 -17
- package/claude/skills/ci-workflow/SKILL.md +5 -4
- package/claude/skills/code-craft/SKILL.md +10 -6
- package/claude/skills/codebase-layout/SKILL.md +3 -5
- package/claude/skills/context-fold/REQUIREMENT.md +4 -4
- package/claude/skills/context-fold/SKILL.md +42 -23
- package/claude/skills/context-fold/references/context-refresh.md +4 -3
- package/claude/skills/context-fold/references/context.md +79 -64
- package/claude/skills/create-rule/SKILL.md +7 -3
- package/claude/skills/create-skill/SKILL.md +27 -7
- package/claude/skills/create-skill/references/skill-reference.md +41 -17
- package/claude/skills/decision-escalate/SKILL.md +8 -5
- package/claude/skills/deploy-app/SKILL.md +1 -1
- package/claude/skills/deprecation-migration/SKILL.md +12 -4
- package/claude/skills/design-taste/SKILL.md +17 -11
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
- package/claude/skills/docs-sync/SKILL.md +17 -6
- package/claude/skills/docs-sync/references/docs.md +54 -21
- package/claude/skills/docs-sync/references/readme.md +32 -8
- package/claude/skills/document-health/SKILL.md +3 -4
- package/claude/skills/draft-and-pick/SKILL.md +73 -47
- package/claude/skills/draft-doc/SKILL.md +9 -4
- package/claude/skills/draft-doc/references/context.md +4 -4
- package/claude/skills/draft-doc/references/docs.md +1 -0
- package/claude/skills/draft-doc/references/wiki.md +3 -2
- package/claude/skills/draft-figure/SKILL.md +9 -7
- package/claude/skills/draft-identity/SKILL.md +24 -52
- package/claude/skills/draft-identity/references/card-route.md +46 -0
- package/claude/skills/draft-ready/SKILL.md +19 -7
- package/claude/skills/draft-screencast/SKILL.md +6 -112
- package/claude/skills/draft-screencast/references/beats-template.md +119 -0
- package/claude/skills/draft-slides/SKILL.md +7 -4
- package/claude/skills/git-branch/SKILL.md +3 -3
- package/claude/skills/git-commit/SKILL.md +5 -3
- package/claude/skills/git-followup/SKILL.md +16 -9
- package/claude/skills/git-issue/SKILL.md +6 -5
- package/claude/skills/git-pr/SKILL.md +56 -44
- package/claude/skills/git-ship/SKILL.md +43 -34
- package/claude/skills/git-ship/references/ci-watch.md +31 -0
- package/claude/skills/git-split/SKILL.md +28 -100
- package/claude/skills/git-split/references/independent.md +40 -0
- package/claude/skills/git-split/references/stacked.md +73 -0
- package/claude/skills/git-stage/SKILL.md +9 -7
- package/claude/skills/git-worktree/SKILL.md +27 -49
- package/claude/skills/git-worktree/references/cleanup.md +55 -0
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/markdown-craft/references/markdown.md +82 -53
- package/claude/skills/plan-feature/SKILL.md +52 -46
- package/claude/skills/plan-feature/references/batches.md +46 -0
- package/claude/skills/plan-groundwork/SKILL.md +60 -74
- package/claude/skills/plan-groundwork/references/output.md +48 -0
- package/claude/skills/plan-intake/SKILL.md +28 -21
- package/claude/skills/plan-intake-answer/SKILL.md +14 -13
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +31 -11
- package/claude/skills/review-address/SKILL.md +76 -158
- package/claude/skills/review-address/references/rebase-only.md +34 -0
- package/claude/skills/review-craft/SKILL.md +27 -11
- package/claude/skills/review-pr/SKILL.md +91 -40
- package/claude/skills/review-ui/SKILL.md +62 -37
- package/claude/skills/review-ui/references/hosted-preview.md +30 -0
- package/claude/skills/role-orchestrator/SKILL.md +105 -74
- package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
- package/claude/skills/role-planner/SKILL.md +66 -64
- package/claude/skills/role-reviewer/SKILL.md +57 -46
- package/claude/skills/role-worker/SKILL.md +68 -63
- package/claude/skills/search-craft/SKILL.md +7 -5
- package/claude/skills/session-compact/SKILL.md +16 -11
- package/claude/skills/session-map/SKILL.md +31 -10
- package/claude/skills/session-relay/SKILL.md +32 -65
- package/claude/skills/session-resume/SKILL.md +18 -13
- package/claude/skills/session-worktree/SKILL.md +70 -42
- package/claude/skills/systematic-debugging/SKILL.md +6 -1
- package/claude/skills/target-check/SKILL.md +13 -6
- package/claude/skills/target-setup/SKILL.md +39 -27
- package/claude/skills/task-board/SKILL.md +68 -60
- package/claude/skills/task-board/references/create-report.md +36 -0
- package/claude/skills/task-complete/SKILL.md +20 -18
- package/claude/skills/teach-workspace/SKILL.md +61 -33
- package/claude/skills/test-craft/SKILL.md +2 -1
- package/claude/skills/test-first/SKILL.md +15 -9
- package/claude/skills/ui-checklist/SKILL.md +18 -16
- package/claude/skills/ux-audit/SKILL.md +9 -10
- package/claude/skills/ux-measure/SKILL.md +22 -18
- package/claude/skills/video-craft/SKILL.md +15 -7
- package/claude/skills/write-human/SKILL.md +9 -1
- package/claude/skills/youtube-transcripts/SKILL.md +2 -1
- package/docs/agents/context-audit-checks.md +19 -1
- package/docs/agents/context-audit.md +2 -2
- package/docs/agents/driver.md +1 -1
- package/docs/agents/hooks.md +21 -1
- package/docs/agents/index.md +10 -14
- package/docs/agents/indexes.md +25 -29
- package/docs/agents/install-and-sync.md +124 -235
- package/docs/agents/markdown-audit-density.md +39 -0
- package/docs/agents/markdown-audit-weight.md +9 -7
- package/docs/agents/markdown-audit.md +18 -14
- package/docs/agents/migrate.md +41 -16
- package/docs/agents/output-shape.md +60 -45
- package/docs/agents/overview.md +36 -12
- package/docs/agents/routing.md +1 -1
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/skills-reach.md +1 -1
- package/docs/agents/targets.md +25 -77
- package/docs/target/migrations.md +1 -1
- package/docs/target/projects.md +2 -2
- package/docs/workflow/ai-workflow.md +2 -2
- package/docs/workflow/parallel-features.md +2 -2
- package/docs/workflow/skill-map.md +1 -1
- package/docs/workflow/visual-design-workflow.md +1 -1
- package/package.json +1 -1
- package/src/commands/claude.ts +1 -1
- package/src/commands/context.ts +106 -7
- package/src/commands/hooks.ts +63 -0
- package/src/commands/markdown.ts +169 -32
- package/src/context/audit.ts +256 -5
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/gate.ts +23 -7
- package/src/context/shape-gated.ts +28 -0
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/gate/measures.ts +15 -190
- package/src/gate/stages.ts +7 -23
- package/src/hooks/reply-links.ts +110 -0
- package/src/markdown/density.ts +258 -0
- package/src/markdown/gate.ts +57 -18
- package/src/markdown/reference-shape.ts +103 -0
- package/src/markdown/scope.ts +174 -0
- package/src/markdown/structure.ts +9 -59
- package/src/shipped/references.ts +1 -1
- package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/docs/agents/commands.md +0 -154
- package/docs/agents/docs.md +0 -27
- package/docs/agents/drift-surfaces.md +0 -201
- package/docs/agents/gov-detect.md +0 -47
- package/docs/agents/scripting.md +0 -142
- package/src/markdown/growth.ts +0 -43
package/docs/agents/commands.md
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Command catalog
|
|
3
|
-
description: Every top-level command with its purpose, each domain's subcommands and the page describing them, the browser commands, and the version skew report
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Command catalog
|
|
7
|
-
|
|
8
|
-
Bare `canon --help` lists every top-level command under five headings, Project, Domains, Author and render, Session and ship, and Repo reports, with descriptions cut at 80 columns. A pipe gets the same text without the frame glyphs. Behavior notes for the install and sync verbs live in `install-and-sync.md`.
|
|
9
|
-
|
|
10
|
-
`canon <command> --help` lists subcommands, and `canon <command> <subcommand> --help` a leaf's flags, exit codes, and examples. `canon <command> --help --all` prints both. An unknown subcommand exits 1 under a group taking no operand.
|
|
11
|
-
|
|
12
|
-
## Project-level
|
|
13
|
-
|
|
14
|
-
One row per top-level command, in the order `canon --help` prints them. A domain's subcommands are in `## Domain commands` below.
|
|
15
|
-
|
|
16
|
-
| Command | Purpose |
|
|
17
|
-
| --------------------------- | ------------------------------------------------------------------------------------------ |
|
|
18
|
-
| `canon init [path]` | Bootstrap a project with selected toolkit domains |
|
|
19
|
-
| `canon sync [path]` | Sync every installed domain, or report drift and version skew with `--check` |
|
|
20
|
-
| `canon upgrade` | Reinstall the CLI globally with the package manager the install path names |
|
|
21
|
-
| `canon migrate <verb>` | Move a project off a retired name or layout, reporting the plan until `--write` |
|
|
22
|
-
| `canon targets <verb>` | Report the projects this toolkit installed into |
|
|
23
|
-
| `canon gov <verb>` | Install and sync governance rules, and audit the tree against them |
|
|
24
|
-
| `canon tooling <verb>` | Sync, diff, and verify tooling stacks |
|
|
25
|
-
| `canon claude <verb>` | Install the Claude workflow and audit both skill corpora |
|
|
26
|
-
| `canon wiki <verb>` | Scaffold the wiki pages |
|
|
27
|
-
| `canon indexes <verb>` | Regenerate `index.md` files from sibling frontmatter, or flatten them |
|
|
28
|
-
| `canon docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name) |
|
|
29
|
-
| `canon design <verb>` | Render or regenerate `canon/DESIGN.md` tokens, emit their CSS, install the base stylesheet |
|
|
30
|
-
| `canon slides <verb>` | Render a deck folder of HTML slides, or list the decks |
|
|
31
|
-
| `canon capture [source]` | Render HTML or a URL to PNG and prove each declared font resolved |
|
|
32
|
-
| `canon serve [dir]` | Serve a directory on loopback and print the link that opens it |
|
|
33
|
-
| `canon demo <verb>` | Compile and record a running app |
|
|
34
|
-
| `canon inventory [subject]` | Group every route's elements by one computed property, never gating |
|
|
35
|
-
| `canon drive <url> <run>` | Walk a page through named interactions and measure each state |
|
|
36
|
-
| `canon transcripts <url>` | Fetch a YouTube transcript with metadata frontmatter (needs `yt-dlp`) |
|
|
37
|
-
| `canon teach <verb>` | Open and author learning workspaces |
|
|
38
|
-
| `canon canvas <verb>` | Serve a local canvas of pages and HTML frames, arrange, edit, and capture them |
|
|
39
|
-
| `canon sandbox [cat:cmd]` | Run sandbox scenarios, toolkit-only like the tree it reads |
|
|
40
|
-
| `canon tasks <verb>` | Read and write the task board, the plans it cites, and its archive |
|
|
41
|
-
| `canon intake <verb>` | Report intake folders and write answers into them |
|
|
42
|
-
| `canon records <verb>` | Validate, size, prune, and back up the session records |
|
|
43
|
-
| `canon sessions <verb>` | Resolve live sessions to worktree and branch, and move one between machines |
|
|
44
|
-
| `canon worktrees <verb>` | Report and remove worktrees whose pull request merged |
|
|
45
|
-
| `canon hooks <verb>` | Run the steps a git hook drives |
|
|
46
|
-
| `canon pr <verb>` | Read a pull request's diff, head, checks, and review, and post its evidence |
|
|
47
|
-
| `canon feedback` | Open a GitHub issue from toolkit feedback on stdin, or print the block on failure |
|
|
48
|
-
| `canon audits <verb>` | Run every audit as one set under one verdict against the recorded baseline |
|
|
49
|
-
| `canon gate <verb>` | Run every stage that guards a branch here |
|
|
50
|
-
| `canon secrets <verb>` | Report credential-shaped values in the tree the package ships |
|
|
51
|
-
| `canon deps <verb>` | Report published advisories against the resolved dependency set |
|
|
52
|
-
| `canon labels <verb>` | Read a changed set against the label map, and scan pull request text |
|
|
53
|
-
| `canon comments <verb>` | Measure comment density by language and kind, with a trend from git |
|
|
54
|
-
| `canon context <verb>` | Report context folder health, and classify changed or stale sections |
|
|
55
|
-
| `canon markdown <verb>` | Fail markdown on a banned character or a dead link, and report its structure |
|
|
56
|
-
| `canon census [path]` | Report tracked file count, extensions, and a line total skipping binaries |
|
|
57
|
-
| `canon upstream <verb>` | Read Claude Code releases from a cursor, and list the toolkit's own mechanisms |
|
|
58
|
-
|
|
59
|
-
`canon serve` drives no browser, which is what separates it from the four that do. All four ship now that `capture` does, so the line between them is the engine rather than the package. A generated page loses its script to an editor preview and to a `file://` open, so the link is the delivery rather than a convenience, and every generated surface here reaches a reader through one. A teach lesson's stylesheet is embedded rather than linked, so only its script still needs a server. It binds `127.0.0.1` and never a wildcard, because what it is pointed at is routinely a gitignored record tree. It sends `cache-control: no-store`, since a preview exists to be edited and reloaded and a cached stylesheet reads as a fix that did not work.
|
|
60
|
-
|
|
61
|
-
A port already in use is the ordinary case rather than a refusal, so it walks forward to the next free one and reports which it took. That is why a caller reads `url` off the `--json` record instead of composing one from the port it asked for. Only contention is walked past. Any other bind failure refuses as `bind-failed` carrying the error's code, rather than being retried twenty times and reported as a range being full, which names a cause nothing checked.
|
|
62
|
-
|
|
63
|
-
A request naming a directory is redirected to its trailing-slash form rather than answered in place. A browser resolves a relative asset against the last slash of the URL it is on, so answering `/lesson` directly leaves the page asking for `/course.css` instead of `/lesson/course.css`, and it renders unstyled through the server that exists to prevent exactly that.
|
|
64
|
-
|
|
65
|
-
Containment is tested after symlinks are followed rather than on the path as written, and the test sits immediately before the read rather than beside the request that produced it. Resolving a request lexically clears a link pointing outside the served root, and a link out of the served root is the shape it guards against. Position is what makes the property hold: a directory request appends its index after the request path has been checked, so a check placed earlier leaves that index untested. `--index` answers a directory holding no `index.html` with a listing read per request, where the default stays a 404. Every entry the listing names takes the same containment test a request for it would, so a link out of the root is absent rather than greyed, and dotfiles are hidden. With no `--entry` and no root `index.html`, the printed link is `/` and `entryExists` reads true. An `--entry` that escapes the root refuses with `no-entry` before a port is taken, because `url` is the field a caller hands to a reader.
|
|
66
|
-
|
|
67
|
-
`canon demo` is the second browser command and the one that ships, since its purpose is running in a target rather than regenerating what this repository commits. It needs a browser binary the package does not carry, installed once with `bunx playwright install chromium`.
|
|
68
|
-
|
|
69
|
-
`canon inventory` is the third and takes the same answer for the same reason. It reads `inventory.toml` at the project root for its base URL, its routes, and the element query each subject runs over, so what it walks comes from the project rather than from the toolkit. It reports how many different answers a site gives for one property and never gates, because whether five focus rings across four routes is a defect is a judgment. A missing server and an unmatched query are both refusals rather than empty listings, since a listing with no rows reads as one consistent answer.
|
|
70
|
-
|
|
71
|
-
```toml
|
|
72
|
-
base-url = "http://localhost:4173"
|
|
73
|
-
routes = ["/", "/pricing", "/docs"]
|
|
74
|
-
|
|
75
|
-
[subjects.focus]
|
|
76
|
-
query = "button, a[href], input, select, textarea, [tabindex]"
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
`canon drive` is the fourth and ships for the same reason the three before it do. What separates it from all three is the axis rather than the destination: `capture` and `inventory` each answer about a page as it loads, and every defect that exists only after a menu opens or the page scrolls is invisible to both. It takes a JSON run file naming the viewport, the probes, and the interaction sequence, since a route catalog is state a project holds and an interaction sequence is a script written for one question. Viewport heights are never defaulted, because the heights a defect hides at belong to the layout rather than to this command. It reports findings and never gates, since every probe it ships carries a class of false finding a throwaway version already produced. See `driver.md`.
|
|
80
|
-
|
|
81
|
-
## Domain commands
|
|
82
|
-
|
|
83
|
-
Each domain exposes a consistent shape where applicable: `list`, `install`, `sync`, `create`. The page named beside a domain carries its flags, records, and refusals, and `canon <domain> --help --all` prints every subcommand's flags.
|
|
84
|
-
|
|
85
|
-
- **`migrate`**, in `migrate.md`: `rename`, `skill-names`, `records`, `surface-roots`, `record-tree`, `rule-layout`, `scratch-evidence`, `record-layout`
|
|
86
|
-
- **`targets`**, in `targets.md`: `list`, `pulls`
|
|
87
|
-
- **`gov`**, in `install-and-sync.md`: `list`, `install`, `sync`, `build`, `regen`, `detect` (in `gov-detect.md`), `test-order`, `counts`, `superseded`, `citations`, `restated`
|
|
88
|
-
- **`tooling`**, in `install-and-sync.md`: `list`, `sync`, `diff`, `reference`, `verify`, `inject`, `prune-gitignore`
|
|
89
|
-
- **`claude`**, in `skills-audit.md`: `init`, `sync`, `setup`, `routing`, `plugin-update`, `seeds list`, `skills list`, `skills audit`, `skills drift`, `skills reach`, `skills rank`
|
|
90
|
-
- **`wiki`**, in `scripting.md`: `init`
|
|
91
|
-
- **`indexes`**, in `indexes.md`: `regen`, `list`
|
|
92
|
-
- **`docs`**, in `docs.md`: `list`, `<topic>`
|
|
93
|
-
- **`design`**, in `install-and-sync.md` for `install`, `sync`, and `fonts`, and below for the rest: `render`, `regen`, `css`, `install`, `sync`, `fonts`
|
|
94
|
-
- **`slides`**, described below: `render`, `list`
|
|
95
|
-
- **`demo`**, in `demo.md`: `compile`, `run`, `frames`
|
|
96
|
-
- **`inventory`**, described above: `run`
|
|
97
|
-
- **`teach`**, in `teach.md`: `list`, `up`, `open`, `resource`, `glossary`, `lesson`, `stylesheet`, `nav`, `render`
|
|
98
|
-
- **`canvas`**, described below: `serve`, `list`, `page add`, `page rename`, `frame add`, `frame move`, `frame resize`, `fit`, `arrange`, `selection`, `edit`, `editing`, `capture`
|
|
99
|
-
- **`sandbox`**, in `sandbox.md`: `run`, `equivalence`, `reset`, `clean`, `check`, `coverage`
|
|
100
|
-
- **`tasks`**, in `tasks.md`: `next-label`, `archive`, `decline`, `plan-citations`, `plan-answers`, `plan-branch`, `plan-reach`, `plan-link`, `pull-request`, `outcome`, `list`, `validate`
|
|
101
|
-
- **`intake`**, in `intake.md`: `list`, `answer`
|
|
102
|
-
- **`records`**, in `records.md`: `validate`, `ordinal`, `size`, `stale`, `prune-tmp`, `push`, `pull`
|
|
103
|
-
- **`sessions`**, in `sessions.md`: `list`, `export`, `import`
|
|
104
|
-
- **`worktrees`**, in `worktrees.md`: `list`, `reclaim`, `repair-bare-flag` (hidden)
|
|
105
|
-
- **`hooks`**, in `hooks.md`: `post-merge`
|
|
106
|
-
- **`pr`**, in `pr-reads.md`: `key-changes`, `head`, `checks`, `review-state`, `evidence`, `preview`, `local`, `frames`, `lift` (in `pr-lift.md`), `tick` (in `pr-tick.md`)
|
|
107
|
-
- **`upstream`**, in `upstream.md`: `fetch`, `catalog`, `due`, `advance`
|
|
108
|
-
- **`audits`**, in `audits.md`: `run`, `list`
|
|
109
|
-
- **`gate`**, in `gate.md`: `run`
|
|
110
|
-
- **`secrets`**, in `state-scoped-risk.md`: `scan`
|
|
111
|
-
- **`deps`**, in `state-scoped-risk.md`: `audit`
|
|
112
|
-
- **`labels`**, in `label-coverage.md`: `audit`, `apply`, `scan`
|
|
113
|
-
- **`comments`**, in `comments.md`: `scan`
|
|
114
|
-
- **`context`**, in `context-audit.md`: `audit`, `classify diff`, `classify sweep`, `classifier show`, `classifier set`
|
|
115
|
-
- **`markdown`**, in `markdown-audit.md`: `audit`
|
|
116
|
-
|
|
117
|
-
Common patterns:
|
|
118
|
-
|
|
119
|
-
- **`list --json`** → machine-readable catalog on stdout.
|
|
120
|
-
- **`install <name> <path>`** → install a specific entry into a target project.
|
|
121
|
-
- **`sync <path>`** → reapply all installed entries in a target project.
|
|
122
|
-
- **`create [name]`** → scaffold a new authoring entry in this repo.
|
|
123
|
-
|
|
124
|
-
Subcommands no other page describes:
|
|
125
|
-
|
|
126
|
-
- **`claude plugin-update`** matches the installed marketplace plugin against `claude/.claude-plugin/plugin.json`'s own name and runs `claude plugin update` on it, reading the version back off `claude plugin list --json`, since the update call reports none of its own (`--json`).
|
|
127
|
-
- **`claude skills rank`** scores either skill corpus's descriptions against a case corpus by TF-IDF cosine similarity, reporting rank-one and top-three (`--cases <path>`).
|
|
128
|
-
- **`design regen`** rewrites this repository's `canon/DESIGN.md` from `src/design/tokens.ts` and `src/design/base.css` from `src/design/neutral.ts`. `design css` emits the tokens and components as CSS on stdout, with `--no-components` for properties alone, and `design render` declares each vendored face the typography table names under `--embed-fonts`.
|
|
129
|
-
- **`slides list --json`** emits one row per deck under `.canon/slides/`, carrying `name`, `title`, `slides`, and `path`.
|
|
130
|
-
- **`slides render [deck]`** takes a deck name or a folder, defaulting to the only deck, and lays out each `.html` file in filename order in Chromium at 1280 by 720 and rebuilds it as editable shapes. Each element drawn as a picture prints one `✗` line on stderr naming the slide, the selector, and the properties that forced it. A link left out, being a `#slide-N` past the deck's end or any target that is neither that nor an absolute URL, prints one too, and the exit stays 0.
|
|
131
|
-
- **`slides.md`** describes a deck folder's `deck.json` and the faces it embeds, its per-slide `<body>` attributes, transitions and entrances, speaker notes, and charts.
|
|
132
|
-
- **`canvas`**, with its verbs, content format, and write routes, is described in `canvas.md`.
|
|
133
|
-
- **`labels apply <number>`** adds the labels this branch earns to its open pull request, refusing a pull request whose head is not the current branch or that is not open, and never creating a label the remote lacks or removing one a person added (`--check` writes nothing and exits 2 when labels are owed, `--base`, `--json`).
|
|
134
|
-
- **`labels scan`** fails a pull request or a posted review whose title, body, or review comment carries a phase label, a label a code span quotes, a gitignored record path, a session link, a banned character, a body heading outside the closed section list or a missing `## Summary` or `## Key changes`, or a title breaking `claude/skills/git-pr/references/pr.md`'s format, casing, or length rule (`--event`, `--body-file`, `--json`).
|
|
135
|
-
|
|
136
|
-
## Version skew
|
|
137
|
-
|
|
138
|
-
`canon sync --check` and `canon claude skills drift` are the two moments a
|
|
139
|
-
target already stops to reconcile with the toolkit, so each reports the
|
|
140
|
-
installed version against the newest published one. No other command performs
|
|
141
|
-
the lookup, which keeps a registry round trip out of the catalog reads an agent
|
|
142
|
-
runs in a loop.
|
|
143
|
-
|
|
144
|
-
The report carries three states and never changes an exit code. `behind` names
|
|
145
|
-
`canon upgrade` as the remedy, `current` says so, and `unknown` carries the
|
|
146
|
-
reason the registry could not be reached. Branch on the `skew.state` field in
|
|
147
|
-
the JSON record rather than on the exit, since an offline machine has to read as
|
|
148
|
-
unmeasured rather than as a failing check.
|
|
149
|
-
|
|
150
|
-
`canon upgrade --json` carries one further state, `pending`, that the skew
|
|
151
|
-
report does not: the working directory's checkout holds a release npm does not
|
|
152
|
-
serve yet, so there is nothing to install. The record names it in `checkout`
|
|
153
|
-
beside `latest`, exits 0, and its `message` starts `CLI stays at`. Outside a
|
|
154
|
-
canon checkout it never reads `pending`.
|
package/docs/agents/docs.md
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Docs
|
|
3
|
-
description: How canon docs resolves the toolkit's own reference surface from an install root, and how a split domain is named
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Docs
|
|
7
|
-
|
|
8
|
-
`canon docs` emits the toolkit's own reference docs so an agent in a target project can orient without the toolkit source checked out. The CLI resolves `docs/` and `canon/context/` from its install root, and which of the two it finds depends on how the CLI was installed. A registry install carries `docs/` alone, since `.claude/` is not published. A clone or a linked worktree carries both.
|
|
9
|
-
|
|
10
|
-
- `canon docs list [--json]` lists the downstream catalog: the consumer-facing `docs/` surface plus per-domain narrative from `canon/context/` when that root is present. Toolkit-internal context entries (`ci`, `development`, `sandbox`) are dropped. From a registry install the context section is absent rather than empty.
|
|
11
|
-
- `canon docs <topic>` prints one doc to stdout, resolved by exact name from `docs/` first, then `canon/context/`. Any doc the install carries is reachable by name, including the toolkit-internal topics the list omits.
|
|
12
|
-
|
|
13
|
-
## How a name resolves
|
|
14
|
-
|
|
15
|
-
A domain too large for one file splits into `<domain>/` with a generated `index.md`, and both verbs name it by the folder. `canon docs <domain>` prints that index, which is the catalog routing to the sub-area files, and the listing describes it from the index's `subtitle` where a sibling file supplies `description`. A folder carrying no `index.md` is absent from both, since a catalog is what makes the sub-areas reachable, and so are the files inside it.
|
|
16
|
-
|
|
17
|
-
A sub-area file resolves by its bare name too, so `canon docs operating-model` reaches `docs/workflow/operating-model.md`. Three spellings are tried in order, being a sibling file, a folder of that name, then a sub-area file one level down, and each spelling is tried across both roots before the next one runs. A sibling file therefore wins over a folder of the same name, and both win over a sub-area file. Reading the folder last is what keeps the sub-area spelling from changing any name that resolved before it existed.
|
|
18
|
-
|
|
19
|
-
The sub-area spelling keeps the root order too. The first root whose folders carry the name answers, so `canon docs indexes` reaches `docs/agents/indexes.md` even though a context folder holds an entry of the same name. A bare name carried by two folders of that one root resolves to neither, which names the available topics and exits 1 rather than answering with whichever folder sorts first.
|
|
20
|
-
|
|
21
|
-
`canon docs list` stops at the folder where `canon docs <topic>` goes on to name each file inside it. The listing is the downstream catalog rather than the index of what a name reaches, so a sub-area file appears there only where it declares a target-facing `category` of its own, and no sub-area file of the context root appears at all. A name that resolves and does not list is the divergence the toolkit-internal topics already carry.
|
|
22
|
-
|
|
23
|
-
## Output
|
|
24
|
-
|
|
25
|
-
Data prints to stdout and the frame to stderr, so `canon docs <topic> > out.md` captures clean markdown. With no topic and no verb, `canon docs` runs `list`. An unknown topic names the available topics on stderr and exits 1.
|
|
26
|
-
|
|
27
|
-
Only a `---` block opening on the first line counts as frontmatter, so a document body carrying horizontal rules emits whole.
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Drift surfaces
|
|
3
|
-
description: The seven sections canon sync --check reports beside the per-domain scan, being seeds, superseded artifacts, unmigrated domains, surfaces at the old root, new rules and skills, and the reverse walk, with the managed-target gate and what counts toward the exit code
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Drift surfaces
|
|
7
|
-
|
|
8
|
-
`canon sync --check` reports seven sections outside the per-domain scan that
|
|
9
|
-
`install-and-sync.md` describes, because each names something
|
|
10
|
-
that walk cannot see: `seeds`, `superseded`, `unmigrated`, `unmovedSurfaces`,
|
|
11
|
-
`newSkills`, `newRules`, and `reverse`. None of them produces a change, and no
|
|
12
|
-
sync command applies any of them. The headings below group the first four
|
|
13
|
-
together and give `newSkills` its description under `newRules`, which answers the
|
|
14
|
-
same question about a different corpus.
|
|
15
|
-
|
|
16
|
-
All seven report only against a toolkit-managed target, which is one carrying a
|
|
17
|
-
`.claude/` directory, a `CLAUDE.md`, or a domain still at the root layout. The
|
|
18
|
-
report says so through `managed` in the JSON and routes an unmanaged directory to
|
|
19
|
-
`canon init`. Seeds are why the gate exists, since they enumerate from the toolkit
|
|
20
|
-
source rather than from what a target installed, so an unmanaged directory would
|
|
21
|
-
otherwise report every seed as `missing`.
|
|
22
|
-
|
|
23
|
-
A root-layout domain counts as a marker on its own, because the detection fires
|
|
24
|
-
only on root files the toolkit ships and a project in the old layout is one the
|
|
25
|
-
toolkit installed. When `managed` is false every section comes back empty rather
|
|
26
|
-
than the render alone going quiet, so a consumer reading `--json` never acts on a
|
|
27
|
-
finding the rendered half withheld.
|
|
28
|
-
|
|
29
|
-
## Seeds, superseded artifacts, unmigrated domains, and old-root surfaces
|
|
30
|
-
|
|
31
|
-
`seeds` classifies every seed the toolkit ships against the target's copy, as
|
|
32
|
-
`matching`, `stale`, `drifted`, or `missing`. `missing` has no per-domain
|
|
33
|
-
equivalent, since the domain walk lists what a target installed and cannot see a
|
|
34
|
-
file that never arrived. There is no `customized` verdict here, because that one
|
|
35
|
-
needs a stamp and seeds carry none, so a file history cannot attribute stays
|
|
36
|
-
`drifted`. Merge the section by hand against the toolkit copy rather than
|
|
37
|
-
replacing a file the project edits.
|
|
38
|
-
|
|
39
|
-
A markdown seed installs rewritten rather than copied, since the `stub: true`
|
|
40
|
-
marker the toolkit's own seed gate reads is stripped on the way in. The
|
|
41
|
-
comparison above runs against what the install would write, so a marked seed a
|
|
42
|
-
target never touched still reports `matching`. Every other seed copies byte for
|
|
43
|
-
byte.
|
|
44
|
-
|
|
45
|
-
`superseded` names a file a newer seed folder replaced, such as `.claude/TASKS.md`
|
|
46
|
-
against the `.canon/tasks/` that now ships. The entry carries `replacedBy` and
|
|
47
|
-
nothing else, and the file is never deleted, since the content belongs to the
|
|
48
|
-
project and only its author can decide where it moves. The list derives from the
|
|
49
|
-
seed tree rather than from a fixed set of filenames, so a folder added later is
|
|
50
|
-
covered without a code change. Only an exact stem matches, which leaves a
|
|
51
|
-
suffixed variant such as `TASKS-ARCHIVE.md` unreported.
|
|
52
|
-
|
|
53
|
-
No skill splits the file. The destination's shape lives in the skill that owns
|
|
54
|
-
it, so the split is the project's own to make.
|
|
55
|
-
|
|
56
|
-
`unmigrated` names a domain sitting at the root layout an older toolkit installed
|
|
57
|
-
to, with nothing at the path the current one reads. It carries `rootPath`,
|
|
58
|
-
`installPath`, and a file count. Without it a project holding an older layout at its
|
|
59
|
-
root reports zero entries for that domain and reads as clean, which is the most
|
|
60
|
-
misleading state the report can produce.
|
|
61
|
-
|
|
62
|
-
The field currently names no domain. Snippets was the one the toolkit ever
|
|
63
|
-
installed at a project root, and it retired outright. A leftover `snippets/`
|
|
64
|
-
folder reports under the reverse walk instead, where `docs/target/sync.md` says
|
|
65
|
-
what to do with it.
|
|
66
|
-
|
|
67
|
-
`unmovedSurfaces` names a tracked surface the target still holds at its `.claude/`
|
|
68
|
-
spelling with nothing at the `canon/` one, such as `.claude/REQUIREMENTS.md` or
|
|
69
|
-
`.claude/context/`. Each entry carries `rel` and `movesTo`, and the render names
|
|
70
|
-
`canon migrate surface-roots`, the verb that moves them. Rules glob the `canon/`
|
|
71
|
-
spelling alone, so a target on the old root stops loading the rules scoped to
|
|
72
|
-
those files until it moves. <!-- canon-keep-surface-root -->
|
|
73
|
-
|
|
74
|
-
## Rules the target never received
|
|
75
|
-
|
|
76
|
-
`newRules` names a rule the target could receive and its tree does not hold. A
|
|
77
|
-
sync refreshes the files a target already holds and adds none, so without this
|
|
78
|
-
section a project's rule set freezes at its install date while every file it
|
|
79
|
-
does hold reports as current. That is the report's most confident wrong
|
|
80
|
-
answer, since a clean result reads as a target holding everything the toolkit
|
|
81
|
-
publishes.
|
|
82
|
-
|
|
83
|
-
The list rides beside `newSkills`, which asks the same question about the plugin
|
|
84
|
-
catalog. Both are names rather than paths, and neither queues a change, because
|
|
85
|
-
the two remedies differ: a skill loads live from the plugin directory and needs
|
|
86
|
-
nothing run, while a rule reaches a target only when someone runs
|
|
87
|
-
`canon gov install`.
|
|
88
|
-
|
|
89
|
-
Read a clean section as reporting rather than as delivering. Nothing here
|
|
90
|
-
installs, nothing counts toward `--exit-code`, and a target can read the list and
|
|
91
|
-
act on none of it. The value stops at an operator reading it, which is the same
|
|
92
|
-
contract the skills list already sets.
|
|
93
|
-
|
|
94
|
-
Since `canon gov install` records the stack it resolved, a target carrying that
|
|
95
|
-
record answers this by comparing its current entitlement against its current
|
|
96
|
-
tree, with no anchor and no git diff involved. That is what lets the section
|
|
97
|
-
name a rule that shipped before the target's last sync: the anchor a sync
|
|
98
|
-
advances plays no part in the read, where an anchor-bound diff can never see a
|
|
99
|
-
rule on the far side of a window a later sync moved past it. The per-file
|
|
100
|
-
`missing` state `canon gov sync` reports comes from the same comparison, so a
|
|
101
|
-
rule the chain lists reaches both surfaces the same way.
|
|
102
|
-
|
|
103
|
-
A target stamped before governance recorded a chain falls back to the older
|
|
104
|
-
rule-folder-inference read below. The measurement there anchors on governance's own
|
|
105
|
-
stamp rather than on the oldest anchor across domains, since rules are
|
|
106
|
-
domain-scoped and a shared anchor would let another domain's sync move the
|
|
107
|
-
revision rules are measured from. A target carrying no chain and no governance anchor
|
|
108
|
-
reports nothing at all: it has no date to measure against, and diffing from the
|
|
109
|
-
start of history would read the whole catalog as new.
|
|
110
|
-
|
|
111
|
-
An anchor this toolkit cannot resolve reports nothing by the same route, and that
|
|
112
|
-
one is not visible. A stamp naming a revision the running clone has never seen,
|
|
113
|
-
which is what a registry install without history or a shallow clone produces,
|
|
114
|
-
fails the read and yields an empty list rather than a stated absence. It looks
|
|
115
|
-
identical to a target holding every rule the toolkit publishes. `newSkills`
|
|
116
|
-
behaves the same way, and neither carries the `historyUnavailable` flag the
|
|
117
|
-
per-domain scan uses to separate the two. Treat an empty section on a toolkit
|
|
118
|
-
that is not a full clone as unmeasured rather than clean. This gap does not
|
|
119
|
-
reach the chain-based read above, since it consults no anchor at all.
|
|
120
|
-
|
|
121
|
-
In the fallback, entitlement is filtered, because a stack does not receive
|
|
122
|
-
every rule. The base stack names ten rules, the language stacks add `code` and
|
|
123
|
-
their own language and testing rules, and every other rule is opt-in, so an
|
|
124
|
-
unfiltered list would tell a base consumer about rules it can never receive and
|
|
125
|
-
train the reader to skip the section.
|
|
126
|
-
|
|
127
|
-
The filter accepts a rule folder on either of two grounds. A folder holding a rule the
|
|
128
|
-
base stack resolves to is entitled to every target, read through the stack file so
|
|
129
|
-
a rule added to base later needs no code change. Every other rule folder is read off the folders the
|
|
130
|
-
target already carries, which is the fallback's only evidence of what a target
|
|
131
|
-
was entitled to before it recorded a chain. One rule folder can be reached by more than
|
|
132
|
-
one stack, so the test over-reports inside a folder the target holds, which
|
|
133
|
-
costs a line where under-reporting would cost the section its point.
|
|
134
|
-
|
|
135
|
-
A rule the target already holds is dropped by name. That is what keeps a rule the
|
|
136
|
-
toolkit moved between rule folders out of the list, since a rename reaches this
|
|
137
|
-
read as an addition and only the name tells the two apart.
|
|
138
|
-
|
|
139
|
-
This closes the dangling-citation case as a side effect rather than checking for
|
|
140
|
-
one. The live instance is a rule citing a sibling authored after the target's
|
|
141
|
-
install, and the section names the sibling as new rather than naming the citation
|
|
142
|
-
as broken. That is enough for an operator to act on, and it is not a citation
|
|
143
|
-
check.
|
|
144
|
-
|
|
145
|
-
## The reverse walk
|
|
146
|
-
|
|
147
|
-
`reverse` is the one section built by walking the target rather than the
|
|
148
|
-
catalog. Every other surface enumerates toolkit-owned keys and asks whether the
|
|
149
|
-
target matches, so a folder the toolkit deleted appears in none of them. It
|
|
150
|
-
carries `unclaimed` and `historyUnavailable`.
|
|
151
|
-
|
|
152
|
-
`unclaimed` names a folder the target holds at a top-level path the toolkit once
|
|
153
|
-
shipped and has since deleted. The candidate roots come from the toolkit's own
|
|
154
|
-
history rather than from a list, so a root dropped later is covered without a
|
|
155
|
-
code change. Scoping to those roots is what keeps the walk useful: walking the
|
|
156
|
-
whole tree reports every project folder as unclaimed, which is true and says
|
|
157
|
-
nothing.
|
|
158
|
-
|
|
159
|
-
The managed gate above applies here too, and it is the one place it surprises.
|
|
160
|
-
A directory holding a dropped folder and nothing else reports an empty `reverse`
|
|
161
|
-
rather than the folder, because it carries none of the three markers. Read an
|
|
162
|
-
empty section on an unmanaged target as a walk that never ran rather than as a
|
|
163
|
-
clean result.
|
|
164
|
-
|
|
165
|
-
Each entry carries `rel`, a file count, and an `attribution` of `dropped`,
|
|
166
|
-
`project`, or `unattributed`. A dropped folder and one the project wrote are the
|
|
167
|
-
same bytes at the same path, so the verdict is traced from history rather than
|
|
168
|
-
guessed from the filesystem.
|
|
169
|
-
|
|
170
|
-
Content matching a version the toolkit published reads as `dropped` and carries
|
|
171
|
-
the `since` commit that published it. Names the toolkit shipped holding content
|
|
172
|
-
it never published read as `unattributed`, which is a state in its own right
|
|
173
|
-
rather than a soft yes. No overlap at all reads as `project`, and the render
|
|
174
|
-
drops those while the JSON keeps them.
|
|
175
|
-
|
|
176
|
-
Only files whose path the toolkit once held are hashed, so a project folder
|
|
177
|
-
colliding on a retired name costs the walk no reads. The cost is that a file the
|
|
178
|
-
toolkit shipped and the target renamed goes unmatched, the same limit the
|
|
179
|
-
`unmigrated` count carries.
|
|
180
|
-
|
|
181
|
-
## What counts toward the gate
|
|
182
|
-
|
|
183
|
-
`unmigrated` counts toward `--exit-code`, since running the relocation closes it.
|
|
184
|
-
`superseded` and every seed state are excluded, for the reason `orphaned` already
|
|
185
|
-
is: only the user can move content they wrote, so failing a job on it leaves the
|
|
186
|
-
job red with no mechanical remedy.
|
|
187
|
-
|
|
188
|
-
`unmovedSurfaces` is excluded although `canon migrate surface-roots` closes it.
|
|
189
|
-
The move rewrites citations across the project, so it is a change the project
|
|
190
|
-
schedules, and a job counting it would go red the day a target updated the CLI.
|
|
191
|
-
|
|
192
|
-
`newRules` is excluded on a different ground, since a command does close it. What
|
|
193
|
-
excludes it is that installing a rule changes what a project is governed by, so
|
|
194
|
-
gating on the count would pressure a target into adopting rules nobody chose.
|
|
195
|
-
`newSkills` is excluded because it needs no command at all.
|
|
196
|
-
|
|
197
|
-
The whole `reverse` section is excluded on the same grounds, and more strongly.
|
|
198
|
-
Every entry in it is a judgment about a file the project may own, and one of its
|
|
199
|
-
three verdicts is a labelled unknown by design. The unmigrated detection shipped
|
|
200
|
-
that exact false positive once, failing a push with no action that cleared it,
|
|
201
|
-
so this section reports and gates nothing.
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Rule detection
|
|
3
|
-
description: Proposing opt-in governance rules from a target's dependencies and paths, the evidence file the verb reads, the record it emits, and its exit codes
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rule detection
|
|
7
|
-
|
|
8
|
-
`canon gov detect` proposes the opt-in governance rules a target's evidence points at, and writes nothing. A rule no stack names reaches a project only through this verb, which `canon:target-setup` calls before it previews an install.
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
canon gov detect
|
|
12
|
-
canon gov detect ../my-app --stack node --json
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
| Option | Behavior |
|
|
16
|
-
| ----------------- | ------------------------------------------------ |
|
|
17
|
-
| `--stack <stack>` | Leave out every rule this stack already resolves |
|
|
18
|
-
| `--json` | Emit the record on stdout instead of the frame |
|
|
19
|
-
|
|
20
|
-
## Evidence
|
|
21
|
-
|
|
22
|
-
Each opt-in rule keeps a table in the toolkit's `governance/detect.toml`, keyed by rule basename. Its `deps` are package names, read from `package.json` (`dependencies` and `devDependencies`), `pyproject.toml`, `go.mod`, and `composer.json`. Its `files` are globs matched against the target's git-listed paths and against each folder on those paths, so `.github/workflows` matches a folder holding a workflow. A glob with no wildcard is also tested on disk, which is how `.canon/canvas` matches in a target that gitignores `.canon/`.
|
|
23
|
-
|
|
24
|
-
Both reads stop at depth two, which reaches a service folder and a workspace package under `packages/<name>/`. Outside git the verb walks the directory to the same depth and skips `.git`, `node_modules`, `vendor`, and `.venv`. A manifest that does not parse contributes nothing.
|
|
25
|
-
|
|
26
|
-
## Record
|
|
27
|
-
|
|
28
|
-
```json
|
|
29
|
-
{
|
|
30
|
-
"target": "/abs/path/my-app",
|
|
31
|
-
"stack": "node",
|
|
32
|
-
"proposals": [
|
|
33
|
-
{
|
|
34
|
-
"rule": "react",
|
|
35
|
-
"evidence": [{ "kind": "dep", "match": "react", "path": "package.json" }]
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
`kind` is `dep` for a dependency, with `path` naming the manifest that declares it, or `file` for a glob, with `path` naming what it matched. `stack` is null when no `--stack` was passed.
|
|
42
|
-
|
|
43
|
-
## Exit codes
|
|
44
|
-
|
|
45
|
-
The verb exits 0 on every readable target, including one with no evidence, which returns an empty `proposals` array. A target that does not exist and a `--stack` that does not resolve each exit 1 with the reason on stderr.
|
|
46
|
-
|
|
47
|
-
Install what the operator kept with `canon gov install --add <rules> <target>`, which needs no stack.
|
package/docs/agents/scripting.md
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Scripting
|
|
3
|
-
description: The runtime catalogs that replace hardcoded names, what each carries, and a headless invocation per domain
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Scripting
|
|
7
|
-
|
|
8
|
-
What a skill or script reads to discover names at runtime, and how each domain is invoked with no TTY.
|
|
9
|
-
|
|
10
|
-
## Runtime catalogs
|
|
11
|
-
|
|
12
|
-
Use these to discover what's available instead of hardcoding names.
|
|
13
|
-
|
|
14
|
-
| Command | Returns |
|
|
15
|
-
| --------------------------------- | ---------------------------------------------------------------- |
|
|
16
|
-
| `canon tooling list --json` | Stacks, extends chain, dep and script counts |
|
|
17
|
-
| `canon gov list --json` | Governance stacks, rule sets, evidence, and unreferenced rules |
|
|
18
|
-
| `canon gov detect --json` | Opt-in rules a target's dependencies and paths propose |
|
|
19
|
-
| `canon claude seeds list --json` | Seed doc sources with content |
|
|
20
|
-
| `canon claude skills list --json` | Plugin skills, descriptions, requirement flag, family vocabulary |
|
|
21
|
-
| `canon docs list --json` | Consumer docs plus per-domain context |
|
|
22
|
-
| `canon audits list --json` | Audits the set runs, the corpus each reads, and whether it gates |
|
|
23
|
-
|
|
24
|
-
### Catalog fields
|
|
25
|
-
|
|
26
|
-
Every catalog serializes through `JSON.stringify`, so a name carrying a quote
|
|
27
|
-
emits valid JSON. `canon tooling list` previously built
|
|
28
|
-
its output with `printf` and no escaping.
|
|
29
|
-
|
|
30
|
-
`canon claude seeds list` reads the same plan `canon claude init` applies, so the
|
|
31
|
-
listing and the install cannot disagree. It now reports
|
|
32
|
-
`canon/context/index.md`, which `init` has always installed and the listing
|
|
33
|
-
never named, and it emits the project-level `CLAUDE.md` last rather than first.
|
|
34
|
-
|
|
35
|
-
`canon gov list` reports each stack's rules already expanded. A stack entry names
|
|
36
|
-
either a rule or a whole rule folder under `governance/rules/`, and the folder
|
|
37
|
-
form reaches this listing as the rules it stands for rather than as the folder
|
|
38
|
-
name. A consumer deduping `--add` extras against a stack therefore reads the same
|
|
39
|
-
set the install writes, whichever form the stack file uses.
|
|
40
|
-
|
|
41
|
-
It also carries `unreferenced`, the rules no stack reaches, on every invocation
|
|
42
|
-
rather than behind a flag. These install only through `--add`, so the key answers
|
|
43
|
-
what a stack leaves out without a caller resolving every stack itself. The key is
|
|
44
|
-
present alongside `stacks` and `rules` and survives `--stacks` or `--rules`
|
|
45
|
-
narrowing the other two.
|
|
46
|
-
|
|
47
|
-
### The skills catalog
|
|
48
|
-
|
|
49
|
-
`canon claude skills list` reads `claude/skills/*/SKILL.md` and reports the folder
|
|
50
|
-
name with the frontmatter description, sorted by name. Internal skills under
|
|
51
|
-
`.claude/skills/` are excluded, since they never install into a target and a
|
|
52
|
-
count spanning both overstates what ships. A skill whose frontmatter is missing
|
|
53
|
-
or unparseable returns an empty description rather than failing the listing, so
|
|
54
|
-
one malformed file cannot hide the rest of the catalog. `--names` emits skill
|
|
55
|
-
names one per line.
|
|
56
|
-
|
|
57
|
-
Each skill in `--json` carries `family`, the `metadata.family` its frontmatter
|
|
58
|
-
declares, or `null` where it declares none. A top-level `families` array holds
|
|
59
|
-
the vocabulary as `{ key, group }` entries in skill map order, where `group` is
|
|
60
|
-
the map heading the family's rows sit under. Read a new skill's family from it
|
|
61
|
-
rather than from the map. `--by-family` prints the human listing as one step per
|
|
62
|
-
family, with a trailing step for any skill whose family is missing or unknown.
|
|
63
|
-
|
|
64
|
-
Each entry also carries `requirement`, whether the folder holds a sibling
|
|
65
|
-
`REQUIREMENT.md`. Every skill is meant to carry one, so a `false` is a gap to
|
|
66
|
-
close rather than a recorded exemption, and the flag answers which skills are
|
|
67
|
-
missing theirs without a caller listing the directory itself. `canon claude skills
|
|
68
|
-
audit` gates that rule across both corpora, so read this flag for the state of
|
|
69
|
-
the shipped catalog and the audit for whether a working tree conforms. Its
|
|
70
|
-
surface is in `skills-audit.md`.
|
|
71
|
-
|
|
72
|
-
## Non-interactive examples
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
# Report what a stack would change, writing nothing
|
|
76
|
-
CANON_NON_INTERACTIVE=1 canon tooling diff astro /path/to/project
|
|
77
|
-
|
|
78
|
-
# Sync a stack into a target project, overwriting its golden configs
|
|
79
|
-
CANON_NON_INTERACTIVE=1 canon tooling sync astro /path/to/project --write
|
|
80
|
-
|
|
81
|
-
# Install a governance stack (the stack argument is required headlessly)
|
|
82
|
-
CANON_NON_INTERACTIVE=1 canon gov install node --add astro,shadcn /path/to/project
|
|
83
|
-
|
|
84
|
-
# Update installed governance rules, dropping a retired .claude/GOV.md
|
|
85
|
-
CANON_NON_INTERACTIVE=1 canon gov sync /path/to/project
|
|
86
|
-
|
|
87
|
-
# Concatenate installed rules into a paste payload
|
|
88
|
-
CANON_NON_INTERACTIVE=1 canon gov build /path/to/project
|
|
89
|
-
|
|
90
|
-
# Sync a monorepo subtree, skipping the base layer the repo root already owns
|
|
91
|
-
CANON_NON_INTERACTIVE=1 canon tooling sync vite-react /path/to/repo/frontend --skip base --write
|
|
92
|
-
|
|
93
|
-
# Verify a stack end-to-end in a throwaway scaffold
|
|
94
|
-
canon tooling verify vite-react
|
|
95
|
-
|
|
96
|
-
# Apply one stack without scanning or prompting, for scripted provisioning
|
|
97
|
-
canon tooling inject base /path/to/project
|
|
98
|
-
canon tooling inject base /path/to/project --configs --seeds
|
|
99
|
-
|
|
100
|
-
# Drop managed gitignore entries a manifest no longer declares
|
|
101
|
-
# Prints the number removed on stdout, diagnostics on stderr
|
|
102
|
-
canon tooling prune-gitignore base /path/to/project
|
|
103
|
-
|
|
104
|
-
# Bootstrap a project. Any flag suppresses the confirmation prompt
|
|
105
|
-
CANON_NON_INTERACTIVE=1 canon init --stack node --skip wiki /path/to/project
|
|
106
|
-
|
|
107
|
-
# Run every domain sync. The git workflow is refused headlessly, so nothing is pushed
|
|
108
|
-
CANON_NON_INTERACTIVE=1 canon sync /path/to/project
|
|
109
|
-
|
|
110
|
-
# Scaffold .claude/wiki/ with a stub index. The target must already exist
|
|
111
|
-
CANON_NON_INTERACTIVE=1 canon wiki init /path/to/project
|
|
112
|
-
|
|
113
|
-
# Run a sandbox scenario non-interactively
|
|
114
|
-
SANDBOX_SCENARIO=sync canon sandbox infra:tooling
|
|
115
|
-
|
|
116
|
-
# Read every audit as one record. Exit 2 is a fact, 3 an audit that did not report
|
|
117
|
-
canon audits run --json
|
|
118
|
-
|
|
119
|
-
# Read committed state rather than an arriving change. Exit 2 carries findings
|
|
120
|
-
canon secrets scan --json
|
|
121
|
-
canon deps audit --json
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
The two state-scoped verbs both exit 2 on findings and mean different things by
|
|
125
|
-
it. A credential in the shipped tree is a fact and fails `canon audits run`, while
|
|
126
|
-
a published advisory is a judgment that reports and moves no verdict. Neither
|
|
127
|
-
reads a diff, so a consumer already running a review surface gets no overlap.
|
|
128
|
-
|
|
129
|
-
Both refuse rather than report clean when they have no corpus, and the refusal
|
|
130
|
-
reason is the field to branch on. A project publishing nothing refuses the secret
|
|
131
|
-
scan with `no-manifest`, and one whose dependencies are not installed refuses the
|
|
132
|
-
advisory check with `no-lockfile`. The aggregate reads those as an absent corpus
|
|
133
|
-
rather than a broken run, so neither pins its verdict at `incomplete`.
|
|
134
|
-
|
|
135
|
-
`canon tooling sync` is the one verb above whose flag is mandatory headlessly. It
|
|
136
|
-
overwrites every golden config a stack ships, which reaches the CI workflow, the
|
|
137
|
-
git hooks, the end-to-end harness, and the shell scripts under `scripts/`, so a
|
|
138
|
-
headless run carrying neither `--check` nor `--write` reports what it would
|
|
139
|
-
replace and exits 1 rather than applying it. Run `--check` first to read the
|
|
140
|
-
list, then `--write` to apply it. `canon tooling sync --help` names both, and
|
|
141
|
-
`canon tooling diff <stack> <target>` reports the per-stack path list resolved
|
|
142
|
-
against a real target.
|
package/src/markdown/growth.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { bodyLines } from '@/markdown/scan'
|
|
2
|
-
import {
|
|
3
|
-
CHECKPOINTS,
|
|
4
|
-
type Checkpoints,
|
|
5
|
-
type LongBlock,
|
|
6
|
-
longBlocks,
|
|
7
|
-
} from '@/markdown/structure'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Reduces text to the words a reader meets, so a block reflowed, re-marked, or
|
|
11
|
-
* moved under another heading still matches the copy it came from.
|
|
12
|
-
*
|
|
13
|
-
* List markers and emphasis marks are dropped because turning a bullet into a
|
|
14
|
-
* labelled bullet or a paragraph changes the shape of a statement and none of
|
|
15
|
-
* its words, which is the edit the sweep makes. A word changed is a text
|
|
16
|
-
* changed, and that is what the growth stage exists to see.
|
|
17
|
-
*/
|
|
18
|
-
export function normalizeProse(text: string): string {
|
|
19
|
-
return text
|
|
20
|
-
.replace(/^\s*(?:[-*+]|\d+\.)\s+/gm, '')
|
|
21
|
-
.replace(/[*_]/g, '')
|
|
22
|
-
.replace(/\s+/g, ' ')
|
|
23
|
-
.trim()
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The paragraphs and top-level bullets of `source` past their checkpoints whose
|
|
28
|
-
* text appears nowhere in `base`.
|
|
29
|
-
*
|
|
30
|
-
* Containment rather than line matching, so an unchanged long block passes
|
|
31
|
-
* wherever it sits and an edited or new one fails. `base` is every document the
|
|
32
|
-
* caller counts as the copy it may have come from, already normalized, since a
|
|
33
|
-
* block moved into a sibling entry is as unchanged as one left in place.
|
|
34
|
-
*/
|
|
35
|
-
export function grownBlocks(
|
|
36
|
-
source: string,
|
|
37
|
-
base: string,
|
|
38
|
-
checkpoints: Checkpoints = CHECKPOINTS,
|
|
39
|
-
): LongBlock[] {
|
|
40
|
-
return longBlocks(bodyLines(source), checkpoints).filter(
|
|
41
|
-
(block) => !base.includes(normalizeProse(block.text)),
|
|
42
|
-
)
|
|
43
|
-
}
|