@erclx/canon 5.63.0 → 5.64.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/references/adopted.md +1 -1
  4. package/claude/skills/context-fold/REQUIREMENT.md +2 -3
  5. package/claude/skills/context-fold/SKILL.md +1 -11
  6. package/claude/skills/context-fold/references/completion-report.md +8 -9
  7. package/claude/skills/create-skill/references/skill-practice.md +16 -1
  8. package/claude/skills/design-taste/references/adopted.md +17 -97
  9. package/claude/skills/design-taste/references/tells.md +2 -2
  10. package/claude/skills/document-health/REQUIREMENT.md +1 -1
  11. package/claude/skills/document-health/SKILL.md +3 -14
  12. package/claude/skills/document-health/references/axes.md +14 -16
  13. package/docs/agents/audits.md +2 -6
  14. package/docs/agents/context-audit.md +1 -1
  15. package/governance/ledger/skills/api-design/SKILL.md +62 -0
  16. package/governance/ledger/skills/code-craft/SKILL.md +53 -0
  17. package/governance/ledger/skills/deprecation-migration/SKILL.md +68 -0
  18. package/governance/ledger/skills/design-taste/SKILL.md +64 -0
  19. package/governance/ledger/skills/design-taste/craft.md +66 -0
  20. package/governance/ledger/skills/design-taste/kinds.md +58 -0
  21. package/governance/ledger/skills/design-taste/systems.md +42 -0
  22. package/governance/ledger/skills/design-taste/tells.md +103 -0
  23. package/package.json +1 -1
  24. package/src/audits/catalog.ts +0 -52
  25. package/src/claude/skills-audit.ts +117 -41
  26. package/src/cli/retired.ts +8 -0
  27. package/src/commands/claude.ts +11 -2
  28. package/src/commands/context.ts +0 -425
  29. package/src/context/citations.ts +9 -3
  30. package/src/gate/measures.ts +1 -1
  31. package/src/git/files.ts +8 -3
  32. package/src/markdown/gated.ts +1 -1
  33. package/src/markdown/scope.ts +0 -1
  34. package/claude/skills/context-fold/references/classify.md +0 -87
  35. package/src/context/classify/extract.ts +0 -443
  36. package/src/context/classify/ollama.ts +0 -172
  37. package/src/context/classify/patterns.ts +0 -75
  38. package/src/context/classify/prompts.ts +0 -74
  39. package/src/context/classify/run.ts +0 -348
  40. package/src/context/classify/settings.ts +0 -196
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.64.0](https://github.com/erclx/canon/compare/v5.63.0...v5.64.0) (2026-10-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * **context:** remove the content classifier ([#2695](https://github.com/erclx/canon/issues/2695)) ([6d92b50](https://github.com/erclx/canon/commit/6d92b50bd0042a12d62574a034b1658eb6486e54))
9
+ * **skills:** ledger the craft skill bodies on their concern groups ([#2700](https://github.com/erclx/canon/issues/2700)) ([02655a5](https://github.com/erclx/canon/commit/02655a5ede3879e572145316461e2c61e307985b))
10
+ * **skills:** source every design-taste rule bullet in a ledger ([#2691](https://github.com/erclx/canon/issues/2691)) ([bb57e71](https://github.com/erclx/canon/commit/bb57e71e7db56ac4fc4d66f85e826b4ac2a3ae4a))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **claude:** resolve seeded records at either surface root ([#2696](https://github.com/erclx/canon/issues/2696)) ([288336c](https://github.com/erclx/canon/commit/288336c07c57c1a9b26a4cc6ea97c988f3338988))
16
+ * **context:** skip the install stamp in the citation scan ([#2699](https://github.com/erclx/canon/issues/2699)) ([d2f0425](https://github.com/erclx/canon/commit/d2f0425bd33f69cf9f3529769d06e916a716b0d5))
17
+ * **git:** leave deleted tracked paths out of the repository listing ([#2698](https://github.com/erclx/canon/issues/2698)) ([baa91e5](https://github.com/erclx/canon/commit/baa91e5a2a5d11bab9567bedf494eae5b63f7c09))
18
+
3
19
  ## [5.63.0](https://github.com/erclx/canon/compare/v5.62.0...v5.63.0) (2026-10-24)
4
20
 
5
21
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "canon",
3
3
  "description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
4
- "version": "5.63.0",
4
+ "version": "5.64.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -17,7 +17,7 @@ Adopted as the opening group, stated as design rules rather than as an observati
17
17
 
18
18
  ### One version per dependency
19
19
 
20
- [Software Engineering at Google, ch. 21](https://abseil.io/resources/swe-book/html/ch21.html) states the One-Version Rule, keeping one version of each dependency in a repository, so a change to it migrates every caller rather than leaving two versions live. Adopted under additive change for a caller that cannot pin, which is any module imported from inside one repository.
20
+ [Software Engineering at Google, ch. 16](https://abseil.io/resources/swe-book/html/ch16.html) states the One-Version Rule, keeping one version of each dependency in a repository, so a change to it migrates every caller rather than leaving two versions live. Adopted under additive change for a caller that cannot pin, which is any module imported from inside one repository.
21
21
 
22
22
  ## Adopted from one external skill
23
23
 
@@ -16,14 +16,13 @@ The context entries describe the repository the session opened with. An entry ke
16
16
  - Name the context entries in a trigger phrase, so a bare request to sync the docs separates this skill from `docs-sync`
17
17
  - Take the refresh scope from the diff and write tracked docs at the current worktree root, only when the diff adds, moves, or removes a folder, falsifies a bullet, or changes a trap
18
18
  - Report a requirements or direction change in one line naming `document-health` rather than writing it
19
- - Close on `canon context audit` and `canon context classify diff` over the fold's whole baseline, reporting findings on files this run wrote or the diff carries
20
- - Apply a `REPLACE` or `HISTORY` finding against its quote, report a `MOVE` with its surface rather than cutting it, and continue the fold when a check cannot run
19
+ - Close on `canon context audit` over the fold's whole baseline, reporting findings on files this run wrote or the diff carries
20
+ - Continue the fold when a check cannot run
21
21
 
22
22
  ## Must not
23
23
 
24
24
  - Write the task board, the design record, `CLAUDE.md`, the requirements record, or a promoted page
25
25
  - Create an entry for a domain the catalog does not list, or report a finding on an entry this run never touched
26
- - Pick a classifier backend, re-run the classifier after a fix, or apply a finding whose quote is not found exactly once
27
26
  - Stop the fold on a finding, a refusal, or a missing subcommand
28
27
 
29
28
  ## Out of scope
@@ -62,7 +62,7 @@ Write each updated file immediately. Claude Code's tool permission dialog is the
62
62
 
63
63
  ## Step 4: audit what the fold touched
64
64
 
65
- Run the structural audit, the markdown audit, and the content classifier, and answer each before the report. Findings never stop the fold.
65
+ Run the structural audit and the markdown audit, and answer each before the report. Findings never stop the fold.
66
66
 
67
67
  ### Structural audit
68
68
 
@@ -85,16 +85,6 @@ Run `canon markdown audit <path>` over every entry Step 3 wrote this run, and fi
85
85
  - Report a finding in a section Step 3 left alone as `⚠ Audit: <rel>, <finding>`, since the rule above keeps unrelated sections as they are
86
86
  - Report a refusal as `⚠ Audit: <message>` and continue
87
87
 
88
- ### Classify
89
-
90
- Skip the classifier only when the Diff baseline section could not resolve a base ref at all, reporting `⚠ No diff to scope against. Skipped the classify check.` The verb needs a resolvable ref, which is the one condition it cannot answer for itself.
91
-
92
- Otherwise read `${CLAUDE_SKILL_DIR}/references/classify.md` for the invocation, its scope, the record fields, applying a finding, the one-line keep reason, the unreachable and missing-subcommand lines, and the report shape.
93
-
94
- - `${CLAUDE_SKILL_DIR}` names this skill's own directory, resolved once when the skill loaded, so read the reference by that resolved path
95
- - Never guess a `.claude/skills/context-fold/references/classify.md` path from the install-time layout, which is a different root than this skill's own files
96
- - The invocation is `canon context classify diff --base <base> --json`, and it runs whether or not that reference resolves
97
-
98
88
  ## After completion
99
89
 
100
90
  Read `${CLAUDE_SKILL_DIR}/references/completion-report.md` before printing anything, for the line each outcome prints, the lines Step 2 and Step 4 add, and when the closing line is suppressed.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Completion report
3
- description: The lines context-fold prints once every step has run, being one per file updated, the direction-change note, Step 4's audit and classify lines, and the closing line with when it is suppressed
3
+ description: The lines context-fold prints once every step has run, being one per file updated, the direction-change note, Step 4's audit lines, and the closing line with when it is suppressed
4
4
  ---
5
5
 
6
6
  # Completion report
@@ -9,15 +9,14 @@ The close of `context-fold`. The session reads this file once every step has run
9
9
 
10
10
  ## Lines
11
11
 
12
- | When | Line |
13
- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------- |
14
- | Per file updated | `✅ Updated: <path written>` |
15
- | Step 2 noted a requirements change | `↪ Direction changed this session: run document-health on canon/REQUIREMENTS.md` |
16
- | Per audit finding Step 4 reported | `⚠ Audit:` in the shape the body gives |
17
- | Step 4's classify half applied or reported a finding | The exact shape `${CLAUDE_SKILL_DIR}/references/classify.md` gives under its Report section |
18
- | No file updated and Step 4 reported nothing | `✅ No changes needed.` |
12
+ | When | Line |
13
+ | ------------------------------------------- | -------------------------------------------------------------------------------- |
14
+ | Per file updated | `✅ Updated: <path written>` |
15
+ | Step 2 noted a requirements change | `↪ Direction changed this session: run document-health on canon/REQUIREMENTS.md` |
16
+ | Per audit finding Step 4 reported | `⚠ Audit:` in the shape the body gives |
17
+ | No file updated and Step 4 reported nothing | `✅ No changes needed.` |
19
18
 
20
- Do not shorten or paraphrase the audit and classify lines here or in the reply, since the quote and the reason are what a reader checks the finding against.
19
+ Do not shorten or paraphrase the audit lines here or in the reply, since the finding is what a reader checks it against.
21
20
 
22
21
  ## Suppressing the closing line
23
22
 
@@ -9,7 +9,7 @@ Applies to a practice skill, one carrying engineering judgment a session applies
9
9
 
10
10
  ## Scope
11
11
 
12
- Governs the closing sections of a practice skill's `skills/<name>/SKILL.md` and the source ledger at `skills/<name>/references/adopted.md` beside it.
12
+ Governs the closing sections of a practice skill's `skills/<name>/SKILL.md`, the source ledger at `skills/<name>/references/adopted.md` beside it, and the per-bullet ledgers a listed skill carries.
13
13
 
14
14
  Does not govern:
15
15
 
@@ -47,6 +47,21 @@ Follow every concern group with `## Excuses and rebuttals`, `## Red flags`, and
47
47
  - State what was adopted, what was declined, and why for each, so a later session extends the position rather than re-deriving it.
48
48
  - Draw first from the default shelf, [Software Engineering at Google](https://abseil.io/resources/swe-book/html/toc.html) and [Google's engineering practices](https://google.github.io/eng-practices/), and record a source from elsewhere the same way.
49
49
 
50
+ ## Per-bullet ledgers
51
+
52
+ A skill whose files list outside-practice directives one per bullet takes a ledger per such file beside `adopted.md`, with one table row per bullet under each H2, the way a governance rule's ledger does.
53
+
54
+ - Once a skill joins the per-bullet list `canon claude skills audit` keeps, every reference but `adopted.md` takes a ledger, so one added later fails until its rows land
55
+ - Exempt by name a checklist restating rules a ledgered file sources, which would cite each source twice, and a glossary, whose definitions direct nothing
56
+ - Mark the skill's `SKILL.md` for a ledger too when the body carries directives of its own
57
+ - Keep the rows outside the plugin, so a target pays nothing for them
58
+ - Move a source out of `adopted.md` once its row lands in a ledger, since two copies drift on the first edit. `adopted.md` keeps the catalog-level record and the sources behind any unledgered file.
59
+
60
+ The audit counts a few lines in a ledgered file apart from a rule's.
61
+
62
+ - Ledger a listed body's concern groups alone, every H2 before its closing sections or `## What this delegates`, since those restate the groups' rules or route
63
+ - Give a top-level ordered step a row the way a bullet takes one, and a `## Contents` list none, since it repeats the headings
64
+
50
65
  ## Which skills are practice skills
51
66
 
52
67
  - `canon claude skills audit` keeps the list of practice skills and checks each listed one for the three closing sections and the ledger.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: Adopted and declined
3
- description: Where each design-taste rule comes from, being a quoted authority, the community catalog of model-output tells, or a house threshold, plus what was declined and why
3
+ description: Where each design-taste rule comes from, being a quoted authority, the community catalog of model-output tells, or a house threshold, where the per-bullet rows for the body and the rule references sit, and what was declined and why
4
4
  ---
5
5
 
6
6
  # Adopted and declined
7
7
 
8
- Every rule in this skill traces to one of three origins. A reader arguing against a rule finds its origin here, and a session extending the skill adds a row rather than re-deriving one.
8
+ Every rule in this skill traces to one of three origins. A reader arguing against a rule finds its origin through this record, and a session extending the skill adds a row rather than re-deriving one.
9
9
 
10
10
  - **An authority.** A typographer, a usability lab, a platform guideline, or the CSS reference states the rule, and the row quotes the passage relied on.
11
11
  - **The catalog.** Community prompt skills recorded what models draw when nothing states a direction. A tell from them is an observation of model output, not established practice.
@@ -15,97 +15,41 @@ A rule a quoted passage only partly backs names the part it backs, and the rest
15
15
 
16
16
  ## Contents
17
17
 
18
+ - [Where the rows sit](#where-the-rows-sit)
18
19
  - [The layer model](#the-layer-model)
19
- - [Craft rules an authority states](#craft-rules-an-authority-states)
20
- - [Systems rules an authority states](#systems-rules-an-authority-states)
21
- - [Tells an authority states](#tells-an-authority-states)
22
20
  - [The catalog](#the-catalog)
23
- - [House choices](#house-choices)
24
21
  - [Declined from the catalogs](#declined-from-the-catalogs)
25
22
  - [Declined from the systems reference](#declined-from-the-systems-reference)
26
23
  - [Carried as a caution](#carried-as-a-caution)
27
24
 
28
- ## The layer model
29
-
30
- The body's layer order subdivides the five planes of Jesse James Garrett's [The Elements of User Experience](http://www.jjg.net/elements/). Its second chapter states the dependency the order rests on, that "Each plane is dependent on the planes below it."
31
-
32
- The same passage gives the constraint running the other way, that "the choices available to us on each plane are constrained by the decisions we make about issues on the planes below it". The nine layers and the grey-box stage are the skill's own subdivision of those planes.
33
-
34
- ## Craft rules an authority states
35
-
36
- Rows for `craft.md`, grouped by its sections.
37
-
38
- ### Type detail
39
-
40
- Each rule below is stated by the type reference or the CSS property that implements it.
41
-
42
- | Rule | Source |
43
- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
44
- | Measure | [Practical Typography](https://practicaltypography.com/line-length.html): "Aim for an average line length of 45–90 characters, including spaces." |
45
- | Figures in columns | [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric): `tabular-nums` sets figures "the same size, allowing them to be easily aligned" |
46
- | Small caps tracked | [Practical Typography](https://practicaltypography.com/letterspacing.html): "always add 5–12% extra letterspacing to text in all caps or small caps" |
47
- | Large type tighter | The same page: typographers "will often remove letterspacing from lowercase text used at larger sizes" |
48
- | Orphans | [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/text-wrap): `balance` suits "a short number of lines, such as headings, captions, and blockquotes" |
49
- | Hanging punctuation | [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/hanging-punctuation): "An opening bracket or quote at the start of the first formatted line" hangs |
50
-
51
- Casing is the `ui-craft` copy reference's, which `craft.md` points at rather than restating.
52
-
53
- ### Optical size, hierarchy, and unfinished work
54
-
55
- The rows below back one bullet each. The error row backs the fix half of its bullet alone.
56
-
57
- | Rule | Source |
58
- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
59
- | Optical size | [Wikipedia, Overshoot](https://en.wikipedia.org/wiki/Overshoot_%28typography%29): round letters overshoot "to achieve an optical effect of being the same size" |
60
- | Hierarchy from weight | [Practical Typography](https://practicaltypography.com/headings.html): with a bold heading, "you can also try reducing the point size" |
61
- | Where the reader is | [NN/g](https://www.nngroup.com/articles/navigation-you-are-here/): "Navigation should not only show where you can go but also where you are now." |
62
- | Error opens on a fix | [NN/g](https://www.nngroup.com/articles/error-message-guidelines/): "offer some potential remedies" |
63
-
64
- That an apology should not lead the error is the catalog's observation, since the NN/g page allows one on a total failure.
65
-
66
- ### Craft rules from the catalog
25
+ ## Where the rows sit
67
26
 
68
- The remaining `craft.md` rules are catalog observations of model output. They are optical centering, bottom-heavy padding, alignment across siblings, color and space carrying hierarchy, the shouting heading, every depth and texture rule, the dead link, the reused portrait, and the copy that reads unfinished.
27
+ Each bullet in the skill body's concern groups and in `craft.md`, `kinds.md`, `systems.md`, and `tells.md` has its own source row in a ledger outside the plugin, one ledger per file and one row per bullet under the H2 the bullet sits under.
69
28
 
70
- ## Systems rules an authority states
29
+ - The toolkit's skill audit fails a ledgered file whose bullets and rows disagree in count under any heading, and a target never carries the rows
30
+ - The body's `## What this delegates` takes no rows, since it routes rather than directs
31
+ - `preflight.md` takes no ledger, since its boxes restate the rules the four ledgered references source
32
+ - `vocabulary.md` takes none either, since it defines terms rather than directing
33
+ - This record keeps the layer model behind the body's order, and what was read and declined
71
34
 
72
- Rows for `systems.md`. The counts it states sit under house choices below.
73
-
74
- | Rule | Source |
75
- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
76
- | Between groups beats within | [NN/g](https://www.nngroup.com/articles/gestalt-proximity/): "Items close together are likely to be perceived as part of the same group" |
77
- | One gap everywhere fails | The same page: a tight label reads as one group "compared to a larger margin before the next label-field pair" |
78
- | Adjacent steps differ | [Practical Typography](https://practicaltypography.com/headings.html): "Use the smallest increment necessary to make a visible difference." |
79
- | Fewer steps than feel enough | The same page: "Limit yourself to three levels of headings. Two is better." |
80
- | Weights beside sizes | The bold heading passage under craft above |
81
- | Dark mode re-derived | [Apple HIG](https://developer.apple.com/design/human-interface-guidelines/dark-mode): dark colors "aren't necessarily inversions of their light counterparts" |
82
-
83
- ### Systems rules from the catalog
84
-
85
- Geometric spacing steps, space responding to the viewport, body size anchoring the scale, and line height moving opposite to size are catalog observations. Practical Typography gives a line spacing range for body text alone, so it does not back the last.
86
-
87
- Every palette rule but the dark mode row is catalog as well, being accent by rarity, one neutral temperature, the separation of surfaces from content, a semantic color kept off the accent, and the saturation budget.
88
-
89
- ## Tells an authority states
35
+ ## The layer model
90
36
 
91
- Two tells and one application UI rule rest on a source rather than on the catalog.
37
+ The body's layer order subdivides the five planes of Jesse James Garrett's [The Elements of User Experience](http://www.jjg.net/elements/). Its second chapter states the dependency the order rests on, that "Each plane is dependent on the planes below it."
92
38
 
93
- | Rule | Source |
94
- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
95
- | Unstyled platform control | [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/color-scheme): it adapts "The default colors of form controls" |
96
- | Transparency with no checkerboard | [Wikipedia](https://en.wikipedia.org/wiki/Transparency_%28graphic%29): an editor "shows transparency by a special pattern, e.g. a checkerboard pattern" |
97
- | Shortcut beside its command | [NN/g](https://www.nngroup.com/articles/ui-copy/): shortcuts sit "to the far right of the menu" and "alongside the command text in tool tips" |
39
+ The same passage gives the constraint running the other way, that "the choices available to us on each plane are constrained by the decisions we make about issues on the planes below it". The nine layers and the grey-box stage are the skill's own subdivision of those planes.
98
40
 
99
41
  ## The catalog
100
42
 
101
- Every other tell in `tells.md`, and the ten defaults in the body, came from community prompt skills that recorded what models draw unguided. None of them is a design authority. Each tell is an observation of model output, falsifiable against a render, rather than established practice.
43
+ Most tells in `tells.md`, and the ten defaults in the body, came from community prompt skills that recorded what models draw unguided. None of them is a design authority. Each tell is an observation of model output, falsifiable against a render, rather than established practice.
102
44
 
103
45
  - **[Taste-Skill](https://github.com/leonxlnx/taste-skill)** and its fork **[claude-taste-skill](https://github.com/nxpatterns/claude-taste-skill)** supplied the composition, content, surface, and motion tells
104
46
  - **[UI/UX Pro Max](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill)** was first read through a vendor listing and later from its repository. Its ranking puts accessibility first, and its lookup corpus was declined.
105
47
  - **[frontend-design](https://github.com/anthropics/skills/tree/main/skills/frontend-design)**, Anthropic's skill, supplied the five clusters current AI design falls into, restated in `tells.md`
106
48
  - **[Impeccable](https://github.com/pbakaus/impeccable)** supplied what a visual direction may lend an application screen and the category self-check, restated in `kinds.md`. Its themed browser surfaces lie behind the platform control tell.
107
49
 
108
- No sentence from any of them is copied. Each idea is restated and cited here.
50
+ No sentence from any of them is copied. Each idea is restated and cited in the ledger row for its bullet.
51
+
52
+ Most Taste-Skill tells came from its v2 experimental skill, which its author later moved to [taste-skill-classics](https://github.com/Leonxlnx/taste-skill-classics), and the rows link it there.
109
53
 
110
54
  ### Adopted with no change
111
55
 
@@ -115,30 +59,6 @@ The three equal cards, the centered hero over a wash, enumerated eyebrows, scrol
115
59
 
116
60
  Source items naming an icon set, a component library, a font by name, or an animation package were rewritten to state what the rule is about. "Do not use Inter" became one family doing every job, since the defensible claim is about pairing and role separation rather than about one typeface.
117
61
 
118
- ## House choices
119
-
120
- Each threshold below is the toolkit's, chosen so a tell can be counted rather than judged.
121
-
122
- | Threshold | Source |
123
- | ----------------------------- | ---------------------------------------------------------------------------------------------- |
124
- | About eight spacing values | House choice: past it, a count tells a scale from arithmetic on a finished surface |
125
- | Five to seven type steps | House choice: fewer forces size to carry every level, and more holds steps nobody tells apart |
126
- | Two or three section tiers | House choice: enough tiers for rhythm, few enough that each section takes one |
127
- | One marquee | House choice: a second sliding strip is where the device reads as filler |
128
- | Two consecutive splits | House choice: a third alternation is where the pattern reads as filler |
129
- | Four first-screen text items | House choice: a label, a headline, a supporting line, and the actions, so a fifth is countable |
130
- | One layout family, five items | House choice: a repeated shape and a long run become counts a reviewer can check |
131
-
132
- The uppercase label count belongs to the `ui-craft` copy reference, whose own ledger records it as a house choice.
133
-
134
- ### The focus ring's weight
135
-
136
- One more lock is the toolkit's own choice.
137
-
138
- | Threshold | Source |
139
- | --------------- | -------------------------------------------------------------------------------------------------------- |
140
- | One ring weight | House choice: a ring varying by component reads as several products. The `ui-craft` skill owns the floor |
141
-
142
62
  ## Declined from the catalogs
143
63
 
144
64
  Each item below is real advice placed in the wrong surface, or a rule that decides nothing.
@@ -77,7 +77,7 @@ The browser and the operating system draw some parts of every page, and a themed
77
77
 
78
78
  ## The countable limits
79
79
 
80
- These rules carry numbers, so they are checked by counting rather than by judging. Each number is a house choice made so the tell can be counted, and `adopted.md` records it as one.
80
+ These rules carry numbers, so they are checked by counting rather than by judging. Each number is a house choice made so the tell can be counted, and its source row records it as one.
81
81
 
82
82
  - **A layout family appears once.** Once a section uses a shape, no other section on the surface uses it. Eight sections need at least four distinct families.
83
83
  - **Two consecutive splits, never three.** Alternating image sides reads as considered twice and as filler by the third. Break it with a full-width section, a vertical stack, or a grid.
@@ -96,4 +96,4 @@ These rules carry numbers, so they are checked by counting rather than by judgin
96
96
 
97
97
  ## Adopted, declined, and why
98
98
 
99
- Most items here are observations of what models draw unguided, gathered from community prompt skills rather than from a design authority. The record of which were adopted, which declined, and why sits in `adopted.md` beside this file, with the few an authority states and the links to the catalog behind the rest.
99
+ Most items here are observations of what models draw unguided, gathered from community prompt skills rather than from a design authority. The record of which catalogs were read, which items were declined, and why sits in `adopted.md` beside this file, and it says where each item's own source row sits.
@@ -16,7 +16,7 @@ Length, placement, and staleness answer to different evidence, and one list hand
16
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
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
- - 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
19
+ - Report a refusal, an absent key, or a missing subcommand as an unread axis naming the cause
20
20
  - Run standalone, reading the requirements record for drift with its reminder, and the design record through `canon design audit --json` and its review reminder, routing findings to `design-record`
21
21
 
22
22
  ## Must not
@@ -34,16 +34,7 @@ canon markdown audit --json
34
34
  canon context audit --json
35
35
  ```
36
36
 
37
- The first answers length, carrying the bullet, paragraph, and depth checkpoints and the per-file weights read against them. The second answers placement for the folders it resolves, carrying entry length, reference form, and index drift.
38
-
39
- Then read which classifier would run, and deepen placement with the verdicts per section:
40
-
41
- ```bash
42
- canon context classifier show
43
- canon context classify sweep --json
44
- ```
45
-
46
- The first names the backend, the model, and the source that decided both. Report which layer answered, since a project with the model layer off reads from the regex layer alone and the sweep says nothing about which one it used.
37
+ The first answers length, carrying the bullet, paragraph, and depth checkpoints and the per-file weights read against them. The second answers placement for the folders it resolves, carrying entry length, reference form, and index drift. Placement reads `shapeFindings`, `extraSections`, and each entry's `provenance`, all `measured`.
47
38
 
48
39
  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
40
 
@@ -58,7 +49,6 @@ Emit the line only for a folder with an entry past the line checkpoint whose Lay
58
49
  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.
59
50
 
60
51
  - `canon context audit` refuses with `reason: "no-folders"` where the layout is not the expected one. Reading that honest refusal as an empty finding set reports a healthy corpus nothing looked at.
61
- - A narrower read is not an unread one. The sweep running on its regex layer alone still answered, so report it with the layer named.
62
52
 
63
53
  ### The design record
64
54
 
@@ -92,10 +82,9 @@ Nothing triggers this review but a request. A finished review hands the rewrite
92
82
 
93
83
  Give each document its three axes, and give each axis three things: the state, the evidence class, and the command or skill that repairs it. Naming the repair is not running it. A length finding names `document-repair`, which rewrites a folder to zero and gates it.
94
84
 
95
- The three classes are what keep the axes apart:
85
+ The two classes are what keep the axes apart:
96
86
 
97
87
  - `measured`: a verb returned a number read against a stated checkpoint
98
- - `classified`: a verb returned a verdict carrying its own confidence
99
88
  - `read`: this session's judgment, backed by no verb
100
89
 
101
90
  Emit no verdict across the three. Two answer from verbs and one answers from a reading, so a roll-up is a figure that lies about the third. Emit no score across the documents either, for the same reason one level up.
@@ -131,7 +120,7 @@ Structure `canon/context/surfaces/`: `cli.md` (300 lines) splits into `cli.md` t
131
120
 
132
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.
133
122
 
134
- 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.
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 two classes exist to prevent.
135
124
 
136
125
  ### The design record row
137
126
 
@@ -35,24 +35,25 @@ Weight is a judgment a reader settles rather than a defect, as the verb states f
35
35
 
36
36
  ## Placement
37
37
 
38
- | Field | Value |
39
- | -------------- | ------------------------------------------------------------------------------------------------------------------------ |
40
- | Measures | Whether a document's content sits in the file that owns it, and whether the catalogs pointing at it resolve |
41
- | Verbs | `canon context audit --json` for the structural half, `canon context classify sweep --json` for the per-section verdicts |
42
- | Evidence class | `measured` for the audit's findings, `classified` for the sweep's verdicts |
38
+ | Field | Value |
39
+ | -------------- | ----------------------------------------------------------------------------------------------------------- |
40
+ | Measures | Whether a document's content sits in the file that owns it, and whether the catalogs pointing at it resolve |
41
+ | Verb | `canon context audit --json` |
42
+ | Evidence class | `measured` |
43
43
 
44
44
  The audit answers required sections, entry length, citation resolution, reference form, catalog tables, provenance, and index drift. Required sections reach context entries.
45
45
 
46
46
  - A citation resolving to nothing is a fact and gates
47
47
  - Entry length, reference form, table shape, and provenance are judgments under every flag
48
48
 
49
- ### The sweep's verdicts
49
+ ### The audit's placement arrays
50
50
 
51
- The sweep classifies each section as keep, replace or rewrite, history, or move. A `move` verdict is the placement finding proper, naming content sitting in the wrong document.
51
+ Three parts of the audit record name content sitting outside the shape its folder allows. Each is a count or a list the verb returned, so every placement finding is `measured`.
52
52
 
53
- - Each verdict carries its own confidence, which is why the class is `classified` rather than `measured`
54
- - A low-confidence `move` is a prompt to look rather than an instruction to cut
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.
53
+ - `shapeFindings`: an entry whose sections break the shape its folder holds, such as a Decisions section or a sixth gotcha
54
+ - `extraSections`: an H2 outside the closed set the folder allows
55
+ - `entries[].provenance`: an entry narrating how it came to be, which is history rather than a description of the tree
56
+ - **Routes to:** the document that owns the passage. The record names no owner, so the project's own content-ownership rules decide the destination.
56
57
 
57
58
  ### The structure line
58
59
 
@@ -66,12 +67,9 @@ The audit record's `length` array lists each entry past the line checkpoint, and
66
67
 
67
68
  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
69
 
69
- ### When a verb resolves nothing
70
+ ### When the verb resolves nothing
70
71
 
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.
72
-
73
- - The audit refuses with `reason: "no-folders"`, naming the folders it looked for. Report that refusal as an unread axis.
74
- - The sweep with the model layer off answers from its regex layer alone, a narrower read rather than a refusal, so say which layer answered
72
+ The audit resolves its folders by surface root rather than by a path written into it, so a project laid out differently resolves nothing. It then refuses with `reason: "no-folders"`, naming the folders it looked for. Report that refusal as an unread axis.
75
73
 
76
74
  ## The design record
77
75
 
@@ -139,7 +137,7 @@ A reading is the weakest evidence in the report and the most consequential findi
139
137
  The axes are not equally actionable, and a report flattening them implies they are. Each is worth reporting and each is worth a different response, so the class travels beside the state on every row rather than once in a preamble a reader skims.
140
138
 
141
139
  - A length finding is a number against a checkpoint
142
- - A placement finding is a verdict carrying a confidence
140
+ - A placement finding is a count or a list the audit returned
143
141
  - A staleness finding is a judgment with nothing behind it
144
142
 
145
143
  Shipping staleness on weaker evidence than the other two is the trade taken deliberately. Cutting it would leave the report answering the two questions that were never the operator's complaint.
@@ -57,18 +57,15 @@ An audit that finds no corpus reports `absent`, which moves neither the verdict
57
57
 
58
58
  **In `bun run check`.**
59
59
 
60
- `bun run check` runs `--corpus tracked --corpus per-machine` as a reporting stage after the gating stages, and never fails on it. `summary` is a flat object of unique scalar keys that a shell stage greps without a JSON parser. `deps` runs weekly instead.
61
-
62
- The placement entry runs pinned to `--backend off`, so its tally stays comparable across machines. Each audit runs as the CLI the caller is running, never a global `canon`.
60
+ `bun run check` runs `--corpus tracked --corpus per-machine` as a reporting stage after the gating stages, and never fails on it. `summary` is a flat object of unique scalar keys that a shell stage greps without a JSON parser. `deps` runs weekly instead. Each audit runs as the CLI the caller is running, never a global `canon`.
63
61
 
64
62
  **Catalog.**
65
63
 
66
- `canon audits list` reports the first 19 rows. The rows marked `outside` run by hand or from a skill and sit beside the aggregate.
64
+ `canon audits list` reports the first 18 rows. The rows marked `outside` run by hand or from a skill and sit beside the aggregate.
67
65
 
68
66
  | Id | Verb | Measures | Finding |
69
67
  | -------------------- | ----------------------------------- | ---------------------------------------------------------------------------------- | -------------- |
70
68
  | `context` | `canon context audit` | Context folder structure, citations, and the requirements record's word cap | Gates |
71
- | `placement` | `canon context classify sweep` | Keep, rewrite, and move tally per context section, regex layer only | Reports |
72
69
  | `markdown` | `canon markdown audit` | Bans, dead links, density, and reference shape | Gates |
73
70
  | `skills` | `canon claude skills audit` | Both skill corpora against the skill standards | Gates |
74
71
  | `skills-reach` | `canon claude skills reach` | Skill bodies citing a path no target receives | Reports |
@@ -90,7 +87,6 @@ The placement entry runs pinned to `--backend off`, so its tally stays comparabl
90
87
  | `outside` | `canon gov superseded <old> <new>` | Where the tree still asserts a value a changed convention no longer produces | Reports |
91
88
  | `outside` | `canon claude skills drift <ref>` | Shipped skill bodies rewritten since a ref | Reports |
92
89
  | `outside` | `canon claude routing` | Per `CLAUDE.md` section, how many bullets name a path and whether a rule covers it | Reports |
93
- | `outside` | `canon context classify diff` | Classification of the chunks a git range changed | Reports |
94
90
 
95
91
  A deliberate secret takes a `canon-allow-secret: <reason>` marker. A deliberate citation takes `canon-allow-citation: <reason>` and a deliberate superseded value takes `canon-allow-superseded: <reason>`, each on its own line or the one above. Run any verb with `--help` for its flags and refusal reasons.
96
92
 
@@ -62,7 +62,7 @@ The exit code follows the mode the run took. The bullets cover where the gate ru
62
62
  - A root resolving no audited folder refuses with `1` and warns, a root measuring no entry warns, and a seed short a section fails with `2`
63
63
  - A seed omitting a required section on purpose sets `stub: true` in its frontmatter. Only the value `true` counts, and both install paths strip the field.
64
64
 
65
- The citation check skips fenced blocks, fixture and harness trees including `*.test.ts`, and a path into a folder the project lacks.
65
+ The citation check skips fenced blocks, fixture and harness trees including `*.test.ts`, the install stamp at any of its spellings, and a path into a folder the project lacks.
66
66
 
67
67
  Append `<!-- audit-ignore-citations: <path> -->` to a line that displays a path without pointing at it. The marker excuses only the paths it names, and a bare `<!-- audit-ignore-citations -->` excuses every citation on the line. In seeds, plugin skill bodies, and stack references, which install into a target, reword the line instead.
68
68
 
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: API design skill ledger
3
+ description: Sources for claude/skills/api-design/SKILL.md, one row per bullet in its concern groups
4
+ ---
5
+
6
+ # API design skill ledger
7
+
8
+ The field is interface design across functions, flags, file formats, and endpoints. Google's API Improvement Proposals and its engineering book carry compatibility, the IETF carries the error and deprecation formats, and Stripe's own docs carry idempotency. The closing sections and `## What this delegates` restate these rules or route, so they take no table.
9
+
10
+ ## Decide what a caller can observe
11
+
12
+ | Bullet | Source | Read |
13
+ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
14
+ | A shape built for the caller | [agent-skills, API and interface design](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/api-and-interface-design/SKILL.md): "Don't leak implementation details. If users can observe it, they will depend on it." | 2026-10-24 |
15
+ | Ordering, timing, and error text count | [Software Engineering at Google, ch. 1](https://abseil.io/resources/swe-book/html/ch01.html): "all observable behaviors of your system will be depended on by somebody", worked through hash iteration ordering | 2026-10-24 |
16
+ | As small as the first caller needs | [AIP-180](https://google.aip.dev/180): new components "may be added to existing APIs in the same major version", while "Removing a component is a backwards incompatible change" | 2026-10-24 |
17
+ | One name for one concept | [AIP-140](https://google.aip.dev/140): "APIs should endeavor to use the same name for the same concept and different names for different concepts" | 2026-10-24 |
18
+
19
+ ## Write the contract first
20
+
21
+ | Bullet | Source | Read |
22
+ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
23
+ | The signature before the body | [agent-skills, API and interface design](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/api-and-interface-design/SKILL.md): "Define the interface before implementing it. The contract is the spec" | 2026-10-24 |
24
+ | What it does, returns, and refuses | [agent-skills, API and interface design](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/api-and-interface-design/SKILL.md): its contract names the refusal beside the return, "Returns a single task or throws NotFoundError" | 2026-10-24 |
25
+ | Machine output on its own channel | [Command Line Interface Guidelines](https://clig.dev/): "Log messages, errors, and so on should all be sent to stderr", so piped commands never feed them "into the next command" | 2026-10-24 |
26
+ | The safe behavior is the default | [Command Line Interface Guidelines](https://clig.dev/): "Confirm before doing anything dangerous", prompting interactively "or requiring them to pass -f or --force otherwise" | 2026-10-24 |
27
+
28
+ ## Keep one error shape per surface
29
+
30
+ | Bullet | Source | Read |
31
+ | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
32
+ | A stable code beside the message | [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457.html): consumers "MUST use the "type" URI" as "the problem type's primary identifier", and "Consumers SHOULD NOT parse the "detail" member for information" | 2026-10-24 |
33
+ | No internals in the message | [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457.html): generators "are encouraged to avoid making implementation details such as a stack dump available through the HTTP interface" | 2026-10-24 |
34
+ | Reuse the project's error type | [agent-skills, API and interface design](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/skills/api-and-interface-design/SKILL.md): "Pick one error strategy and use it everywhere" | 2026-10-24 |
35
+
36
+ ## Validate at the boundary
37
+
38
+ | Bullet | Source | Read |
39
+ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
40
+ | Check once where input enters | [Parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/): checks spread through processing deprive "the program of the ability to reject invalid input instead of processing it" | 2026-10-24 |
41
+ | Trust the value inside | [Parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/): shotgun parsing mixes checks "with and spread across processing code", hoping "one or another would catch all the "bad" cases" | 2026-10-24 |
42
+ | Parse into a typed value | [Parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/): "Get your data into the most precise representation you need as quickly as you can. Ideally, this should happen at the boundary of your system" | 2026-10-24 |
43
+ | A value read back is input | [OWASP Input Validation Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html): "Validate data from internal APIs, partner feeds, queues, and stored records when it crosses a trust boundary" | 2026-10-24 |
44
+
45
+ ## Change additively
46
+
47
+ | Bullet | Source | Read |
48
+ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
49
+ | Optional, with the old behavior default | [AIP-180](https://google.aip.dev/180): code written against the previous surface "must continue to be treated the same way as before. New required fields must not be added" | 2026-10-24 |
50
+ | No rename or removal in place | [AIP-180](https://google.aip.dev/180): "Renaming a component is semantically equivalent to "remove and add"", and a service "may add the new component, but must not remove the existing one" | 2026-10-24 |
51
+ | No new meaning or type under a name | [AIP-180](https://google.aip.dev/180): fields "must not have their type changed", and APIs "must not change visible behavior or semantics in ways that are likely to break reasonable user code" | 2026-10-24 |
52
+ | One live version for an unpinned caller | [Software Engineering at Google, ch. 16](https://abseil.io/resources/swe-book/html/ch16.html): "Developers must never have a choice of "What version of this component should I depend upon?"", named the One-Version Rule | 2026-10-24 |
53
+ | Deprecation recorded where a caller looks | [RFC 9745](https://www.rfc-editor.org/rfc/rfc9745.html): a response signals "that the resource will be or has been deprecated" and links "to a resource that provides further information about planned or existing deprecation" | 2026-10-24 |
54
+
55
+ ## Make a retried write safe
56
+
57
+ | Bullet | Source | Read |
58
+ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
59
+ | Answer a repeat with the stored result | [Stripe idempotent requests](https://docs.stripe.com/api/idempotent_requests): "Stripe saves the status code and body of the first request made with a given idempotency key", and "Retries with the same key return the saved response" | 2026-10-24 |
60
+ | Claim the key atomically | [Implementing Stripe-like idempotency keys in Postgres](https://brandur.org/idempotency-keys): a unique index on the key, locked "so that no other requests that might be operating concurrently also try the operation" | 2026-10-24 |
61
+ | A reused key with another body fails | [Stripe idempotent requests](https://docs.stripe.com/api/idempotent_requests): the layer "compares incoming parameters to those of the original request and errors if they're not the same to prevent accidental misuse" | 2026-10-24 |
62
+ | Keep the key past the retry window | [Stripe idempotent requests](https://docs.stripe.com/api/idempotent_requests): keys go once "at least 24 hours old", and "We generate a new request if a key is reused after the original is pruned" | 2026-10-24 |