@erclx/canon 5.5.0 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/codebase-layout/REQUIREMENT.md +3 -0
- package/claude/skills/codebase-layout/SKILL.md +28 -0
- package/claude/skills/codebase-layout/references/adopted.md +6 -0
- package/claude/skills/plan-feature/REQUIREMENT.md +4 -0
- package/claude/skills/plan-feature/SKILL.md +4 -0
- package/claude/skills/review-craft/references/ui.md +2 -0
- package/claude/skills/review-pr/SKILL.md +2 -2
- package/claude/skills/review-ui/REQUIREMENT.md +54 -0
- package/claude/skills/review-ui/SKILL.md +108 -0
- package/claude/skills/review-ui/references/driving.md +50 -0
- package/claude/skills/review-ui/references/post.md +60 -0
- package/claude/skills/review-ui/scripts/pw.sh +60 -0
- package/claude/skills/role-orchestrator/SKILL.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +15 -1
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +6 -3
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +10 -4
- package/claude/skills/role-orchestrator/scripts/poll.sh +72 -10
- package/claude/skills/role-reviewer/REQUIREMENT.md +2 -2
- package/claude/skills/role-reviewer/SKILL.md +8 -5
- package/claude/skills/teach-workspace/REQUIREMENT.md +3 -0
- package/claude/skills/teach-workspace/SKILL.md +2 -1
- package/claude/skills/teach-workspace/references/lesson-craft.md +8 -1
- package/claude/skills/test-craft/REQUIREMENT.md +4 -1
- package/claude/skills/test-craft/SKILL.md +20 -2
- package/claude/skills/test-craft/references/adopted.md +3 -1
- package/claude/skills/ui-checklist/REQUIREMENT.md +1 -0
- package/claude/skills/ui-checklist/SKILL.md +11 -1
- package/docs/agents/index.md +1 -1
- package/docs/agents/skills-audit.md +6 -3
- package/docs/workflow/operating-model.md +1 -1
- package/docs/workflow/skill-map.md +9 -8
- package/package.json +1 -1
- package/src/claude/cases/workflow.ts +5 -0
- package/src/claude/skills-audit.ts +81 -1
- package/src/commands/claude.ts +33 -0
- package/src/gate/measures.ts +43 -1
- package/src/gate/stages.ts +9 -0
- package/standards/index.md +1 -0
- package/standards/skill-practice.md +51 -0
- package/standards/skill.md +3 -1
- package/tooling/web/seeds/.cspell/tech-stack.txt +1 -0
|
@@ -12,16 +12,40 @@ export const DESCRIPTION_LIMIT = 1024
|
|
|
12
12
|
/** The two headings the requirement template declares, matched at any level. */
|
|
13
13
|
export const REQUIREMENT_SECTIONS: readonly string[] = ['Gap', 'Must']
|
|
14
14
|
|
|
15
|
+
/** The one tree that ships to a target, and the only one the practice list names. */
|
|
16
|
+
export const SHIPPED_CORPUS = join('claude', 'skills')
|
|
17
|
+
|
|
15
18
|
/**
|
|
16
19
|
* Both trees the standard governs. `claude/skills/` ships to a target and
|
|
17
20
|
* `.claude/skills/` stays here, and every rule measured below applies to each,
|
|
18
21
|
* so a corpus reading one of them reports a pass over half the subject.
|
|
19
22
|
*/
|
|
20
23
|
export const CORPORA: readonly string[] = [
|
|
21
|
-
|
|
24
|
+
SHIPPED_CORPUS,
|
|
22
25
|
join('.claude', 'skills'),
|
|
23
26
|
]
|
|
24
27
|
|
|
28
|
+
/**
|
|
29
|
+
* The practice skills `standards/skill-practice.md` describes, keyed by corpus-relative
|
|
30
|
+
* folder rather than by name, so a target's own `.claude/skills/` folder that
|
|
31
|
+
* shares a name is never swept in. The list lives here rather than in a skill's
|
|
32
|
+
* frontmatter because a skill declaring its own kind could exempt itself.
|
|
33
|
+
*/
|
|
34
|
+
export const PRACTICE_SKILLS: readonly string[] = [
|
|
35
|
+
join(SHIPPED_CORPUS, 'codebase-layout'),
|
|
36
|
+
join(SHIPPED_CORPUS, 'test-craft'),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
/** The closing H2s a practice skill carries, matched exactly outside fences. */
|
|
40
|
+
export const PRACTICE_SECTIONS: readonly string[] = [
|
|
41
|
+
'Excuses and rebuttals',
|
|
42
|
+
'Red flags',
|
|
43
|
+
'Before handing over',
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
/** The source ledger every practice skill carries beside its body. */
|
|
47
|
+
export const PRACTICE_LEDGER = join('references', 'adopted.md')
|
|
48
|
+
|
|
25
49
|
/**
|
|
26
50
|
* The one reason this audit refuses. A project carrying neither corpus is the
|
|
27
51
|
* ordinary state of a target that has not adopted either skills convention,
|
|
@@ -34,6 +58,8 @@ const KEBAB_CASE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/
|
|
|
34
58
|
|
|
35
59
|
const HEADING = /^#{1,6}\s+(.+?)\s*$/
|
|
36
60
|
|
|
61
|
+
const SECTION = /^##\s+(.+?)\s*$/
|
|
62
|
+
|
|
37
63
|
/**
|
|
38
64
|
* An ISO date, read as provenance wherever a reader is told it. The context
|
|
39
65
|
* audit's detector clears a date after "measured" or "verified", and a skill
|
|
@@ -69,6 +95,7 @@ export interface SkillsAudit {
|
|
|
69
95
|
readonly longDescription: readonly SkillFinding[]
|
|
70
96
|
readonly requirementSections: readonly SkillFinding[]
|
|
71
97
|
readonly datedProvenance: readonly SkillFinding[]
|
|
98
|
+
readonly practiceShape: readonly SkillFinding[]
|
|
72
99
|
}
|
|
73
100
|
|
|
74
101
|
interface SkillSource {
|
|
@@ -79,6 +106,9 @@ interface SkillSource {
|
|
|
79
106
|
readonly description: string | undefined
|
|
80
107
|
/** Undefined when the folder carries no `REQUIREMENT.md` at all. */
|
|
81
108
|
readonly requirementHeadings: readonly string[] | undefined
|
|
109
|
+
/** Every H2 in `SKILL.md` outside a fence, for the practice shape. */
|
|
110
|
+
readonly sections: readonly string[]
|
|
111
|
+
readonly hasLedger: boolean
|
|
82
112
|
/**
|
|
83
113
|
* `SKILL.md` and every reference below the folder, keyed by the path a
|
|
84
114
|
* finding names. `REQUIREMENT.md` and `EVAL.md` are left out, since the
|
|
@@ -134,6 +164,13 @@ export async function auditSkills(root: string): Promise<SkillsAudit> {
|
|
|
134
164
|
datedProvenance: sources.flatMap((source) =>
|
|
135
165
|
source.bodies.flatMap(dateFindings),
|
|
136
166
|
),
|
|
167
|
+
practiceShape: [
|
|
168
|
+
...missingPracticeSkills(
|
|
169
|
+
present.some((corpus) => corpus.rel === SHIPPED_CORPUS),
|
|
170
|
+
sources,
|
|
171
|
+
),
|
|
172
|
+
...sources.flatMap(practiceFindings),
|
|
173
|
+
],
|
|
137
174
|
}
|
|
138
175
|
}
|
|
139
176
|
|
|
@@ -190,6 +227,11 @@ async function readSkill(
|
|
|
190
227
|
description: declared(readField(fields, 'description')),
|
|
191
228
|
requirementHeadings:
|
|
192
229
|
requirement === undefined ? undefined : headings(requirement),
|
|
230
|
+
sections: bodyLines(body)
|
|
231
|
+
.filter((line) => !line.fenced)
|
|
232
|
+
.map((line) => SECTION.exec(line.text)?.[1])
|
|
233
|
+
.filter((text): text is string => text !== undefined),
|
|
234
|
+
hasLedger: existsSync(join(skillDir, PRACTICE_LEDGER)),
|
|
193
235
|
bodies: [
|
|
194
236
|
{ rel: join(skillRel, 'SKILL.md'), text: body },
|
|
195
237
|
...references.map((path, index) => ({
|
|
@@ -252,6 +294,44 @@ function sectionFindings(source: SkillSource): SkillFinding[] {
|
|
|
252
294
|
]
|
|
253
295
|
}
|
|
254
296
|
|
|
297
|
+
/**
|
|
298
|
+
* A listed folder the shipped corpus does not hold, such as a renamed skill or
|
|
299
|
+
* a misspelled append, would otherwise read as a pass. Silent where the
|
|
300
|
+
* shipped corpus is absent, since a target carries none of the listed skills.
|
|
301
|
+
*/
|
|
302
|
+
function missingPracticeSkills(
|
|
303
|
+
hasShippedCorpus: boolean,
|
|
304
|
+
sources: readonly SkillSource[],
|
|
305
|
+
): SkillFinding[] {
|
|
306
|
+
if (!hasShippedCorpus) return []
|
|
307
|
+
const found = new Set(sources.map((source) => source.rel))
|
|
308
|
+
return PRACTICE_SKILLS.filter((rel) => !found.has(rel)).map((rel) => ({
|
|
309
|
+
rel,
|
|
310
|
+
detail: 'missing skill: no folder under the shipped corpus',
|
|
311
|
+
}))
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Matches each section as an exact H2, so a heading carrying trailing text or
|
|
316
|
+
* sitting at another level reads as missing rather than as a near match the
|
|
317
|
+
* standard never names.
|
|
318
|
+
*/
|
|
319
|
+
function practiceFindings(source: SkillSource): SkillFinding[] {
|
|
320
|
+
if (!PRACTICE_SKILLS.includes(source.rel)) return []
|
|
321
|
+
|
|
322
|
+
const sections = PRACTICE_SECTIONS.filter(
|
|
323
|
+
(section) => !source.sections.includes(section),
|
|
324
|
+
).map((section) => ({
|
|
325
|
+
rel: source.rel,
|
|
326
|
+
detail: `missing section: ${section}`,
|
|
327
|
+
}))
|
|
328
|
+
const ledger = source.hasLedger
|
|
329
|
+
? []
|
|
330
|
+
: [{ rel: source.rel, detail: `missing ledger: ${PRACTICE_LEDGER}` }]
|
|
331
|
+
|
|
332
|
+
return [...sections, ...ledger]
|
|
333
|
+
}
|
|
334
|
+
|
|
255
335
|
/**
|
|
256
336
|
* A date inside a fence or a code span is example data a reader is shown, such
|
|
257
337
|
* as a sample frontmatter block, so only prose outside both is read.
|
package/src/commands/claude.ts
CHANGED
|
@@ -26,7 +26,11 @@ import {
|
|
|
26
26
|
auditSkills,
|
|
27
27
|
CORPORA,
|
|
28
28
|
DESCRIPTION_LIMIT,
|
|
29
|
+
PRACTICE_LEDGER,
|
|
30
|
+
PRACTICE_SECTIONS,
|
|
31
|
+
PRACTICE_SKILLS,
|
|
29
32
|
REQUIREMENT_SECTIONS,
|
|
33
|
+
SHIPPED_CORPUS,
|
|
30
34
|
type SkillFinding,
|
|
31
35
|
type SkillsAudit,
|
|
32
36
|
type SkillsAuditRefusal,
|
|
@@ -1398,6 +1402,7 @@ async function runSkillsAudit(
|
|
|
1398
1402
|
reportFolder(report)
|
|
1399
1403
|
reportRequirementShape(report)
|
|
1400
1404
|
reportProvenance(report)
|
|
1405
|
+
reportPracticeShape(report)
|
|
1401
1406
|
reportUnmeasured()
|
|
1402
1407
|
outro()
|
|
1403
1408
|
}
|
|
@@ -1420,11 +1425,14 @@ async function runSkillsAudit(
|
|
|
1420
1425
|
folderName: report.folderName,
|
|
1421
1426
|
requirementSections: report.requirementSections,
|
|
1422
1427
|
datedProvenance: report.datedProvenance,
|
|
1428
|
+
practiceShape: report.practiceShape,
|
|
1423
1429
|
},
|
|
1424
1430
|
checkpoints: {
|
|
1425
1431
|
descriptionLimit: DESCRIPTION_LIMIT,
|
|
1426
1432
|
requirementSections: REQUIREMENT_SECTIONS,
|
|
1427
1433
|
corpora: CORPORA,
|
|
1434
|
+
practiceSkills: PRACTICE_SKILLS,
|
|
1435
|
+
practiceSections: PRACTICE_SECTIONS,
|
|
1428
1436
|
},
|
|
1429
1437
|
})}\n`,
|
|
1430
1438
|
)
|
|
@@ -1615,6 +1623,31 @@ function reportProvenance(report: SkillsAudit): void {
|
|
|
1615
1623
|
reportFindings(report.datedProvenance)
|
|
1616
1624
|
}
|
|
1617
1625
|
|
|
1626
|
+
/**
|
|
1627
|
+
* Reports without failing the run for the reason provenance does. The list
|
|
1628
|
+
* names shipped folders alone, which the step says so a target reading a pass
|
|
1629
|
+
* knows its own skills were never in scope.
|
|
1630
|
+
*/
|
|
1631
|
+
function reportPracticeShape(report: SkillsAudit): void {
|
|
1632
|
+
logStep('Practice shape')
|
|
1633
|
+
logInfo(
|
|
1634
|
+
`A listed practice skill closes with ${PRACTICE_SECTIONS.map((section) => `## ${section}`).join(', ')}, and carries ${PRACTICE_LEDGER}.`,
|
|
1635
|
+
)
|
|
1636
|
+
logInfo(
|
|
1637
|
+
`The list is kept here and names ${plural(PRACTICE_SKILLS.length, 'shipped skill')}, so a skill outside ${SHIPPED_CORPUS} is never read.`,
|
|
1638
|
+
)
|
|
1639
|
+
|
|
1640
|
+
if (report.practiceShape.length === 0) {
|
|
1641
|
+
logInfo('Every listed practice skill carries its shape.')
|
|
1642
|
+
return
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
logWarn(
|
|
1646
|
+
`${plural(report.practiceShape.length, 'missing part')} across the listed practice skills`,
|
|
1647
|
+
)
|
|
1648
|
+
reportFindings(report.practiceShape)
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1618
1651
|
/**
|
|
1619
1652
|
* Stated on every run, including the run where everything above passed. A
|
|
1620
1653
|
* report that lists only what it measured reads as a verdict on the standard
|
package/src/gate/measures.ts
CHANGED
|
@@ -13,7 +13,12 @@ import {
|
|
|
13
13
|
measureArchitecture,
|
|
14
14
|
missingRevisit,
|
|
15
15
|
} from '@/context/architecture'
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
auditSkills,
|
|
18
|
+
PRACTICE_LEDGER,
|
|
19
|
+
PRACTICE_SKILLS,
|
|
20
|
+
SHIPPED_CORPUS,
|
|
21
|
+
} from '@/claude/skills-audit'
|
|
17
22
|
import { listRepositoryFiles } from '@/git-files'
|
|
18
23
|
import { ceilingFindings } from '@/markdown/ceiling'
|
|
19
24
|
import { resolveMarkdown } from '@/markdown/files'
|
|
@@ -314,6 +319,43 @@ export const skillProvenance: Measure = async (ctx) => {
|
|
|
314
319
|
}
|
|
315
320
|
}
|
|
316
321
|
|
|
322
|
+
/**
|
|
323
|
+
* Every listed practice skill against the closing sections and the ledger
|
|
324
|
+
* `standards/skill-practice.md` requires of one.
|
|
325
|
+
*
|
|
326
|
+
* Read in-process for the reason `skillProvenance` is, so the verb keeps its
|
|
327
|
+
* missing-requirement-only exit. The list names shipped folders alone, so a
|
|
328
|
+
* tree without `claude/skills/` reports unmeasured rather than a vacuous pass.
|
|
329
|
+
*/
|
|
330
|
+
export const skillPracticeShape: Measure = async (ctx) => {
|
|
331
|
+
const report = await auditSkills(ctx.root)
|
|
332
|
+
if (!report.corpora.some((corpus) => corpus.rel === SHIPPED_CORPUS)) {
|
|
333
|
+
return {
|
|
334
|
+
emissions: [],
|
|
335
|
+
unmeasured: `no skill corpus at ${SHIPPED_CORPUS} resolved, so no practice skill was read.`,
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const found = report.practiceShape
|
|
340
|
+
if (found.length > 0) {
|
|
341
|
+
const where = found
|
|
342
|
+
.map((finding) => `${finding.rel} ${finding.detail}`)
|
|
343
|
+
.join(', ')
|
|
344
|
+
return {
|
|
345
|
+
emissions: [],
|
|
346
|
+
failure: `${plural(found.length, 'practice shape finding')}: ${where}. Add the closing H2 exactly as named, or the ledger at ${PRACTICE_LEDGER}.`,
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
emissions: [
|
|
352
|
+
info(
|
|
353
|
+
`${plural(PRACTICE_SKILLS.length, 'practice skill')} carry every closing section and a ledger`,
|
|
354
|
+
),
|
|
355
|
+
],
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
317
359
|
/**
|
|
318
360
|
* Every tracked markdown document against the whole-document ceiling.
|
|
319
361
|
*
|
package/src/gate/stages.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
seedStandards,
|
|
15
15
|
rawFieldFileReference,
|
|
16
16
|
shippedReferences,
|
|
17
|
+
skillPracticeShape,
|
|
17
18
|
skillProvenance,
|
|
18
19
|
standardCriteria,
|
|
19
20
|
unreferencedRules,
|
|
@@ -486,6 +487,14 @@ export const STAGES: readonly Stage[] = [
|
|
|
486
487
|
label: 'Skill provenance',
|
|
487
488
|
checks: [{ kind: 'measure', measure: skillProvenance }],
|
|
488
489
|
},
|
|
490
|
+
{
|
|
491
|
+
// The audit verb only reports a listed practice skill missing a closing
|
|
492
|
+
// section or its ledger, so a target is told without failing. The list
|
|
493
|
+
// names this repository's shipped skills, so the stage fails here alone.
|
|
494
|
+
id: 'skill-practice-shape',
|
|
495
|
+
label: 'Skill practice shape',
|
|
496
|
+
checks: [{ kind: 'measure', measure: skillPracticeShape }],
|
|
497
|
+
},
|
|
489
498
|
{
|
|
490
499
|
id: 'standard-criteria',
|
|
491
500
|
label: 'Standard success criteria',
|
package/standards/index.md
CHANGED
|
@@ -31,6 +31,7 @@ Reference docs for consistent authoring across the toolkit and target projects.
|
|
|
31
31
|
- [Requirements reference](requirements.md): Shape and content rules for canon/REQUIREMENTS.md
|
|
32
32
|
- [Governance rule reference](rule.md): Rule frontmatter, body shape, and voice for .claude/rules files
|
|
33
33
|
- [Session map reference](session.md): Filename and location, the sections a handoff carries, the write and read procedures, and how a role extends it
|
|
34
|
+
- [Practice skill reference](skill-practice.md): Closing sections and source ledger for a skill carrying engineering practice
|
|
34
35
|
- [Skill requirement reference](skill-requirement.md): Shape and content rules for the REQUIREMENT.md beside a skill
|
|
35
36
|
- [Claude skill reference](skill.md): Claude skill structure and authoring rules
|
|
36
37
|
- [Slug reference](slug.md): Transform from a git branch name to a slug, and the three responses to an empty result
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Practice skill reference
|
|
3
|
+
description: Closing sections and source ledger for a skill carrying engineering practice
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Practice skill reference
|
|
7
|
+
|
|
8
|
+
Applies to a practice skill, one carrying engineering judgment a session applies while it works, where the failure is skipping the practice or cutting it short rather than not knowing it. Its body takes the reference shape, and this file fixes how it closes and what it cites.
|
|
9
|
+
|
|
10
|
+
## Scope
|
|
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.
|
|
13
|
+
|
|
14
|
+
Does not govern:
|
|
15
|
+
|
|
16
|
+
- The skill folder, its frontmatter, the body rules, and the choice between skill types: `skill.md`
|
|
17
|
+
- The `REQUIREMENT.md` beside the body: `skill-requirement.md`
|
|
18
|
+
- Voice, rhythm, and sentence construction: the `write-human` skill
|
|
19
|
+
- Punctuation, formatting, and word choice: `markdown.md`
|
|
20
|
+
|
|
21
|
+
## What a working practice skill looks like
|
|
22
|
+
|
|
23
|
+
A practice skill works when a session about to cut the practice short meets the answer before it does:
|
|
24
|
+
|
|
25
|
+
- Does every excuse row name a reason a session has actually given to skip the practice?
|
|
26
|
+
- Can a session spot each red flag in its own work while it is still working?
|
|
27
|
+
- Can a session run every line of the closing checklist against what it produced, and get a yes or a no?
|
|
28
|
+
- Can a reader open each source the ledger names and find the version the body states?
|
|
29
|
+
|
|
30
|
+
A practice skill failing any of these is non-conforming even when every heading below is present.
|
|
31
|
+
|
|
32
|
+
## Closing sections
|
|
33
|
+
|
|
34
|
+
- Follow every concern group with three H2s in this order: `## Excuses and rebuttals`, `## Red flags`, and `## Before handing over`. A section naming what the skill delegates comes after the three, and nothing else does.
|
|
35
|
+
- Spell each heading exactly. An H3, or a heading carrying more words such as `## Red flags that mean start over`, reads as missing.
|
|
36
|
+
- Write `## Excuses and rebuttals` as a two-column table pairing a reason a session gives to skip or shortcut the practice with the answer to it. Never write a row rebutting an objection nobody raised, since that row is ceremony. Revisit when a practice skill's table is observed failing to stop an excuse it names.
|
|
37
|
+
- Write `## Red flags` as bullets naming signs a session can observe in its own work mid-task, never a restatement of a rule above.
|
|
38
|
+
- Write `## Before handing over` as the exit checklist, each line a check against what the session produced.
|
|
39
|
+
|
|
40
|
+
## Source ledger
|
|
41
|
+
|
|
42
|
+
- Carry `references/adopted.md` in every practice skill, recording each external source the body draws on.
|
|
43
|
+
- Link each source, or pin it to a commit, so a reader can open the version the body adopted.
|
|
44
|
+
- State what was adopted, what was declined, and why for each, so a later session extends the position rather than re-deriving it.
|
|
45
|
+
- 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.
|
|
46
|
+
|
|
47
|
+
## Which skills are practice skills
|
|
48
|
+
|
|
49
|
+
- `canon claude skills audit` keeps the list of practice skills and checks each listed one for the three closing sections and the ledger.
|
|
50
|
+
- Never mark a skill as a practice skill in its own frontmatter, since a self-declared kind lets a skill exempt itself.
|
|
51
|
+
- The list names this toolkit's shipped skills alone, so a project's own practice skill takes this shape with no check behind it.
|
package/standards/skill.md
CHANGED
|
@@ -16,6 +16,7 @@ Governs a skill folder under `skills/` as one artifact: `SKILL.md`, its siblings
|
|
|
16
16
|
Does not govern:
|
|
17
17
|
|
|
18
18
|
- What a `REQUIREMENT.md` must answer, its sections, and its template: `skill-requirement.md`
|
|
19
|
+
- A practice skill's closing sections and ledger: `skill-practice.md`
|
|
19
20
|
- Path-scoped coding rules, which load on a file match rather than on a request match: `rule.md`
|
|
20
21
|
- Voice, rhythm, and sentence construction in a skill body: the `write-human` skill
|
|
21
22
|
- Punctuation, formatting, and word choice in a skill body: `markdown.md`
|
|
@@ -45,6 +46,7 @@ Pick the type before writing. It decides the body shape.
|
|
|
45
46
|
|
|
46
47
|
- Reference: conventions, patterns, and domain knowledge Claude applies inline. The body is rule bullets grouped by concern.
|
|
47
48
|
- Task: step-by-step workflows Claude executes as actions. The body is numbered steps plus the rules constraining them.
|
|
49
|
+
- Practice: judgment a session may skip, shaped by `skill-practice.md`.
|
|
48
50
|
|
|
49
51
|
A task skill takes the template below. A reference skill takes the same frontmatter and replaces `## Steps` and `## Rules` with one H2 per concern group, each holding constraint bullets.
|
|
50
52
|
|
|
@@ -105,7 +107,7 @@ allowed-tools: <tools required>
|
|
|
105
107
|
- Group bullets under H2 headings by domain concern. Keep dos and don'ts together under the topic they belong to rather than splitting them into flat rules and constraints sections.
|
|
106
108
|
- One actionable constraint per bullet. Prefer the `X over Y` form for preferences.
|
|
107
109
|
- Do not include code examples unless a one to three line inline snippet captures a pattern the model cannot infer.
|
|
108
|
-
-
|
|
110
|
+
- Keep a statement only when removing it would change what the agent does, naming a principle as a few-word handle rather than explaining it. Revisit when a run shows the model ignoring a principle named only as a handle.
|
|
109
111
|
|
|
110
112
|
### Progressive disclosure
|
|
111
113
|
|