@erclx/aitk 0.22.1 → 0.24.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 (37) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/claude-roadmap/references/roadmap.md +12 -2
  3. package/claude/skills/claude-standards-audit/SKILL.md +3 -3
  4. package/claude/skills/create-standard/references/snippets.md +9 -0
  5. package/claude/skills/git-branch/references/branch.md +12 -1
  6. package/claude/skills/git-commit/references/commit.md +11 -1
  7. package/claude/skills/git-issue/references/issue.md +10 -0
  8. package/claude/skills/git-pr/references/branch.md +12 -1
  9. package/claude/skills/git-pr/references/pr.md +12 -1
  10. package/claude/skills/git-split/references/branch.md +12 -1
  11. package/claude/skills/git-split/references/pr.md +12 -1
  12. package/claude/skills/git-stage/references/commit.md +11 -1
  13. package/docs/agents.md +10 -5
  14. package/package.json +1 -1
  15. package/src/commands/sandbox.ts +99 -5
  16. package/src/sandbox/census.ts +228 -0
  17. package/standards/architecture.md +10 -2
  18. package/standards/bundled/branch.md +12 -1
  19. package/standards/bundled/commit.md +11 -1
  20. package/standards/bundled/issue.md +10 -0
  21. package/standards/bundled/pr.md +12 -1
  22. package/standards/bundled/roadmap.md +12 -2
  23. package/standards/bundled/snippets.md +9 -0
  24. package/standards/context.md +11 -0
  25. package/standards/design.md +9 -1
  26. package/standards/diagrams.md +13 -2
  27. package/standards/prose.md +11 -0
  28. package/standards/readme.md +9 -0
  29. package/standards/requirements.md +10 -1
  30. package/standards/rule.md +10 -0
  31. package/standards/skill.md +11 -0
  32. package/standards/standard.md +24 -4
  33. package/standards/tasks.md +11 -0
  34. package/standards/versioning.md +11 -0
  35. package/standards/wireframes.md +11 -1
  36. package/claude/skills/claude-standards-audit/references/branch.md +0 -49
  37. package/claude/skills/claude-standards-audit/references/pr.md +0 -124
@@ -0,0 +1,228 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs'
2
+ import { join } from 'node:path'
3
+ import { collectCoverage, type CoverageReport } from '@/sandbox/coverage'
4
+
5
+ /**
6
+ * Holds the exemption declarations, beside the scenario categories rather than
7
+ * inside one. `listScenarios` in `coverage.ts` walks directories only, so a file
8
+ * at that level joins no category and never reads as a scenario.
9
+ */
10
+ const EXEMPT_FILE = 'exempt.toml'
11
+
12
+ export type SkillVerdict = 'asserted' | 'should-be-asserted' | 'exempt'
13
+
14
+ export interface SkillCensusEntry {
15
+ readonly skill: string
16
+ readonly verdict: SkillVerdict
17
+ /**
18
+ * Every `<category>:<command>` pairing to this skill, empty when none does.
19
+ * Plural because the mapping is many-to-one: two scenarios can drive one
20
+ * skill, and naming only the first would credit its arms to the wrong file.
21
+ */
22
+ readonly scenarios: readonly string[]
23
+ /**
24
+ * Each armed arm as `<category>:<command>/<arm>`. Qualified rather than bare,
25
+ * because a skill two scenarios drive can hold two arms of the same name and
26
+ * a bare list renders them as one label twice. Deduplicating instead would
27
+ * read as one arm where two assert, which understates in the one direction
28
+ * this report exists to keep honest.
29
+ */
30
+ readonly armed: readonly string[]
31
+ /** Why no arm asserts this skill. Present only on `exempt`. */
32
+ readonly reason?: string
33
+ }
34
+
35
+ export interface CensusReport {
36
+ readonly skills: readonly SkillCensusEntry[]
37
+ readonly totalSkills: number
38
+ readonly asserted: number
39
+ readonly shouldBeAsserted: number
40
+ readonly exempt: number
41
+ /** Exemptions naming a skill the tree does not carry. */
42
+ readonly staleExemptions: readonly string[]
43
+ /**
44
+ * Exemptions on a skill an arm now asserts. The claim is wrong in the one
45
+ * direction a verdict decays, and the entry outranks nothing, so dropping it
46
+ * silently leaves committed data nobody is told to delete.
47
+ */
48
+ readonly supersededExemptions: readonly string[]
49
+ }
50
+
51
+ function directories(path: string): string[] {
52
+ if (!existsSync(path)) return []
53
+
54
+ return readdirSync(path, { withFileTypes: true })
55
+ .filter((entry) => entry.isDirectory())
56
+ .map((entry) => entry.name)
57
+ .sort()
58
+ }
59
+
60
+ /**
61
+ * Every skill the plugin ships, which is the census denominator. Reads the
62
+ * authoring root rather than `.claude/skills/`, since the latter holds
63
+ * toolkit-internal skills that reach no target and would inflate the count.
64
+ */
65
+ export function listSkills(root: string): string[] {
66
+ return directories(join(root, 'claude', 'skills'))
67
+ }
68
+
69
+ /**
70
+ * Maps a scenario to the skill it drives, trying two spellings in order.
71
+ *
72
+ * `<category>-<command>` is the rule `.claude/context/sandbox.md` states, and it
73
+ * alone pairs 29 of 55 skills. The bare `<command>` fallback is what reaches the
74
+ * rest: `claude/setup-init.sh` drives the `setup-init` skill, not a
75
+ * `claude-setup-init` that does not exist. Stating one spelling and shipping two
76
+ * is what let the audit report a paired skill as unpaired.
77
+ *
78
+ * Returns undefined for a scenario driving no skill at all, which is every
79
+ * `infra/` and `tooling/` scenario. Those exercise a CLI domain rather than a
80
+ * skill and belong to the scenario count, not to this one.
81
+ */
82
+ export function skillForScenario(
83
+ category: string,
84
+ command: string,
85
+ skills: ReadonlySet<string>,
86
+ ): string | undefined {
87
+ const prefixed = `${category}-${command}`
88
+ if (skills.has(prefixed)) return prefixed
89
+ if (skills.has(command)) return command
90
+
91
+ return undefined
92
+ }
93
+
94
+ /**
95
+ * Reads the exemption declarations, keyed by skill with a `reason` each.
96
+ *
97
+ * The reason cannot live in the arm's `manual` array, which is where `#723` put
98
+ * prose a checker could not assert. `resolveVerdict` fails any declaration
99
+ * carrying zero mechanical assertions, so an `expect.toml` holding only an
100
+ * exempt reason goes red at the moment it is written. An exempt skill has no
101
+ * assertion to pair the prose with, which is what makes it exempt, so the two
102
+ * cases cannot share a home.
103
+ *
104
+ * Throws on a malformed file and on a table carrying no usable `reason`, rather
105
+ * than reporting a smaller set. Both losses are invisible downstream: the skill
106
+ * reclassifies to should-be-asserted and rejoins a work queue someone already
107
+ * ruled it out of, with nothing naming the entry that stopped counting. This is
108
+ * the stray-key rule `contentArray` applies in `expect.ts` for the same reason,
109
+ * where the declaration is well-formed and silently lost a key it appears to
110
+ * carry. `runCoverage` catches both and frames them.
111
+ */
112
+ export function parseExemptions(source: string): Map<string, string> {
113
+ const parsed = Bun.TOML.parse(source) as Record<string, unknown>
114
+ const exemptions = new Map<string, string>()
115
+
116
+ for (const [skill, value] of Object.entries(parsed)) {
117
+ if (typeof value !== 'object' || value === null) {
118
+ throw new Error(
119
+ `exemption ${skill} is not a table. Write [${skill}] with a reason below it.`,
120
+ )
121
+ }
122
+
123
+ const reason = (value as Record<string, unknown>).reason
124
+ if (typeof reason !== 'string' || reason === '') {
125
+ throw new Error(
126
+ `exemption ${skill} declares no reason. An exemption without one cannot be checked or overturned.`,
127
+ )
128
+ }
129
+
130
+ exemptions.set(skill, reason)
131
+ }
132
+
133
+ return exemptions
134
+ }
135
+
136
+ function readExemptions(root: string): Map<string, string> {
137
+ const path = join(root, 'scripts', 'sandbox', EXEMPT_FILE)
138
+ if (!existsSync(path)) return new Map()
139
+
140
+ return parseExemptions(readFileSync(path, 'utf8'))
141
+ }
142
+
143
+ /**
144
+ * Gives every shipped skill an asserted, should-be-asserted, or exempt verdict
145
+ * against declared expectations rather than against a scenario existing.
146
+ *
147
+ * A paired scenario is not an asserted skill. A scenario with no `expect.toml`
148
+ * provisions a state and prints a human-readable `Expect:` line, so a run over
149
+ * it exits zero having proved nothing. Counting pairs would report coverage the
150
+ * suite does not have, which is the measure this report exists to replace.
151
+ *
152
+ * An armed arm outranks an exemption. A skill listed exempt that acquired an arm
153
+ * is asserted in fact, and reporting the stale claim instead would hide the one
154
+ * direction the verdict decays in.
155
+ */
156
+ export function collectCensus(
157
+ root: string,
158
+ coverage: CoverageReport = collectCoverage(root),
159
+ ): CensusReport {
160
+ const skills = listSkills(root)
161
+ const known = new Set(skills)
162
+ const exemptions = readExemptions(root)
163
+
164
+ const pairings = new Map<string, { scenarios: string[]; armed: string[] }>()
165
+ for (const scenario of coverage.scenarios) {
166
+ const skill = skillForScenario(scenario.category, scenario.command, known)
167
+ if (skill === undefined) continue
168
+
169
+ // Accumulate rather than assign. Dropping a second scenario would report a
170
+ // skill unarmed while an arm under the other spelling asserts it.
171
+ const pair = `${scenario.category}:${scenario.command}`
172
+ const existing = pairings.get(skill) ?? { scenarios: [], armed: [] }
173
+ existing.scenarios.push(pair)
174
+ existing.armed.push(...scenario.armed.map((arm) => `${pair}/${arm}`))
175
+ pairings.set(skill, existing)
176
+ }
177
+
178
+ const entries = skills.map((skill): SkillCensusEntry => {
179
+ const pairing = pairings.get(skill)
180
+ const scenarios = pairing?.scenarios ?? []
181
+ const armed = pairing?.armed ?? []
182
+ const reason = exemptions.get(skill)
183
+
184
+ if (armed.length > 0) {
185
+ return { skill, verdict: 'asserted', scenarios, armed }
186
+ }
187
+
188
+ if (reason !== undefined) {
189
+ return { skill, verdict: 'exempt', scenarios, armed, reason }
190
+ }
191
+
192
+ return { skill, verdict: 'should-be-asserted', scenarios, armed }
193
+ })
194
+
195
+ // An exemption outranked by an arm is as wrong as one naming no skill, and it
196
+ // is the case the armed-wins rule creates rather than one the tree arrives
197
+ // with. Reading `entries` rather than recomputing keeps the two in step, so a
198
+ // change to the precedence cannot leave the report contradicting the verdict.
199
+ const assertedSkills = new Set(
200
+ entries.filter((e) => e.verdict === 'asserted').map((e) => e.skill),
201
+ )
202
+
203
+ return {
204
+ skills: entries,
205
+ totalSkills: entries.length,
206
+ asserted: assertedSkills.size,
207
+ shouldBeAsserted: entries.filter((e) => e.verdict === 'should-be-asserted')
208
+ .length,
209
+ exempt: entries.filter((e) => e.verdict === 'exempt').length,
210
+ staleExemptions: [...exemptions.keys()]
211
+ .filter((skill) => !known.has(skill))
212
+ .sort(),
213
+ supersededExemptions: [...exemptions.keys()]
214
+ .filter((skill) => assertedSkills.has(skill))
215
+ .sort(),
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Whole percent, floored, over skills rather than scenarios. Floored for the
221
+ * reason `coveragePercent` is: the number exists to look worse than a wall of
222
+ * green does.
223
+ */
224
+ export function assertedPercent(report: CensusReport): number {
225
+ if (report.totalSkills === 0) return 0
226
+
227
+ return Math.floor((report.asserted / report.totalSkills) * 100)
228
+ }
@@ -7,6 +7,16 @@ description: Shape and content rules for .claude/ARCHITECTURE.md
7
7
 
8
8
  Applies to `.claude/ARCHITECTURE.md`. Describes the system shape and the decisions behind it, not a tutorial, setup guide, or implementation walkthrough. Pair it with `CLAUDE.md`: principles live there, patterns and decisions live here. Update when a decision is made or a risk is resolved.
9
9
 
10
+ ## Scope
11
+
12
+ Governs the system-shape document at `.claude/ARCHITECTURE.md`: the overview, the decision entries, and the open risks.
13
+
14
+ Does not govern:
15
+
16
+ - Per-domain structure and narrative: `context.md`
17
+ - Setup commands and install instructions: `readme.md`
18
+ - Product scope, goals, and non-goals: `requirements.md`
19
+
10
20
  ## What goes in
11
21
 
12
22
  - A high-level overview of how the system is structured and why
@@ -15,8 +25,6 @@ Applies to `.claude/ARCHITECTURE.md`. Describes the system shape and the decisio
15
25
 
16
26
  ## What does not go in
17
27
 
18
- - Per-domain structure and narrative. That belongs in `.claude/context/<domain>.md`, one file per domain.
19
- - Setup commands and install instructions. Those live in the README.
20
28
  - How individual functions work line by line. The code carries its own behavior.
21
29
  - Full type definitions. They live in code. Reference the shape conceptually if needed.
22
30
 
@@ -1,11 +1,22 @@
1
1
  ---
2
2
  title: Branch reference
3
3
  description: Branch naming format and type conventions
4
- consumers: git-branch, git-split, git-pr, claude-standards-audit
4
+ consumers: git-branch, git-split, git-pr
5
5
  ---
6
6
 
7
7
  # Branch reference
8
8
 
9
+ ## Scope
10
+
11
+ Governs a git branch name: its structure, its length, and the type vocabulary it draws from.
12
+
13
+ Does not govern:
14
+
15
+ - Commit subject format, which shares the type vocabulary: `commit.md`
16
+ - Pull request title and body: `pr.md`
17
+ - Whether a phase label may appear in a branch name: `versioning.md`
18
+ - Deriving an output filename from a branch name, which is a transform the skill running it owns
19
+
9
20
  ## Format
10
21
 
11
22
  - Structure: `<type>/<description>` or `<type>/<ticket>-<description>`
@@ -6,6 +6,16 @@ consumers: git-commit, git-stage
6
6
 
7
7
  # Commit message reference
8
8
 
9
+ ## Scope
10
+
11
+ Governs a git commit message: subject structure, the type and scope vocabulary, and the body.
12
+
13
+ Does not govern:
14
+
15
+ - Branch naming, which shares the type vocabulary: `branch.md`
16
+ - Pull request title and body, which share the subject form: `pr.md`
17
+ - Whether a phase label or a semver tag may appear in a subject: `versioning.md`
18
+
9
19
  ## Format
10
20
 
11
21
  - Structure: `<type>(<scope>): <subject>`
@@ -26,7 +36,7 @@ consumers: git-commit, git-stage
26
36
  - `ci`: CI/CD pipeline changes (GitHub Actions)
27
37
  - `revert`: revert a previous commit
28
38
 
29
- ## Scope
39
+ ## Scope vocabulary
30
40
 
31
41
  - Single lowercase word representing a system component
32
42
  - Prefer single word
@@ -6,6 +6,16 @@ consumers: git-issue
6
6
 
7
7
  # Issue reference
8
8
 
9
+ ## Scope
10
+
11
+ Governs a tracker issue: its title, its labels, and the sections its body carries.
12
+
13
+ Does not govern:
14
+
15
+ - Pull request title and body: `pr.md`
16
+ - Whether a phase label may appear in issue text: `versioning.md`
17
+ - Voice, punctuation, and banned words in issue prose: `prose.md`
18
+
9
19
  ## Title
10
20
 
11
21
  - Format: `<type>: <subject>`
@@ -1,11 +1,22 @@
1
1
  ---
2
2
  title: Pull request reference
3
3
  description: Pull request title and body conventions
4
- consumers: git-split, git-pr, claude-standards-audit
4
+ consumers: git-split, git-pr
5
5
  ---
6
6
 
7
7
  # Pull request reference
8
8
 
9
+ ## Scope
10
+
11
+ Governs a pull request title and body: their format and the sections the body carries.
12
+
13
+ Does not govern:
14
+
15
+ - Commit subject format, which shares the title form: `commit.md`
16
+ - Branch naming: `branch.md`
17
+ - Whether a phase label or a semver tag may appear in a title or body: `versioning.md`
18
+ - Voice, punctuation, and banned words in pull request prose: `prose.md`
19
+
9
20
  ## Title
10
21
 
11
22
  - Format: `<type>(<scope>): <subject>`
@@ -10,6 +10,17 @@ Applies to `.claude/ROADMAP.md`. Sequences the scope from `.claude/REQUIREMENTS.
10
10
 
11
11
  The roadmap is one scannable table. That is what keeps it distinct from `.claude/tasks/`: the roadmap is an overview read at a glance, while tasks are worked one file at a time.
12
12
 
13
+ ## Scope
14
+
15
+ Governs the sequencing document at `.claude/ROADMAP.md`: the version table, its columns, and its lifecycle.
16
+
17
+ Does not govern:
18
+
19
+ - What the scope is, which the roadmap sequences rather than defines: `requirements.md`
20
+ - Task files, outcomes, and board state: `tasks.md`
21
+ - Phase-label format and semver discipline: `versioning.md`
22
+ - Rationale for a technical choice: `architecture.md`
23
+
13
24
  ## What goes in
14
25
 
15
26
  - One row per version, ordered top to bottom by sequence
@@ -20,9 +31,8 @@ The roadmap is one scannable table. That is what keeps it distinct from `.claude
20
31
 
21
32
  ## What does not go in
22
33
 
23
- - Task breakdown, checkboxes, or per-feature file lists. Those live in `.claude/tasks/` and `.claude/plans/`.
34
+ - Task breakdown, checkboxes, or per-feature file lists
24
35
  - Implementation detail, API names, or component references
25
- - Rationale for tech choices. That belongs in `.claude/ARCHITECTURE.md`.
26
36
  - Sentence-long cells. Keep each cell terse so the table stays scannable.
27
37
 
28
38
  ## Format
@@ -6,6 +6,15 @@ consumers: create-standard
6
6
 
7
7
  # Snippet reference
8
8
 
9
+ ## Scope
10
+
11
+ Governs a snippet file: what one is for, how it is invoked, and the structure of its body.
12
+
13
+ Does not govern:
14
+
15
+ - Skill folders, which carry frontmatter, references, and scripts a snippet has none of: `skill.md`
16
+ - Voice, punctuation, and formatting in snippet prose: `prose.md`
17
+
9
18
  ## What a snippet is
10
19
 
11
20
  A snippet is a short, focused prompt stored as a plain markdown file. Invoke one to insert a prepared instruction into any AI chat without retyping it. Each snippet covers one purpose. If a prompt needs headers or multiple goals, use a system prompt instead.
@@ -7,6 +7,17 @@ description: Shape and content rules for .claude/context/<domain>.md entries
7
7
 
8
8
  Applies to per-domain narrative entries under `.claude/context/`. Skip for `index.md`, which is regenerated by `aitk indexes regen`.
9
9
 
10
+ ## Scope
11
+
12
+ Governs per-domain narrative entries under `.claude/context/`: their structure, the decisions and gotchas they carry, and what they leave to the code.
13
+
14
+ Does not govern:
15
+
16
+ - Cross-domain decisions and system-wide risks: `architecture.md`
17
+ - Product scope, goals, and non-goals: `requirements.md`
18
+ - Path-scoped coding rules: `rule.md`
19
+ - Diagrams and wireframes, which answer structure and layout questions an entry hands off: `diagrams.md` and `wireframes.md`
20
+
10
21
  ## Organizing principle
11
22
 
12
23
  Weight the entry toward what cannot be re-derived from the repo. That single rule sorts every section below.
@@ -7,6 +7,15 @@ description: Shape and content rules for .claude/DESIGN.md
7
7
 
8
8
  Applies to `.claude/DESIGN.md`. Captures visual intent and the decisions behind how things look, not a style guide, component spec, or framework reference. Update when a visual decision is made or a rule changes.
9
9
 
10
+ ## Scope
11
+
12
+ Governs the visual-intent document at `.claude/DESIGN.md`: tokens described as intent, layout constraints, and the omissions that keep visual scope closed.
13
+
14
+ Does not govern:
15
+
16
+ - Screen layout, on-screen copy, and interaction intent: `wireframes.md`
17
+ - Per-domain implementation narrative: `context.md`
18
+
10
19
  ## What goes in
11
20
 
12
21
  - Tokens described as intent ("mid gray, muted text"), not computed values. Exact values live in code.
@@ -17,7 +26,6 @@ Applies to `.claude/DESIGN.md`. Captures visual intent and the decisions behind
17
26
  ## What does not go in
18
27
 
19
28
  - CSS classes, computed values, component filenames, and prop names. Those live in code.
20
- - UX copy and interaction flows. Those live in the wireframes.
21
29
  - Anything that needs updating every time the code is refactored
22
30
 
23
31
  ## Format
@@ -9,6 +9,17 @@ Applies to per-kind entries under `.claude/diagrams/`. Skip for `index.md`, whic
9
9
 
10
10
  A diagram entry answers one question about the system with one or more Mermaid diagrams and the prose that makes them readable. It is not a rendering of the file tree. The check for any single line: does it tell a reader something the code layout would not have told them? If not, it belongs in `.claude/context/`.
11
11
 
12
+ ## Scope
13
+
14
+ Governs per-kind diagram entries under `.claude/diagrams/`: which question each answers, the Mermaid source, the accessibility fields, and the explanation prose beneath. It states the voice for that prose, which is the yield `prose.md` grants a surface whose own standard sets one.
15
+
16
+ Does not govern:
17
+
18
+ - Punctuation, formatting, and language in explanation prose and node labels: `prose.md`, whose bans the yield does not lift
19
+ - The mechanism behind any component a diagram draws: `context.md`
20
+ - UI layout, on-screen copy, and interaction intent: `wireframes.md`
21
+ - The decision record a components diagram is drawn from: `architecture.md`
22
+
12
23
  ## What a working entry looks like
13
24
 
14
25
  An entry works when a reader who has not opened the repository can answer its question:
@@ -82,7 +93,7 @@ A second entry for one kind takes a suffixed name (`request-flow-admin.md`) and
82
93
  - Do not duplicate prose across entries. An entry that restates its neighbor has taken the neighbor's job.
83
94
  - The audience is mixed, so vocabulary runs as a gradient across the set. `System context` assumes no knowledge of the repository. `Deployment` may assume the reader has read the others.
84
95
 
85
- This section states the voice for the surface, which is what claims the yield `standards/prose.md` grants to a surface whose own standard sets it. Explanation prose is pedagogical here and the default developer-facing voice does not apply. The yield covers voice alone. Punctuation, formatting, and language bans stay in force, and the standards-audit hook enforces them on every write.
96
+ This section states the voice for the surface, which is what claims the yield `prose.md` grants to a surface whose own standard sets it. Explanation prose is pedagogical here and the default developer-facing voice does not apply. The yield covers voice alone. Punctuation, formatting, and language bans stay in force.
86
97
 
87
98
  ## Verification
88
99
 
@@ -109,5 +120,5 @@ Reference the context entry by path when a reader needs the mechanism. The diagr
109
120
  - `System context` has no named source signal beyond `.claude/REQUIREMENTS.md`, so nothing tells a session it went stale. Re-read it when the boundary or the set of external dependencies moves.
110
121
  - The `claude-docs` sweep watches two things and writes frontmatter only. It appends `stale` when a path an entry cites leaves the tree, and it stubs a kind when a diff adds the source signal that kind is drawn from. Diagram bodies and explanation paragraphs are off limits to it, because a change that removes a module does not carry the new correct shape of the picture.
111
122
  - That watch samples thinly. It sees the one or two paths an entry happened to cite and nothing else, so a change elsewhere leaves the entry looking current. `verified` is what covers the gap, and an entry whose date sits far behind the branch is due a read whether or not anything flagged it.
112
- - Mermaid blocks are inside fenced code, so the prose-standards hook ignores them. The explanation paragraphs around them are still prose. Follow `standards/prose.md`.
123
+ - The explanation paragraphs around a Mermaid block are prose and follow `prose.md`. The fenced block itself is not, which is why a check scoped to prose is the wrong thing to rely on for what sits inside it.
113
124
  - The punctuation bans still apply to node and subgraph labels, and nothing checks them there. An em dash in a label passes every gate the repository has, so read the labels before shipping the entry.
@@ -7,6 +7,17 @@ description: Voice, structure, formatting, and language rules for reference mark
7
7
 
8
8
  Applies to markdown reference docs, READMEs, and inline documentation in repos. It is the default voice for `.md` files and yields to any surface with its own voice, such as blogs, emails, changelogs, or commit messages. It also yields wherever another standard states the voice for the surface it governs, which is how a surface claims the exemption without this file having to name it. The yield covers voice alone. Punctuation, formatting, and language rules below stay in force on every surface, including the surfaces no automated check reaches, which is what the scan below is for.
9
9
 
10
+ ## Scope
11
+
12
+ Governs voice, punctuation, formatting, and word choice wherever prose is written. It is an attribute standard rather than a document-type one, so it applies over documents whose shape another standard sets, and yields on voice alone where that standard states one.
13
+
14
+ Does not govern:
15
+
16
+ - What sections a document has, or what belongs in each: the standard for that document type
17
+ - Which frontmatter fields a document carries, which is that standard's own subject. This file governs the wording of a `title` and a `description` and nothing else about them.
18
+ - Phase-label and semver discipline: `versioning.md`
19
+ - Code style and language conventions, which are governance rules rather than a standard
20
+
10
21
  ## Voice
11
22
 
12
23
  - Write for a developer who is scanning, not studying. Every sentence should be understandable on first read.
@@ -9,6 +9,15 @@ Applies to every `README.md`. The `## Voice` section states the voice for a repo
9
9
 
10
10
  The reader is what changes. Reference prose serves someone who already committed to the project and is scanning for a fact. A root README meets someone deciding whether to commit at all, and it is often the only file they read.
11
11
 
12
+ ## Scope
13
+
14
+ Governs every `README.md`: voice, heading structure, required and optional sections, badge selection, and what the page links out to instead of carrying.
15
+
16
+ Does not govern:
17
+
18
+ - Punctuation, formatting, spelling, and banned words in README prose: `prose.md`, which yields the voice and keeps the rest
19
+ - Product scope and goals: `requirements.md`
20
+
12
21
  ## Voice
13
22
 
14
23
  Scoped to the README at a repository root. A nested README documenting a folder, a harness, or an internal tool keeps the reference voice in `prose.md`, since its reader has already committed and arrived looking for a fact.
@@ -7,6 +7,16 @@ description: Shape and content rules for .claude/REQUIREMENTS.md
7
7
 
8
8
  Applies to `.claude/REQUIREMENTS.md`. Describes what the product does and why, not how it works. Update when scope changes, goals shift, or a non-goal is promoted to a feature.
9
9
 
10
+ ## Scope
11
+
12
+ Governs the product-scope document at `.claude/REQUIREMENTS.md`: problem, goals, non-goals, MVP features, distribution, stack, and constraints.
13
+
14
+ Does not govern:
15
+
16
+ - Rationale for a technical choice: `architecture.md`
17
+ - Sequencing the scope into ordered versions: `roadmap.md`
18
+ - Per-domain structure and narrative: `context.md`
19
+
10
20
  ## What goes in
11
21
 
12
22
  - The problem being solved and for whom
@@ -19,7 +29,6 @@ Applies to `.claude/REQUIREMENTS.md`. Describes what the product does and why, n
19
29
  ## What does not go in
20
30
 
21
31
  - Implementation details, API names, or internal component references
22
- - Rationale for tech choices. That belongs in `.claude/ARCHITECTURE.md`.
23
32
  - Anything that describes how a feature is built rather than what it does
24
33
 
25
34
  ## Sections
package/standards/rule.md CHANGED
@@ -9,6 +9,16 @@ description: Rule frontmatter, body shape, and voice for .claude/rules files
9
9
 
10
10
  Rules give Claude Code coding constraints scoped to file paths. Claude Code discovers `.claude/rules/**/*.md` at session start. A rule with no `paths:` field always applies, at the same priority as `CLAUDE.md`. A rule with `paths:` applies when Claude reads a file matching the glob. Author one rule per topic so the scope stays precise.
11
11
 
12
+ ## Scope
13
+
14
+ Governs governance rules under `.claude/rules/`: their location, numbering, frontmatter, and body shape.
15
+
16
+ Does not govern:
17
+
18
+ - Authoring conventions for a document type, which are standards rather than rules. A rule points at the standard that owns one and never restates it.
19
+ - Skill folders and skill frontmatter: `skill.md`
20
+ - Cross-domain behavior rules, which live in `CLAUDE.md` at the project root
21
+
12
22
  ## Location
13
23
 
14
24
  - Rules live at `.claude/rules/<subdirectory>/<n>-<slug>.md`
@@ -9,6 +9,17 @@ description: Claude skill structure and authoring rules
9
9
 
10
10
  Skills give Claude Code domain-specific constraints and rules inline, so it can act immediately without reading all docs. Each skill body contains actionable rules for its domain. Full reference docs are the fallback for edge cases and deeper context. Skills use progressive disclosure: Claude reads only frontmatter at session start (~100 tokens each), matches a query against descriptions, then loads the full skill body.
11
11
 
12
+ ## Scope
13
+
14
+ Governs a skill folder as one artifact: `SKILL.md`, its optional sibling `REQUIREMENT.md`, and the bundled `references/`, `scripts/`, and `assets/` beside them.
15
+
16
+ Does not govern:
17
+
18
+ - Path-scoped coding rules, which load on a file match rather than on a request match: `rule.md`
19
+ - Single-purpose chat prompts carrying no frontmatter, references, or scripts: `snippets.md`
20
+ - Voice, punctuation, and formatting in a skill body: `prose.md`
21
+ - The domain conventions a skill cites, each of which belongs to the standard that owns it
22
+
12
23
  ## Skill types
13
24
 
14
25
  Pick the type before writing. It decides the body shape.
@@ -9,22 +9,42 @@ Applies to each authored standard in the folder. Skip for `index.md`, which is g
9
9
 
10
10
  ## Overview
11
11
 
12
- A standard is a target-facing authoring convention for one document type. It installs into a project under `.claude/standards/` and is consumed by skills and developers alike. This file governs itself, so every rule below applies to it.
12
+ A standard is a target-facing authoring convention for one document type, or for one attribute carried across every document. It installs into a project under `.claude/standards/` and is consumed by skills and developers alike. This file governs itself, so every rule below applies to it.
13
+
14
+ ## Scope
15
+
16
+ Governs what an authored standard contains: its stated jurisdiction, success criterion, frontmatter, structure, and rule phrasing.
17
+
18
+ Does not govern:
19
+
20
+ - The voice, punctuation, and formatting a standard is written in: `prose.md`
21
+ - The shape of any artifact a standard governs, which is that standard's own subject
13
22
 
14
23
  ## What a working standard looks like
15
24
 
16
25
  A standard answers these questions. Each can be answered wrong, which is what makes them a test rather than a preamble.
17
26
 
18
- - Which single document type does this govern, and where does that document live?
27
+ - Which single document type or attribute does this govern, and where does it apply?
19
28
  - Can an author who has seen no example produce a conforming document from this file alone?
20
29
  - Does every rule state a shape the document must have, rather than a fact about the repository that happens to store it?
21
30
  - What does a conforming document achieve, stated so a reviewer can call one non-conforming without appealing to taste?
22
31
 
23
32
  A standard failing these questions is non-conforming even when it satisfies every shape rule below.
24
33
 
25
- ## Scope
34
+ ## Scoping rules
35
+
36
+ ### Declaring scope
37
+
38
+ - Govern one document type per standard, or one attribute across every document. Split unrelated conventions into separate files.
39
+ - Open with a `## Scope` section stating what the standard governs and what it does not, placed above the shape rules. A standard that specifies shape exhaustively and jurisdiction nowhere cannot refuse a rule, so the rule with no obvious owner lands in whichever standard sits nearest.
40
+ - Write it as one line naming the artifact or attribute and where it applies, then a `Does not govern:` list. Give each entry the excluded concern and the owner it goes to. Name a sibling standard by bare filename, since standards install as siblings, and name the surface instead where the owner is one, such as a coding rule, a project policy, or the code.
41
+ - Cut an entry that names no owner at all. It is either excluding something nothing was going to claim, or it is a content exclusion, which the rule below sends to the shape rules instead.
42
+ - Declare a boundary from both sides. A yield, an exemption, or a handoff stated in one standard alone is never checked against the standard on the other side of it, which is how two files come to claim the same rule or neither does.
43
+ - Separate a jurisdiction exclusion from a content exclusion. The first names a concern another standard owns and belongs in `## Scope`. The second names what does not belong inside the document and stays with the shape rules. Merging them puts a boundary claim where no sibling will read it.
44
+ - Stay silent on a section the standard holds today but should not own. Claiming it makes the scope statement false the moment it moves, and the mismatch is the evidence that moves it.
45
+
46
+ ### Staying inside it
26
47
 
27
- - Govern one document type per standard. Split unrelated conventions into separate files.
28
48
  - Name no path, filename, or folder outside the document type the standard governs. A standard reaches projects whose layout is their own, so a path borrowed from the authoring repository is wrong in a target and nothing reports it.
29
49
  - State the rule, never the mechanism enforcing it. Hooks, scripts, checks, and skill catalogs are facts about one repository. Name the condition the document must meet and let the enforcing surface name its own case.
30
50
  - Invent inline examples rather than citing a real file elsewhere in the project. A cited file moves or is deleted and the standard goes stale in silence.
@@ -9,6 +9,17 @@ Applies to `.claude/tasks/`. Tracks what is being built and why, at the level of
9
9
 
10
10
  The folder is gitignored. Board state changes when work ships rather than when a branch is written, so committing it would put a claim about the future into the diff of an unrelated pull request. The git log records what shipped.
11
11
 
12
+ ## Scope
13
+
14
+ Governs the task board under `.claude/tasks/`: folder layout, filenames, frontmatter, file format, origin lines, and archiving.
15
+
16
+ Does not govern:
17
+
18
+ - Phase-label format and which surfaces a label may appear on: `versioning.md`
19
+ - Sequencing across versions and why the order is what it is: `roadmap.md`
20
+ - Architectural reasoning that outlives a task: `architecture.md`
21
+ - When a project opens a task at all, which is project policy rather than a shape rule
22
+
12
23
  ## Layout
13
24
 
14
25
  ```plaintext
@@ -7,6 +7,17 @@ description: Phase label vs semver discipline across tasks, PRs, reviews, issues
7
7
 
8
8
  Two namespaces, kept separate.
9
9
 
10
+ ## Scope
11
+
12
+ Governs the two version namespaces, phase labels and semver tags, and which surfaces each may appear on. It is an attribute standard rather than a document-type one, so it applies wherever either namespace is written.
13
+
14
+ Does not govern:
15
+
16
+ - The format of a phase label, which is project-specific by the rule below
17
+ - Task filenames and board layout: `tasks.md`
18
+ - Commit subject, branch name, and pull request title format: `commit.md`, `branch.md`, and `pr.md`
19
+ - Voice, punctuation, and formatting in any text carrying a label: `prose.md`
20
+
10
21
  ## Phase labels
11
22
 
12
23
  Internal coordination vocabulary used in the task board and chat.