@erclx/canon 5.25.0 → 5.26.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/README.md +2 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canvas/SKILL.md +1 -1
- package/claude/skills/context-fold/REQUIREMENT.md +6 -2
- package/claude/skills/context-fold/SKILL.md +8 -6
- package/claude/skills/context-fold/references/anchor-sweep.md +2 -2
- package/claude/skills/design-taste/REQUIREMENT.md +1 -1
- package/claude/skills/design-taste/SKILL.md +4 -2
- package/claude/skills/design-taste/references/adopted.md +40 -0
- package/claude/skills/design-taste/references/kinds.md +1 -1
- package/claude/skills/design-taste/references/systems.md +1 -7
- package/claude/skills/design-taste/references/tells.md +2 -24
- package/claude/skills/docs-sync/REQUIREMENT.md +2 -1
- package/claude/skills/document-health/REQUIREMENT.md +2 -0
- package/claude/skills/document-health/SKILL.md +21 -0
- package/claude/skills/document-health/references/axes.md +12 -0
- package/claude/skills/draft-and-pick/SKILL.md +1 -1
- package/claude/skills/draft-identity/SKILL.md +1 -1
- package/claude/skills/draft-screencast/SKILL.md +9 -7
- package/claude/skills/draft-slides/REQUIREMENT.md +17 -12
- package/claude/skills/draft-slides/SKILL.md +31 -20
- package/claude/skills/git-issue/references/issue.md +10 -0
- package/claude/skills/git-pr/references/evidence.md +8 -0
- package/claude/skills/git-pr/references/labels.md +12 -0
- package/claude/skills/git-split/SKILL.md +19 -8
- package/claude/skills/markdown-propose/references/format.md +9 -0
- package/claude/skills/memory-review/references/later-phases.md +7 -0
- package/claude/skills/review-ui/references/post.md +4 -2
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +8 -0
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +13 -0
- package/claude/skills/search-craft/REQUIREMENT.md +1 -1
- package/claude/skills/search-craft/SKILL.md +3 -1
- package/claude/skills/search-craft/references/adopted.md +30 -0
- package/claude/skills/target-setup/references/detect.md +8 -0
- package/claude/skills/target-setup/references/indexes.md +13 -0
- package/claude/skills/target-setup/references/verify.md +8 -0
- package/claude/skills/test-first/SKILL.md +2 -0
- package/claude/skills/test-first/references/adopted.md +36 -0
- package/claude/skills/write-human/SKILL.md +1 -1
- package/claude/skills/write-human/references/machine-tells.md +13 -0
- package/docs/agents/canvas.md +3 -1
- package/docs/agents/capture.md +1 -1
- package/docs/agents/commands.md +3 -3
- package/docs/agents/index.md +2 -2
- package/docs/agents/records-stale.md +22 -9
- package/docs/agents/records.md +1 -1
- package/docs/agents/sandbox.md +1 -1
- package/docs/agents/skills-audit.md +10 -3
- package/docs/agents/slides.md +15 -3
- package/docs/workflow/ai-workflow.md +1 -1
- package/docs/workflow/index.md +1 -0
- package/docs/workflow/parallel-features.md +1 -1
- package/docs/workflow/skill-map-on-request.md +42 -0
- package/docs/workflow/skill-map.md +1 -34
- package/package.json +1 -1
- package/scripts/lib/sandbox-dispatch.sh +1 -1
- package/scripts/lib/sandbox-git.sh +1 -9
- package/scripts/lib/sandbox-path.sh +1 -1
- package/scripts/sandbox-hook.sh +99 -0
- package/src/canvas/capture.ts +1 -9
- package/src/canvas/client/inspector/color-field.tsx +368 -0
- package/src/canvas/client/inspector/fields.css +163 -22
- package/src/canvas/client/inspector/values.ts +123 -0
- package/src/canvas/client/inspector.tsx +46 -69
- package/src/capture/render.ts +45 -7
- package/src/capture/sources.ts +43 -0
- package/src/census/count.ts +1 -1
- package/src/claude/cases/workflow.ts +5 -0
- package/src/claude/seeds.ts +1 -1
- package/src/claude/skills-audit.ts +68 -14
- package/src/client-commands.ts +1 -1
- package/src/commands/claude.ts +27 -2
- package/src/commands/feedback.ts +3 -3
- package/src/commands/records.ts +88 -6
- package/src/commands/sandbox.ts +50 -10
- package/src/commands/slides.ts +31 -77
- package/src/context/audit.ts +1 -1
- package/src/design/tokens.ts +2 -18
- package/src/docs/read.ts +1 -1
- package/src/{github.ts → feedback/github.ts} +1 -1
- package/src/gate/measures.ts +6 -4
- package/src/gov/citations.ts +1 -1
- package/src/gov/payload.ts +1 -1
- package/src/gov/superseded.ts +2 -2
- package/src/markdown/ceiling.ts +1 -1
- package/src/record-root.ts +1 -0
- package/src/records/backup.ts +1 -0
- package/src/records/push-guard.ts +1 -1
- package/src/records/stale-canonical.ts +146 -0
- package/src/records/stale.ts +1 -1
- package/src/sandbox/hooks.ts +128 -0
- package/src/sandbox/provision.ts +596 -0
- package/src/sandbox/tree.ts +103 -4
- package/src/secrets/marker.ts +2 -2
- package/src/secrets/scan.ts +1 -1
- package/src/shipped/references.ts +2 -2
- package/src/slides/convert/export.ts +2 -16
- package/src/slides/decks.ts +110 -0
- package/src/standards/read.ts +1 -1
- package/src/sync/seeds-report.ts +1 -1
- package/src/tasks/answers.ts +1 -1
- package/src/tasks/archive.ts +1 -1
- package/src/teach/nav.ts +1 -1
- package/src/tooling/inject.ts +1 -1
- package/src/web/readme-citations.ts +1 -1
- package/standards/architecture.md +1 -0
- package/standards/canvas.md +1 -1
- package/standards/requirements.md +2 -0
- package/standards/skill-practice.md +2 -1
- package/standards/skill.md +1 -0
- package/scripts/manage-sandbox.sh +0 -472
- package/src/slides/layouts.ts +0 -478
- package/src/slides/parse.ts +0 -84
- package/src/slides/render.ts +0 -110
- package/src/slides/styles.ts +0 -96
- /package/claude/skills/write-human/references/{source-material.md → adopted.md} +0 -0
- /package/src/{commands/feedback-format.ts → feedback/body.ts} +0 -0
- /package/src/{github-format.ts → feedback/github-format.ts} +0 -0
- /package/src/{frontmatter.ts → markdown/frontmatter.ts} +0 -0
- /package/src/{binary.ts → sweep/binary.ts} +0 -0
- /package/src/{exempt-marker.ts → sweep/exempt-marker.ts} +0 -0
- /package/src/{paths.ts → tasks/paths.ts} +0 -0
- /package/src/{seed-marker.ts → tooling/seed-marker.ts} +0 -0
package/src/secrets/marker.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { isMarked } from '@/exempt-marker'
|
|
1
|
+
import { isMarked } from '@/sweep/exempt-marker'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The inline token exempting one line from the secret scan.
|
|
5
5
|
*
|
|
6
|
-
* Shaped on the `stub: true` precedent in `src/seed-marker.ts`, which answers
|
|
6
|
+
* Shaped on the `stub: true` precedent in `src/tooling/seed-marker.ts`, which answers
|
|
7
7
|
* a check whose own comment records a false-positive class. The exemption
|
|
8
8
|
* travels with the line it exempts rather than sitting in a path list away
|
|
9
9
|
* from it, so a reader meeting a muted match finds the reason on the spot.
|
package/src/secrets/scan.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
|
-
import { isBinary } from '@/binary'
|
|
3
|
+
import { isBinary } from '@/sweep/binary'
|
|
4
4
|
import { listRepositoryFiles } from '@/git-files'
|
|
5
5
|
import { isExempt } from '@/secrets/marker'
|
|
6
6
|
import { matchLine } from '@/secrets/patterns'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
|
-
import { isMarked } from '@/exempt-marker'
|
|
3
|
+
import { isMarked } from '@/sweep/exempt-marker'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* The corpora a target reader reaches, which is the `files` field less `src`.
|
|
@@ -113,7 +113,7 @@ const COMMIT_SHA = /(?<![0-9A-Za-z_@/#])([0-9a-f]{7,40})(?![0-9A-Za-z_])/g
|
|
|
113
113
|
* one.
|
|
114
114
|
*
|
|
115
115
|
* The literal is hardcoded rather than read from `package.json` or
|
|
116
|
-
* `git remote`, matching `src/github-format.ts` and `src/commands/repo.ts`,
|
|
116
|
+
* `git remote`, matching `src/feedback/github-format.ts` and `src/commands/repo.ts`,
|
|
117
117
|
* which already hardcode it.
|
|
118
118
|
*
|
|
119
119
|
* Same word-boundary discipline as the two patterns above: a word character
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
copyFileSync,
|
|
3
|
-
mkdirSync,
|
|
4
|
-
readdirSync,
|
|
5
|
-
readFileSync,
|
|
6
|
-
writeFileSync,
|
|
7
|
-
} from 'node:fs'
|
|
1
|
+
import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
8
2
|
import { basename, join } from 'node:path'
|
|
9
3
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
10
4
|
import JSZip from 'jszip'
|
|
@@ -42,6 +36,7 @@ import {
|
|
|
42
36
|
type WalkedSlide,
|
|
43
37
|
walkSlide,
|
|
44
38
|
} from '@/slides/convert/walk'
|
|
39
|
+
import { slideFiles } from '@/slides/decks'
|
|
45
40
|
import { embedFonts, type FontNotice } from '@/slides/package/fonts'
|
|
46
41
|
import {
|
|
47
42
|
type EntranceSpec,
|
|
@@ -127,15 +122,6 @@ function refused(reason: ExportRefusal, message: string): ExportResult {
|
|
|
127
122
|
return { status: 'refused', reason, message }
|
|
128
123
|
}
|
|
129
124
|
|
|
130
|
-
/** Every `.html` file directly in the folder, in filename order. */
|
|
131
|
-
export function slideFiles(sourceDir: string): string[] {
|
|
132
|
-
return readdirSync(sourceDir, { withFileTypes: true })
|
|
133
|
-
.filter((entry) => entry.isFile() && entry.name.endsWith('.html'))
|
|
134
|
-
.map((entry) => entry.name)
|
|
135
|
-
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))
|
|
136
|
-
.map((name) => join(sourceDir, name))
|
|
137
|
-
}
|
|
138
|
-
|
|
139
125
|
/** A picture whose bytes the post-write pass replaces or whose corners it rounds. */
|
|
140
126
|
interface Patch {
|
|
141
127
|
readonly slide: number
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from 'node:fs'
|
|
2
|
+
import { join, relative, resolve } from 'node:path'
|
|
3
|
+
import { creationRel, recordDir } from '@/record-root'
|
|
4
|
+
import { readDeck } from '@/slides/convert/deck'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A deck is a folder under the record root's `slides/`, holding its `.html`
|
|
8
|
+
* slides, an optional `deck.json`, and its assets. `layouts/` beside the decks
|
|
9
|
+
* holds the project's shared layouts and is never a deck itself.
|
|
10
|
+
*/
|
|
11
|
+
export const SLIDES_FOLDER = 'slides'
|
|
12
|
+
|
|
13
|
+
export const LAYOUTS_FOLDER = 'layouts'
|
|
14
|
+
|
|
15
|
+
export interface Deck {
|
|
16
|
+
readonly name: string
|
|
17
|
+
/** From `deck.json`, falling back to the folder name as the export does. */
|
|
18
|
+
readonly title: string
|
|
19
|
+
readonly slides: number
|
|
20
|
+
/** Relative to the project root. */
|
|
21
|
+
readonly path: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DeckRefusal = 'no-decks' | 'ambiguous' | 'no-deck'
|
|
25
|
+
|
|
26
|
+
export type DeckResolution =
|
|
27
|
+
| { readonly status: 'resolved'; readonly dir: string }
|
|
28
|
+
| {
|
|
29
|
+
readonly status: 'refused'
|
|
30
|
+
readonly reason: DeckRefusal
|
|
31
|
+
readonly message: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Every `.html` file directly in the folder, in filename order. */
|
|
35
|
+
export function slideFiles(dir: string): string[] {
|
|
36
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
37
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.html'))
|
|
38
|
+
.map((entry) => entry.name)
|
|
39
|
+
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))
|
|
40
|
+
.map((name) => join(dir, name))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function listDecks(root: string): Deck[] {
|
|
44
|
+
const dir = recordDir(root, SLIDES_FOLDER)
|
|
45
|
+
if (!isDirectory(dir)) return []
|
|
46
|
+
|
|
47
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
48
|
+
.filter((entry) => entry.isDirectory() && entry.name !== LAYOUTS_FOLDER)
|
|
49
|
+
.map((entry) => entry.name)
|
|
50
|
+
.sort((a, b) => a.localeCompare(b))
|
|
51
|
+
.flatMap((name) => {
|
|
52
|
+
const deckDir = join(dir, name)
|
|
53
|
+
const slides = slideFiles(deckDir).length
|
|
54
|
+
if (slides === 0) return []
|
|
55
|
+
const read = readDeck(deckDir)
|
|
56
|
+
const title = read.status === 'read' ? read.deck.title : name
|
|
57
|
+
return [{ name, title, slides, path: relative(root, deckDir) }]
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The folder `render` reads. A deck name wins over a folder of the same name
|
|
63
|
+
* relative to the root, and no name at all takes the only deck there is.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveDeck(
|
|
66
|
+
root: string,
|
|
67
|
+
target: string | undefined,
|
|
68
|
+
): DeckResolution {
|
|
69
|
+
const decks = listDecks(root)
|
|
70
|
+
const at = creationRel(root, SLIDES_FOLDER)
|
|
71
|
+
|
|
72
|
+
if (target === undefined) {
|
|
73
|
+
const [only, ...rest] = decks
|
|
74
|
+
if (only === undefined) {
|
|
75
|
+
return refuse('no-decks', `No deck under ${at}/. Draw one there first.`)
|
|
76
|
+
}
|
|
77
|
+
if (rest.length > 0) {
|
|
78
|
+
return refuse(
|
|
79
|
+
'ambiguous',
|
|
80
|
+
`${decks.length} decks under ${at}/, name one: ${names(decks)}`,
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
return { status: 'resolved', dir: join(root, only.path) }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const named = decks.find((deck) => deck.name === target)
|
|
87
|
+
if (named) return { status: 'resolved', dir: join(root, named.path) }
|
|
88
|
+
|
|
89
|
+
const folder = resolve(root, target)
|
|
90
|
+
if (isDirectory(folder)) return { status: 'resolved', dir: folder }
|
|
91
|
+
|
|
92
|
+
return refuse(
|
|
93
|
+
'no-deck',
|
|
94
|
+
decks.length === 0
|
|
95
|
+
? `${target} is neither a deck under ${at}/ nor a folder`
|
|
96
|
+
: `${target} is neither a deck nor a folder. Decks: ${names(decks)}`,
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function names(decks: readonly Deck[]): string {
|
|
101
|
+
return decks.map((deck) => deck.name).join(', ')
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function refuse(reason: DeckRefusal, message: string): DeckResolution {
|
|
105
|
+
return { status: 'refused', reason, message }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function isDirectory(path: string): boolean {
|
|
109
|
+
return existsSync(path) && statSync(path).isDirectory()
|
|
110
|
+
}
|
package/src/standards/read.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
2
2
|
import { basename, join } from 'node:path'
|
|
3
|
-
import { stripFrontmatter } from '@/frontmatter'
|
|
3
|
+
import { stripFrontmatter } from '@/markdown/frontmatter'
|
|
4
4
|
import { PROJECT_ROOT } from '@/project-root'
|
|
5
5
|
|
|
6
6
|
export const INDEX_FILE = 'index.md'
|
package/src/sync/seeds-report.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs'
|
|
2
2
|
import { relative } from 'node:path'
|
|
3
3
|
import { planSeeds, type Seed } from '@/claude/seeds'
|
|
4
|
-
import { rewritesOnInstall, stripSeedMarker } from '@/seed-marker'
|
|
4
|
+
import { rewritesOnInstall, stripSeedMarker } from '@/tooling/seed-marker'
|
|
5
5
|
import { findInstalledOrigin, readHistoryIndex } from '@/sync/history'
|
|
6
6
|
|
|
7
7
|
/**
|
package/src/tasks/answers.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { readFile } from 'node:fs/promises'
|
|
3
3
|
import { isAbsolute, relative, resolve } from 'node:path'
|
|
4
|
-
import { isUnder } from '@/paths'
|
|
4
|
+
import { isUnder } from '@/tasks/paths'
|
|
5
5
|
import { recordDir, recordDirs } from '@/record-root'
|
|
6
6
|
import {
|
|
7
7
|
hasStagedBatches,
|
package/src/tasks/archive.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync } from 'node:fs'
|
|
|
2
2
|
import { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { basename, dirname, join, relative, resolve, sep } from 'node:path'
|
|
4
4
|
import { regenOne } from '@/indexes/regen'
|
|
5
|
-
import { isUnder } from '@/paths'
|
|
5
|
+
import { isUnder } from '@/tasks/paths'
|
|
6
6
|
import { recordDir, recordDirs } from '@/record-root'
|
|
7
7
|
|
|
8
8
|
const TASKS = 'tasks'
|
package/src/teach/nav.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from '@/design/components'
|
|
8
8
|
import { buildDesignCss } from '@/design/css'
|
|
9
9
|
import { FAVICON_COLORS, faviconLink, renderFavicon } from '@/design/favicon'
|
|
10
|
-
import { stripFrontmatter } from '@/frontmatter'
|
|
10
|
+
import { stripFrontmatter } from '@/markdown/frontmatter'
|
|
11
11
|
import { parseFrontmatter, readField } from '@/indexes/frontmatter'
|
|
12
12
|
import { PROJECT_ROOT } from '@/project-root'
|
|
13
13
|
import { compileScript } from '@/teach/browser/compile'
|
package/src/tooling/inject.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
|
3
3
|
import { dirname, join, relative } from 'node:path'
|
|
4
4
|
import { $ } from 'bun'
|
|
5
5
|
import { copyPreservingMode } from '@/copy'
|
|
6
|
-
import { rewritesOnInstall, stripSeedMarker } from '@/seed-marker'
|
|
6
|
+
import { rewritesOnInstall, stripSeedMarker } from '@/tooling/seed-marker'
|
|
7
7
|
import { resolveSurfacePath } from '@/surface-root'
|
|
8
8
|
import { mergeSections, pruneSections } from '@/tooling/gitignore'
|
|
9
9
|
import {
|
|
@@ -54,6 +54,7 @@ Use `## Overview`, `## Key technical decisions` with one named H3 per decision,
|
|
|
54
54
|
|
|
55
55
|
- Rewrite a decision a later one changed rather than appending the change beside it. A reader should find the design that stands in one place, with the alternative that lost stated once.
|
|
56
56
|
- Hold only what is open under `## Risks / open questions`. An entry leaves the section in the change that settles it, becoming a decision here when it fills a slot and moving to the domain context entry it constrains when it does not.
|
|
57
|
+
- Carry an optional `reviewed: YYYY-MM-DD` frontmatter field naming the day someone last read the record whole for drift. Whoever finishes that review sets it as the review's last edit, and `canon records stale canonical` reads it to count the releases shipped since. A record with no field reads as never reviewed.
|
|
57
58
|
|
|
58
59
|
## Verification anchors
|
|
59
60
|
|
package/standards/canvas.md
CHANGED
|
@@ -78,7 +78,7 @@ The keys below are the ones a reader parses. The frame names are placeholders.
|
|
|
78
78
|
- Do not assume a viewport. A frame renders at its layout width on the canvas and in a capture alike, so size it with media queries against that width rather than against the operator's window.
|
|
79
79
|
- Do not assume the theme. The canvas theme toggle is the operator's own state, and a capture shows each frame in its default theme.
|
|
80
80
|
- Do not assume a network. Name only fonts the machine has, or ship the font beside the frame, since a capture refuses a frame naming a font it cannot find.
|
|
81
|
-
- Do not assume a default font. Set `font-family`
|
|
81
|
+
- Do not assume a default font. Set `font-family` with an installed family first on an element the frame's text inherits from, since a capture checks the first family of the text it renders and the browser's default serif is absent from many machines.
|
|
82
82
|
- Do not assume the frame is the source. A picked direction is carried into the project's design document or its wireframes, and the operator clears the frame once it has been carried.
|
|
83
83
|
- Do not assume the canvas survives the checkout. The folder is gitignored, so a lost checkout loses every page in it.
|
|
84
84
|
|
|
@@ -46,6 +46,8 @@ This file loads into every session, so its weight is paid before any work starts
|
|
|
46
46
|
|
|
47
47
|
Once every entry in the MVP list, or in a later scope section, has shipped, delete the section. Git keeps the old text, and the document states the project as it stands. Do not annotate an entry as shipped and leave it in place. While any entry is unshipped, do not renumber the list or append to it.
|
|
48
48
|
|
|
49
|
+
The record may carry an optional `reviewed: YYYY-MM-DD` frontmatter field naming the day someone last read it whole for identity drift. Whoever finishes that review sets it as the review's last edit, and `canon records stale canonical` reads it to count the releases shipped since. A record with no field reads as never reviewed.
|
|
50
|
+
|
|
49
51
|
Later scope arrives as a new section rather than as an extension of the MVP list. Name the section for what it delivers and state its entries as outcomes, the same way the goals are stated. Nothing sequences either list into versions. Work reaches the board as discrete tasks under `tasks.md`, and `board.md` orders them by readiness, so a section here states what is wanted and never when it lands.
|
|
50
52
|
|
|
51
53
|
## Distribution
|
|
@@ -47,5 +47,6 @@ A practice skill failing any of these is non-conforming even when every heading
|
|
|
47
47
|
## Which skills are practice skills
|
|
48
48
|
|
|
49
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
|
+
- It keeps a wider ledger list beside it, holding every practice skill plus the skills that teach a craft drawn from outside sources without a practice's closing shape. A skill on the wider list alone owes the ledger and none of the three sections.
|
|
50
51
|
- Never mark a skill as a practice skill in its own frontmatter, since a self-declared kind lets a skill exempt itself.
|
|
51
|
-
-
|
|
52
|
+
- Both lists name 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
|
@@ -130,6 +130,7 @@ allowed-tools: <tools required>
|
|
|
130
130
|
- Below the ceiling, name the branch that skips a block before moving it. A block every run dereferences costs a read and saves nothing.
|
|
131
131
|
- Past the ceiling, move a whole step to a reference, preferring a step a named branch skips. Keep the step heading in the body with one line naming the file to read on reaching it, so the body still shows every step in order.
|
|
132
132
|
- Name every file under `references/` in the body at the point a session reads it, since an unnamed reference is never loaded.
|
|
133
|
+
- Open a file under `references/` running over 100 lines with a `## Contents` H2 of anchor links after its H1 and intro, so a session that reads only the top of the file still sees everything it holds.
|
|
133
134
|
- Keep the trigger, the skip condition, and the guard in the body. A run that never reaches the block has to decide that without opening the reference.
|
|
134
135
|
- Never point one skill at a sibling skill's folder for a reference both read. Each skill carries its own copy under `references/`, generated rather than hand-copied by the rule in `## Path resolution`.
|
|
135
136
|
|