@erclx/canon 5.24.0 → 5.25.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/backlog-triage/REQUIREMENT.md +2 -2
- package/claude/skills/backlog-triage/SKILL.md +19 -6
- package/claude/skills/canvas/REQUIREMENT.md +49 -0
- package/claude/skills/canvas/SKILL.md +106 -0
- package/claude/skills/design-extract/REQUIREMENT.md +1 -1
- package/claude/skills/draft-doc/REQUIREMENT.md +1 -1
- package/claude/skills/draft-figure/REQUIREMENT.md +14 -3
- package/claude/skills/draft-figure/SKILL.md +24 -51
- package/claude/skills/draft-figure/references/architecture-set.md +35 -0
- package/claude/skills/draft-figure/references/hand-drawn.md +31 -0
- package/claude/skills/draft-figure/references/mermaid.md +55 -0
- package/claude/skills/git-followup/SKILL.md +17 -6
- package/claude/skills/git-pr/references/evidence.md +4 -2
- package/claude/skills/git-split/SKILL.md +1 -1
- package/claude/skills/index-lookup/SKILL.md +2 -2
- package/claude/skills/review-address/SKILL.md +6 -13
- package/claude/skills/review-address/references/rest-reads.md +43 -0
- package/claude/skills/review-craft/references/ui.md +7 -1
- package/claude/skills/review-pr/REQUIREMENT.md +1 -0
- package/claude/skills/review-pr/SKILL.md +9 -3
- package/claude/skills/review-pr/references/close-out.md +2 -2
- package/claude/skills/review-pr/references/post.md +17 -5
- package/claude/skills/review-pr/references/scope.md +10 -8
- package/claude/skills/review-ui/SKILL.md +12 -4
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +30 -1
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +4 -0
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +4 -4
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +6 -0
- package/claude/skills/role-orchestrator/scripts/poll.ts +90 -27
- package/claude/skills/role-orchestrator/scripts/repo.ts +3 -5
- package/claude/skills/role-orchestrator/scripts/watch.ts +4 -7
- package/docs/agents/canvas.md +1 -1
- package/docs/agents/commands.md +45 -45
- package/docs/agents/context-audit-checks.md +2 -2
- package/docs/agents/index.md +0 -1
- package/docs/agents/key-changes.md +3 -3
- package/docs/agents/pr-evidence.md +11 -2
- package/docs/agents/pr-reads.md +5 -4
- package/docs/target/projects.md +4 -4
- package/docs/workflow/ai-workflow.md +0 -1
- package/docs/workflow/skill-map.md +3 -3
- package/docs/workflow/visual-design-workflow.md +1 -0
- package/governance/renames.toml +0 -4
- package/governance/rules/standards/markdown.md +1 -0
- package/package.json +1 -2
- package/scripts/core/install-check.sh +1 -1
- package/src/audits/catalog.ts +2 -2
- package/src/canvas/client/inspector/field.tsx +200 -0
- package/src/canvas/client/inspector/fields.css +151 -0
- package/src/canvas/client/inspector/section.tsx +27 -0
- package/src/canvas/client/inspector/values.ts +60 -0
- package/src/canvas/client/inspector.tsx +154 -115
- package/src/canvas/client/shell.css +0 -101
- package/src/claude/cases/misc.ts +5 -0
- package/src/claude/cases/workflow.ts +1 -1
- package/src/claude/seeds.ts +0 -1
- package/src/commands/design.ts +2 -64
- package/src/commands/pr.ts +219 -202
- package/src/context/audit.ts +7 -6
- package/src/help.ts +2 -2
- package/src/migrate/skill-names.ts +7 -1
- package/src/pr/evidence.ts +25 -5
- package/src/pr/rest.ts +137 -0
- package/standards/canvas.md +112 -0
- package/standards/context.md +2 -1
- package/standards/figures.md +0 -1
- package/standards/index.md +1 -1
- package/standards/markdown.md +1 -0
- package/standards/mermaid.md +1 -7
- package/tooling/claude/reference.md +0 -5
- package/claude/skills/draft-diagram/REQUIREMENT.md +0 -45
- package/claude/skills/draft-diagram/SKILL.md +0 -177
- package/docs/agents/design-board.md +0 -33
- package/governance/rules/standards/diagrams.md +0 -14
- package/governance/rules/standards/mermaid.md +0 -15
- package/scripts/core/check-gallery-exclusion.sh +0 -50
- package/src/design/board.ts +0 -576
- package/standards/diagrams.md +0 -132
- package/tooling/claude/seeds/.claude/diagrams/index.md +0 -8
|
@@ -20,7 +20,6 @@ interface Review {
|
|
|
20
20
|
|
|
21
21
|
export interface Payload {
|
|
22
22
|
comments?: Comment[]
|
|
23
|
-
headRefOid?: string
|
|
24
23
|
reviews?: Review[]
|
|
25
24
|
}
|
|
26
25
|
|
|
@@ -416,11 +415,80 @@ const parseJson = (text: string): unknown => {
|
|
|
416
415
|
}
|
|
417
416
|
}
|
|
418
417
|
|
|
418
|
+
/**
|
|
419
|
+
* One JSON object per line, which is what `.[] | <projection> | @json` prints
|
|
420
|
+
* across every page. The projection keeps stdout to the fields the mappers
|
|
421
|
+
* read, since a whole REST row carries user objects and links and a long thread
|
|
422
|
+
* could overrun the spawn buffer and read as unreadable. A failed read and a
|
|
423
|
+
* line that does not parse both return null, so neither reads as a thread with
|
|
424
|
+
* nothing on it.
|
|
425
|
+
*/
|
|
426
|
+
const readRows = (
|
|
427
|
+
path: string,
|
|
428
|
+
fields: string,
|
|
429
|
+
): null | Record<string, unknown>[] => {
|
|
430
|
+
const read = run('gh', [
|
|
431
|
+
'api',
|
|
432
|
+
'--paginate',
|
|
433
|
+
`repos/{owner}/{repo}/${path}`,
|
|
434
|
+
'--jq',
|
|
435
|
+
`.[] | {${fields}} | @json`,
|
|
436
|
+
])
|
|
437
|
+
if (!read.isOk) return null
|
|
438
|
+
|
|
439
|
+
const rows: Record<string, unknown>[] = []
|
|
440
|
+
for (const line of read.stdout.split('\n')) {
|
|
441
|
+
if (line.trim() === '') continue
|
|
442
|
+
const row = parseJson(line)
|
|
443
|
+
if (typeof row !== 'object' || row === null) return null
|
|
444
|
+
rows.push(row as Record<string, unknown>)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return rows
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const text = (value: unknown): null | string =>
|
|
451
|
+
typeof value === 'string' ? value : null
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* The REST rows carry snake_case names, mapped onto the camelCase shape the
|
|
455
|
+
* classifiers read. `commit_id` becomes `commit.oid`. A pending review has no
|
|
456
|
+
* `submitted_at`, which maps to null.
|
|
457
|
+
*/
|
|
458
|
+
export const toReview = (row: Record<string, unknown>): Review => ({
|
|
459
|
+
body: text(row.body),
|
|
460
|
+
commit: { oid: text(row.commit_id) },
|
|
461
|
+
submittedAt: text(row.submitted_at),
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
export const toComment = (row: Record<string, unknown>): Comment => ({
|
|
465
|
+
body: text(row.body),
|
|
466
|
+
createdAt: text(row.created_at),
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Two reads feed one payload, so either failing makes the pull request
|
|
471
|
+
* unreadable rather than a thread missing half its rows.
|
|
472
|
+
*/
|
|
473
|
+
const readPayload = (number: string): null | Payload => {
|
|
474
|
+
const reviews = readRows(
|
|
475
|
+
`pulls/${number}/reviews?per_page=100`,
|
|
476
|
+
'body, commit_id, submitted_at',
|
|
477
|
+
)
|
|
478
|
+
const comments = readRows(
|
|
479
|
+
`issues/${number}/comments?per_page=100`,
|
|
480
|
+
'body, created_at',
|
|
481
|
+
)
|
|
482
|
+
if (reviews === null || comments === null) return null
|
|
483
|
+
|
|
484
|
+
return { comments: comments.map(toComment), reviews: reviews.map(toReview) }
|
|
485
|
+
}
|
|
486
|
+
|
|
419
487
|
type Snapshot = { baseline: Baseline } | { row: Row }
|
|
420
488
|
|
|
421
489
|
const nowSeconds = (): number => Math.floor(Date.now() / 1000)
|
|
422
490
|
|
|
423
|
-
const readHead = (number: string
|
|
491
|
+
const readHead = (number: string): string => {
|
|
424
492
|
// The tip is the authority for the head, not the pull request object, which
|
|
425
493
|
// lags the ref by up to a minute after a push. The object's head is the
|
|
426
494
|
// fallback for a target on an older binary with no `pr head` verb.
|
|
@@ -432,13 +500,20 @@ const readHead = (number: string, payload: Payload): string => {
|
|
|
432
500
|
? (record as Record<string, unknown>).tip
|
|
433
501
|
: undefined
|
|
434
502
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
503
|
+
if (typeof tip === 'string' && tip !== '') return tip
|
|
504
|
+
|
|
505
|
+
const pull = run('gh', [
|
|
506
|
+
'api',
|
|
507
|
+
`repos/{owner}/{repo}/pulls/${number}`,
|
|
508
|
+
'--jq',
|
|
509
|
+
'.head.sha',
|
|
510
|
+
])
|
|
511
|
+
|
|
512
|
+
return pull.isOk ? pull.stdout.trim() : ''
|
|
438
513
|
}
|
|
439
514
|
|
|
440
515
|
/**
|
|
441
|
-
*
|
|
516
|
+
* The pull read's `mergeable_state` reports unknown until GitHub finishes
|
|
442
517
|
* computing it, which is exactly when a poll asks. merge-tree answers locally
|
|
443
518
|
* against the base this machine has. It exits non-zero on a ref it cannot
|
|
444
519
|
* resolve as well as on a real conflict, so both sides are checked first.
|
|
@@ -530,12 +605,9 @@ const main = (): number => {
|
|
|
530
605
|
// one as GONE. That is a louder wrong answer than the one this script was
|
|
531
606
|
// fixed for, so the run aborts rather than classify on it.
|
|
532
607
|
const listed = run('gh', [
|
|
533
|
-
'
|
|
534
|
-
'
|
|
535
|
-
'
|
|
536
|
-
'open',
|
|
537
|
-
'--json',
|
|
538
|
-
'number',
|
|
608
|
+
'api',
|
|
609
|
+
'--paginate',
|
|
610
|
+
'repos/{owner}/{repo}/pulls?state=open&per_page=100',
|
|
539
611
|
'--jq',
|
|
540
612
|
'.[].number',
|
|
541
613
|
])
|
|
@@ -550,19 +622,10 @@ const main = (): number => {
|
|
|
550
622
|
|
|
551
623
|
const snapshots: Snapshot[] = []
|
|
552
624
|
for (const number of listed.stdout.split(/\s+/).filter((n) => n !== '')) {
|
|
553
|
-
// A
|
|
554
|
-
//
|
|
555
|
-
// single place to surface.
|
|
556
|
-
const
|
|
557
|
-
'pr',
|
|
558
|
-
'view',
|
|
559
|
-
number,
|
|
560
|
-
'--json',
|
|
561
|
-
'headRefOid,reviews,comments',
|
|
562
|
-
])
|
|
563
|
-
const payload = view.isOk
|
|
564
|
-
? (parseJson(view.stdout) as Payload | null)
|
|
565
|
-
: null
|
|
625
|
+
// A read that failed and a pull request with no reviews both arrive as an
|
|
626
|
+
// empty result, so each read returns null on failure and the payload gives
|
|
627
|
+
// the failure a single place to surface.
|
|
628
|
+
const payload = readPayload(number)
|
|
566
629
|
const old = known.get(number)
|
|
567
630
|
const unreadable = (reason: string): void => {
|
|
568
631
|
if (old === undefined) {
|
|
@@ -578,12 +641,12 @@ const main = (): number => {
|
|
|
578
641
|
snapshots.push({ baseline: carryForward(old) })
|
|
579
642
|
}
|
|
580
643
|
|
|
581
|
-
if (payload === null
|
|
644
|
+
if (payload === null) {
|
|
582
645
|
unreadable('could not be read')
|
|
583
646
|
continue
|
|
584
647
|
}
|
|
585
648
|
|
|
586
|
-
const head = readHead(number
|
|
649
|
+
const head = readHead(number)
|
|
587
650
|
if (head === '') {
|
|
588
651
|
unreadable('returned no head')
|
|
589
652
|
continue
|
|
@@ -53,12 +53,10 @@ export const baseRef = (): string => {
|
|
|
53
53
|
if (symbolic.isOk && ref !== '') return ref
|
|
54
54
|
|
|
55
55
|
const repo = run('gh', [
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'--json',
|
|
59
|
-
'defaultBranchRef',
|
|
56
|
+
'api',
|
|
57
|
+
'repos/{owner}/{repo}',
|
|
60
58
|
'--jq',
|
|
61
|
-
'.
|
|
59
|
+
'.default_branch',
|
|
62
60
|
])
|
|
63
61
|
const name = repo.isOk ? repo.stdout.trim() : ''
|
|
64
62
|
|
|
@@ -175,14 +175,11 @@ export const pass = (
|
|
|
175
175
|
|
|
176
176
|
const readPulls = (): Read<string[]> => {
|
|
177
177
|
const listed = run('gh', [
|
|
178
|
-
'
|
|
179
|
-
'
|
|
180
|
-
'
|
|
181
|
-
'open',
|
|
182
|
-
'--json',
|
|
183
|
-
'number,headRefName,title',
|
|
178
|
+
'api',
|
|
179
|
+
'--paginate',
|
|
180
|
+
'repos/{owner}/{repo}/pulls?state=open&per_page=100',
|
|
184
181
|
'--jq',
|
|
185
|
-
'.[] | "PR-OPEN #\\(.number) \\(.
|
|
182
|
+
'.[] | "PR-OPEN #\\(.number) \\(.head.ref) \\(.title)"',
|
|
186
183
|
])
|
|
187
184
|
if (!listed.isOk) return { isOk: false }
|
|
188
185
|
|
package/docs/agents/canvas.md
CHANGED
|
@@ -5,7 +5,7 @@ description: The canvas server, its content format, and the verbs that list, arr
|
|
|
5
5
|
|
|
6
6
|
# Canvas
|
|
7
7
|
|
|
8
|
-
`canon canvas` serves a local canvas of pages and HTML frames and gives an agent the verbs the operator's mouse has. A page is a folder under `.canon/canvas/`, a frame is one HTML file in it, and `layout.json` beside them holds each frame's box.
|
|
8
|
+
`canon canvas` serves a local canvas of pages and HTML frames and gives an agent the verbs the operator's mouse has. A page is a folder under `.canon/canvas/`, a frame is one HTML file in it, and `layout.json` beside them holds each frame's box. `standards/canvas.md` fixes that content format, and the `canvas` skill carries the procedure a session follows to drive the canvas.
|
|
9
9
|
|
|
10
10
|
## Serve
|
|
11
11
|
|
package/docs/agents/commands.md
CHANGED
|
@@ -11,50 +11,50 @@ Full help: `canon <command> --help`. Bare `canon --help` lists every top-level c
|
|
|
11
11
|
|
|
12
12
|
One row per top-level command, in the order `canon --help` prints them. A domain's subcommands are in `## Domain commands` below.
|
|
13
13
|
|
|
14
|
-
| Command | Purpose
|
|
15
|
-
| --------------------------- |
|
|
16
|
-
| `canon init [path]` | Bootstrap a project with selected toolkit domains
|
|
17
|
-
| `canon sync [path]` | Sync every installed domain, or report drift and version skew with `--check`
|
|
18
|
-
| `canon upgrade` | Reinstall the CLI globally with the package manager the install path names
|
|
19
|
-
| `canon migrate <verb>` | Move a project off a retired name or layout, reporting the plan until `--write`
|
|
20
|
-
| `canon targets <verb>` | Report the projects this toolkit installed into
|
|
21
|
-
| `canon gov <verb>` | Install and sync governance rules, and audit the tree against them
|
|
22
|
-
| `canon standards <verb>` | List, audit, or print a standard by name
|
|
23
|
-
| `canon tooling <verb>` | Sync, diff, and verify tooling stacks
|
|
24
|
-
| `canon claude <verb>` | Install the Claude workflow and audit both skill corpora
|
|
25
|
-
| `canon wiki <verb>` | Scaffold the wiki pages
|
|
26
|
-
| `canon indexes <verb>` | Regenerate `index.md` files from sibling frontmatter, or flatten them
|
|
27
|
-
| `canon docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name)
|
|
28
|
-
| `canon design <verb>` | Render `canon/DESIGN.md` tokens,
|
|
29
|
-
| `canon slides <verb>` | Render a `.claude/SLIDES.md` deck, or list its layouts
|
|
30
|
-
| `canon capture [source]` | Render HTML or a URL to PNG and prove each declared font resolved
|
|
31
|
-
| `canon serve [dir]` | Serve a directory on loopback and print the link that opens it
|
|
32
|
-
| `canon demo <verb>` | Compile and record a running app
|
|
33
|
-
| `canon inventory [subject]` | Group every route's elements by one computed property, never gating
|
|
34
|
-
| `canon drive <url> <run>` | Walk a page through named interactions and measure each state
|
|
35
|
-
| `canon transcripts <url>` | Fetch a YouTube transcript with metadata frontmatter (needs `yt-dlp`)
|
|
36
|
-
| `canon teach <verb>` | Open and author learning workspaces
|
|
37
|
-
| `canon canvas <verb>` | Serve a local canvas of pages and HTML frames, arrange, edit, and capture them
|
|
38
|
-
| `canon sandbox [cat:cmd]` | Run sandbox scenarios, toolkit-only like the tree it reads
|
|
39
|
-
| `canon tasks <verb>` | Read and write the task board, the plans it cites, and its archive
|
|
40
|
-
| `canon intake <verb>` | Report intake folders and write answers into them
|
|
41
|
-
| `canon records <verb>` | Validate, size, prune, and back up the session records
|
|
42
|
-
| `canon sessions <verb>` | Resolve live sessions to worktree and branch, and move one between machines
|
|
43
|
-
| `canon worktrees <verb>` | Report and remove worktrees whose pull request merged
|
|
44
|
-
| `canon hooks <verb>` | Run the steps a git hook drives
|
|
45
|
-
| `canon autoship <verb>` | Decide whether a changed set needs the review pass
|
|
46
|
-
| `canon pr <verb>` | Read a pull request's diff, head, checks, and review, and post its evidence
|
|
47
|
-
| `canon feedback` | Write toolkit feedback from stdin, or open an issue with `--github`
|
|
48
|
-
| `canon audits <verb>` | Run every audit as one set under one verdict against the recorded baseline
|
|
49
|
-
| `canon gate <verb>` | Run every stage that guards a branch here
|
|
50
|
-
| `canon secrets <verb>` | Report credential-shaped values in the tree the package ships
|
|
51
|
-
| `canon deps <verb>` | Report published advisories against the resolved dependency set
|
|
52
|
-
| `canon labels <verb>` | Read a changed set against the label map, and scan pull request text
|
|
53
|
-
| `canon comments <verb>` | Measure comment density by language and kind, with a trend from git
|
|
54
|
-
| `canon context <verb>` | Report context folder health, and classify changed or stale sections
|
|
55
|
-
| `canon markdown <verb>` | Fail markdown on a banned character or a dead link, and report its structure
|
|
56
|
-
| `canon repo <verb>` | Propose and apply the remote's description, homepage, and topics
|
|
57
|
-
| `canon census [path]` | Report tracked file count, extensions, and a line total skipping binaries
|
|
14
|
+
| Command | Purpose |
|
|
15
|
+
| --------------------------- | ------------------------------------------------------------------------------------------ |
|
|
16
|
+
| `canon init [path]` | Bootstrap a project with selected toolkit domains |
|
|
17
|
+
| `canon sync [path]` | Sync every installed domain, or report drift and version skew with `--check` |
|
|
18
|
+
| `canon upgrade` | Reinstall the CLI globally with the package manager the install path names |
|
|
19
|
+
| `canon migrate <verb>` | Move a project off a retired name or layout, reporting the plan until `--write` |
|
|
20
|
+
| `canon targets <verb>` | Report the projects this toolkit installed into |
|
|
21
|
+
| `canon gov <verb>` | Install and sync governance rules, and audit the tree against them |
|
|
22
|
+
| `canon standards <verb>` | List, audit, or print a standard by name |
|
|
23
|
+
| `canon tooling <verb>` | Sync, diff, and verify tooling stacks |
|
|
24
|
+
| `canon claude <verb>` | Install the Claude workflow and audit both skill corpora |
|
|
25
|
+
| `canon wiki <verb>` | Scaffold the wiki pages |
|
|
26
|
+
| `canon indexes <verb>` | Regenerate `index.md` files from sibling frontmatter, or flatten them |
|
|
27
|
+
| `canon docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name) |
|
|
28
|
+
| `canon design <verb>` | Render or regenerate `canon/DESIGN.md` tokens, emit their CSS, install the base stylesheet |
|
|
29
|
+
| `canon slides <verb>` | Render a `.claude/SLIDES.md` deck, or list its layouts |
|
|
30
|
+
| `canon capture [source]` | Render HTML or a URL to PNG and prove each declared font resolved |
|
|
31
|
+
| `canon serve [dir]` | Serve a directory on loopback and print the link that opens it |
|
|
32
|
+
| `canon demo <verb>` | Compile and record a running app |
|
|
33
|
+
| `canon inventory [subject]` | Group every route's elements by one computed property, never gating |
|
|
34
|
+
| `canon drive <url> <run>` | Walk a page through named interactions and measure each state |
|
|
35
|
+
| `canon transcripts <url>` | Fetch a YouTube transcript with metadata frontmatter (needs `yt-dlp`) |
|
|
36
|
+
| `canon teach <verb>` | Open and author learning workspaces |
|
|
37
|
+
| `canon canvas <verb>` | Serve a local canvas of pages and HTML frames, arrange, edit, and capture them |
|
|
38
|
+
| `canon sandbox [cat:cmd]` | Run sandbox scenarios, toolkit-only like the tree it reads |
|
|
39
|
+
| `canon tasks <verb>` | Read and write the task board, the plans it cites, and its archive |
|
|
40
|
+
| `canon intake <verb>` | Report intake folders and write answers into them |
|
|
41
|
+
| `canon records <verb>` | Validate, size, prune, and back up the session records |
|
|
42
|
+
| `canon sessions <verb>` | Resolve live sessions to worktree and branch, and move one between machines |
|
|
43
|
+
| `canon worktrees <verb>` | Report and remove worktrees whose pull request merged |
|
|
44
|
+
| `canon hooks <verb>` | Run the steps a git hook drives |
|
|
45
|
+
| `canon autoship <verb>` | Decide whether a changed set needs the review pass |
|
|
46
|
+
| `canon pr <verb>` | Read a pull request's diff, head, checks, and review, and post its evidence |
|
|
47
|
+
| `canon feedback` | Write toolkit feedback from stdin, or open an issue with `--github` |
|
|
48
|
+
| `canon audits <verb>` | Run every audit as one set under one verdict against the recorded baseline |
|
|
49
|
+
| `canon gate <verb>` | Run every stage that guards a branch here |
|
|
50
|
+
| `canon secrets <verb>` | Report credential-shaped values in the tree the package ships |
|
|
51
|
+
| `canon deps <verb>` | Report published advisories against the resolved dependency set |
|
|
52
|
+
| `canon labels <verb>` | Read a changed set against the label map, and scan pull request text |
|
|
53
|
+
| `canon comments <verb>` | Measure comment density by language and kind, with a trend from git |
|
|
54
|
+
| `canon context <verb>` | Report context folder health, and classify changed or stale sections |
|
|
55
|
+
| `canon markdown <verb>` | Fail markdown on a banned character or a dead link, and report its structure |
|
|
56
|
+
| `canon repo <verb>` | Propose and apply the remote's description, homepage, and topics |
|
|
57
|
+
| `canon census [path]` | Report tracked file count, extensions, and a line total skipping binaries |
|
|
58
58
|
|
|
59
59
|
`canon serve` drives no browser, which is what separates it from the four that do. All four ship now that `capture` does, so the line between them is the engine rather than the package. A generated page loses its script to an editor preview and to a `file://` open, so the link is the delivery rather than a convenience, and every generated surface here reaches a reader through one. A teach lesson's stylesheet is embedded rather than linked, so only its script still needs a server. It binds `127.0.0.1` and never a wildcard, because what it is pointed at is routinely a gitignored record tree. It sends `cache-control: no-store`, since a preview exists to be edited and reloaded and a cached stylesheet reads as a fix that did not work.
|
|
60
60
|
|
|
@@ -91,7 +91,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
|
|
|
91
91
|
- `wiki`, in `scripting.md`: `init`
|
|
92
92
|
- `indexes`, in `indexes.md`: `regen`, `list`
|
|
93
93
|
- `docs`, in `docs.md`: `list`, `<topic>`
|
|
94
|
-
- `design`, in `
|
|
94
|
+
- `design`, in `install-and-sync.md` for `install` and `sync`, and described below for the rest: `render`, `regen`, `css`, `install`, `sync`
|
|
95
95
|
- `slides`, described below: `render`, `list`
|
|
96
96
|
- `demo`, in `demo.md`: `compile`, `run`, `frames`
|
|
97
97
|
- `inventory`, described above: `run`
|
|
@@ -85,9 +85,9 @@ All three wireframe findings are printed under a bare run. The states-mismatch f
|
|
|
85
85
|
|
|
86
86
|
The provenance check covers `canon/context/` alone, the reference-form check covers the split folders inside it, the required-section check covers `canon/context/` and `canon/wireframes/`, length and the table finding reach every audited folder, and the wireframe states check covers `canon/wireframes/` alone.
|
|
87
87
|
|
|
88
|
-
What narrows the provenance check is stated in `standards/context.md`, which opens its scope by handing
|
|
88
|
+
What narrows the provenance check is stated in `standards/context.md`, which opens its scope by handing figures to the `draft-figure` skill and wireframes to `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram or wireframe entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder, and what decides it is which tier states the rule rather than what the check measures.
|
|
89
89
|
|
|
90
|
-
Length and the table finding generalize as judgments about how far a reader travels, so both reach wherever the audit is pointed. Required sections narrow for a plainer reason: each list is one standard's own, so it reaches the folder that standard governs. The context and wireframe standards each state a set, and
|
|
90
|
+
Length and the table finding generalize as judgments about how far a reader travels, so both reach wherever the audit is pointed. Required sections narrow for a plainer reason: each list is one standard's own, so it reaches the folder that standard governs. The context and wireframe standards each state a set, and an older install's diagrams folder has no standard to state one.
|
|
91
91
|
|
|
92
92
|
The same test is what moved depth and bullet weight out of this command entirely. A rule stated at the attribute tier reaches every markdown file, and a check reaching every markdown file has no reason to require a folder that resolves.
|
|
93
93
|
|
package/docs/agents/index.md
CHANGED
|
@@ -20,7 +20,6 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
20
20
|
- [Doc classifier](context-classify.md): Classifying canonical-doc content as keep, replace/rewrite, history, or move in diff and sweep mode, the classifier setting pair, the record shape, and the exit codes
|
|
21
21
|
- [Self-stated counts](counts.md): Reading a sentence that asserts a closed catalog's size, how a match is decided, the plausibility filter that keeps a generic word from matching a subset, and why the sweep reports rather than gates
|
|
22
22
|
- [Demo](demo.md): Compiling a screencast draft into a runnable plan, driving a served application to a recording and a still, reading numbered frames back out of a recording, the pointer the recording paints, and what each refusal reports
|
|
23
|
-
- [Design board](design-board.md): Generating a static index over a project's design surfaces, what each panel reads, and which two stay toolkit-checkout-only
|
|
24
23
|
- [Docs](docs.md): How canon docs resolves the toolkit's own reference surface from an install root, and how a split domain is named
|
|
25
24
|
- [Drift surfaces](drift-surfaces.md): The seven sections canon sync --check reports beside the per-domain scan, being seeds, superseded artifacts, unmigrated domains, surfaces at the old root, new rules and skills, and the reverse walk, with the managed-target gate and what counts toward the exit code
|
|
26
25
|
- [Driver](driver.md): Walking a page through named interactions, the probe catalog and the false finding each one carries, why viewport heights are never defaulted, and what each refusal reports
|
|
@@ -26,9 +26,9 @@ The positional is the pull request to read, defaulting to the one open on this b
|
|
|
26
26
|
|
|
27
27
|
`--base` names the far side of that range and never the commit the comparison runs against directly. The reader resolves the merge base between `HEAD` and the ref, so `--base origin/main` measures what the branch wrote rather than what the trunk gained while the branch was open. Passing the trunk as it stands today is therefore safe on a branch of any age, and a ref sharing no history with `HEAD` refuses as `bad-base`.
|
|
28
28
|
|
|
29
|
-
Without `--body` the body
|
|
29
|
+
Without `--body` the body and the head commit come off the REST pull read and the file list off the paginated files endpoint. Every read runs on REST, since a cloud session's GitHub proxy refuses the GraphQL that `gh pr view` runs on. A push landing between the two reads compares a body against the next head's files, a window the verb accepts for the cloud reach.
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
A failed page refuses as `gh-failed` rather than comparing against a set known to be short. A set silently one file short is the worst input this takes, since the missing file is exactly what a correct bullet would then be accused of inventing. With no number named, the verb reads the one pull request open on the checkout's branch, and refuses as `ambiguous-pull` when two are open against different bases.
|
|
32
32
|
|
|
33
33
|
## The two directions
|
|
34
34
|
|
|
@@ -91,7 +91,7 @@ Three refusals separate a clean pass from a read that produced nothing:
|
|
|
91
91
|
|
|
92
92
|
An empty extraction read as a clean pass is the failure shape this repository has recorded twice, which is why the middle one is its own reason rather than a zero count.
|
|
93
93
|
|
|
94
|
-
`gh-missing`, `gh-failed`, `
|
|
94
|
+
`gh-missing`, `gh-failed`, `ambiguous-pull`, `unreadable-body`, `unreadable-tree`, `no-base`, `bad-base`, and `unreadable-changes` cover the reads that never reached a comparison.
|
|
95
95
|
|
|
96
96
|
## What it was measured against
|
|
97
97
|
|
|
@@ -138,7 +138,7 @@ call, is what keeps two close-out comments from landing beside each other the
|
|
|
138
138
|
way `review-pr` once posted, before that skill's own guard existed. It is
|
|
139
139
|
also why this verb renders the whole comment body rather than handing each
|
|
140
140
|
skill a record to format on its own: a fix to the table shape or the
|
|
141
|
-
|
|
141
|
+
details wrapper lands once, not twice.
|
|
142
142
|
|
|
143
143
|
## The preview line
|
|
144
144
|
|
|
@@ -232,7 +232,16 @@ render needs, so it never refuses `no-base`. The orchestrator's draft lift is
|
|
|
232
232
|
the caller, and lifts only on `settled`, so a refusal holds it the same as
|
|
233
233
|
`owed` does.
|
|
234
234
|
|
|
235
|
-
##
|
|
235
|
+
## When the comment opens
|
|
236
|
+
|
|
237
|
+
The comment opens every state while it carries six images or fewer, counting one
|
|
238
|
+
per row for the head plus one per row that is not new, and closes every state
|
|
239
|
+
past that, so the whole comment is open or closed together. A line under
|
|
240
|
+
`## Evidence` names the compared base and head as short shas, which tells a
|
|
241
|
+
reader whether the images match the latest push. The base is the merge base the
|
|
242
|
+
compare endpoint returns, not trunk's tip.
|
|
243
|
+
|
|
244
|
+
## What the comment still leaves to GitHub
|
|
236
245
|
|
|
237
246
|
GitHub already draws its own before-and-after comparison on the Files Changed
|
|
238
247
|
tab for any tracked image that changed. This comment does not make that view
|
package/docs/agents/pr-reads.md
CHANGED
|
@@ -18,7 +18,7 @@ canon pr review-state 1341 --json
|
|
|
18
18
|
|
|
19
19
|
## The pull request object is not the authority for a head
|
|
20
20
|
|
|
21
|
-
`
|
|
21
|
+
The pull request's head sha, `head.sha` on the REST pull read and `headRefOid` in `gh pr view`, is a field on the pull request object. That object trails the branch ref by up to a minute after a push and carries nothing saying how far behind it is, so a session that keys a read on it is describing whichever commit GitHub last folded into the object.
|
|
22
22
|
|
|
23
23
|
Two failures on 2026-09-01 came off that one field. A reviewing session posted a finding calling a pushed commit unpushed. A worker fired a green claim and retracted it on its own thread minutes later. Neither session did anything wrong with the value it was handed. The value was stale and said so nowhere.
|
|
24
24
|
|
|
@@ -74,7 +74,7 @@ Both empty cases report `pending` instead: a tip carrying no run yet, and a list
|
|
|
74
74
|
|
|
75
75
|
The verb keeps the newest run per check name rather than rolling every matched run into the state. A workflow that fires twice on one commit used to leave its first, stale run beside the rerun, where a failing one could outvote a passing rerun. Grouping the matched set by name and keeping the highest `id` per group removes that stale run before the rollup runs. `collapsed` on the record counts what the fold discards, so a caller reading it against `matched` sees the dedupe directly, instead of reading a `matched` above the check count as the verb disagreeing with `gh pr checks`.
|
|
76
76
|
|
|
77
|
-
A conflicted branch produces no `pull_request` check runs rather than a failing one. GitHub builds no merge ref for it, so no `pull_request` workflow starts and a repository running only that trigger leaves the listing empty, which reads as `pending` and never leaves it. A workflow triggered by a push to the branch still runs on the tip, so `matched` rises above zero, `conflicted` stays false, and the wait ends on those runs rather than on the reading. `
|
|
77
|
+
A conflicted branch produces no `pull_request` check runs rather than a failing one. GitHub builds no merge ref for it, so no `pull_request` workflow starts and a repository running only that trigger leaves the listing empty, which reads as `pending` and never leaves it. A workflow triggered by a push to the branch still runs on the tip, so `matched` rises above zero, `conflicted` stays false, and the wait ends on those runs rather than on the reading. The pull request's `mergeable_state` is the field that separates the two. The verb raises it to upper case, matching the GraphQL `mergeStateStatus` it replaced, and the record carries `conflicted: true` and `mergeState` when it reads `DIRTY` with no run belonging to the tip. A `DIRTY` reading beside runs on the tip leaves the state as those runs say, since a conflict arising after they completed does not unsay them. `UNKNOWN` is transient while GitHub computes the merge state, right after a push, so it reads as not conflicted and costs one more poll. A binary predating the field keeps answering `pending`.
|
|
78
78
|
|
|
79
79
|
A listing carrying even one foreign run reports `pending` whatever the matching half says. A set that describes another commit says nothing about this one, so answering off the rows that happen to match would put a verdict on a set already known to be incomplete.
|
|
80
80
|
|
|
@@ -90,6 +90,7 @@ Each refusal names a different repair:
|
|
|
90
90
|
| -------------------- | ------------------------------------------------------------------------------------------ |
|
|
91
91
|
| `gh-missing` | `gh` is not on the path, so no pull request resolved |
|
|
92
92
|
| `gh-failed` | `gh` could not answer for this branch, so name a number instead |
|
|
93
|
+
| `ambiguous-pull` | Two open pull requests share the branch against different bases, so name a number |
|
|
93
94
|
| `no-branch` | The pull request carries no head branch name, so no ref could be read |
|
|
94
95
|
| `unresolvable-ref` | The remote read failed, which is not the same answer as an absent branch |
|
|
95
96
|
| `no-remote-branch` | The remote carries no branch by that name, so there is no tip to compare against |
|
|
@@ -105,6 +106,6 @@ One remote round trip per call, sampled here at 0.41s, 0.55s, and 0.67s on 2026-
|
|
|
105
106
|
|
|
106
107
|
One head-sensitive read is left on the object deliberately. `canon targets pulls` reads `statusCheckRollup` for every open pull request across every target, where resolving a tip per row would cost one remote read per pull request across a dozen projects, against a surface that reports a listing rather than gating a push.
|
|
107
108
|
|
|
108
|
-
The orchestrator poll spends that same read per open pull request and repeats it on a three-minute timer, which makes it the heaviest caller here rather than an exception to the paragraph above. Six open pull requests is around 120 remote reads an hour. It
|
|
109
|
+
The orchestrator poll spends that same read per open pull request and repeats it on a three-minute timer, which makes it the heaviest caller here rather than an exception to the paragraph above. Six open pull requests is around 120 remote reads an hour. It reads over REST alone, one reviews read and one issue-comments read per pull request, plus a pull read only when `canon pr head` returns no tip. It spends a further read per pull request per tick besides, since `canon pr review-state` makes its own REST reviews read beside the payload the poll already fetched. That one is an API round trip rather than a remote ref read, and it buys a coverage test that answers about what a session read. What separates the two cases is what each reading decides rather than what it costs. The poll's head fires the review trigger, so a stale one sends a pass at a commit nobody read or withholds one that is owed. The listing decides nothing, so the same spend buys a fresher column in a report and no correctness at all.
|
|
109
110
|
|
|
110
|
-
`canon pr key-changes` also stays on the object, for a different reason. It reads the body
|
|
111
|
+
`canon pr key-changes` also stays on the object, for a different reason. It reads the body and the head off one pull read, so the two describe one commit. That is a consistency requirement rather than a freshness one, and keying its head elsewhere would break it. The file list comes off a second read, since only GraphQL returns it beside the body and a cloud session's proxy refuses GraphQL.
|
package/docs/target/projects.md
CHANGED
|
@@ -73,14 +73,14 @@ Scaffold installs tooling and seeds. It does not fill the planning docs or the d
|
|
|
73
73
|
|
|
74
74
|
1. Fill `canon/REQUIREMENTS.md` and `canon/ARCHITECTURE.md`. The seed provides the files, the scope and decisions are yours to write. Each seed states its own caps, 12 decisions of at most 150 words and 6 risk bullets for the architecture record and 600 words for the requirements, and `canon context audit` gates on them. Edit a number in the record to loosen it.
|
|
75
75
|
2. For a UI project, invoke `canon:design-extract` to draft `canon/DESIGN.md`. With no UI code yet it takes the greenfield path and proposes tokens from the requirements and a `## Personality` section. Skip for non-UI projects.
|
|
76
|
-
3. Optionally invoke `canon:draft-
|
|
76
|
+
3. Optionally invoke `canon:draft-figure` naming an architecture view, such as system context or components, and the document it belongs in. It draws the view from the architecture and the requirements and renders it to verify the layout, which downloads the Mermaid CLI on first use and takes about 15 seconds.
|
|
77
77
|
4. Start the feature loop. See [AI workflow](../workflow/ai-workflow.md) for the per-feature sequence.
|
|
78
78
|
|
|
79
|
-
A machine without a renderer still gets the
|
|
79
|
+
A machine without a renderer still gets the figure and is told which check was skipped.
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
Nothing watches a figure once it is drawn. Run `canon:draft-figure` again when the code a view is drawn from moves.
|
|
82
82
|
|
|
83
|
-
`canon/ARCHITECTURE.md`
|
|
83
|
+
`canon/ARCHITECTURE.md` is watched where a figure is not. `canon:context-fold` anchors a decision it amends to the paths that decision cites, and reports an anchored decision whose cited path the branch touched.
|
|
84
84
|
|
|
85
85
|
### Stack decision
|
|
86
86
|
|
|
@@ -26,7 +26,6 @@ canon/
|
|
|
26
26
|
└── rules/ ← path-scoped governance rules, written by canon gov install
|
|
27
27
|
|
|
28
28
|
.canon/
|
|
29
|
-
├── diagrams/ ← one Mermaid entry per diagram kind with a generated index.md, redrawn on demand
|
|
30
29
|
├── tasks/ ← one file per task with a generated index.md, local scratch
|
|
31
30
|
├── plans/ ← one plan per feature, archived inside itself once it ships
|
|
32
31
|
├── memory/ ← durable session facts no context entry owns
|
|
@@ -6,7 +6,7 @@ category: Workflow
|
|
|
6
6
|
|
|
7
7
|
# Skill map
|
|
8
8
|
|
|
9
|
-
Groups run in the order a project meets them
|
|
9
|
+
Groups run in the order a project meets them. They reconcile the scenarios in [AI workflow](ai-workflow.md) with the lifecycle [target projects](../target/projects.md) describes, so every moment either one names has a group. Each row says when to reach for a skill, and its description says what it does.
|
|
10
10
|
|
|
11
11
|
This page is the corpus the coverage claim is measured against: every name `canon claude skills list --names` reports takes exactly one row here. A skill serving two moments sits at the earlier one, and a mention on any other page is prose rather than routing. The landing page's skills field renders from this page, so its build refuses a skill with no row and a row naming no skill.
|
|
12
12
|
|
|
@@ -18,7 +18,6 @@ This page is the corpus the coverage claim is measured against: every name `cano
|
|
|
18
18
|
| `canon:canon-operator` | On a project that already exists, to read what it carries before an install is picked |
|
|
19
19
|
| `canon:sketch-design` | Before `design-extract`'s greenfield path, to trace a design direction from reference images or URLs |
|
|
20
20
|
| `canon:design-extract` | Before the first UI feature, to draft `canon/DESIGN.md` |
|
|
21
|
-
| `canon:draft-diagram` | Once the architecture is written, to draft per-kind entries under `.canon/diagrams/` |
|
|
22
21
|
| `canon:deploy-app` | Once a project is ready to publish, to set up its Cloudflare or Vercel deploy and stop for token and domain |
|
|
23
22
|
| `canon:repo-metadata` | When the GitHub About text, homepage, or topics may have drifted, to reconcile them against the README |
|
|
24
23
|
|
|
@@ -32,6 +31,7 @@ This page is the corpus the coverage claim is measured against: every name `cano
|
|
|
32
31
|
| `canon:plan-groundwork` | When the state is unmeasured and more than one approach is live |
|
|
33
32
|
| `canon:decision-escalate` | When open decisions turn on your preference and want batching into one set |
|
|
34
33
|
| `canon:draft-and-pick` | When the call is taste and wants several candidates rendered side by side |
|
|
34
|
+
| `canon:canvas` | When a direction should be drawn as frames the operator can see, select, and edit |
|
|
35
35
|
| `canon:task-board` | When a decided item needs a file on the board, or a shipped one needs archiving |
|
|
36
36
|
| `canon:plan-feature` | When the approach is settled and the next step is a plan |
|
|
37
37
|
| `canon:codebase-layout` | When a plan or change adds a file and you need to decide which folder holds it |
|
|
@@ -125,7 +125,7 @@ This page is the corpus the coverage claim is measured against: every name `cano
|
|
|
125
125
|
| `canon:create-standard` | For a new authoring convention |
|
|
126
126
|
| `canon:draft-doc` | For a brand-new `docs/` page, context entry, wireframe surface, wiki reference page, or `README.md`, drafted against the standard for its kind |
|
|
127
127
|
| `canon:draft-ready` | For finished files a worker should copy, written as a ready folder with its overview, thin plan, and task |
|
|
128
|
-
| `canon:draft-figure` | For a hand-drawn figure inside an existing doc, drafted
|
|
128
|
+
| `canon:draft-figure` | For a hand-drawn figure or an architecture view inside an existing doc, drafted in Mermaid or freehand SVG |
|
|
129
129
|
| `canon:bash-cli-script` | For a small non-interactive shell wrapper, stopping at 100 lines in favor of TypeScript on Bun |
|
|
130
130
|
| `canon:ci-workflow` | For a GitHub Actions workflow file |
|
|
131
131
|
| `canon:draft-slides` | For a deck, drafted as `.claude/SLIDES.md` and rendered to PowerPoint |
|
|
@@ -41,6 +41,7 @@ A cell no source anchors ends in `? verify`, and the preview shows that marker b
|
|
|
41
41
|
- `canon:ux-audit` for UX gap detection on existing surfaces
|
|
42
42
|
- `canon:ux-measure` for what a running surface costs to paint, read against published thresholds
|
|
43
43
|
- `canon:draft-and-pick` for a call settled by looking, drafting several candidates onto one page and taking your pick
|
|
44
|
+
- `canon:canvas` for a direction worked out over several turns, drawn as HTML frames you drag, select, and restyle in the browser while the session reads your changes back. Only the pick moves into `canon/DESIGN.md`, since the canvas folder is gitignored
|
|
44
45
|
- `canon:ux-walkthrough` for a multi-finding inspection pass over a running app with the operator, drafting arms from the app's own markup and recording each pick for a builder
|
|
45
46
|
- `canon:draft-identity` to draft a project's logo mark and compose it into an icon sequence and a social card, through `draft-and-pick`'s own render-and-pick loop. On an Astro project holding the card route scaffold, the card lands as a route the project keeps and is captured through a running server, so it reads the project's real stylesheet rather than typed copies of every color. Everywhere else it ships as a PNG and the run says so.
|
|
46
47
|
- Anthropic's `frontend-design` plugin optional for light visual steering
|
package/governance/renames.toml
CHANGED
|
@@ -38,13 +38,11 @@
|
|
|
38
38
|
"557-intake" = "657-intake"
|
|
39
39
|
"558-plan" = "658-plan"
|
|
40
40
|
"559-memory" = "659-memory"
|
|
41
|
-
"560-diagrams" = "660-diagrams"
|
|
42
41
|
"561-teach" = "661-teach"
|
|
43
42
|
"562-session" = "662-session"
|
|
44
43
|
"563-ready" = "663-ready"
|
|
45
44
|
"500-prose" = "800-prose"
|
|
46
45
|
"501-markdown" = "801-markdown"
|
|
47
|
-
"502-mermaid" = "802-mermaid"
|
|
48
46
|
"580-readme" = "880-readme"
|
|
49
47
|
"591-standard-authoring" = "891-standard-authoring"
|
|
50
48
|
"065-spelling" = "765-spelling"
|
|
@@ -61,13 +59,11 @@
|
|
|
61
59
|
"656-groundwork" = "groundwork"
|
|
62
60
|
"657-intake" = "intake"
|
|
63
61
|
"659-memory" = "memory"
|
|
64
|
-
"660-diagrams" = "diagrams"
|
|
65
62
|
"661-teach" = "teach"
|
|
66
63
|
"662-session" = "session"
|
|
67
64
|
"663-ready" = "ready"
|
|
68
65
|
"570-skill" = "skill"
|
|
69
66
|
"590-rule-authoring" = "rule"
|
|
70
67
|
"801-markdown" = "markdown"
|
|
71
|
-
"802-mermaid" = "mermaid"
|
|
72
68
|
"880-readme" = "readme"
|
|
73
69
|
"891-standard-authoring" = "standard"
|
|
@@ -13,3 +13,4 @@ paths:
|
|
|
13
13
|
- Read it before a substantial markdown edit. Do not work the banned characters from memory.
|
|
14
14
|
- Run `canon markdown audit <path>` after the edit, and rewrite the sentence carrying a hit rather than swapping the token for a near-synonym.
|
|
15
15
|
- Voice, rhythm, and sentence construction are a separate topic. `800-prose` routes them.
|
|
16
|
+
- Load the `canon:draft-figure` skill before drafting or revising a Mermaid fence or a figure, and report it rather than proceeding silently when it does not resolve.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erclx/canon",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.25.0",
|
|
5
5
|
"description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -45,7 +45,6 @@
|
|
|
45
45
|
"web:favicon": "bun scripts/core/regen-web-favicon.ts",
|
|
46
46
|
"web:previews": "bun scripts/core/regen-web-previews.ts",
|
|
47
47
|
"web:build": "bun run web:tokens && bun run web:favicon && bun run web:previews && cd web && astro check && astro build",
|
|
48
|
-
"web:gallery": "cd web && astro build --config gallery.config.mjs",
|
|
49
48
|
"web:card": "cd web && astro dev --config card.config.mjs",
|
|
50
49
|
"web:card:check": "PROJECT_ROOT=web bash tooling/astro/configs/scripts/check-card-exclusion.sh",
|
|
51
50
|
"web:preview": "cd web && astro preview",
|
|
@@ -101,7 +101,7 @@ log_step "Assert scaffold"
|
|
|
101
101
|
# scaffold reads a standard through `canon standards <name>`, resolving against
|
|
102
102
|
# the toolkit rather than a copy this gate could assert on. The two
|
|
103
103
|
# rule paths stand for the `claude` and `canon` groups `base` takes whole.
|
|
104
|
-
for path in "CLAUDE.md" ".claude/wiki/index.md" ".claude" "canon/context/index.md" "canon/wireframes/index.md"
|
|
104
|
+
for path in "CLAUDE.md" ".claude/wiki/index.md" ".claude" "canon/context/index.md" "canon/wireframes/index.md" \
|
|
105
105
|
".prettierrc" ".editorconfig" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.sh" \
|
|
106
106
|
".claude/rules/canon/claude/565-behavior.md" ".claude/rules/canon/canon/604-scratch.md"; do
|
|
107
107
|
if [ ! -e "$TARGET_DIR/$path" ]; then
|
package/src/audits/catalog.ts
CHANGED
|
@@ -587,8 +587,8 @@ export const AUDITS: readonly AuditSpec[] = [
|
|
|
587
587
|
corpus: 'tracked',
|
|
588
588
|
// The one reason this verb refuses for that is an absence rather than a
|
|
589
589
|
// break, on the same test the reach check and the skill audit take: no
|
|
590
|
-
// target adopts `canon/context/`, `.canon/diagrams/`,
|
|
591
|
-
// `canon/wireframes/` all at once, so without the allowance every such
|
|
590
|
+
// target adopts `canon/context/`, an older install's `.canon/diagrams/`,
|
|
591
|
+
// and `canon/wireframes/` all at once, so without the allowance every such
|
|
592
592
|
// project reports the verb unmeasured on every run and never changes.
|
|
593
593
|
absentReasons: ['no-folders'] satisfies ContextAuditRefusal[],
|
|
594
594
|
counts: contextCounts,
|