@erclx/canon 4.117.0 → 4.119.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canon-operator/SKILL.md +1 -1
- package/claude/skills/canon-rollout/SKILL.md +2 -2
- package/claude/skills/design-extract/SKILL.md +1 -1
- package/claude/skills/docs-fold/SKILL.md +2 -2
- package/claude/skills/draft-ready/REQUIREMENT.md +1 -1
- package/claude/skills/draft-ready/SKILL.md +1 -1
- package/claude/skills/draft-ready/references/assembly.md +8 -0
- package/claude/skills/draft-screencast/SKILL.md +1 -1
- package/claude/skills/git-pr/SKILL.md +5 -3
- package/claude/skills/memory-capture/SKILL.md +3 -3
- package/claude/skills/memory-review/SKILL.md +3 -3
- package/claude/skills/plan-feature/REQUIREMENT.md +1 -0
- package/claude/skills/plan-feature/SKILL.md +8 -1
- package/claude/skills/review-branch/SKILL.md +1 -1
- package/claude/skills/review-pr/REQUIREMENT.md +1 -0
- package/claude/skills/review-pr/SKILL.md +4 -2
- package/claude/skills/role-planner/SKILL.md +1 -1
- package/claude/skills/role-worker/REQUIREMENT.md +1 -1
- package/claude/skills/role-worker/SKILL.md +10 -41
- package/claude/skills/seed-sync/SKILL.md +1 -1
- package/claude/skills/session-compact/SKILL.md +1 -1
- package/claude/skills/session-map/SKILL.md +1 -1
- package/claude/skills/session-relay/REQUIREMENT.md +7 -1
- package/claude/skills/session-relay/SKILL.md +4 -7
- package/claude/skills/session-worktree/REQUIREMENT.md +5 -1
- package/claude/skills/session-worktree/SKILL.md +7 -1
- package/claude/skills/session-worktree/references/main-root-writes.md +24 -0
- package/claude/skills/target-check/references/domains.md +1 -1
- package/claude/skills/task-board/SKILL.md +4 -3
- package/claude/skills/teach-workspace/SKILL.md +4 -4
- 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/claude/skills/ux-walkthrough/references/relay.md +1 -1
- package/docs/agents/commands.md +3 -3
- package/docs/agents/context-audit-checks.md +2 -28
- package/docs/agents/context-audit.md +1 -1
- package/docs/agents/install-and-sync.md +28 -17
- package/docs/agents/tasks.md +4 -4
- package/docs/target-projects.md +2 -2
- package/docs/workflow/ai-workflow.md +9 -9
- package/docs/workflow/operating-model.md +1 -1
- package/docs/workflow/visual-design-workflow.md +2 -2
- package/governance/renames.toml +13 -0
- package/governance/rules/claude/510-context.md +0 -12
- package/governance/rules/core/005-behavior.md +1 -2
- package/governance/rules/core/015-output.md +1 -3
- package/governance/rules/core/035-tasks.md +1 -3
- package/governance/rules/core/045-memory.md +0 -1
- package/governance/rules/core/055-scratch.md +2 -4
- package/governance/rules/core/070-planning.md +1 -4
- package/governance/rules/core/085-worktrees.md +2 -8
- package/governance/rules/core/087-git.md +2 -2
- package/governance/rules/core/090-code-comments.md +1 -1
- package/governance/rules/ui/460-design-taste.md +0 -15
- package/package.json +1 -1
- package/src/claude/cases/workflow.ts +10 -0
- package/src/commands/context.ts +11 -111
- package/src/commands/sync.ts +11 -3
- package/src/commands/tasks.ts +9 -8
- package/src/context/audit.ts +3 -145
- package/src/design/base.css +19 -19
- package/src/design/board.ts +18 -7
- package/src/design/neutral.ts +127 -0
- package/src/design/regen.ts +6 -4
- package/src/design/tokens.ts +5 -2
- package/src/gate/measures.ts +37 -0
- package/src/gate/stages.ts +13 -4
- package/src/gov/adapter.ts +59 -7
- package/src/gov/install.ts +13 -3
- package/src/gov/renames.ts +76 -0
- package/src/gov/stacks.ts +5 -1
- package/src/records/validate.ts +5 -1
- package/src/sync/check.ts +25 -4
- package/src/sync/engine.ts +154 -10
- package/src/sync/stamp.ts +44 -0
- package/src/tasks/archive.ts +28 -7
- package/src/tasks/record.ts +16 -9
- package/src/tasks/validate.ts +3 -1
- package/standards/plan.md +24 -1
- package/standards/tasks.md +5 -3
- package/governance/rules/core/091-channel.md +0 -13
- package/src/context/narration.ts +0 -99
|
@@ -12,7 +12,7 @@ Read `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` before writing any file. It
|
|
|
12
12
|
## Guards
|
|
13
13
|
|
|
14
14
|
- Resolve the board at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo. Every read and write below resolves against that root. The board is gitignored scratch shared across worktrees, so a linked worktree writing to its own `pwd` creates a second board nothing else reads.
|
|
15
|
-
-
|
|
15
|
+
- A new task file is a main-root write, so it goes out as a heredoc. Archiving already runs through `canon tasks archive`, which resolves the root in-process. Marking an outcome shipped is `docs-fold` and runs through `canon tasks outcome`. Resolve that root and route the write the way `session-worktree` states.
|
|
16
16
|
- If `.canon/tasks/` does not exist at that root, stop: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
|
|
17
17
|
- Route on the request rather than on a flag. Creating names work that does not exist yet, archiving names a task file already shipped, and declining names one decided against. If the request fits none of the three, stop: `❌ Ambiguous. Say whether to create a task, archive one, or decline one.`
|
|
18
18
|
- Never hand-edit `.canon/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. Do not run the regen command directly, except after a shell write from a linked worktree: the hook matches `Write|Edit|MultiEdit` and nothing fires on `Bash`, so that one case regenerates explicitly with `canon indexes regen --no-stage --root <main-root> <main-root>/.canon/tasks/index.md`.
|
|
@@ -53,7 +53,7 @@ Check the roster for a live orchestrator before writing either file. Read `canon
|
|
|
53
53
|
|
|
54
54
|
- **Found.** Do not write `priority.md` or `backlog.md`. Report the surface the row would take and the reason worked out above, then hand off by messaging that session with the same information so it places the row itself rather than two sessions writing the board at once.
|
|
55
55
|
- **Not found, and this session's own name (already read above) starts with `worker-` or `planner-`.** Do not write either file. Those two role bodies ban a board write with no exception, and an orchestrator absent from the roster is not consent to break it. Report the row and the surface it would take, so the operator or a later orchestrator places it.
|
|
56
|
-
- **Not found otherwise, or the roster read fails.** Write the row directly, as today. A failed read is indistinguishable from a solo project holding no orchestrator, and stopping would strand the row on the one path this section otherwise keeps unconditional.
|
|
56
|
+
- **Not found otherwise, or the roster read fails.** Write the row directly, as today. A failed read is indistinguishable from a solo project holding no orchestrator, and stopping would strand the row on the one path this section otherwise keeps unconditional. The row is a main-root write too, so it lands through the same heredoc route the file itself took.
|
|
57
57
|
|
|
58
58
|
Say which branch fired and why in the report. The call is a judgment restated on every sweep rather than a property of the task, and a placement with no stated reason is one the next sweep re-derives from nothing.
|
|
59
59
|
|
|
@@ -98,7 +98,7 @@ git fetch origin main --quiet && git log origin/main --oneline -20
|
|
|
98
98
|
|
|
99
99
|
Match the shipped outcomes against that log, widening to `gh pr list --state merged --limit 20` when a remote is configured and the log does not settle it. When the work is not on `main`, name the task and stop: `❌ Work not on main. Archiving now loses the task if the pull request is abandoned.`
|
|
100
100
|
|
|
101
|
-
The board is gitignored, so an archived task has no history behind it and nothing restores one archived early. Skip this check when the task carries a `Pull request:` line and
|
|
101
|
+
The board is gitignored, so an archived task has no history behind it and nothing restores one archived early. Skip this check when the task carries a `Pull request:` line and the last number it lists is merged, since the number already proves what the log is being read for.
|
|
102
102
|
|
|
103
103
|
### Step 2: run the archive
|
|
104
104
|
|
|
@@ -118,6 +118,7 @@ Each reason has one resolution and none of them is to archive around it:
|
|
|
118
118
|
|
|
119
119
|
- `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `docs-fold` when the work shipped and nothing marked it. Leave the task on the board when the outcome is real. When the work is being abandoned, cut it by striking the body, `- ~~<outcome>~~ <why>`, whatever the checkbox holds, so the board records what was dropped rather than meeting this refusal a second time.
|
|
120
120
|
- `ambiguous`: two tasks name one pull request, which is the misfile `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
|
|
121
|
+
- `earlier-slice`: the number is listed on the task but is not the last, so a later slice is still to merge. Leave the task on the board. Its last slice's merge archives it.
|
|
121
122
|
- `no-match`: the stem or number names nothing on the board. Check the name against the listed stems.
|
|
122
123
|
- `bad-input`: the command line was wrong rather than the board. Read the message, fix the arguments, and run it again. Nothing on the board needs repair, which is what separates this from the two above.
|
|
123
124
|
|
|
@@ -32,10 +32,10 @@ canon teach list --json
|
|
|
32
32
|
|
|
33
33
|
It reports every workspace with its path, its counts, and the ordinal a new one would take. A `no-teach` refusal means the project has opened none yet, which is the new-workspace path in Step 1 rather than a reason to stop. The open verb creates the folder.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Every path under the main root is a main-root write, routed the way `session-worktree` states. The route splits by what the write does to the file:
|
|
36
36
|
|
|
37
|
-
- Creating a whole file that does not exist yet, which is a lesson, a reference page, and a learning record, goes out as
|
|
38
|
-
- Changing a line inside a file that already exists goes through the verb that owns it
|
|
37
|
+
- Creating a whole file that does not exist yet, which is a lesson, a reference page, and a learning record, goes out as a heredoc
|
|
38
|
+
- Changing a line inside a file that already exists goes through the verb that owns it
|
|
39
39
|
|
|
40
40
|
## Step 1: open or resume
|
|
41
41
|
|
|
@@ -239,7 +239,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to
|
|
|
239
239
|
|
|
240
240
|
The handoff is its own file rather than a shared one. The routed-facts file another skill writes is deleted by whichever pass folds it, so a second producer's unread work goes with it, and a sibling path costs the folding skill one more read and removes the interaction.
|
|
241
241
|
|
|
242
|
-
An append is a whole-file operation, so send it as a
|
|
242
|
+
An append is a whole-file operation, so send it as a heredoc, per Step 0. Then tell the operator that `/docs-fold` folds the file in from a branch. The proposal costs nothing tracked and runs anywhere, while the page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
|
|
243
243
|
|
|
244
244
|
## Output
|
|
245
245
|
|
|
@@ -72,7 +72,7 @@ When a checklist is produced, write it directly to `.canon/tmp/handoff/ui-checkl
|
|
|
72
72
|
|
|
73
73
|
The path names the artifact rather than this skill, so it does not move when the skill is renamed. A checklist written by an older binary still lands where the consumer looks.
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
The checklist is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states.
|
|
76
76
|
|
|
77
77
|
Skip the file write when there is nothing to verify visually and nothing shipping untested.
|
|
78
78
|
|
|
@@ -64,7 +64,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to
|
|
|
64
64
|
|
|
65
65
|
Write the full report directly to `.canon/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
The report is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states.
|
|
68
68
|
|
|
69
69
|
If there are no observations, write `✅ No observations.` to the file with a timestamp.
|
|
70
70
|
|
|
@@ -108,7 +108,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to
|
|
|
108
108
|
|
|
109
109
|
Write the full reading directly to `.canon/review/ux-measure-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
The reading is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states.
|
|
112
112
|
|
|
113
113
|
The `.canon/review/` directory is gitignored. Do not stage or commit the file.
|
|
114
114
|
|
|
@@ -4,7 +4,7 @@ Read when the operator calls a batch, and at the start of the walkthrough when a
|
|
|
4
4
|
|
|
5
5
|
## Where the batch goes
|
|
6
6
|
|
|
7
|
-
- Send it to the controller where the session was dispatched by one,
|
|
7
|
+
- Send it to the controller where the session was dispatched by one, through `canon:session-relay`, which resolves the address and carries the send.
|
|
8
8
|
- Give it to the operator as one list in the conversation where no controller exists. The walkthrough file is the handoff either way.
|
|
9
9
|
|
|
10
10
|
## When
|
package/docs/agents/commands.md
CHANGED
|
@@ -23,10 +23,10 @@ Full help: `canon <command> --help`. Bare `canon --help` lists every top-level c
|
|
|
23
23
|
| `canon indexes list [path]` | Flatten every folder index under a path into one `{path, title, description}` catalog (`--json`) |
|
|
24
24
|
| `canon docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name) |
|
|
25
25
|
| `canon design render` | Render `canon/DESIGN.md` tokens to HTML and CSS, declaring each vendored face the typography table names with `--embed-fonts` |
|
|
26
|
-
| `canon design regen` | Rewrite this repository's `canon/DESIGN.md` and `src/design/base.css` from `src/design/
|
|
26
|
+
| `canon design regen` | Rewrite this repository's `canon/DESIGN.md` from `src/design/tokens.ts` and `src/design/base.css` from `src/design/neutral.ts` |
|
|
27
27
|
| `canon design board` | Generate a static page set indexing tokens, surfaces, wireframes, past candidates, components, and references against a caller-resolved `--root` (`--out`), defaulting to the main worktree |
|
|
28
28
|
| `canon design css` | Emit the design tokens and components as CSS on stdout (`--no-components` for properties alone) |
|
|
29
|
-
| `canon design install` | Install the base stylesheet into a project at `.claude/design/base.css`
|
|
29
|
+
| `canon design install` | Install the neutral base stylesheet into a project at `.claude/design/base.css` |
|
|
30
30
|
| `canon design sync` | Update a base stylesheet already installed under `.claude/design/` |
|
|
31
31
|
| `canon slides render` | Render a `.claude/SLIDES.md` source into a PowerPoint deck, reporting any unrecognized layout name on stderr |
|
|
32
32
|
| `canon slides list` | List the available slide layouts (`--json` for the catalog) |
|
|
@@ -70,7 +70,7 @@ Full help: `canon <command> --help`. Bare `canon --help` lists every top-level c
|
|
|
70
70
|
| `canon worktrees list` | Report which worktrees are reclaimable, keyed on the pull request having merged, with every refusal and the removal route named (`--json`) |
|
|
71
71
|
| `canon worktrees reclaim` | Remove every reclaimable worktree and the branch behind it, reporting without acting under `--dry-run` (`--json`) |
|
|
72
72
|
| `canon comments scan` | Measure comment density by language and comment kind, with a trend recomputed from git |
|
|
73
|
-
| `canon context audit` | Report required sections, length, cited paths, reference form, catalog tables, provenance,
|
|
73
|
+
| `canon context audit` | Report required sections, length, cited paths, reference form, catalog tables, provenance, index drift, the architecture record against its own ceiling and entry cap and its word weight, and wireframe states against their evidence folders |
|
|
74
74
|
| `canon context classify diff` | Classify the chunks a git range changed, each with its enclosing section, as keep, replace, history, or move (`--base`, `--doc-types`, `--json`) |
|
|
75
75
|
| `canon context classify sweep` | Classify every section of the five canonical doc types, split at H3, as keep, rewrite, or move (`--doc-types`, `--json`) |
|
|
76
76
|
| `canon context classifier show` | Report the resolved classifier backend and model and which source decided them (`--json`) |
|
|
@@ -63,32 +63,6 @@ A release label reports with or without its leading `v` at three segments, since
|
|
|
63
63
|
|
|
64
64
|
Fenced blocks are excluded, which keeps a pinned version in an install command from reading as a claim the entry makes. Frontmatter is excluded with them, since the content checks read the body alone, and that is what keeps a diagram entry's dated `verified` stamp a record of its last check rather than a marker to settle. Length is the exception, counting the whole file, so a reader applying the 150-rendered-line checkpoint against the body alone lands a few lines under what the tool reports.
|
|
65
65
|
|
|
66
|
-
## Narration
|
|
67
|
-
|
|
68
|
-
The narration check reports a bullet that states the design a sibling bullet replaced instead of rewriting it. `standards/context.md` asks for the rewrite because the subject is still live and two bullets on one subject leave a reader to work out which of them is current, and no other measure sees that shape.
|
|
69
|
-
|
|
70
|
-
It reads structure rather than words, which the corpus decided. Measured across the 39 entries this toolkit held the day it shipped, the terms carrying clean signal for a supersession are too rare to catch anything: `superseded` appears twice, `previously` three times, and `formerly`, `originally`, and `at first` never. The one term that would have caught the case a review caught by hand is `now`, which appears 57 times across 24 entries in correct present-tense prose. A list including it reports 57 lines to catch one, and a list excluding it reports nothing.
|
|
71
|
-
|
|
72
|
-
What it matches instead is a bullet doing three things at once: opening with a pronoun whose antecedent is the bullet above it, carrying a past-tense verb, and following another top-level bullet. All three are required. Eight bullets in the corpus open with a back-reference, and the verb set narrows those to one.
|
|
73
|
-
|
|
74
|
-
The pronoun is matched cased and anchored to the opening, since a mid-sentence `this` is a determiner rather than a reference back. The verb is matched uncased anywhere in the bullet, and rejected when a copula sits in front of it, since `is used to resolve the folder` is the passive of `use` rather than the past habitual the set means.
|
|
75
|
-
|
|
76
|
-
Both sets are published under `## Narration pronouns` and `## Narration verbs` in a governance rule and read at run time, so widening either costs a rule edit rather than a TypeScript change. The copula list stays in code, because it is English grammar rather than corpus vocabulary and a rule publishing two of three headings would be another absent state to carry. Discovery keys on the headings rather than the filename, because rules are numbered and a renumber would empty the sets while the check kept reporting clean. A run finding no rule that publishes both says it scanned nothing rather than reporting clean.
|
|
77
|
-
|
|
78
|
-
A blank line does not end the run. Markdown reads the bullets around one as a single loose list, so a walker that broke there would leave the shape reachable by anyone who spaced their bullets out. What ends a run is content that is neither a bullet nor indented under one, which is what keeps the first bullet under a heading from reading as a reply to the last bullet above it.
|
|
79
|
-
|
|
80
|
-
A fence answers that test for itself, because every scan here skips a fenced line before reaching it. An unindented fence ends the run, since CommonMark reads one at column zero as interrupting the list and the bullets around it are then two lists with no antecedent crossing between them. A fence indented under its bullet stays inside the item and leaves the run intact.
|
|
81
|
-
|
|
82
|
-
The opening delimiter decides that for the whole block rather than each line deciding for itself. A blank line inside an indented fence carries no indentation to read, and a content line may sit at column zero inside one because CommonMark strips the fence's own indent and nothing further. Reading either as unindented ends a run that should have continued, which costs findings rather than inventing them, so no corpus count moves when it is wrong.
|
|
83
|
-
|
|
84
|
-
Two fenced blocks with nothing between them are one contiguous run of fenced lines, so the mark alone cannot say where the first ends. The line walker reports which block each line sits in, and the boundary re-reads indentation whenever that number changes, so an unindented block written directly behind an indented one ends the run rather than inheriting the answer above it. No markdown file this repository tracks holds that shape, because a formatter inserts a blank line between two fences on contact, and a target running these commands over an unformatted tree still can.
|
|
85
|
-
|
|
86
|
-
Precision is the whole value, so recall is the accepted exposure, and two shapes are knowingly out of reach. A narration written as one bullet carrying its own before and after slips through, and nothing else sees it either. So does the perfect passive, since `has been superseded` narrates a supersession and the copula guard rejects it with the passives it exists for.
|
|
87
|
-
|
|
88
|
-
A rejected alternative is a back-reference in the past tense by construction, and the standard keeps what was tried and why it lost, so a legitimate hit exists and no measure separates it from a violation. The report states that on every run, which is why the finding names a line to read rather than a line to delete.
|
|
89
|
-
|
|
90
|
-
The JSON record carries the findings per entry as `entries[].narration` and the sets as `checkpoints.narration`, which is absent under `--citations-only` where the run never loads them and null where no rule publishes both.
|
|
91
|
-
|
|
92
66
|
## The architecture record
|
|
93
67
|
|
|
94
68
|
Four findings read `canon/ARCHITECTURE.md` rather than a folder, and only the first two are facts.
|
|
@@ -127,9 +101,9 @@ All three wireframe findings are printed under a bare run. The states-mismatch f
|
|
|
127
101
|
|
|
128
102
|
## Which folders each check reaches
|
|
129
103
|
|
|
130
|
-
The provenance
|
|
104
|
+
The provenance check covers `canon/context/` alone, the reference-form check covers the split folders inside it, the required-section check covers `canon/context/` and `canon/wireframes/`, length and the table finding reach every audited folder, and the wireframe states check covers `canon/wireframes/` alone.
|
|
131
105
|
|
|
132
|
-
What narrows the
|
|
106
|
+
What narrows the provenance check is stated in `standards/context.md`, which opens its scope by handing diagrams and wireframes to `diagrams.md` and `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder, and what decides it is which tier states the rule rather than what the check measures.
|
|
133
107
|
|
|
134
108
|
Length and the table finding generalize as judgments about how far a reader travels, so both reach wherever the audit is pointed. Required sections narrow for a plainer reason: each list is one standard's own, so it reaches the folder that standard governs. The context and wireframe standards each state a set, and the diagram standard states none.
|
|
135
109
|
|
|
@@ -41,7 +41,7 @@ Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a gating find
|
|
|
41
41
|
|
|
42
42
|
`bun run check` in the toolkit repository reads both limits through its own Architecture record stage rather than through this verb, since the verb's only gating stage there runs `--citations-only` and never opens the record.
|
|
43
43
|
|
|
44
|
-
Entry length, reference form, table, provenance,
|
|
44
|
+
Entry length, reference form, table, provenance, the record's claim classification, and every word figure print and return `0` under every mode, because each is a judgment or a weight read alongside one, and failing a push on either would make the check something to route around.
|
|
45
45
|
|
|
46
46
|
Required-section, index, and wireframe-states findings sit between the two. All three are answerable from the file rather than weighed, so `--gate` promotes them to failing codes while a bare run leaves them advisory. Sketch-with-evidence sits with the printed measures instead, for the reason `context-audit-checks.md` states: it reads a whole entry against whether any of its states has evidence, not one layout against its own evidence, so a conforming file can still trip it. The toolkit runs the bare form against itself and the widened form against the seed tree, described below.
|
|
47
47
|
|
|
@@ -17,22 +17,29 @@ matched, or reported on, which is how project-authored rules survive. It also
|
|
|
17
17
|
removes a stale `.claude/GOV.md` from the retired build. Use
|
|
18
18
|
`canon gov install` to add rules.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
a
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
the
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
Everything under `.claude/rules/canon/` belongs to the toolkit, so a rule
|
|
21
|
+
there that the toolkit no longer ships is deleted on sync, edited or not. That
|
|
22
|
+
is how a retired rule stops loading in a target. A renamed or renumbered rule
|
|
23
|
+
the toolkit declares in `governance/renames.toml` moves instead: the sync
|
|
24
|
+
installs the rule under its new name and deletes the old file, whether or not
|
|
25
|
+
the target's stamp records a stack. Local edits to the old file are not
|
|
26
|
+
carried, and the sync says so. The sync lists each change by path before it
|
|
27
|
+
applies, and the target's git diff is the record afterwards. `canon sync
|
|
28
|
+
--check` lists the same file as `retired` or `renamed` before any sync runs. A project's own rules belong under `.claude/rules/project/`, where
|
|
29
|
+
`canon standards rule` reserves `900-999` for them, and a rule placed under
|
|
30
|
+
`canon/` instead is lost on the next sync.
|
|
31
|
+
|
|
32
|
+
A sync never deletes a rule that a newer canon release installed. The stamp
|
|
33
|
+
records the newest release that synced governance, and an older binary holds
|
|
34
|
+
every rule it finds no source for, naming both releases and asking for an
|
|
35
|
+
upgrade, rather than deleting what it cannot recognize.
|
|
36
|
+
|
|
37
|
+
A renamed rule loses its old file and gains nothing under the new name unless
|
|
38
|
+
the target's stamp records the stack it installed, in which case the new name
|
|
39
|
+
shows as `missing` and `canon gov install <stack>` adds it.
|
|
40
|
+
|
|
41
|
+
Design's own orphans are the target's overrides and are meant to stay where
|
|
42
|
+
they are, so `canon design sync` deletes nothing it finds no source for.
|
|
36
43
|
|
|
37
44
|
`canon design install` copies one toolkit-owned file to
|
|
38
45
|
`.claude/design/base.css` and creates no override. A project overrides a value
|
|
@@ -160,7 +167,11 @@ matches what the toolkit installed, `customized` when the project edited it,
|
|
|
160
167
|
`stranded` when it sits at a path the toolkit no longer installs to, `orphaned`
|
|
161
168
|
when the project authored it, or `drifted` when no stamp covers it. Governance
|
|
162
169
|
also reports `missing`, for a rule the target's recorded stack lists that its
|
|
163
|
-
tree does not hold at all
|
|
170
|
+
tree does not hold at all, `retired`, for a rule under
|
|
171
|
+
`.claude/rules/canon/` the toolkit no longer ships, which the next sync
|
|
172
|
+
deletes, and `renamed`, for one the toolkit ships under a new name, which the
|
|
173
|
+
next sync moves. A `retired` or `renamed` file counts toward `--exit-code`,
|
|
174
|
+
since one sync clears it.
|
|
164
175
|
|
|
165
176
|
Use `--json` for the machine-readable report and `--exit-code` to fail a CI job. Orphaned
|
|
166
177
|
and missing files are both excluded from that exit code: a project-authored
|
package/docs/agents/tasks.md
CHANGED
|
@@ -50,7 +50,7 @@ canon tasks archive --pull-request 673 --json
|
|
|
50
50
|
| `--json` | Emit a machine-readable record on stdout |
|
|
51
51
|
| `--root <path>` | Board root, defaulting to the main worktree |
|
|
52
52
|
|
|
53
|
-
Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, or `bad-input`.
|
|
53
|
+
Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, `earlier-slice`, or `bad-input`. `earlier-slice` fires when `--pull-request` names a number that is not the last on the task's `Pull request:` line, since outcomes are ticked at ship time and only the last slice's merge closes the task.
|
|
54
54
|
|
|
55
55
|
An outcome whose body is struck reads as cut rather than open or closed, whatever its checkbox holds: `- ~~<outcome>~~ <why>`. A task carrying only cut outcomes archives, since the gate refuses `no-outcomes` only when both the closed and the cut counts are zero. The success record carries `closed` and `cut` as counts, so a reader tells a shipped task from an abandoned one without opening the file.
|
|
56
56
|
|
|
@@ -245,13 +245,13 @@ canon tasks plan-link v28.1-trigger-escalation .canon/plans/feature-dispatch-ans
|
|
|
245
245
|
|
|
246
246
|
The plan resolves the same way `canon tasks plan-answers` resolves one, against the project root first and `.canon/tasks/` second, so a bare slug and a board-relative path both work. A reference resolving to no file refuses as `no-plan`, naming every base it looked under.
|
|
247
247
|
|
|
248
|
-
The write
|
|
248
|
+
The write adds the line when it is absent and corrects the target in place when it exists, anchored on the H1 rather than on the last origin line, since `Plan:` is the first origin line a task carries rather than the last. The `action` field reports `added`, `corrected`, or `unchanged`, which makes a rerun against the same plan safe.
|
|
249
249
|
|
|
250
250
|
Exit codes: `0` recorded, `1` refused. The `reason` field carries `no-board`, `no-match`, `no-plan`, or `bad-input`.
|
|
251
251
|
|
|
252
252
|
## Pull request
|
|
253
253
|
|
|
254
|
-
`canon tasks pull-request` records the number a branch's pull request carries onto the task that branch closes. It adds `Pull request: #NNN` under the `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines the task already holds,
|
|
254
|
+
`canon tasks pull-request` records the number a branch's pull request carries onto the task that branch closes. It adds `Pull request: #NNN` under the `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines the task already holds. When the line exists it appends `, #NNN` rather than replacing it, so a task shipped in slices lists every pull request oldest first, and a number already listed leaves the line alone. A line that does not read as a comma-separated list of `#NNN` entries is replaced whole.
|
|
255
255
|
|
|
256
256
|
Name the task by its filename stem, or by the plan its `Plan:` line points at:
|
|
257
257
|
|
|
@@ -266,7 +266,7 @@ canon tasks pull-request 673 --plan worktree-scratch-routing --json
|
|
|
266
266
|
| `--json` | Emit a machine-readable record on stdout |
|
|
267
267
|
| `--root <path>` | Board root, defaulting to the main worktree |
|
|
268
268
|
|
|
269
|
-
A plan is matched on the token both spellings share, so `worktree-scratch-routing`, `feature-worktree-scratch-routing`, and `.canon/plans/feature-worktree-scratch-routing.md` all select the same task. The `action` field reports `added`, `corrected`, or `unchanged`, which makes a rerun against the same number safe.
|
|
269
|
+
A plan is matched on the token both spellings share, so `worktree-scratch-routing`, `feature-worktree-scratch-routing`, and `.canon/plans/feature-worktree-scratch-routing.md` all select the same task. The `action` field reports `added`, `appended`, `corrected`, or `unchanged`, which makes a rerun against the same number safe.
|
|
270
270
|
|
|
271
271
|
Exit codes: `0` recorded, `1` refused. The `reason` field carries `no-board`, `no-match`, or `ambiguous`. `git-pr` skips silently on those three, because each is a case where a guessed write would archive the wrong task once the branch merges.
|
|
272
272
|
|
package/docs/target-projects.md
CHANGED
|
@@ -118,7 +118,7 @@ The plugin corpus carries runtime behavior rather than reference prose alone, be
|
|
|
118
118
|
When a new need appears after scaffold, install the one domain without re-running `canon init`.
|
|
119
119
|
|
|
120
120
|
- Governance rule for a newly adopted library: invoke `canon:target-setup gov`, or run `canon gov install <stack> --add <rule> <path>`
|
|
121
|
-
- Project-specific rule the toolkit does not ship: invoke `canon:create-rule`. It scaffolds a rule into `.claude/rules/` with a non-colliding number, and `canon gov sync` leaves it untouched.
|
|
121
|
+
- Project-specific rule the toolkit does not ship: invoke `canon:create-rule`. It scaffolds a rule into `.claude/rules/project/` with a non-colliding number, and `canon gov sync` leaves it untouched. A rule placed under `.claude/rules/canon/` instead is deleted on the next sync, since that folder belongs to the toolkit.
|
|
122
122
|
- Index.md system for a markdown-heavy folder that emerged: invoke `canon:target-setup indexes`
|
|
123
123
|
|
|
124
124
|
Standards and snippets are not on that list, and there is nothing to add for either. Neither installs into a project, by default or by flag, so a session reads a standard with `canon standards <name>` and a snippet through its `@` reference off the live plugin symlink, both resolving against the toolkit rather than a project copy. A project holding a `.claude/standards/` or `.claude/snippets/` folder from an older toolkit is carrying a stale artifact nothing reads, and deleting it is safe.
|
|
@@ -225,7 +225,7 @@ The report opens by naming the binary running it. The installed version reads ag
|
|
|
225
225
|
|
|
226
226
|
#### Then the causes
|
|
227
227
|
|
|
228
|
-
A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `canon:seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is a relocation the report names but no command runs.
|
|
228
|
+
A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `canon:seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is a relocation the report names but no command runs. A `retired` rule is one under `.claude/rules/canon/` the toolkit no longer ships, and the next `canon gov sync` deletes it. A `renamed` rule is one the toolkit now ships under a new name, and the next sync installs the new name and deletes the old file.
|
|
229
229
|
|
|
230
230
|
That attribution comes from `canon/config/config.json`, which every install and sync now writes, falling back to `.claude/canon/config.json` for a target stamped before that move. A target stamped before that path shipped is read from the retired `.claude/canon.json` instead, reported rather than migrated. Governance records a hash per installed file, plus the stack `canon gov install` was given, and tooling records the stack chain it resolved instead of any file hash, since its install runs no per-file walk to attribute.
|
|
231
231
|
|
|
@@ -224,15 +224,15 @@ This section is the corpus the coverage claim is measured against: every name `c
|
|
|
224
224
|
|
|
225
225
|
### Build the feature
|
|
226
226
|
|
|
227
|
-
| Skill | When to use
|
|
228
|
-
| ---------------------------- |
|
|
229
|
-
| `canon:session-worktree` | At the plan-to-execute boundary, to get an isolated tree and branch
|
|
230
|
-
| `canon:auto-ship` | After plan approval, to chain implement, verify, review, draft PR
|
|
231
|
-
| `canon:project-commands` | When the project's own command needs running
|
|
232
|
-
| `canon:test-first` | Before implementing a planned change, to run its test red, green, then refactor
|
|
233
|
-
| `canon:test-craft` | When writing or changing any test, to pick its layer and filter what it asserts
|
|
234
|
-
| `canon:systematic-debugging` | When a test fails or a bug surfaces, to force root cause first
|
|
235
|
-
| `canon:ui-checklist` | After a UI change, to write what to look at and name what ships untested
|
|
227
|
+
| Skill | When to use |
|
|
228
|
+
| ---------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
229
|
+
| `canon:session-worktree` | At the plan-to-execute boundary, to get an isolated tree and branch, or to route a refused main-root write |
|
|
230
|
+
| `canon:auto-ship` | After plan approval, to chain implement, verify, review, draft PR |
|
|
231
|
+
| `canon:project-commands` | When the project's own command needs running |
|
|
232
|
+
| `canon:test-first` | Before implementing a planned change, to run its test red, green, then refactor |
|
|
233
|
+
| `canon:test-craft` | When writing or changing any test, to pick its layer and filter what it asserts |
|
|
234
|
+
| `canon:systematic-debugging` | When a test fails or a bug surfaces, to force root cause first |
|
|
235
|
+
| `canon:ui-checklist` | After a UI change, to write what to look at and name what ships untested |
|
|
236
236
|
|
|
237
237
|
### Check the work before it leaves the branch
|
|
238
238
|
|
|
@@ -263,4 +263,4 @@ port-collision detail.
|
|
|
263
263
|
|
|
264
264
|
- [Claude Code and git worktrees](../../wiki/claude/claude-worktrees.md) for the isolation and fan-out mechanics
|
|
265
265
|
- [Claude Code subagents](../../wiki/claude/claude-subagents.md) for in-session parallelism without worktrees
|
|
266
|
-
- `canon/context/claude-plugin/skill-strategy.md` for how the skills in the loop are categorized
|
|
266
|
+
- `canon/context/claude-plugin/skill-strategy/overview.md` for how the skills in the loop are categorized
|
|
@@ -24,7 +24,7 @@ The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table t
|
|
|
24
24
|
|
|
25
25
|
The `canon:design-extract` skill drafts the file, sourcing tokens from a project's existing prose and CLI UI surfaces, or proposing them from `canon/REQUIREMENTS.md` and a `## Personality` paragraph when no UI code exists yet. `canon design render` writes an HTML plus CSS preview to `.canon/tmp/render/design/` for eyeballing the current system without leaving Claude Code. See `canon/context/design.md`.
|
|
26
26
|
|
|
27
|
-
A project wanting
|
|
27
|
+
A project wanting a neutral starting point to override runs `canon design install`, which copies one stylesheet to `.claude/design/base.css` carrying an achromatic token set as custom properties and two components built on them. Greys run from near-black to near-white and the accent is monochrome, so the only palette the project renders is one it writes itself. That file is toolkit-owned and `canon design sync` refreshes it, so a project overrides a value in `.claude/design/project/` instead, which sync never touches. Nothing arrives without that install, and the two channels are independent: a record drafted by the extract skill is the project's own, and the installed stylesheet is the toolkit's.
|
|
28
28
|
|
|
29
29
|
A cell no source anchors ends in `? verify`, and the preview shows that marker beside the value rather than folding it in, so a swatch and a font sample stay built from the value alone. A confidence line above the sections names how many cells are anchored against how many are tagged, which is what tells a reader whether they are looking at a record of the code or a proposal about it. It reads the columns a source could anchor and leaves out the row names, so the ratio is not diluted by cells no tag could ever reach. The proposal path tags nearly all of them, so that count reads low on day one by design.
|
|
30
30
|
|
|
@@ -150,7 +150,7 @@ Resist over-tiering early. Moving up is cheap because tiers stack. Moving down m
|
|
|
150
150
|
## References
|
|
151
151
|
|
|
152
152
|
- [Claude Design](../../wiki/claude/claude-design.md): first-party hosted design product and handoff bundle
|
|
153
|
-
- `canon/context/claude-plugin/skill-strategy.md`: how to decide between workflow and domain-knowledge skills
|
|
153
|
+
- `canon/context/claude-plugin/skill-strategy/overview.md`: how to decide between workflow and domain-knowledge skills
|
|
154
154
|
- [`microsoft/playwright-mcp`](https://github.com/microsoft/playwright-mcp): browser automation MCP used in tier 1 and tier 2
|
|
155
155
|
- [`ChromeDevTools/chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp): live frontend debugging MCP used in tier 1 and tier 2
|
|
156
156
|
- [`yctimlin/mcp_excalidraw`](https://github.com/yctimlin/mcp_excalidraw): community MCP server behind the tier 1 wireframe companion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Rule renames a sync carries a target across. Each key under [renamed] is an
|
|
2
|
+
# old rule basename and its value the basename the same rule ships under now,
|
|
3
|
+
# so `canon gov sync` replaces a held old file with the rule under its new name
|
|
4
|
+
# rather than only deleting it.
|
|
5
|
+
#
|
|
6
|
+
# An entry declares one-to-one identity and nothing else. A fold of several
|
|
7
|
+
# rules into one, or a split of one into several, is a retirement plus an
|
|
8
|
+
# addition and takes no entry here. Add the entry in the same change as the
|
|
9
|
+
# rename or renumber, and never prune one: a target can sit any number of
|
|
10
|
+
# releases behind, and a chain A to B to C resolves A only while both links
|
|
11
|
+
# stay. A key must name no live rule and every chain must end on one, which
|
|
12
|
+
# `src/gov/renames.test.ts` checks against this file.
|
|
13
|
+
[renamed]
|
|
@@ -12,18 +12,6 @@ paths:
|
|
|
12
12
|
- Before non-trivial work in a domain, read its `canon/context/<domain>.md` entry. Use `canon/context/index.md` to find it.
|
|
13
13
|
- Leave the entry conforming when work in its domain changes what it describes.
|
|
14
14
|
|
|
15
|
-
## Narration pronouns
|
|
16
|
-
|
|
17
|
-
Do not open a bullet with one of these where the antecedent is the bullet above it.
|
|
18
|
-
|
|
19
|
-
- `It`, `That`, `This`, `These`, `Those`, `They`
|
|
20
|
-
|
|
21
|
-
## Narration verbs
|
|
22
|
-
|
|
23
|
-
Do not put a sibling bullet's design in the past with one of these.
|
|
24
|
-
|
|
25
|
-
- `was`, `were`, `became`, `replaced`, `superseded`, `used to`
|
|
26
|
-
|
|
27
15
|
## Authority
|
|
28
16
|
|
|
29
17
|
- Follow the context standard for entry shape: frontmatter, sections, length, and what goes in. It is the single source. Read it with `canon standards context`.
|
|
@@ -13,8 +13,7 @@ description: Handle judgment calls, scope discipline, and file-editing mechanics
|
|
|
13
13
|
- When facing a judgment call with 2-3 reasonable options mid-flow, pick one and state the tradeoff in one sentence. Enumerate options only when the user's preference is the deciding factor.
|
|
14
14
|
- Put a call the user's preference decides through the structured question surface, such as `AskUserQuestion` in Claude Code, and fall back to a numbered list in one message where none exists. Rank the recommendation first and mark it, order the rest behind it, and give each option its cost, since an option with no stated cost is picked blind.
|
|
15
15
|
- Author the real choices only. A structured surface appends its own trailing escapes for a free-text answer and for reopening the question as conversation, so never write either as an option. On the numbered-list fallback, say that answering outside the list is fine.
|
|
16
|
-
- Answer from the artifact when one already put the question in writing with a suggestion, rather than re-asking it.
|
|
17
|
-
- Rewrite the `- Suggested:` line rather than the blank `- Answer:` slot when execution decides against an unanswered plan question's suggestion, per the plan standard, which your toolkit resolves by name.
|
|
16
|
+
- Answer from the artifact when one already put the question in writing with a suggestion, rather than re-asking it.
|
|
18
17
|
|
|
19
18
|
## Scope discipline
|
|
20
19
|
|
|
@@ -11,9 +11,7 @@ description: Report file paths correctly for the reading surface and group them
|
|
|
11
11
|
- When it reads `claude-desktop`, emit each path as a markdown link carrying the path as its text and an absolute `file://` URI as its target, resolving a relative path against the main project root to build that target. The desktop file tree hides dotted folders, so a bare path into one names a file the reader cannot reach.
|
|
12
12
|
- On every other value, including unset, emit the path bare. A terminal emulator makes it clickable through its own path detection, and link markup defeats that.
|
|
13
13
|
- Both forms govern a path emitted in a response. A path written into a markdown file follows the markdown standard instead, which your toolkit resolves by name, and which backticks a file reference and never repeats it as a link label.
|
|
14
|
-
-
|
|
15
|
-
- In the main worktree: relative from `pwd` works because `pwd` equals the editor root.
|
|
16
|
-
- In a linked worktree (under `.claude/worktrees/<name>/`): use absolute paths. Relative paths from worktree `pwd` would not resolve against the editor's project root. A `PostToolUse` hook computes this form after each write and hands it back as additional context where it is installed. Prefer that form when it arrives, and fall back to computing the absolute path yourself when it does not.
|
|
14
|
+
- In a linked worktree (under `.claude/worktrees/<name>/`), emit the absolute path, since the editor is rooted at the main project root and a path relative to the worktree resolves nowhere there. Prefer the form a `PostToolUse` hook hands back after a write where one is installed.
|
|
17
15
|
|
|
18
16
|
## Grouping multiple files
|
|
19
17
|
|
|
@@ -6,8 +6,6 @@ description: Scope, size, and link a task file correctly
|
|
|
6
6
|
|
|
7
7
|
## Task files
|
|
8
8
|
|
|
9
|
-
- `.canon/tasks/` is gitignored local session scratch, one file per task. Edit freely. No staging or revert before commits.
|
|
10
9
|
- Only create a task for work that spans multiple sessions or has real dependencies. Handle small edits immediately without a task entry.
|
|
11
10
|
- Do not add tasks retroactively for work already completed. Completed work is visible in git.
|
|
12
|
-
- When a task needs execution detail beyond its own file,
|
|
13
|
-
- Write the plan in the same session as the task file. The session that executes the plan later inherits reasoning context it would otherwise have to re-derive.
|
|
11
|
+
- When a task needs execution detail beyond its own file, write a plan in `.canon/plans/` in the same session as the task and link to it from the task's intro paragraph. The session that executes the plan later inherits reasoning context it would otherwise have to re-derive.
|
|
@@ -9,4 +9,3 @@ description: Keep memory writes scoped to .canon/memory/ and out of context-owne
|
|
|
9
9
|
- Write all memory files to `.canon/memory/`, not `~/.claude/projects/`
|
|
10
10
|
- A fact about a domain goes to that domain's `canon/context/` entry, not to memory. `canon:memory-capture` routes it there and `canon:docs-fold` folds it in. Memory keeps only what no context entry owns. Report it rather than proceeding silently when either skill does not resolve. Both ship with the plugin and this rule ships with the CLI, so a project that installed governance alone does not have them.
|
|
11
11
|
- Never delete a memory entry. Retire one by moving it to `.canon/memory/archive/`, which `canon records push` backs. A bulk retire runs through the shell, where no file edit fires a path-scoped rule.
|
|
12
|
-
- Follow the memory standard for the filename and type prefix, the frontmatter, the body shape each type carries, and the lifecycle. Read it with `canon standards memory`. Check every entry in the pen against that standard and fix what breaks it, since nothing keeps the folder conforming on its own.
|
|
@@ -6,7 +6,5 @@ description: Write temporary files to the scratch folder structure
|
|
|
6
6
|
|
|
7
7
|
## Temporary files
|
|
8
8
|
|
|
9
|
-
- Write temporary files to `.canon/tmp/<slug>/<file>.md`
|
|
10
|
-
- Write to `.claude/.tmp/<slug>/` instead in a project that carries no `.canon/` root,
|
|
11
|
-
- "The project root" above means the current worktree by default. `085-worktrees.md` states the same mixed default for `.canon/tmp/` and defers to each skill's own body for which write resolves at the main root instead.
|
|
12
|
-
- `runs/`, `hooks/`, `handoff/`, `pr/`, and `render/` are reserved under `tmp/` for build and command output that can be regenerated, hook state, skill-to-skill handoff, pull request scratch, and render output. A session slug must not take one of these five names.
|
|
9
|
+
- Write temporary files to `.canon/tmp/<slug>/<file>.md` at the current worktree's root, a nested folder with a kebab-slug tied to the topic rather than a flat `<slug>-<file>.md`. The slug must not take one of the five reserved names `runs`, `hooks`, `handoff`, `pr`, and `render`. A skill that resolves a write at the main root instead states so in its own body.
|
|
10
|
+
- Write to `.claude/.tmp/<slug>/` instead in a project that carries no `.canon/` root, and `canon migrate records` moves it to the first spelling. <!-- canon-keep-record-root -->
|
|
@@ -6,14 +6,11 @@ description: Enforce planning standards before implementation
|
|
|
6
6
|
|
|
7
7
|
## Planning
|
|
8
8
|
|
|
9
|
-
-
|
|
9
|
+
- Confirm a numbered implementation plan before a change whose diff cannot be described in one sentence.
|
|
10
10
|
- Challenge ambiguous or over-engineered requests before implementation.
|
|
11
11
|
- Search the project, its dependencies, and the standard library for an existing implementation before writing new code.
|
|
12
12
|
- State where the search ran and why each candidate was rejected. Do not assert a search without naming its results.
|
|
13
13
|
- Propose the simplest solution that satisfies the requirement before implementing complex patterns.
|
|
14
14
|
- Write or update tests as part of every implementation plan.
|
|
15
15
|
- Write the test for a behavior before the code that implements it. Confirm visual output after implementing it, not before.
|
|
16
|
-
- Load the `canon:test-first` skill before writing the implementation for a behavior whose test does not exist yet, and report it rather than proceeding silently when the skill does not resolve.
|
|
17
16
|
- Run `canon gov test-order` before shipping a branch. Fix what it names as reaching history ahead of its test.
|
|
18
|
-
- Load the `canon:systematic-debugging` skill before proposing a fix for a failing test, a surfaced bug, or behavior nobody has explained yet, and report it rather than proceeding silently when the skill does not resolve.
|
|
19
|
-
- Do not modify code without a confirmed plan.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Enter a linked worktree for implementation, resolve shared session scratch at the main root, and route a refused main-root write through session-worktree
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Worktrees standards
|
|
@@ -11,10 +11,4 @@ description: Route tracked-file writes and shared session scratch correctly from
|
|
|
11
11
|
## Shared session scratch
|
|
12
12
|
|
|
13
13
|
- Shared session scratch (`.canon/plans/`, `.canon/review/`, `.canon/memory/`, `.canon/tasks/`) lives at the main worktree root, not inside a linked worktree. From a linked worktree, resolve these paths against the main root via `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`. Fall back to `pwd` if not a git repo.
|
|
14
|
-
-
|
|
15
|
-
- From a linked worktree, every `Edit` or `Write` to a tracked file (source, docs) must use a path starting with `pwd`.
|
|
16
|
-
- From a linked worktree, `Edit` and `Write` are refused for every main-root path, session scratch included. The refusal names session isolation and points at the worktree copy, which is a second gitignored file no later session reads, so never take that redirect.
|
|
17
|
-
- `Read` resolves against the main root normally from a linked worktree. A main-root write reaches it only through `Bash`, as one plain command rather than a compound one, which is refused for complexity.
|
|
18
|
-
- Route a main-root write by what it does to the file. Creating a whole file goes out as one plain `Bash` command carrying a heredoc. Changing a line inside a file that already exists goes through a command that resolves the main root in-process, because the shell route for that case is the stream editor this file bans.
|
|
19
|
-
- A background session that entered no worktree at all meets the identical refusal writing to the main root, since the guard gates on isolation rather than on sitting inside a linked worktree. A planner writing its plan file from no worktree takes the same heredoc route for that reason.
|
|
20
|
-
- The heredoc route costs nothing on `.canon/plans/` and `.canon/review/`, which no `PostToolUse` hook watches, and costs the index on `.canon/tasks/` and `.canon/memory/`, since a hook matching `Write|Edit|MultiEdit` never fires on `Bash`. Regenerate positionally: in-process where a verb such as `canon tasks archive` already calls it, elsewhere by an explicit `canon indexes regen` call.
|
|
14
|
+
- From a linked worktree, or from a background session that entered none, `Edit` and `Write` refuse a main-root path and redirect to a worktree copy no later session reads. Never take that redirect. Route the write the way the `session-worktree` skill states, and report it rather than proceeding silently when that 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.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Route every git operation through the canon git skills,
|
|
2
|
+
description: Route every git operation through the canon git skills, which choose the surface and never authorize the operation
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Git standards
|
|
@@ -12,4 +12,4 @@ description: Route every git operation through the canon git skills, and run one
|
|
|
12
12
|
|
|
13
13
|
## Whether to act
|
|
14
14
|
|
|
15
|
-
-
|
|
15
|
+
- The bullets above decide which surface performs an operation already decided, never whether to take one.
|
|
@@ -11,19 +11,4 @@ paths:
|
|
|
11
11
|
## Authority
|
|
12
12
|
|
|
13
13
|
- Load the `canon:design-taste` skill for which design decision settles first, what must stay constant across a surface, and the defaults to reach past. It is the single source for all three.
|
|
14
|
-
- Load it before drafting, not after revising. A revision recovers a color and never recovers the composition a draft already settled.
|
|
15
14
|
- 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.
|
|
16
|
-
- Do not work the layer ordering or the coherence locks from memory.
|
|
17
|
-
|
|
18
|
-
## When this fires and when it does not
|
|
19
|
-
|
|
20
|
-
- This rule scopes to the files where an undecided visual choice lands, which is the stylesheet and the design document. Building a surface somebody already decided is implementation rather than design, and the rules below carry what implementation owes.
|
|
21
|
-
- Load the skill by name when a component edit makes a visual choice nobody has taken yet, such as a new section's shape, a spacing relationship, or a radius. The glob cannot see that intent and no glob can.
|
|
22
|
-
- Do not load it to ship a decided design. A worker wiring a picked composition pays the read and gets nothing back.
|
|
23
|
-
|
|
24
|
-
## Boundaries
|
|
25
|
-
|
|
26
|
-
- Accessibility, keyboard interaction and ARIA are a separate topic. `410-a11y` routes them, on every rendered path.
|
|
27
|
-
- States, empty and loading coverage, and destructive confirmation are a separate topic. `430-ux-completeness` routes them.
|
|
28
|
-
- Rendered copy casing is a separate topic. `465-interface-casing` routes it. Button labels and error wording are separate too, and `400-ui` routes them.
|
|
29
|
-
- The floor those three carry is not restated in the skill, and it is not traded against a preference where the two collide.
|