@erclx/canon 5.32.0 → 5.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/SKILL.md +1 -1
- package/claude/skills/auto-ship/references/worktree-name.md +1 -1
- package/claude/skills/backlog-triage/REQUIREMENT.md +2 -2
- package/claude/skills/backlog-triage/SKILL.md +1 -1
- package/claude/skills/canon-cli/REQUIREMENT.md +16 -13
- package/claude/skills/canon-cli/SKILL.md +75 -32
- package/claude/skills/canon-feedback/SKILL.md +1 -1
- package/claude/skills/{canvas → canvas-board}/REQUIREMENT.md +2 -2
- package/claude/skills/{canvas → canvas-board}/SKILL.md +2 -2
- package/{standards → claude/skills/canvas-board/references}/design.md +11 -2
- package/claude/skills/context-fold/REQUIREMENT.md +25 -33
- package/claude/skills/context-fold/SKILL.md +25 -70
- package/claude/skills/context-fold/references/classify.md +3 -3
- package/claude/skills/context-fold/references/completion-report.md +4 -4
- package/claude/skills/context-fold/references/context-refresh.md +5 -5
- package/{standards → claude/skills/context-fold/references}/context.md +16 -5
- package/claude/skills/context-fold/references/unusable-baseline.md +3 -5
- package/claude/skills/create-rule/SKILL.md +2 -2
- package/{standards → claude/skills/create-rule/references}/rule.md +12 -5
- package/claude/skills/create-skill/SKILL.md +2 -2
- package/{standards → claude/skills/create-skill/references}/skill.md +17 -14
- package/claude/skills/design-taste/REQUIREMENT.md +3 -3
- package/claude/skills/design-taste/SKILL.md +1 -1
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -1
- package/claude/skills/docs-sync/SKILL.md +3 -3
- package/{standards → claude/skills/docs-sync/references}/docs.md +11 -0
- package/{standards → claude/skills/docs-sync/references}/readme.md +9 -2
- package/claude/skills/draft-and-pick/SKILL.md +5 -5
- package/claude/skills/draft-doc/SKILL.md +6 -6
- package/claude/skills/draft-figure/REQUIREMENT.md +2 -2
- package/claude/skills/draft-figure/SKILL.md +2 -2
- package/claude/skills/draft-figure/references/hand-drawn.md +1 -1
- package/claude/skills/draft-figure/references/mermaid-path.md +1 -1
- package/claude/skills/draft-identity/REQUIREMENT.md +2 -2
- package/claude/skills/draft-identity/SKILL.md +2 -2
- package/claude/skills/draft-ready/SKILL.md +1 -1
- package/claude/skills/git-branch/SKILL.md +1 -1
- package/{standards → claude/skills/git-branch/references}/branch.md +1 -1
- package/claude/skills/git-commit/SKILL.md +2 -2
- package/claude/skills/git-followup/REQUIREMENT.md +1 -1
- package/claude/skills/git-followup/SKILL.md +1 -1
- package/claude/skills/git-issue/SKILL.md +1 -1
- package/claude/skills/git-pr/SKILL.md +13 -13
- package/claude/skills/git-pr/references/evidence.md +2 -2
- package/claude/skills/git-pr/references/final-command.md +38 -14
- package/claude/skills/git-pr/references/labels.md +5 -1
- package/{standards → claude/skills/git-pr/references}/pr.md +19 -9
- package/{standards → claude/skills/git-pr/references}/publish.md +4 -2
- package/claude/skills/git-pr/references/task-number.md +1 -1
- package/claude/skills/git-ship/SKILL.md +15 -14
- package/claude/skills/git-split/SKILL.md +3 -3
- package/claude/skills/git-stage/SKILL.md +1 -1
- package/claude/skills/plan-feature/REQUIREMENT.md +1 -1
- package/claude/skills/review-address/SKILL.md +1 -1
- package/claude/skills/review-address/references/post-review-findings.md +1 -1
- package/claude/skills/review-pr/REQUIREMENT.md +1 -1
- package/claude/skills/review-pr/SKILL.md +3 -3
- package/claude/skills/review-pr/references/body-variants.md +2 -2
- package/claude/skills/review-pr/references/key-changes.md +3 -3
- package/claude/skills/review-pr/references/post.md +4 -2
- package/claude/skills/review-ui/REQUIREMENT.md +1 -1
- package/claude/skills/review-ui/SKILL.md +1 -1
- package/claude/skills/review-ui/references/post.md +1 -1
- package/claude/skills/role-orchestrator/REQUIREMENT.md +3 -0
- package/claude/skills/role-orchestrator/SKILL.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +8 -5
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +23 -1
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-resume.md +3 -0
- package/claude/skills/role-planner/REQUIREMENT.md +2 -1
- package/claude/skills/role-planner/SKILL.md +13 -2
- package/claude/skills/role-reviewer/SKILL.md +1 -1
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +9 -1
- package/claude/skills/session-map/SKILL.md +1 -1
- package/claude/skills/session-resume/REQUIREMENT.md +2 -2
- package/claude/skills/session-worktree/SKILL.md +5 -5
- package/claude/skills/target-setup/references/detect.md +1 -1
- package/claude/skills/task-board/REQUIREMENT.md +7 -12
- package/claude/skills/task-board/SKILL.md +5 -17
- package/claude/skills/task-board/references/tasks.md +2 -2
- package/claude/skills/task-complete/REQUIREMENT.md +47 -0
- package/claude/skills/task-complete/SKILL.md +86 -0
- package/claude/skills/{task-board → task-complete}/references/archive.md +4 -4
- package/claude/skills/{context-fold → task-complete}/references/receipt-sweep.md +5 -5
- package/claude/skills/task-complete/references/unusable-baseline.md +19 -0
- package/claude/skills/teach-workspace/REQUIREMENT.md +6 -2
- package/claude/skills/teach-workspace/SKILL.md +8 -4
- package/claude/skills/teach-workspace/references/lesson-craft.md +1 -1
- package/claude/skills/{context-fold/references/promoted-pages.md → teach-workspace/references/promotion-fold.md} +3 -3
- package/claude/skills/teach-workspace/references/promotion.md +3 -3
- package/claude/skills/ui-checklist/SKILL.md +1 -1
- package/claude/skills/ux-audit/SKILL.md +1 -1
- package/claude/skills/ux-measure/SKILL.md +1 -1
- package/docs/agents/canvas.md +1 -1
- package/docs/agents/commands.md +3 -2
- package/docs/agents/context-audit-checks.md +4 -4
- package/docs/agents/index.md +3 -3
- package/docs/agents/indexes.md +1 -1
- package/docs/agents/install-and-sync.md +6 -11
- package/docs/agents/key-changes.md +5 -5
- package/docs/agents/label-coverage.md +11 -0
- package/docs/agents/migrate.md +1 -1
- package/docs/agents/records-push.md +2 -2
- package/docs/agents/records-stale.md +12 -47
- package/docs/agents/records-validate.md +3 -7
- package/docs/agents/records.md +5 -27
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/sandbox.md +4 -4
- package/docs/agents/skills-audit.md +1 -1
- package/docs/agents/tasks-plans.md +2 -2
- package/docs/agents/tasks.md +2 -2
- package/docs/target/migrations.md +10 -2
- package/docs/target/projects.md +1 -1
- package/docs/target/sync.md +1 -1
- package/docs/workflow/operating-model.md +2 -2
- package/docs/workflow/parallel-features.md +7 -7
- package/docs/workflow/skill-map-on-request.md +9 -9
- package/docs/workflow/skill-map.md +12 -11
- package/docs/workflow/visual-design-workflow.md +2 -2
- package/governance/renames.toml +0 -11
- package/governance/rules/canon/context.md +13 -0
- package/governance/rules/claude/skill.md +17 -0
- package/governance/stacks/base.toml +2 -4
- package/package.json +4 -4
- package/scripts/core/install-check.sh +3 -3
- package/scripts/lib/ui.sh +0 -159
- package/src/audits/catalog.ts +0 -1
- package/src/claude/cases/misc.ts +1 -1
- package/src/claude/cases/setup.ts +4 -0
- package/src/claude/cases/workflow.ts +6 -1
- package/src/claude/seeds.ts +1 -1
- package/src/claude/skills-audit.ts +2 -2
- package/src/cli/help.ts +3 -1
- package/src/cli/ui.ts +2 -3
- package/src/commands/claude.ts +1 -1
- package/src/commands/gov.ts +2 -15
- package/src/commands/labels.ts +326 -7
- package/src/commands/migrate.ts +6 -1
- package/src/commands/pr.ts +1 -1
- package/src/commands/records.ts +13 -399
- package/src/commands/sandbox.ts +3 -6
- package/src/commands/tasks.ts +3 -3
- package/src/context/audit.ts +5 -5
- package/src/context/folders.ts +1 -1
- package/src/design/budget.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/regen.ts +1 -1
- package/src/design/render.ts +1 -1
- package/src/gate/measures.ts +1 -1
- package/src/gate/sequencer.ts +56 -1
- package/src/gate/stages.ts +1 -7
- package/src/gov/install.ts +2 -3
- package/src/gov/stacks.ts +1 -1
- package/src/hooks/post-merge.ts +1 -1
- package/src/labels/apply.ts +39 -0
- package/src/labels/format.ts +3 -3
- package/src/labels/phase.ts +3 -3
- package/src/labels/sections.ts +43 -0
- package/src/migrate/skill-names.ts +20 -1
- package/src/pr/paths.ts +4 -4
- package/src/records/backup.ts +16 -6
- package/src/records/stale-canonical.ts +31 -1
- package/src/records/validate.ts +2 -188
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/coverage.ts +2 -6
- package/src/sandbox/equivalence.ts +5 -44
- package/src/sandbox/expect.ts +4 -4
- package/src/sandbox/provision.ts +13 -36
- package/src/sandbox/scenario.ts +26 -48
- package/src/sandbox/tree.ts +2 -6
- package/src/standards/read.ts +14 -1
- package/src/sync/git.ts +1 -1
- package/src/tasks/archive.ts +5 -5
- package/src/tasks/branch.ts +3 -3
- package/src/tasks/label.ts +1 -1
- package/src/tasks/record.ts +2 -2
- package/src/tasks/validate.ts +1 -1
- package/standards/index.md +0 -13
- package/standards/standard.md +1 -7
- package/tooling/base/reference.md +1 -1
- package/tooling/base/seeds/.github/pull_request_template.md +2 -2
- package/tooling/claude/reference.md +1 -1
- package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +9 -1
- package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +171 -0
- package/tooling/claude/seeds/.claude/settings.json +9 -0
- package/governance/rules/standards/context.md +0 -14
- package/governance/rules/standards/design.md +0 -12
- package/governance/rules/standards/readme.md +0 -12
- package/governance/rules/standards/rule.md +0 -13
- package/governance/rules/standards/skill.md +0 -21
- package/governance/rules/standards/standard.md +0 -13
- package/scripts/config.sh +0 -11
- package/scripts/lib/gov.sh +0 -14
- package/scripts/lib/sandbox-fixtures.sh +0 -191
- package/scripts/lib/sandbox-git.sh +0 -125
- package/scripts/lib/sandbox-path.sh +0 -50
- package/scripts/sandbox-hook.sh +0 -99
- package/src/gov/standard-rules.ts +0 -179
- package/src/records/migrate.ts +0 -78
- package/src/records/stale.ts +0 -243
- package/src/sandbox/hooks.ts +0 -128
- /package/claude/skills/{canvas → canvas-board}/references/canvas.md +0 -0
- /package/{standards → claude/skills/draft-figure/references}/figures.md +0 -0
- /package/{standards → claude/skills/git-branch/references}/slug.md +0 -0
- /package/{standards → claude/skills/git-commit/references}/commit.md +0 -0
- /package/{standards → claude/skills/git-commit/references}/versioning.md +0 -0
|
@@ -38,23 +38,23 @@ The plan's shape is fixed by `claude/skills/plan-feature/references/plan.md`: th
|
|
|
38
38
|
|
|
39
39
|
An execution that picks other than the suggestion rewrites the `- Suggested:` line as `overridden at execution to <pick>,` followed by the measurement that moved it, and leaves the slot blank. That fixed phrase is how a reader of the archived plan tells an override from a suggestion the execution accepted, since an authored suggestion often carries a number of its own. The same deviation takes one line in the open task's `## Findings`, which is the register that survives the plan being archived. A deviation from a question somebody already answered goes back to whoever answered it instead, since a filled slot is a decision already made.
|
|
40
40
|
|
|
41
|
-
`canon records validate plans` reports where a plan and that standard disagree: a filename that is not `feature-<slug>.md`, a missing required section, a files-to-touch entry naming no file, and a question carrying a suggestion with no answer slot. The same verb takes `groundwork`, `intake`,
|
|
41
|
+
`canon records validate plans` reports where a plan and that standard disagree: a filename that is not `feature-<slug>.md`, a missing required section, a files-to-touch entry naming no file, and a question carrying a suggestion with no answer slot. The same verb takes `groundwork`, `intake`, and `teach`, which are governed the same way and were unreachable for the same reason. Nothing fires it automatically, because all four folders are gitignored and every check the repository runs reads changed files from git. It reports and never writes, since the folders are per-machine scratch with no history to recover a wrong repair from.
|
|
42
42
|
|
|
43
43
|
`canon records push` carries these folders off the disk they live on, and `canon records pull` brings them back. Every top-level entry under `.canon/` is backed except `tmp`, `ordinal-locks`, and `.records.git`, so a folder added later enters the payload on its own rather than waiting on a name written into a list. Push names each folder it carries the first time it sees it, which is what keeps a stray folder visible instead of silently entering the payload. It refuses the whole push, naming each path, when a new or changed file is over 25 MB or carries a credential `canon secrets scan` would report. The history lives in a second git directory at `.canon/.records.git` with `.canon/` as its work tree, so every path a task file cites stays where it is.
|
|
44
44
|
|
|
45
45
|
A person points it at a private repository once and both verbs refuse until they have, and `push` refuses when that origin is also a remote of the project, since the payload is the task board and the groundwork trails. `.husky/post-merge` runs the push after its archive loop, on every merge rather than only on one that closed a task. See [records push](../agents/records-push.md) for the refusal table.
|
|
46
46
|
|
|
47
|
-
`canon records size` reports what each of these folders holds, heaviest first, along with `.canon/tmp`. Each row carries the file count, the bytes, how many files were written in the last 7 and 30 days, and the dates of the least and most recently written one. Nothing fails on a number, because a record folder has no correct size. What the verb replaces is a reading somebody had to remember to take:
|
|
47
|
+
`canon records size` reports what each of these folders holds, heaviest first, along with `.canon/tmp`. Each row carries the file count, the bytes, how many files were written in the last 7 and 30 days, and the dates of the least and most recently written one. Nothing fails on a number, because a record folder has no correct size. What the verb replaces is a reading somebody had to remember to take: a pen went from 44 entries to 236 between two counts made by hand a fortnight apart, and nothing reported the rate in between.
|
|
48
48
|
|
|
49
49
|
`canon records prune-tmp` reports scratch under `.canon/tmp` nobody has touched inside an age window, and deletes it only with `--write`. A `tmp/handoff/` folder and the live `tmp/pr/poll/` baseline are never offered, since a reader deletes a handoff once it is read and a poll baseline is state a session still needs. See [records](../agents/records.md) for the candidate shapes and the exit codes.
|
|
50
50
|
|
|
51
|
-
`canon records stale
|
|
51
|
+
`canon records stale canonical` reports when the requirements record was last reviewed and how many releases have shipped since, so a review of it starts from a count rather than from the tag list. It writes nothing. See [records stale](../agents/records-stale.md) for how the count is taken and the refusals.
|
|
52
52
|
|
|
53
53
|
A plan that ships is archived, never deleted. `canon tasks archive` moves it to `.canon/plans/archive/` alongside the task it belonged to and retargets that task's `Plan:` line at the new location, so a completed task still leads to the reasoning behind it. An archive sits inside the record folder it archives rather than beside it, so one ignore entry and one backed-folder entry cover a record and everything it has retired. The folder is gitignored, which is why a deleted plan had no recovery path. A plan cited by more than one task stays put until the last of them closes, since moving it early would strand every other pointer.
|
|
54
54
|
|
|
55
|
-
An older branch review report takes the other route and is swept rather than archived. It sits flat in `.canon/review/` as `branch-<slug>.md`, the session addressing it read it once, and the durable record of what a review found is the comment `review-pr` posts on the pull request, so `
|
|
55
|
+
An older branch review report takes the other route and is swept rather than archived. It sits flat in `.canon/review/` as `branch-<slug>.md`, the session addressing it read it once, and the durable record of what a review found is the comment `review-pr` posts on the pull request, so `canon:task-complete` deletes any report whose branch is gone. The body that writes a report owns how long it lives, which leaves the shipping branch's own report on disk through the run that cites it and collects it a branch later. What that loses is a local-only review on a branch that never opened a pull request, which is why the report says so where a reader meets it.
|
|
56
56
|
|
|
57
|
-
`canon:
|
|
57
|
+
`canon:task-complete` decides which task closed by reading the diff rather than the conversation, as the ship-chain step after `canon:context-fold`. It resolves a merge base against `origin/main`, unions the committed diff with the working tree and untracked files, then matches unchecked outcomes on the board against what shipped. A task that shipped without ever being discussed still gets marked. Decisions stay session-sourced, because a diff cannot carry a judgment, and `canon:context-fold` folds them into the context entries. The requirements record is never folded. A direction change gets one report line naming `canon:document-health`, which reviews that record only when asked.
|
|
58
58
|
|
|
59
59
|
## Shipping a fan-out
|
|
60
60
|
|
|
@@ -87,12 +87,12 @@ A hand-maintained `priority.md` sits beside the index carrying execution order a
|
|
|
87
87
|
|
|
88
88
|
Past that shape, it checks what a surviving row claims against what the tree holds: every plan pointer resolves, every task file is named by a board row or a backlog line and never by both, no task sits in two groups, and every row marked ready names its files. One check across both surfaces is what lets a task move between the board and the backlog without the move reading as a dropped file. Paths two ready rows share go to a `shared` array moving no exit code, the candidate list the orchestrator's conflict check reads. Blockers re-takes what a parked row waits on, reporting one whose cited task reached the trunk and one whose cited file nothing running still holds. A cited task settles the row by being archived, or by closing every outcome and naming a pull request the trunk carries, since the checkbox alone is marked while the branch is still in review. Both halves read a citation out of the blocker cell, so a row citing neither is reported as untested rather than counted clean, and so is a cited task the trunk could not answer for. It reports and never writes, because a row is the orchestrator's claim and a validator repairing one would assert the claim it exists to test. Nothing fires it automatically, since the board is gitignored per-machine scratch with no shared moment to hang a hook on, so the orchestrator's sweep calls it at the point the readiness claim is made and follows it with the parked re-test.
|
|
89
89
|
|
|
90
|
-
`canon:task-board`
|
|
90
|
+
`canon:task-board` creates the file, holding the filename convention and the frontmatter contract so a malformed write cannot break the index for every sibling, and declines a task decided against. `canon:task-complete` marks a shipped task's outcomes and moves one the merge hook left to `.canon/tasks/archive/`. Creation is where the origin invariant is enforced: every task names a plan, a groundwork folder, an intake folder, or an issue, since a task with no origin is either lost context or work nobody decided to do.
|
|
91
91
|
|
|
92
92
|
Archiving a task carries its plan with it, in the same act. The merge is what settles a plan, and the hook below reaches the archive with nobody watching, so a second call after it would be a second failure point leaving the task archived and the plan live. A task whose plan a sibling still cites archives on its own and leaves the plan live, since moving it on the first task to close strands every other pointer at a path that has gone.
|
|
93
93
|
|
|
94
94
|
Nothing chained that archive until the `post-merge` git hook landed. Every earlier step fires from `canon:auto-ship` or `canon:git-ship`, both of which finish while the pull request is still open, so a task archived there would close for work that may be abandoned. The board is gitignored, which rules out reading it from anywhere but the machine that pulled. The hook archives the task a merged pull request closed, through the same verb the base stack ships to every target, and does nothing on a project with no board.
|
|
95
95
|
|
|
96
|
-
The archive gates on a pull request number the merge carried and a closed task, because outcomes are marked on the branch and a task can read all `[x]` while its pull request is still open, so `canon:task-
|
|
96
|
+
The archive gates on a pull request number the merge carried and a closed task, because outcomes are marked on the branch and a task can read all `[x]` while its pull request is still open, so `canon:task-complete` still confirms the work reached `main` when a person archives by hand. A companion `post-rewrite` hook carries the same steps for anyone pulling with rebase, which fires that event instead of `post-merge`.
|
|
97
97
|
|
|
98
98
|
The hook archives through `canon tasks archive`, which carries the refusals above, so a task whose pull request has not merged stays where it is. Both hooks ship with the `base` tooling stack, so a target project running this workflow gets the same trigger, and `CANON_SKIP_RECLAIM`, `CANON_SKIP_UPGRADE`, and `CANON_SKIP_PLUGIN_UPDATE` turn off the three steps that act on the machine.
|
|
@@ -25,15 +25,15 @@ These two groups hold the skills no single moment in a project's life calls for,
|
|
|
25
25
|
|
|
26
26
|
## Answer a question at any point
|
|
27
27
|
|
|
28
|
-
| Skill | When to use
|
|
29
|
-
| --------------------------- |
|
|
30
|
-
| `canon:canon-cli` |
|
|
31
|
-
| `canon:youtube-transcripts` | When a video transcript is wanted in the repo as context
|
|
32
|
-
| `canon:read-frames` | To read a recorded demo back frame by frame and report what each one shows, with no verdict on whether the recording looks right
|
|
33
|
-
| `canon:teach-workspace` | To learn a subject across sessions, in a workspace that holds the progress
|
|
34
|
-
| `canon:markdown-craft` | Before a substantial markdown edit, for the format and structure rules and the audit that follows
|
|
35
|
-
| `canon:write-human` | Before drafting or revising prose, for voice, rhythm, and density
|
|
28
|
+
| Skill | When to use |
|
|
29
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `canon:canon-cli` | To pick the `canon` verb that does a job, or before a sync or migrate, to learn which verbs can lose the project's edits |
|
|
31
|
+
| `canon:youtube-transcripts` | When a video transcript is wanted in the repo as context |
|
|
32
|
+
| `canon:read-frames` | To read a recorded demo back frame by frame and report what each one shows, with no verdict on whether the recording looks right |
|
|
33
|
+
| `canon:teach-workspace` | To learn a subject across sessions, in a workspace that holds the progress |
|
|
34
|
+
| `canon:markdown-craft` | Before a substantial markdown edit, for the format and structure rules and the audit that follows |
|
|
35
|
+
| `canon:write-human` | Before drafting or revising prose, for voice, rhythm, and density |
|
|
36
36
|
|
|
37
37
|
Every row answers a question rather than marking a point in a project's life, so filing one under a phase on the [skill map](skill-map.md) would send a reader to the wrong group.
|
|
38
38
|
|
|
39
|
-
A learning workspace produces two halves and only one of them leaves. A lesson is worked through once and stays in the workspace, and a reference page or a glossary carries no learner, so it belongs wherever the project already keeps prose on that subject. Asking `canon:teach-workspace` to promote sorts each durable page by who owns its subject, sending an Anthropic-owned subject to the wiki, an internal one to the matching context entry, and everything else, subject-neutral material included, to the public docs. It proposes and waits, because a promoted page is public prose that needs a line naming who owns the subject, and it writes nothing to a destination: each page the operator confirms goes to a handoff file that `canon:
|
|
39
|
+
A learning workspace produces two halves and only one of them leaves. A lesson is worked through once and stays in the workspace, and a reference page or a glossary carries no learner, so it belongs wherever the project already keeps prose on that subject. Asking `canon:teach-workspace` to promote sorts each durable page by who owns its subject, sending an Anthropic-owned subject to the wiki, an internal one to the matching context entry, and everything else, subject-neutral material included, to the public docs. It proposes and waits, because a promoted page is public prose that needs a line naming who owns the subject, and it writes nothing to a destination: each page the operator confirms goes to a handoff file that `canon:teach-workspace` folds in from a branch in its fold mode. A project with no wiki folder gets a refusal naming `canon wiki init` rather than a folder it never asked for.
|
|
@@ -29,8 +29,8 @@ Each row sits under the group its skill's `metadata.family` names. The landing p
|
|
|
29
29
|
| `canon:plan-groundwork` | When the state is unmeasured and more than one approach is live |
|
|
30
30
|
| `canon:decision-escalate` | When open decisions turn on your preference and want batching into one set |
|
|
31
31
|
| `canon:draft-and-pick` | When the call is taste and wants several candidates rendered side by side |
|
|
32
|
-
| `canon:canvas`
|
|
33
|
-
| `canon:task-board` | When a decided item needs a file on the board, or
|
|
32
|
+
| `canon:canvas-board` | When a direction should be drawn as frames the operator can see, select, and edit |
|
|
33
|
+
| `canon:task-board` | When a decided item needs a file on the board, or one is decided against |
|
|
34
34
|
| `canon:plan-feature` | When the approach is settled and the next step is a plan |
|
|
35
35
|
| `canon:codebase-layout` | When a plan or change adds a file and you need to decide which folder holds it |
|
|
36
36
|
|
|
@@ -63,15 +63,16 @@ Each row sits under the group its skill's `metadata.family` names. The landing p
|
|
|
63
63
|
|
|
64
64
|
## Ship it
|
|
65
65
|
|
|
66
|
-
| Skill
|
|
67
|
-
|
|
|
68
|
-
| `canon:git-ship`
|
|
69
|
-
| `canon:context-fold`
|
|
70
|
-
| `canon:
|
|
71
|
-
| `canon:
|
|
72
|
-
| `canon:git-
|
|
73
|
-
| `canon:git-
|
|
74
|
-
| `canon:git-
|
|
66
|
+
| Skill | When to use |
|
|
67
|
+
| --------------------- | ----------------------------------------------------------------------------------------------- |
|
|
68
|
+
| `canon:git-ship` | To run the whole post-feature chain from the verify gate through open PR |
|
|
69
|
+
| `canon:context-fold` | When decisions diverged from the plan, or the diff left a context entry stale |
|
|
70
|
+
| `canon:task-complete` | After the fold, to mark the outcomes the diff shipped, or to archive a task the merge hook left |
|
|
71
|
+
| `canon:docs-sync` | When a change since main left `README.md` or `docs/` stale |
|
|
72
|
+
| `canon:git-stage` | When the staged set spans several concerns and wants one commit each |
|
|
73
|
+
| `canon:git-commit` | When the staged set is one concern, or was staged hunk by hand |
|
|
74
|
+
| `canon:git-branch` | When a branch name needs generating or renaming to conventional form |
|
|
75
|
+
| `canon:git-pr` | When a pull request needs a title and body written from the diff |
|
|
75
76
|
|
|
76
77
|
## After the pull request opens
|
|
77
78
|
|
|
@@ -20,7 +20,7 @@ Claude Code reads it and writes the implementation. Works for CLI tools, interna
|
|
|
20
20
|
|
|
21
21
|
### Seed shape
|
|
22
22
|
|
|
23
|
-
The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table template with a starting set of roles, and `
|
|
23
|
+
The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table template with a starting set of roles, and `claude/skills/canvas-board/references/design.md` carries the same tables under `## Template` with placeholder rows. The column headers are what the renderer parses, so they stay verbatim in either, while the rows and values are the project's own.
|
|
24
24
|
|
|
25
25
|
`canon design render` writes an HTML plus CSS preview to `.canon/tmp/render/design/` for eyeballing the current system without leaving Claude Code. See `canon/context/design/index.md`.
|
|
26
26
|
|
|
@@ -39,7 +39,7 @@ A cell no source anchors ends in `? verify`, and the preview shows that marker b
|
|
|
39
39
|
- `canon:ux-audit` for UX gap detection on existing surfaces
|
|
40
40
|
- `canon:ux-measure` for what a running surface costs to paint, read against published thresholds
|
|
41
41
|
- `canon:draft-and-pick` for a call settled by looking, drafting several candidates as frames on the canvas and taking your pick
|
|
42
|
-
- `canon:canvas` for a direction worked out over several turns, drawn as HTML frames you drag, select, and restyle in the browser while the session reads your changes back. Only the pick moves into `canon/DESIGN.md`, since the canvas folder is gitignored
|
|
42
|
+
- `canon:canvas-board` for a direction worked out over several turns, drawn as HTML frames you drag, select, and restyle in the browser while the session reads your changes back. Only the pick moves into `canon/DESIGN.md`, since the canvas folder is gitignored
|
|
43
43
|
- `canon:draft-identity` to draft a project's logo mark and compose it into an icon sequence and a social card, through `draft-and-pick`'s own render-and-pick loop. On an Astro project holding the card route scaffold, the card lands as a route the project keeps and is captured through a running server, so it reads the project's real stylesheet rather than typed copies of every color. Everywhere else it ships as a PNG and the run says so.
|
|
44
44
|
- Anthropic's `frontend-design` plugin optional for light visual steering
|
|
45
45
|
|
package/governance/renames.toml
CHANGED
|
@@ -13,10 +13,6 @@
|
|
|
13
13
|
# resolves A only while both links stay. A key must name no live rule and every
|
|
14
14
|
# chain must end on one, which `src/gov/renames.test.ts` checks against this
|
|
15
15
|
# file.
|
|
16
|
-
#
|
|
17
|
-
# A numbered rule replaced by the rule `canon gov regen` generates from its
|
|
18
|
-
# standard is a rename too: the generated rule keeps every glob and bullet, so
|
|
19
|
-
# the pair is one-to-one identity under the standard's name.
|
|
20
16
|
[renamed]
|
|
21
17
|
"015-output" = "566-output"
|
|
22
18
|
"035-tasks" = "602-tasks"
|
|
@@ -25,22 +21,15 @@
|
|
|
25
21
|
"087-git" = "606-git"
|
|
26
22
|
"510-context" = "610-context"
|
|
27
23
|
"511-indexes" = "611-indexes"
|
|
28
|
-
"550-design" = "650-design"
|
|
29
24
|
"555-tasks" = "655-tasks"
|
|
30
25
|
"558-plan" = "658-plan"
|
|
31
26
|
"501-markdown" = "801-markdown"
|
|
32
|
-
"580-readme" = "880-readme"
|
|
33
|
-
"591-standard-authoring" = "891-standard-authoring"
|
|
34
27
|
"065-spelling" = "765-spelling"
|
|
35
28
|
"075-dependencies" = "775-dependencies"
|
|
36
29
|
"080-config-comments" = "780-config-comments"
|
|
37
30
|
"090-code-comments" = "790-code-comments"
|
|
38
31
|
"658-plan" = "plan"
|
|
39
32
|
"610-context" = "context"
|
|
40
|
-
"650-design" = "design"
|
|
41
33
|
"655-tasks" = "tasks"
|
|
42
34
|
"570-skill" = "skill"
|
|
43
|
-
"590-rule-authoring" = "rule"
|
|
44
35
|
"801-markdown" = "markdown"
|
|
45
|
-
"880-readme" = "readme"
|
|
46
|
-
"891-standard-authoring" = "standard"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Route edits under canon/context/ to the context-fold skill for the entry shape, and keep each entry conforming to the work in its domain
|
|
3
|
+
paths:
|
|
4
|
+
- 'canon/context/**'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Context standards
|
|
8
|
+
|
|
9
|
+
## Context entries
|
|
10
|
+
|
|
11
|
+
- Load the `canon:context-fold` skill before a hand edit under `canon/context/`. It carries the entry shape and the content rules for a domain entry. Report it rather than proceeding silently when the skill does not resolve.
|
|
12
|
+
- Before non-trivial work in a domain, read its `canon/context/<domain>/` entry. Use `canon/context/index.md` to find it.
|
|
13
|
+
- Leave the entry conforming when work in its domain changes what it describes.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Route edits to a skill body or its requirement to the create-skill skill for the shape, and hold the creation-time questions and the re-read rule
|
|
3
|
+
paths:
|
|
4
|
+
- '.claude/skills/**/SKILL.md'
|
|
5
|
+
- 'claude/skills/**/SKILL.md'
|
|
6
|
+
- '.claude/skills/**/REQUIREMENT.md'
|
|
7
|
+
- 'claude/skills/**/REQUIREMENT.md'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Skill standards
|
|
11
|
+
|
|
12
|
+
## Skill files
|
|
13
|
+
|
|
14
|
+
- Load the `canon:create-skill` skill before a hand edit to a `SKILL.md` or a `REQUIREMENT.md`. It carries the skill structure, the requirement shape, and the path rules for a skill body. Report it rather than proceeding silently when the skill does not resolve. It ships with the plugin and this rule ships with the CLI, so a project that installed governance alone does not have it.
|
|
15
|
+
- Confirm `canon:create-skill`'s two creation-time questions are answered before a new `SKILL.md` lands, whether drafted by hand, by another skill, or by `canon:create-skill` itself. Carry the third question into the sibling `REQUIREMENT.md`'s `Must not` section as a review criterion rather than a gate.
|
|
16
|
+
- Re-read a skill body this session edited before invoking that skill again in the same session.
|
|
17
|
+
- Do not read a resolved file path in a held body as evidence the body is current.
|
|
@@ -5,7 +5,5 @@ extends = ""
|
|
|
5
5
|
# session conduct and `.claude/` authoring rules, `tooling` the dev setup and
|
|
6
6
|
# CI workflow rules, and `writing` the prose and document-shape rules. The
|
|
7
7
|
# `code` group is left to the stacks that write code, so a docs or writing
|
|
8
|
-
# project loads no rule it can never apply.
|
|
9
|
-
|
|
10
|
-
# standard's frontmatter rather than authored.
|
|
11
|
-
rules = ["canon", "claude", "standards", "tooling", "writing"]
|
|
8
|
+
# project loads no rule it can never apply.
|
|
9
|
+
rules = ["canon", "claude", "tooling", "writing"]
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erclx/canon",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.33.0",
|
|
5
5
|
"description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"check:spell": "cspell '**' '.*/**' '.*' --no-progress --color --show-context",
|
|
29
|
-
"format": "prettier --write --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --write --indent 2 scripts/
|
|
30
|
-
"check:format": "prettier --check --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --diff --indent 2 scripts/
|
|
31
|
-
"check:shell": "find scripts
|
|
29
|
+
"format": "prettier --write --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --write --indent 2 scripts/ tooling/ claude/",
|
|
30
|
+
"check:format": "prettier --check --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --diff --indent 2 scripts/ tooling/ claude/",
|
|
31
|
+
"check:shell": "find scripts tooling claude .claude/hooks -name '*.sh' -exec shellcheck --severity=warning {} + && find .husky -maxdepth 1 -type f -exec shellcheck --severity=warning --shell=sh {} +",
|
|
32
32
|
"check:types": "tsc --noEmit",
|
|
33
33
|
"check:install": "./scripts/core/install-check.sh",
|
|
34
34
|
"test": "bun --bun vitest run",
|
|
@@ -55,10 +55,10 @@ open_timeline "Install verification"
|
|
|
55
55
|
# nothing, so the excluded tree has to exist here before its absence below can
|
|
56
56
|
# mean the publish left it out.
|
|
57
57
|
log_step "Assert excluded path exists in source"
|
|
58
|
-
if [ ! -f "$PROJECT_ROOT/sandbox/
|
|
59
|
-
log_error "sandbox/
|
|
58
|
+
if [ ! -f "$PROJECT_ROOT/sandbox/exempt.toml" ]; then
|
|
59
|
+
log_error "sandbox/exempt.toml is missing from the source tree, so the absence check below would pass on nothing"
|
|
60
60
|
fi
|
|
61
|
-
log_info "Present: sandbox/
|
|
61
|
+
log_info "Present: sandbox/exempt.toml"
|
|
62
62
|
|
|
63
63
|
log_step "Pack"
|
|
64
64
|
TARBALL_PATH="$(cd "$PROJECT_ROOT" && bun pm pack --quiet --ignore-scripts --destination "$PACK_DIR" | tail -n 1)"
|
package/scripts/lib/ui.sh
CHANGED
|
@@ -6,12 +6,6 @@ if [ "${BASH_VERSINFO[0]:-0}" -lt 4 ]; then
|
|
|
6
6
|
exit 1
|
|
7
7
|
fi
|
|
8
8
|
|
|
9
|
-
# Resolved from this file's own location rather than `$PROJECT_ROOT`, because
|
|
10
|
-
# `require_project_root` is what several scripts call before anything has
|
|
11
|
-
# established a root.
|
|
12
|
-
# shellcheck source=/dev/null
|
|
13
|
-
source "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/sandbox-path.sh"
|
|
14
|
-
|
|
15
9
|
# `NO_COLOR` follows the published convention, where any non-empty value turns
|
|
16
10
|
# color off whatever the value says.
|
|
17
11
|
supports_color() {
|
|
@@ -111,156 +105,3 @@ guard_root() {
|
|
|
111
105
|
log_error "Cannot run against toolkit root. Files here are the source of truth."
|
|
112
106
|
fi
|
|
113
107
|
}
|
|
114
|
-
|
|
115
|
-
require_project_root() {
|
|
116
|
-
local GREEN RED YELLOW WHITE GREY NC
|
|
117
|
-
set_palette 2
|
|
118
|
-
local sandbox in_sandbox=0
|
|
119
|
-
if [ -n "${CANON_SANDBOX_DIR:-}" ]; then
|
|
120
|
-
sandbox="$CANON_SANDBOX_DIR"
|
|
121
|
-
[[ "$PWD" == "$sandbox" || "$PWD" == "$sandbox"/* ]] && in_sandbox=1
|
|
122
|
-
else
|
|
123
|
-
sandbox="$(sandbox_dir_prefix)"
|
|
124
|
-
[[ "$PWD" == "$sandbox" || "$PWD" == "$sandbox"/* || "$PWD" == "$sandbox"-* ]] && in_sandbox=1
|
|
125
|
-
fi
|
|
126
|
-
if [ "$in_sandbox" -eq 1 ]; then
|
|
127
|
-
echo -e "${GREY}┌${NC}" >&2
|
|
128
|
-
log_error "Execution restricted: Command cannot be run from inside the sandbox environment."
|
|
129
|
-
fi
|
|
130
|
-
if [[ "$PWD" != "$PROJECT_ROOT"* ]]; then
|
|
131
|
-
echo -e "${GREY}┌${NC}" >&2
|
|
132
|
-
log_error "Context Error: You must run this command from inside the repository."
|
|
133
|
-
fi
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
# The retired spelling stays honored, and permanently. This variable is the
|
|
137
|
-
# documented way to drive any command headlessly, so every skill body, CI job,
|
|
138
|
-
# and operator script already written sets the old name, and those callers live
|
|
139
|
-
# in repositories and plugin caches this release cannot reach. Dropping it
|
|
140
|
-
# leaves them waiting on a TTY nobody is watching.
|
|
141
|
-
is_non_interactive() {
|
|
142
|
-
# canon-keep-retired
|
|
143
|
-
[[ "${CANON_NON_INTERACTIVE:-}" == "1" || "${AITK_NON_INTERACTIVE:-}" == "1" ]]
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
ask() {
|
|
147
|
-
local GREEN RED YELLOW WHITE GREY NC
|
|
148
|
-
set_palette 2
|
|
149
|
-
local prompt_text=$1
|
|
150
|
-
local var_name=$2
|
|
151
|
-
local default_val=$3
|
|
152
|
-
local input=""
|
|
153
|
-
local char
|
|
154
|
-
local display_default=""
|
|
155
|
-
if [ -n "$default_val" ]; then
|
|
156
|
-
display_default=" (${default_val})"
|
|
157
|
-
fi
|
|
158
|
-
if is_non_interactive; then
|
|
159
|
-
echo -e "${GREY}│${NC}" >&2
|
|
160
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${default_val}${NC}" >&2
|
|
161
|
-
export "$var_name"="$default_val"
|
|
162
|
-
return
|
|
163
|
-
fi
|
|
164
|
-
echo -e "${GREY}│${NC}" >&2
|
|
165
|
-
echo -ne "${GREEN}◆${NC} ${prompt_text}${display_default} " >&2
|
|
166
|
-
while IFS= read -r -s -n1 char; do
|
|
167
|
-
if [[ $char == $'\x1b' ]]; then
|
|
168
|
-
read -rsn2 -t 0.001 _ || true
|
|
169
|
-
echo -ne "\r\033[K" >&2
|
|
170
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${RED}Cancelled${NC}" >&2
|
|
171
|
-
exit 1
|
|
172
|
-
elif [[ $char == $'\x7f' || $char == $'\x08' ]]; then
|
|
173
|
-
if [ -n "$input" ]; then
|
|
174
|
-
input="${input%?}"
|
|
175
|
-
echo -ne "\b \b" >&2
|
|
176
|
-
fi
|
|
177
|
-
elif [[ -z "$char" ]]; then
|
|
178
|
-
break
|
|
179
|
-
else
|
|
180
|
-
input+="$char"
|
|
181
|
-
echo -n "$char" >&2
|
|
182
|
-
fi
|
|
183
|
-
done
|
|
184
|
-
[ -z "$input" ] && input="$default_val"
|
|
185
|
-
echo -ne "\r\033[K" >&2
|
|
186
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${input}${NC}" >&2
|
|
187
|
-
export "$var_name"="$input"
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
select_or_route_scenario() {
|
|
191
|
-
local GREEN RED YELLOW WHITE GREY NC
|
|
192
|
-
set_palette 2
|
|
193
|
-
local prompt_text=$1
|
|
194
|
-
shift
|
|
195
|
-
local options=("$@")
|
|
196
|
-
|
|
197
|
-
if [ -n "${SANDBOX_SCENARIO:-}" ]; then
|
|
198
|
-
echo -e "${GREY}│${NC}" >&2
|
|
199
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${SANDBOX_SCENARIO}${NC}" >&2
|
|
200
|
-
export SELECTED_OPTION="$SANDBOX_SCENARIO"
|
|
201
|
-
return
|
|
202
|
-
fi
|
|
203
|
-
|
|
204
|
-
select_option "$prompt_text" "${options[@]}"
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
select_option() {
|
|
208
|
-
local GREEN RED YELLOW WHITE GREY NC
|
|
209
|
-
set_palette 2
|
|
210
|
-
local prompt_text=$1
|
|
211
|
-
shift
|
|
212
|
-
local options=("$@")
|
|
213
|
-
local cur=0
|
|
214
|
-
local count=${#options[@]}
|
|
215
|
-
|
|
216
|
-
if is_non_interactive; then
|
|
217
|
-
echo -e "${GREY}│${NC}" >&2
|
|
218
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${options[0]}${NC}" >&2
|
|
219
|
-
export SELECTED_OPTION="${options[0]}"
|
|
220
|
-
return
|
|
221
|
-
fi
|
|
222
|
-
|
|
223
|
-
if [ ! -t 0 ]; then
|
|
224
|
-
log_error "${prompt_text} requires a TTY. Pass an argument or set CANON_NON_INTERACTIVE=1."
|
|
225
|
-
fi
|
|
226
|
-
|
|
227
|
-
echo -e "${GREY}│${NC}" >&2
|
|
228
|
-
echo -ne "${GREEN}◆${NC} ${prompt_text}\n" >&2
|
|
229
|
-
|
|
230
|
-
while true; do
|
|
231
|
-
for i in "${!options[@]}"; do
|
|
232
|
-
if [ "$i" -eq "$cur" ]; then
|
|
233
|
-
echo -e "${GREY}│${NC} ${GREEN}❯ ${options[$i]}${NC}" >&2
|
|
234
|
-
else
|
|
235
|
-
echo -e "${GREY}│${NC} ${GREY}${options[$i]}${NC}" >&2
|
|
236
|
-
fi
|
|
237
|
-
done
|
|
238
|
-
|
|
239
|
-
read -rsn1 key
|
|
240
|
-
case "$key" in
|
|
241
|
-
$'\x1b')
|
|
242
|
-
if read -rsn2 -t 0.001 key_seq; then
|
|
243
|
-
if [[ "$key_seq" == "[A" ]]; then cur=$(((cur - 1 + count) % count)); fi
|
|
244
|
-
if [[ "$key_seq" == "[B" ]]; then cur=$(((cur + 1) % count)); fi
|
|
245
|
-
else
|
|
246
|
-
echo -ne "\033[$((count + 1))A\033[J" >&2
|
|
247
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${RED}Cancelled${NC}" >&2
|
|
248
|
-
exit 1
|
|
249
|
-
fi
|
|
250
|
-
;;
|
|
251
|
-
"k") cur=$(((cur - 1 + count) % count)) ;;
|
|
252
|
-
"j") cur=$(((cur + 1) % count)) ;;
|
|
253
|
-
"q")
|
|
254
|
-
echo -ne "\033[$((count + 1))A\033[J" >&2
|
|
255
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${RED}Cancelled${NC}" >&2
|
|
256
|
-
exit 1
|
|
257
|
-
;;
|
|
258
|
-
"") break ;;
|
|
259
|
-
esac
|
|
260
|
-
echo -ne "\033[${count}A" >&2
|
|
261
|
-
done
|
|
262
|
-
|
|
263
|
-
echo -ne "\033[$((count + 1))A\033[J" >&2
|
|
264
|
-
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${options[$cur]}${NC}" >&2
|
|
265
|
-
export SELECTED_OPTION="${options[$cur]}"
|
|
266
|
-
}
|
package/src/audits/catalog.ts
CHANGED
|
@@ -468,7 +468,6 @@ const RECORD_KINDS: readonly (readonly [string, Corpus])[] = [
|
|
|
468
468
|
['plans', 'per-machine'],
|
|
469
469
|
['groundwork', 'per-machine'],
|
|
470
470
|
['intake', 'per-machine'],
|
|
471
|
-
['memory', 'per-machine'],
|
|
472
471
|
['standards', 'tracked'],
|
|
473
472
|
['teach', 'per-machine'],
|
|
474
473
|
]
|
package/src/claude/cases/misc.ts
CHANGED
|
@@ -40,6 +40,10 @@ export const SETUP_CASES: readonly SkillCase[] = [
|
|
|
40
40
|
"Before I run this sync, tell me exactly what it's going to overwrite.",
|
|
41
41
|
expect: 'canon-cli',
|
|
42
42
|
},
|
|
43
|
+
{
|
|
44
|
+
prompt: 'Which canon command tells me if my markdown breaks the rules?',
|
|
45
|
+
expect: 'canon-cli',
|
|
46
|
+
},
|
|
43
47
|
{
|
|
44
48
|
prompt:
|
|
45
49
|
'Something about the toolkit itself is broken, write it up and send it back to the maintainers.',
|
|
@@ -31,7 +31,7 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
|
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
prompt:
|
|
34
|
-
'Fold what we decided this session into the context entries
|
|
34
|
+
'Fold what we decided this session into the context entries before this branch goes out.',
|
|
35
35
|
expect: 'context-fold',
|
|
36
36
|
},
|
|
37
37
|
{
|
|
@@ -127,6 +127,11 @@ export const WORKFLOW_CASES: readonly SkillCase[] = [
|
|
|
127
127
|
prompt: 'Open a new entry on the task board for this piece of work.',
|
|
128
128
|
expect: 'task-board',
|
|
129
129
|
},
|
|
130
|
+
{
|
|
131
|
+
prompt:
|
|
132
|
+
'This branch finished the pagination work, so tick off whichever board outcomes it actually delivered.',
|
|
133
|
+
expect: 'task-complete',
|
|
134
|
+
},
|
|
130
135
|
{
|
|
131
136
|
prompt: 'Open a learning workspace so I can study this topic properly.',
|
|
132
137
|
expect: 'teach-workspace',
|
package/src/claude/seeds.ts
CHANGED
|
@@ -17,7 +17,7 @@ const HOOKS = 'hooks'
|
|
|
17
17
|
* stem in an older layout, which is what `@/sync/layout` pairs a target against
|
|
18
18
|
* to find a superseded artifact.
|
|
19
19
|
*/
|
|
20
|
-
export const SUBDIRS: readonly string[] = [HOOKS, 'context', '
|
|
20
|
+
export const SUBDIRS: readonly string[] = [HOOKS, 'context', 'tasks']
|
|
21
21
|
|
|
22
22
|
export type SeedScope = 'claude' | 'root'
|
|
23
23
|
|
|
@@ -7,7 +7,7 @@ import { bodyLines, maskDisplayed } from '@/markdown/scan'
|
|
|
7
7
|
/** Returned when a skill folder carries no `REQUIREMENT.md`, the gating check. */
|
|
8
8
|
export const EXIT_MISSING_REQUIREMENT = 2
|
|
9
9
|
|
|
10
|
-
/** The description ceiling stated in the frontmatter rules of `
|
|
10
|
+
/** The description ceiling stated in the frontmatter rules of `claude/skills/create-skill/references/skill.md`. */
|
|
11
11
|
export const DESCRIPTION_LIMIT = 1024
|
|
12
12
|
|
|
13
13
|
/** The two headings the requirement template declares, matched at any level. */
|
|
@@ -160,7 +160,7 @@ interface SkillText {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
|
-
* Measures both skill corpora against the rules `
|
|
163
|
+
* Measures both skill corpora against the rules `claude/skills/create-skill/references/skill.md` states
|
|
164
164
|
* mechanically. A corpus the project does not carry is skipped rather than
|
|
165
165
|
* reported, so a target holding only `.claude/skills/` reads as in scope.
|
|
166
166
|
*
|
package/src/cli/help.ts
CHANGED
|
@@ -10,6 +10,8 @@ type HelpStream = { isTTY?: boolean }
|
|
|
10
10
|
|
|
11
11
|
// The grouping mirrors the README's domain table and has no other source, so a
|
|
12
12
|
// command added to the program needs a row here or help-option.test.ts fails.
|
|
13
|
+
// A row here also needs a `canon <verb>` line in claude/skills/canon-cli, or a
|
|
14
|
+
// name in TOOLKIT_ONLY in canon-cli-skill.test.ts, which reads this list.
|
|
13
15
|
export const COMMAND_GROUPS: { title: string; rows: CommandRow[] }[] = [
|
|
14
16
|
{
|
|
15
17
|
title: 'Project',
|
|
@@ -25,7 +27,7 @@ export const COMMAND_GROUPS: { title: string; rows: CommandRow[] }[] = [
|
|
|
25
27
|
title: 'Domains',
|
|
26
28
|
rows: [
|
|
27
29
|
['gov [cmd]', 'Governance rules (install, sync, list)'],
|
|
28
|
-
['standards [cmd]', 'Standards (
|
|
30
|
+
['standards [cmd]', 'Standards (list, <name>)'],
|
|
29
31
|
['tooling [cmd]', 'Tooling stacks (sync, ref, create)'],
|
|
30
32
|
['claude [cmd]', 'Claude workflow (init, sync, setup)'],
|
|
31
33
|
['wiki [cmd]', 'Wiki pages (init)'],
|
package/src/cli/ui.ts
CHANGED
|
@@ -154,9 +154,8 @@ export function isNonInteractive(): boolean {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
/**
|
|
157
|
-
* `nonInteractiveDefault` opts a prompt into
|
|
158
|
-
*
|
|
159
|
-
* option instead of failing. Callers that would rather fail loudly than pick
|
|
157
|
+
* `nonInteractiveDefault` opts a prompt into resolving to its first option
|
|
158
|
+
* under `CANON_NON_INTERACTIVE=1` instead of failing. Callers that would rather fail loudly than pick
|
|
160
159
|
* for the user leave it off.
|
|
161
160
|
*/
|
|
162
161
|
export async function select<Value>(opts: {
|
package/src/commands/claude.ts
CHANGED
|
@@ -386,7 +386,7 @@ export function register(program: Command): void {
|
|
|
386
386
|
skills
|
|
387
387
|
.command('audit')
|
|
388
388
|
.description(
|
|
389
|
-
'Report both skill corpora against the mechanical rules in
|
|
389
|
+
'Report both skill corpora against the mechanical rules in claude/skills/create-skill/references/skill.md',
|
|
390
390
|
)
|
|
391
391
|
.argument('[path]', 'Project root, defaulting to the current directory')
|
|
392
392
|
.helpOption('-h, --help', 'Show this help message')
|
package/src/commands/gov.ts
CHANGED
|
@@ -12,7 +12,6 @@ import { checkoutMismatchWarning, PROJECT_ROOT } from '@/roots/project'
|
|
|
12
12
|
import { creationRel, SCRATCH } from '@/roots/record'
|
|
13
13
|
import { createGovAdapter } from '@/gov/adapter'
|
|
14
14
|
import { regenConsumedRules } from '@/gov/consumed'
|
|
15
|
-
import { regenStandardRules } from '@/gov/standard-rules'
|
|
16
15
|
import { installRules, lookupRules } from '@/gov/install'
|
|
17
16
|
import { buildGovCatalog, describeRule, describeStack } from '@/gov/list'
|
|
18
17
|
import { buildRulesPayload, listRuleFiles } from '@/gov/payload'
|
|
@@ -191,18 +190,14 @@ export function register(program: Command): void {
|
|
|
191
190
|
|
|
192
191
|
gov
|
|
193
192
|
.command('regen')
|
|
194
|
-
.description(
|
|
195
|
-
"Rebuild the standard-pointer rules and a repository's own .claude/rules/",
|
|
196
|
-
)
|
|
193
|
+
.description("Rebuild a repository's own .claude/rules/")
|
|
197
194
|
.helpOption('-h, --help', 'Show this help message')
|
|
198
195
|
.option('--root <path>', 'Repository root to regenerate', PROJECT_ROOT)
|
|
199
196
|
.addHelpText(
|
|
200
197
|
'after',
|
|
201
198
|
[
|
|
202
199
|
'',
|
|
203
|
-
'
|
|
204
|
-
'fields in each standard under standards/. Then reads',
|
|
205
|
-
'internal/governance.toml and installs the stack it names, plus any',
|
|
200
|
+
'Reads internal/governance.toml and installs the stack it names, plus any',
|
|
206
201
|
'rules under internal/rules/. Unlike install and sync, this runs',
|
|
207
202
|
'against the toolkit root, whose .claude/rules/ is produced output.',
|
|
208
203
|
'',
|
|
@@ -1121,14 +1116,6 @@ async function runRegen(
|
|
|
1121
1116
|
|
|
1122
1117
|
const root = resolve(opts.root ?? PROJECT_ROOT)
|
|
1123
1118
|
|
|
1124
|
-
// The consumed copy installs from `governance/rules/`, so the band this
|
|
1125
|
-
// writes has to be fresh before that copy is built from it.
|
|
1126
|
-
const generated = await regenStandardRules(root)
|
|
1127
|
-
if (!generated.ok) {
|
|
1128
|
-
process.stderr.write(`Standard-rules regen failed: ${generated.reason}\n`)
|
|
1129
|
-
return 1
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
1119
|
const result = await regenConsumedRules(root)
|
|
1133
1120
|
|
|
1134
1121
|
if (!result.ok) {
|