@erclx/canon 5.57.0 → 5.58.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/CHANGELOG.md +14 -0
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/context-fold/references/context.md +1 -1
- package/claude/skills/document-health/REQUIREMENT.md +2 -2
- package/claude/skills/document-health/SKILL.md +14 -0
- package/claude/skills/document-health/references/axes.md +12 -0
- package/claude/skills/document-repair/REQUIREMENT.md +6 -1
- package/claude/skills/document-repair/SKILL.md +21 -0
- package/claude/skills/plan-feature/SKILL.md +1 -1
- package/docs/agents/context-audit.md +1 -1
- package/governance/rules/code/routing.md +5 -1
- package/governance/rules/ui/design-taste.md +4 -0
- package/package.json +1 -1
- package/src/context/audit.ts +26 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.58.0](https://github.com/erclx/canon/compare/v5.57.0...v5.58.0) (2026-10-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **governance:** widen design-taste paths to component files ([#2645](https://github.com/erclx/canon/issues/2645)) ([01b1445](https://github.com/erclx/canon/commit/01b144514eced1150c90b18acc78f0be33990a23))
|
|
9
|
+
* **rules:** route interface changes to api-design ([#2647](https://github.com/erclx/canon/issues/2647)) ([09a073c](https://github.com/erclx/canon/commit/09a073ca38324a399de5c2c2e702fbcede6bb38c))
|
|
10
|
+
* **skills:** offer a restructure before document-repair rewrites ([#2648](https://github.com/erclx/canon/issues/2648)) ([7c2776a](https://github.com/erclx/canon/commit/7c2776a95b86a6626c44e399056b9eaa22418d65))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **context:** count table rows toward no folder paragraph ([#2646](https://github.com/erclx/canon/issues/2646)) ([a99b020](https://github.com/erclx/canon/commit/a99b02064105b81bc3a4f6e4820c73198942785e))
|
|
16
|
+
|
|
3
17
|
## [5.57.0](https://github.com/erclx/canon/compare/v5.56.0...v5.57.0) (2026-10-24)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -71,7 +71,7 @@ An entry carries three H2 sections and no other, being `Overview`, `Layout`, and
|
|
|
71
71
|
|
|
72
72
|
Layout gives each folder doing real work its own H3, titled with the folder path in a code span, such as ``### `src/design/` ``.
|
|
73
73
|
|
|
74
|
-
- Open the H3 with a one-paragraph lead stating what the folder does, then at most five bullets on what it does now
|
|
74
|
+
- Open the H3 with a one-paragraph lead stating what the folder does, then at most five bullets on what it does now. A table after the lead counts toward neither, with one sentence to lead the bullets
|
|
75
75
|
- Put every trivial folder under `### Other folders` as a one-line bullet in owns-X form
|
|
76
76
|
- Name folders only, never files, and write no decisions and no history under any H3
|
|
77
77
|
- Give each folder under the code roots one H3 or `Other folders` line, since a second entry may cite it but never claims it
|
|
@@ -13,8 +13,8 @@ Length, placement, and staleness answer to different evidence, and one list hand
|
|
|
13
13
|
|
|
14
14
|
## Must
|
|
15
15
|
|
|
16
|
-
- Report per document across the length, placement, and staleness axes, marking each finding with its evidence class
|
|
17
|
-
-
|
|
16
|
+
- Report per document across the length, placement, and staleness axes, marking each finding with its evidence class, read through the verb owning each measurement and its record's checkpoints
|
|
17
|
+
- Propose a split or an owner as a structure line for each overgrown entry and doubled or unnamed coverage finding, with the headings and the reason
|
|
18
18
|
- Ship the staleness axis as a reading rather than cutting it for lacking a verb
|
|
19
19
|
- Report a refusal, an absent key, or a missing subcommand as an unread axis naming the cause, and say which layer answered the classifier sweep
|
|
20
20
|
- Run standalone, read the requirements record for identity drift when the scope reaches it, and print the `canon records stale canonical` reminder
|
|
@@ -47,6 +47,12 @@ The first names the backend, the model, and the source that decided both. Report
|
|
|
47
47
|
|
|
48
48
|
Take the checkpoints from the record each verb returns rather than from a number written here. A checkpoint the CLI moves reaches this report with no edit, and a number held in this body goes stale on its own cadence.
|
|
49
49
|
|
|
50
|
+
### The structure line
|
|
51
|
+
|
|
52
|
+
The context audit record already carries what a restructure needs, so the placement axis gains a structure line per area folder and runs no further verb. `${CLAUDE_SKILL_DIR}/references/axes.md` holds how to read `length` and `coverage` into a proposed split or owner.
|
|
53
|
+
|
|
54
|
+
Emit the line only for a folder with an entry past the line checkpoint whose Layout headings group into two or more domains, or with a doubled or unnamed coverage finding. A folder with neither gets no line, and `document-repair` goes straight to its rewrite.
|
|
55
|
+
|
|
50
56
|
### An unread axis is not a healthy one
|
|
51
57
|
|
|
52
58
|
A refusal, an absent key, and a subcommand the project's binary does not carry each leave an axis unread. Report it as unread against the documents it would have covered, name the read that could not be taken, and name the cause.
|
|
@@ -106,4 +112,12 @@ When Step 3 read the canonical records, add one reminder line per doc the verb r
|
|
|
106
112
|
|
|
107
113
|
Write `reviewed value is not a date: <value>` for a doc carrying `invalidReviewed`, and `no release tags to count` in place of the count when `tagged` is false. Name the unread cause instead when the verb refused or the binary carries no `canonical` kind.
|
|
108
114
|
|
|
115
|
+
Under the table, add one structure line per area folder that earned one, naming the entry and the split, or the finding and its owner:
|
|
116
|
+
|
|
117
|
+
```markdown
|
|
118
|
+
Structure `canon/context/surfaces/`: `cli.md` (300 lines) splits into `cli.md` taking <headings> and `cli-<domain>.md` taking <headings>, because <reason>.
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The line is a proposal for the operator, with the headings each entry takes and why. Health applies nothing, and `document-repair` offers the proposal before it rewrites.
|
|
122
|
+
|
|
109
123
|
Keep the evidence line under the table on every run. A table read without it flattens a judgment into a measurement, which is the one shape the three classes exist to prevent.
|
|
@@ -54,6 +54,18 @@ The sweep classifies each section as keep, replace or rewrite, history, or move.
|
|
|
54
54
|
- A low-confidence `move` is a prompt to look rather than an instruction to cut
|
|
55
55
|
- **Routes to:** the document the verdict names as the owner. Where the move crosses a tier rather than a file, the project's own content-ownership rules decide the destination.
|
|
56
56
|
|
|
57
|
+
### The structure line
|
|
58
|
+
|
|
59
|
+
The audit record's `length` array lists each entry past the line checkpoint, and `coverage.findings` lists the `doubled` and `unnamed` ones. The structure line reads both, so it carries the `measured` class for the finding and `read` for the proposal built on it.
|
|
60
|
+
|
|
61
|
+
- **Overgrown entry:** read its `causes` in `length` first, since `history: yes` points at cutting provenance and one domain at a trim, so neither earns a split
|
|
62
|
+
- **Split:** group the Layout headings by domain, one new entry per group beyond the first, naming each entry's headings and one reason
|
|
63
|
+
- **Domain boundaries:** no verb measures one, so state the grouping as a judgment.
|
|
64
|
+
- **Doubled coverage:** two entries describe one source area. Propose the one that owns it, from which entry already holds the area's traps, and the other points at it.
|
|
65
|
+
- **Unnamed coverage:** no entry names the area. Propose an owner among the existing entries before a new one, since a new entry is the larger change.
|
|
66
|
+
|
|
67
|
+
A proposal names headings and a reason, so an operator judges a concrete split. A split nobody can act on names none of those.
|
|
68
|
+
|
|
57
69
|
### When a verb resolves nothing
|
|
58
70
|
|
|
59
71
|
Both verbs resolve their folders by surface root rather than by a path written into them, so a project laid out differently resolves nothing. The two degrade differently.
|
|
@@ -15,14 +15,19 @@ A folder repaired by hand also drifts back, since a target gates nothing until a
|
|
|
15
15
|
|
|
16
16
|
- Each batch takes one folder and leaves it at zero findings or reports it ungated
|
|
17
17
|
- A folder gates only through `canon markdown gated add`, which refuses one with a finding left
|
|
18
|
-
- A rewrite keeps every stated reason, command, and path the original carried
|
|
18
|
+
- A rewrite keeps every stated reason, command, and path the original carried, and leaves a context entry no more shape findings than it started with
|
|
19
19
|
- The body names the verbs and states no limit number
|
|
20
20
|
- A requirement gates by its own path, never through a folder prefix
|
|
21
21
|
|
|
22
|
+
## Restructure first
|
|
23
|
+
|
|
24
|
+
An overgrown context folder is offered the restructure `document-health` proposes before any rewrite, and the restructure applies only on the operator's word.
|
|
25
|
+
|
|
22
26
|
## Must not
|
|
23
27
|
|
|
24
28
|
- Edit `canon/config/markdown.toml` by hand
|
|
25
29
|
- Report a folder gated that the verb refused
|
|
30
|
+
- Reach zero density findings by growing the context shape findings
|
|
26
31
|
- Change what a document claims to pass the audit
|
|
27
32
|
- Be reachable only by its name, since `document-health` names it for every length finding
|
|
28
33
|
|
|
@@ -18,6 +18,15 @@ The CLI holds every number. `canon markdown audit` measures, and `canon markdown
|
|
|
18
18
|
- `gated add` refusing with `canon-checkout`: stop. Canon's own checkout gates through a constant in its source, which a code change edits.
|
|
19
19
|
- Branch on each record's own fields rather than on an exit status a shell wrapper can flatten. A call with no terminal on stdin already runs headless, so no command takes a prefix.
|
|
20
20
|
|
|
21
|
+
## Step 0: offer the restructure
|
|
22
|
+
|
|
23
|
+
Restructure an overgrown context folder before rewriting it, so the effort is spent once. Run this step only when `canon/context/` is a candidate, meaning it is not yet listed in `canon/config/markdown.toml`, and skip it silently otherwise.
|
|
24
|
+
|
|
25
|
+
- Take the structure line `document-health` reports for each area folder, or read it from `canon context audit --json` the way that skill does
|
|
26
|
+
- A folder with no overgrown entry and no doubled or unnamed coverage finding has no line, so go straight to Step 1 with no prompt
|
|
27
|
+
- Show the operator each proposal and ask before applying it, since a split moves files other entries cite. Re-run the audit afterward to confirm the citations still resolve.
|
|
28
|
+
- Take a declined proposal as a decision and rewrite the entry as it stands
|
|
29
|
+
|
|
21
30
|
## Step 1: read the audit
|
|
22
31
|
|
|
23
32
|
Run the audit over the whole tree and take the density and reference shape findings from its record:
|
|
@@ -26,6 +35,12 @@ Run the audit over the whole tree and take the density and reference shape findi
|
|
|
26
35
|
canon markdown audit --json
|
|
27
36
|
```
|
|
28
37
|
|
|
38
|
+
When `canon/context/` is a candidate, read the context shape beside it and keep each entry's `shapeFindings` issues as the baseline Step 3 holds the rewrite to:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
canon context audit --json
|
|
42
|
+
```
|
|
43
|
+
|
|
29
44
|
Take the candidate folders from the order table in `${CLAUDE_SKILL_DIR}/references/batches.md` rather than from the findings, since a clean folder carries no finding and would never be gated. Drop every folder `canon/config/markdown.toml` already lists, since a listed folder already gates.
|
|
30
45
|
|
|
31
46
|
Sort what is left in two. A candidate the findings never name needs no rewrite, so gate it through Step 4 before the first batch. Group the findings under the rest, which Steps 2 and 3 rewrite.
|
|
@@ -46,6 +61,12 @@ canon markdown audit <prefix> --json
|
|
|
46
61
|
|
|
47
62
|
Read `${CLAUDE_SKILL_DIR}/references/batches.md` for what a rewrite may cut. A stated reason survives every rewrite, and the audit reaching zero cannot see one that went missing.
|
|
48
63
|
|
|
64
|
+
### Hold the context shape
|
|
65
|
+
|
|
66
|
+
For a file under a folder the context audit resolves, also re-run `canon context audit --json` and compare the entry's `shapeFindings` issues with the baseline. A density fix that splits a Layout paragraph into several can grow `layout-paragraphs`.
|
|
67
|
+
|
|
68
|
+
A rewrite leaving the entry with more shape issues than it started with is not done. Undo it, or fold the split into a table or a linked page, and report the entry as stopped when neither reaches the baseline. Zero density findings reached by growing shape findings only moves the failure.
|
|
69
|
+
|
|
49
70
|
## Step 4: gate the folder
|
|
50
71
|
|
|
51
72
|
```bash
|
|
@@ -84,7 +84,7 @@ What this skill adds on top of the standard:
|
|
|
84
84
|
Every `- Suggested:` line takes senior judgment, picking the best option in one line with its reason or main tradeoff, and naming alternatives only when they change the pick.
|
|
85
85
|
|
|
86
86
|
- Suggest a real default when best practice, the codebase, or prior context points to one
|
|
87
|
-
-
|
|
87
|
+
- Before `## Files to touch`, load `canon:codebase-layout` for a new path (its reason) and `canon:api-design` for a changed verb, flag, output, record shape, or endpoint. Report either if missing.
|
|
88
88
|
- Fill `## Design references` with the `canon/design/<surface>/` folder for each surface a UI file in `## Files to touch` renders, and write `None identified.` in a project with no folder
|
|
89
89
|
- Write `## Verification` as one bullet per outcome naming the test or command that proves it
|
|
90
90
|
- Write `## Review focus` as the inputs or states that would break the change, carrying the risk you understood to the executor and the reviewer
|
|
@@ -46,7 +46,7 @@ The shape kinds are `retired-section`, `gotcha-count`, `gotcha-heading`, `gotcha
|
|
|
46
46
|
|
|
47
47
|
- A `## Decisions` H2, or a `Gotchas` section past five bullets or holding a heading or paragraph
|
|
48
48
|
- A `Layout` H3 titled neither a code-spanned path nor `Other folders`, or a heading below H3 under `Layout`
|
|
49
|
-
- A folder H3 past five bullets or its one-paragraph lead
|
|
49
|
+
- A folder H3 past five bullets or its one-paragraph lead, where table rows and the sentence leading the bullets after a table count toward neither
|
|
50
50
|
|
|
51
51
|
The development entry may carry a `Scripts` H3 exempt from both folder caps. `SHAPE_GATED_FOLDERS` lives in `src/context/shape-gated.ts`.
|
|
52
52
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Routes code placement and
|
|
2
|
+
description: Routes code placement, shape, and interface decisions to the skills that carry them, and library calls to the official docs
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Code standards
|
|
@@ -12,6 +12,10 @@ description: Routes code placement and shape decisions to the skills that carry
|
|
|
12
12
|
|
|
13
13
|
- Load the `canon:code-craft` skill before deciding the shape of a new function, class, or module, and report it rather than proceeding silently when it does not resolve.
|
|
14
14
|
|
|
15
|
+
## Interfaces
|
|
16
|
+
|
|
17
|
+
- Load `canon:api-design` before shaping a public function, flag or output, record format, endpoint, or caller-handled error, and report it rather than proceeding silently when it does not resolve.
|
|
18
|
+
|
|
15
19
|
## Libraries
|
|
16
20
|
|
|
17
21
|
- Before calling a library API the codebase does not already use, fetch the official docs for the installed version and match the call to them, since recall of an API goes stale.
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Route edits that decide how a surface looks to the design-taste skill for the layer ordering, the coherence locks, and the defaults a model reaches for
|
|
3
3
|
paths:
|
|
4
|
+
- '**/*.tsx'
|
|
5
|
+
- '**/*.jsx'
|
|
6
|
+
- '**/*.astro'
|
|
7
|
+
- '**/*.html'
|
|
4
8
|
- '**/*.css'
|
|
5
9
|
- '**/*.scss'
|
|
6
10
|
- 'canon/DESIGN.md'
|
package/package.json
CHANGED
package/src/context/audit.ts
CHANGED
|
@@ -616,8 +616,16 @@ function shapeIssues(
|
|
|
616
616
|
let inItem = false
|
|
617
617
|
let inParagraph = false
|
|
618
618
|
let afterBlank = false
|
|
619
|
+
let afterTable = false
|
|
620
|
+
let deferred = false
|
|
621
|
+
|
|
622
|
+
const settleDeferred = (): void => {
|
|
623
|
+
if (deferred && folder) folder.paragraphs++
|
|
624
|
+
deferred = false
|
|
625
|
+
}
|
|
619
626
|
|
|
620
627
|
const closeFolder = (): void => {
|
|
628
|
+
settleDeferred()
|
|
621
629
|
if (folder && !exempt.has(folder.text)) {
|
|
622
630
|
if (folder.paragraphs > LAYOUT_PARAGRAPH_CAP) {
|
|
623
631
|
issues.push({
|
|
@@ -661,6 +669,7 @@ function shapeIssues(
|
|
|
661
669
|
inItem = false
|
|
662
670
|
inParagraph = false
|
|
663
671
|
afterBlank = false
|
|
672
|
+
afterTable = false
|
|
664
673
|
|
|
665
674
|
if (level <= 2) {
|
|
666
675
|
closeFolder()
|
|
@@ -697,11 +706,22 @@ function shapeIssues(
|
|
|
697
706
|
inItem = true
|
|
698
707
|
inParagraph = false
|
|
699
708
|
afterBlank = false
|
|
709
|
+
afterTable = false
|
|
710
|
+
deferred = false
|
|
700
711
|
if (gotchas) gotchas.bullets++
|
|
701
712
|
if (folder) folder.bullets++
|
|
702
713
|
continue
|
|
703
714
|
}
|
|
704
715
|
|
|
716
|
+
if (folder && TABLE_ROW.test(line.text)) {
|
|
717
|
+
settleDeferred()
|
|
718
|
+
inItem = false
|
|
719
|
+
inParagraph = false
|
|
720
|
+
afterBlank = false
|
|
721
|
+
afterTable = true
|
|
722
|
+
continue
|
|
723
|
+
}
|
|
724
|
+
|
|
705
725
|
const continues = inItem && (!afterBlank || INDENTED.test(line.text))
|
|
706
726
|
afterBlank = false
|
|
707
727
|
if (continues) continue
|
|
@@ -717,7 +737,12 @@ function shapeIssues(
|
|
|
717
737
|
text: line.text.trim(),
|
|
718
738
|
})
|
|
719
739
|
}
|
|
720
|
-
if (folder)
|
|
740
|
+
if (folder) {
|
|
741
|
+
settleDeferred()
|
|
742
|
+
if (afterTable) deferred = true
|
|
743
|
+
else folder.paragraphs++
|
|
744
|
+
}
|
|
745
|
+
afterTable = false
|
|
721
746
|
}
|
|
722
747
|
|
|
723
748
|
closeFolder()
|