@erclx/canon 5.25.0 → 5.27.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 +4 -3
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +2 -0
- package/claude/skills/auto-ship/SKILL.md +3 -11
- package/claude/skills/auto-ship/references/review-findings.md +20 -0
- package/claude/skills/backlog-triage/SKILL.md +2 -0
- package/claude/skills/bash-cli-script/SKILL.md +2 -0
- package/claude/skills/build-in-slices/SKILL.md +2 -0
- package/claude/skills/canon-cli/SKILL.md +2 -0
- package/claude/skills/canon-feedback/SKILL.md +2 -0
- package/claude/skills/canon-feedback-triage/SKILL.md +2 -0
- package/claude/skills/canon-operator/SKILL.md +2 -0
- package/claude/skills/canon-rollout/SKILL.md +3 -11
- package/claude/skills/canon-rollout/references/failure-recovery.md +20 -0
- package/claude/skills/canvas/SKILL.md +14 -1
- package/claude/skills/ci-workflow/SKILL.md +2 -0
- package/claude/skills/code-craft/SKILL.md +2 -0
- package/claude/skills/codebase-layout/SKILL.md +2 -0
- package/claude/skills/context-fold/REQUIREMENT.md +6 -2
- package/claude/skills/context-fold/SKILL.md +9 -21
- package/claude/skills/context-fold/references/anchor-sweep.md +2 -2
- package/claude/skills/context-fold/references/completion-report.md +26 -0
- package/claude/skills/create-rule/SKILL.md +2 -0
- package/claude/skills/create-skill/SKILL.md +2 -0
- package/claude/skills/create-standard/SKILL.md +2 -0
- package/claude/skills/decision-escalate/SKILL.md +2 -0
- package/claude/skills/deploy-app/SKILL.md +2 -0
- package/claude/skills/deprecation-migration/SKILL.md +2 -0
- package/claude/skills/design-extract/SKILL.md +2 -0
- package/claude/skills/design-taste/REQUIREMENT.md +1 -1
- package/claude/skills/design-taste/SKILL.md +6 -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/docs-sync/SKILL.md +2 -0
- package/claude/skills/document-health/REQUIREMENT.md +2 -0
- package/claude/skills/document-health/SKILL.md +23 -0
- package/claude/skills/document-health/references/axes.md +12 -0
- package/claude/skills/draft-and-pick/SKILL.md +3 -1
- package/claude/skills/draft-doc/SKILL.md +2 -0
- package/claude/skills/draft-doc/references/wiki.md +1 -1
- package/claude/skills/draft-figure/SKILL.md +2 -0
- package/claude/skills/draft-identity/SKILL.md +3 -1
- package/claude/skills/draft-ready/SKILL.md +2 -0
- package/claude/skills/draft-screencast/SKILL.md +11 -7
- package/claude/skills/draft-slides/REQUIREMENT.md +17 -12
- package/claude/skills/draft-slides/SKILL.md +33 -20
- package/claude/skills/git-branch/SKILL.md +2 -0
- package/claude/skills/git-commit/SKILL.md +2 -0
- package/claude/skills/git-followup/SKILL.md +2 -0
- package/claude/skills/git-issue/SKILL.md +2 -0
- package/claude/skills/git-issue/references/issue.md +10 -0
- package/claude/skills/git-pr/SKILL.md +2 -0
- package/claude/skills/git-pr/references/evidence.md +14 -6
- package/claude/skills/git-pr/references/labels.md +12 -0
- package/claude/skills/git-ship/SKILL.md +2 -0
- package/claude/skills/git-split/SKILL.md +21 -8
- package/claude/skills/git-stage/SKILL.md +2 -0
- package/claude/skills/git-worktree/SKILL.md +2 -0
- package/claude/skills/index-lookup/SKILL.md +2 -0
- package/claude/skills/markdown-propose/SKILL.md +2 -0
- package/claude/skills/markdown-propose/references/format.md +9 -0
- package/claude/skills/memory-capture/SKILL.md +2 -0
- package/claude/skills/memory-review/SKILL.md +2 -0
- package/claude/skills/memory-review/references/later-phases.md +7 -0
- package/claude/skills/plan-feature/SKILL.md +2 -0
- package/claude/skills/plan-groundwork/SKILL.md +2 -0
- package/claude/skills/plan-intake/SKILL.md +2 -0
- package/claude/skills/plan-intake-answer/SKILL.md +2 -0
- package/claude/skills/project-commands/SKILL.md +2 -0
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +2 -0
- package/claude/skills/repo-metadata/SKILL.md +2 -0
- package/claude/skills/restate-plainly/SKILL.md +2 -0
- package/claude/skills/review-address/SKILL.md +3 -7
- package/claude/skills/review-address/references/post-review-findings.md +16 -0
- package/claude/skills/review-branch/SKILL.md +2 -0
- package/claude/skills/review-craft/SKILL.md +2 -0
- package/claude/skills/review-craft/references/ui.md +2 -2
- package/claude/skills/review-pr/SKILL.md +4 -8
- package/claude/skills/review-pr/references/body-variants.md +52 -0
- package/claude/skills/review-pr/references/key-changes.md +16 -0
- package/claude/skills/review-pr/references/post.md +15 -43
- package/claude/skills/review-ui/SKILL.md +3 -1
- package/claude/skills/review-ui/references/post.md +4 -2
- package/claude/skills/role-orchestrator/SKILL.md +5 -14
- 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/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +23 -0
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +5 -33
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +1 -21
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +38 -0
- package/claude/skills/role-orchestrator/references/orchestrator-watch.md +26 -0
- package/claude/skills/role-planner/SKILL.md +2 -0
- package/claude/skills/role-reviewer/REQUIREMENT.md +1 -1
- package/claude/skills/role-reviewer/SKILL.md +2 -0
- package/claude/skills/role-worker/SKILL.md +2 -0
- package/claude/skills/search-craft/REQUIREMENT.md +1 -1
- package/claude/skills/search-craft/SKILL.md +5 -1
- package/claude/skills/search-craft/references/adopted.md +30 -0
- package/claude/skills/seed-sync/SKILL.md +2 -0
- package/claude/skills/session-compact/SKILL.md +2 -0
- package/claude/skills/session-map/SKILL.md +2 -0
- package/claude/skills/session-relay/SKILL.md +2 -0
- package/claude/skills/session-resume/SKILL.md +2 -0
- package/claude/skills/session-worktree/SKILL.md +3 -11
- package/claude/skills/session-worktree/references/install-command.md +20 -0
- package/claude/skills/sketch-design/SKILL.md +2 -0
- package/claude/skills/systematic-debugging/SKILL.md +2 -0
- package/claude/skills/target-check/SKILL.md +2 -0
- package/claude/skills/target-setup/SKILL.md +2 -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/task-board/SKILL.md +2 -0
- package/claude/skills/teach-workspace/SKILL.md +5 -15
- package/claude/skills/teach-workspace/references/lesson-build.md +75 -0
- package/claude/skills/teach-workspace/references/lesson-craft.md +13 -69
- package/claude/skills/teach-workspace/references/revisit.md +22 -0
- package/claude/skills/test-craft/SKILL.md +2 -0
- package/claude/skills/test-first/SKILL.md +4 -0
- package/claude/skills/test-first/references/adopted.md +36 -0
- package/claude/skills/ui-checklist/SKILL.md +2 -0
- package/claude/skills/ux-audit/SKILL.md +2 -0
- package/claude/skills/ux-measure/SKILL.md +2 -0
- package/claude/skills/ux-walkthrough/SKILL.md +2 -0
- package/claude/skills/video-craft/SKILL.md +2 -0
- package/claude/skills/write-human/SKILL.md +3 -1
- package/claude/skills/write-human/references/machine-tells.md +13 -0
- package/claude/skills/youtube-transcripts/SKILL.md +2 -0
- package/docs/agents/canvas.md +24 -6
- package/docs/agents/capture.md +6 -6
- package/docs/agents/commands.md +5 -5
- package/docs/agents/index.md +5 -5
- package/docs/agents/install-and-sync.md +7 -0
- package/docs/agents/key-changes.md +1 -1
- package/docs/agents/pr-evidence.md +38 -15
- package/docs/agents/pr-local.md +19 -13
- package/docs/agents/pr-preview.md +44 -21
- package/docs/agents/records-stale.md +22 -9
- package/docs/agents/records.md +1 -1
- package/docs/agents/sandbox.md +29 -5
- package/docs/agents/scripting.md +8 -1
- package/docs/agents/skills-audit.md +11 -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/operating-model.md +5 -6
- package/docs/workflow/parallel-features.md +23 -2
- package/docs/workflow/skill-map-on-request.md +42 -0
- package/docs/workflow/skill-map.md +3 -34
- package/docs/workflow/zshrc-aliases.md +1 -1
- package/package.json +1 -1
- package/scripts/core/regen-hero.ts +1 -1
- package/scripts/lib/sandbox-git.sh +1 -9
- package/scripts/lib/sandbox-path.sh +6 -162
- package/scripts/sandbox-hook.sh +99 -0
- package/src/audits/run.ts +1 -1
- package/src/canvas/address.ts +12 -3
- package/src/canvas/capture.ts +1 -9
- package/src/canvas/client/inspector/align-grid.tsx +162 -0
- package/src/canvas/client/inspector/color-field.tsx +398 -0
- package/src/canvas/client/inspector/color-inputs.tsx +139 -0
- package/src/canvas/client/inspector/color-picker.tsx +668 -0
- package/src/canvas/client/inspector/color-space.ts +240 -0
- package/src/canvas/client/inspector/field.tsx +5 -1
- package/src/canvas/client/inspector/fields.css +547 -17
- package/src/canvas/client/inspector/size-field.tsx +69 -0
- package/src/canvas/client/inspector/values.ts +166 -1
- package/src/canvas/client/inspector.tsx +236 -73
- package/src/canvas/client/selection.tsx +197 -0
- package/src/canvas/client/shell.css +104 -12
- package/src/canvas/client/state.ts +69 -9
- package/src/canvas/client/surface.tsx +147 -22
- package/src/canvas/content.ts +50 -1
- package/src/canvas/edit.ts +37 -4
- package/src/canvas/editing.ts +203 -0
- package/src/canvas/global.d.ts +15 -0
- package/src/canvas/server.ts +149 -12
- package/src/canvas/tokens.ts +59 -17
- package/src/capture/render.ts +45 -7
- package/src/capture/sources.ts +43 -0
- package/src/census/count.ts +2 -2
- package/src/claude/cases/workflow.ts +5 -0
- package/src/claude/seeds.ts +2 -2
- package/src/claude/skills-audit.ts +96 -14
- package/src/claude/skills-drift.ts +1 -1
- package/src/claude/skills-families.ts +36 -0
- package/src/claude/skills-list.ts +76 -15
- package/src/commands/audits.ts +2 -2
- package/src/commands/canvas.ts +179 -2
- package/src/commands/claude.ts +94 -11
- package/src/commands/design.ts +142 -2
- package/src/commands/feedback.ts +3 -3
- package/src/commands/gov.ts +1 -1
- package/src/commands/hooks.ts +1 -1
- package/src/commands/indexes.ts +1 -1
- package/src/commands/init.ts +1 -1
- package/src/commands/intake.ts +1 -1
- package/src/commands/migrate.ts +1 -1
- package/src/commands/pr.ts +105 -58
- package/src/commands/records.ts +89 -7
- package/src/commands/repo.ts +1 -1
- package/src/commands/sandbox.ts +103 -11
- package/src/commands/sessions.ts +1 -1
- package/src/commands/slides.ts +31 -77
- package/src/commands/sync.ts +1 -1
- package/src/commands/tasks.ts +2 -2
- package/src/commands/teach.ts +1 -1
- package/src/commands/transcripts.ts +1 -1
- package/src/commands/worktrees.ts +1 -1
- package/src/comments/scan.ts +1 -1
- package/src/comments/trend.ts +1 -1
- package/src/context/audit.ts +1 -1
- package/src/context/citations.ts +1 -1
- package/src/context/classify/extract.ts +2 -2
- package/src/design/project-fonts.ts +392 -0
- package/src/design/tokens.ts +2 -18
- package/src/docs/read.ts +1 -1
- package/src/{github.ts → feedback/github.ts} +2 -2
- package/src/{client-commands.ts → gate/client-commands.ts} +1 -1
- package/src/gate/measures.ts +53 -13
- package/src/gate/sequencer.ts +1 -1
- package/src/gate/stages.ts +9 -0
- package/src/{git-files.ts → git/files.ts} +2 -2
- package/src/{git-ignore.ts → git/ignore.ts} +1 -1
- package/src/{worktree.ts → git/worktree.ts} +1 -1
- package/src/gov/citations.ts +2 -2
- package/src/gov/install.ts +1 -1
- package/src/gov/payload.ts +1 -1
- package/src/gov/superseded.ts +3 -3
- package/src/gov/test-order.ts +2 -2
- package/src/help.ts +1 -1
- package/src/hooks/post-merge.ts +1 -1
- package/src/indexes/walk.ts +1 -1
- package/src/labels/audit.ts +1 -1
- package/src/markdown/ceiling.ts +1 -1
- package/src/markdown/files.ts +1 -1
- package/src/migrate/apply.ts +1 -1
- package/src/pr/bijection.ts +1 -1
- package/src/pr/evidence.ts +96 -43
- package/src/pr/local.ts +16 -10
- package/src/pr/preview.ts +78 -2
- package/src/record-root.ts +1 -0
- package/src/records/backup.ts +2 -1
- 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/headless/dispatch.ts +264 -0
- package/src/sandbox/headless/run.ts +653 -0
- package/src/sandbox/headless/watch.ts +145 -0
- package/src/sandbox/hooks.ts +128 -0
- package/src/sandbox/provision.ts +607 -0
- package/src/sandbox/tree.ts +99 -4
- package/src/secrets/marker.ts +2 -2
- package/src/secrets/scan.ts +2 -2
- package/src/sessions/claim.ts +1 -1
- package/src/sessions/resolve.ts +1 -1
- package/src/sessions/transfer/bundle.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/slides/package/fonts.ts +6 -2
- package/src/standards/audit.ts +2 -2
- package/src/standards/read.ts +1 -1
- package/src/sync/check.ts +2 -2
- package/src/sync/engine.ts +2 -2
- package/src/sync/git.ts +1 -1
- package/src/sync/history.ts +1 -1
- package/src/sync/reverse.ts +1 -1
- package/src/sync/seeds-report.ts +1 -1
- package/src/sync/target.ts +1 -1
- package/src/sync/workflow.ts +1 -1
- package/src/targets/pulls.ts +2 -2
- package/src/targets/sweep.ts +2 -2
- package/src/tasks/answers.ts +1 -1
- package/src/tasks/archive.ts +1 -1
- package/src/tasks/reach.ts +1 -1
- package/src/tasks/trunk.ts +1 -1
- package/src/teach/nav.ts +1 -1
- package/src/tooling/inject.ts +2 -2
- package/src/tooling/subfolder.ts +1 -1
- package/src/web/readme-citations.ts +2 -2
- package/src/worktrees/bare-flag.ts +1 -1
- package/src/worktrees/reclaim.ts +2 -2
- package/src/worktrees/remove.ts +1 -1
- package/standards/architecture.md +1 -0
- package/standards/canvas.md +3 -2
- package/standards/requirements.md +2 -0
- package/standards/skill-practice.md +2 -1
- package/standards/skill.md +2 -0
- package/standards/wiki.md +12 -3
- package/tooling/base/configs/.github/workflows/pr-local-preview.yml +2 -2
- package/scripts/lib/sandbox-dispatch.sh +0 -190
- 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/{git-base.ts → git/base.ts} +0 -0
- /package/src/{git-env.ts → git/env.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/{copy.ts → sync/copy.ts} +0 -0
- /package/src/{target.ts → targets/validate.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/commands/canvas.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
readPage,
|
|
13
13
|
readSelection,
|
|
14
14
|
renamePage,
|
|
15
|
+
resizeFrame,
|
|
15
16
|
} from '@/canvas/content'
|
|
16
17
|
import { captureCanvas, captureComposite } from '@/canvas/capture'
|
|
17
18
|
import {
|
|
@@ -19,10 +20,22 @@ import {
|
|
|
19
20
|
editFrameAtIndex,
|
|
20
21
|
STYLE_PROPERTIES,
|
|
21
22
|
} from '@/canvas/edit'
|
|
23
|
+
import {
|
|
24
|
+
clearEditing,
|
|
25
|
+
EDITING_TTL_MS,
|
|
26
|
+
markEditing,
|
|
27
|
+
readEditing,
|
|
28
|
+
} from '@/canvas/editing'
|
|
22
29
|
import { CANVAS_PORT, startCanvas } from '@/canvas/server'
|
|
23
30
|
import { PROJECT_ROOT } from '@/project-root'
|
|
24
31
|
import { resolveFrameTokens } from '@/canvas/tokens'
|
|
25
32
|
import { displayPath, parsePort, waitForInterrupt } from '@/serve/report'
|
|
33
|
+
import {
|
|
34
|
+
callerIdentity,
|
|
35
|
+
type Located,
|
|
36
|
+
resolveSessions,
|
|
37
|
+
selfOf,
|
|
38
|
+
} from '@/sessions/resolve'
|
|
26
39
|
import {
|
|
27
40
|
intro,
|
|
28
41
|
logAdd,
|
|
@@ -33,7 +46,7 @@ import {
|
|
|
33
46
|
outro,
|
|
34
47
|
plural,
|
|
35
48
|
} from '@/ui'
|
|
36
|
-
import { mainWorktreeRoot } from '@/worktree'
|
|
49
|
+
import { mainWorktreeRoot } from '@/git/worktree'
|
|
37
50
|
|
|
38
51
|
const BANNER = 'canon canvas'
|
|
39
52
|
|
|
@@ -135,7 +148,7 @@ export function register(program: Command): void {
|
|
|
135
148
|
.command('canvas')
|
|
136
149
|
.helpOption('-h, --help', 'Show this help message')
|
|
137
150
|
.description(
|
|
138
|
-
'Local canvas of pages and HTML frames (serve, list, page, frame, selection, edit, capture)',
|
|
151
|
+
'Local canvas of pages and HTML frames (serve, list, page, frame, selection, edit, editing, capture)',
|
|
139
152
|
)
|
|
140
153
|
.addHelpText(
|
|
141
154
|
'after',
|
|
@@ -152,6 +165,7 @@ export function register(program: Command): void {
|
|
|
152
165
|
' canon canvas frame move drafts hero --x 200 --y 120',
|
|
153
166
|
' canon canvas selection --json',
|
|
154
167
|
" canon canvas edit drafts/hero --element 4 --set 'color=var(--color-accent)'",
|
|
168
|
+
' canon canvas editing drafts/hero',
|
|
155
169
|
' canon canvas capture drafts/hero',
|
|
156
170
|
' canon canvas list --json',
|
|
157
171
|
'',
|
|
@@ -341,6 +355,56 @@ export function register(program: Command): void {
|
|
|
341
355
|
},
|
|
342
356
|
)
|
|
343
357
|
|
|
358
|
+
withRoot(
|
|
359
|
+
frame
|
|
360
|
+
.command('resize')
|
|
361
|
+
.description('Resize a frame, and move it when given a position')
|
|
362
|
+
.argument('<page>', 'Page the frame is on')
|
|
363
|
+
.argument('<name>', 'Frame name')
|
|
364
|
+
.option('--width <px>', 'New width, defaulting to the frame width')
|
|
365
|
+
.option('--height <px>', 'New height, defaulting to the frame height')
|
|
366
|
+
.option('--x <px>', 'New x, defaulting to where the frame is')
|
|
367
|
+
.option('--y <px>', 'New y, defaulting to where the frame is'),
|
|
368
|
+
).action(
|
|
369
|
+
async (
|
|
370
|
+
pageName: string,
|
|
371
|
+
name: string,
|
|
372
|
+
opts: RootOptions & {
|
|
373
|
+
width?: string
|
|
374
|
+
height?: string
|
|
375
|
+
x?: string
|
|
376
|
+
y?: string
|
|
377
|
+
},
|
|
378
|
+
) => {
|
|
379
|
+
const resolved = await resolveRoot(opts)
|
|
380
|
+
if (!resolved.ok) {
|
|
381
|
+
process.exitCode = refuse(resolved, opts.json ?? false)
|
|
382
|
+
return
|
|
383
|
+
}
|
|
384
|
+
const { root } = resolved
|
|
385
|
+
const current = readPage(root, pageName)?.frames.find(
|
|
386
|
+
(candidate) => candidate.name === name,
|
|
387
|
+
)
|
|
388
|
+
const outcome = resizeFrame(root, pageName, name, {
|
|
389
|
+
x: parsePosition(opts.x, current?.x ?? 0),
|
|
390
|
+
y: parsePosition(opts.y, current?.y ?? 0),
|
|
391
|
+
width: parseSize(opts.width, current?.width ?? DEFAULT_FRAME.width),
|
|
392
|
+
height: parseSize(opts.height, current?.height ?? DEFAULT_FRAME.height),
|
|
393
|
+
})
|
|
394
|
+
if (!outcome.ok) {
|
|
395
|
+
process.exitCode = refuse(outcome, opts.json ?? false)
|
|
396
|
+
return
|
|
397
|
+
}
|
|
398
|
+
if (opts.json) writeJson(outcome)
|
|
399
|
+
intro(BANNER)
|
|
400
|
+
logAdd(`${outcome.page}/${outcome.file}`)
|
|
401
|
+
logInfo(
|
|
402
|
+
`${outcome.box.width} × ${outcome.box.height} at ${outcome.box.x}, ${outcome.box.y}`,
|
|
403
|
+
)
|
|
404
|
+
outro()
|
|
405
|
+
},
|
|
406
|
+
)
|
|
407
|
+
|
|
344
408
|
withRoot(
|
|
345
409
|
canvas
|
|
346
410
|
.command('selection')
|
|
@@ -487,6 +551,91 @@ export function register(program: Command): void {
|
|
|
487
551
|
},
|
|
488
552
|
)
|
|
489
553
|
|
|
554
|
+
withRoot(
|
|
555
|
+
canvas
|
|
556
|
+
.command('editing')
|
|
557
|
+
.description('Mark a frame as being edited, clear it, or list the marks')
|
|
558
|
+
.argument('[target]', '<page>/<frame>, or none to list the marks')
|
|
559
|
+
.option('--done', 'Clear the mark once the edits are written')
|
|
560
|
+
.option('--by <name>', 'The label the mark shows, over the session name'),
|
|
561
|
+
)
|
|
562
|
+
.addHelpText(
|
|
563
|
+
'after',
|
|
564
|
+
[
|
|
565
|
+
'',
|
|
566
|
+
'Mark a frame before writing it and clear it with --done after, so an',
|
|
567
|
+
`open canvas shows who is editing it. A mark lapses after ${EDITING_TTL_MS / 60_000} minutes`,
|
|
568
|
+
'unless marked again, so re-mark during a long edit. A mark gates no',
|
|
569
|
+
'write, and --done on a frame holding no mark succeeds.',
|
|
570
|
+
'',
|
|
571
|
+
].join('\n'),
|
|
572
|
+
)
|
|
573
|
+
.action(
|
|
574
|
+
async (
|
|
575
|
+
target: string | undefined,
|
|
576
|
+
opts: RootOptions & { done?: boolean; by?: string },
|
|
577
|
+
) => {
|
|
578
|
+
const emitJson = opts.json ?? false
|
|
579
|
+
const resolved = await resolveRoot(opts)
|
|
580
|
+
if (!resolved.ok) {
|
|
581
|
+
process.exitCode = refuse(resolved, emitJson)
|
|
582
|
+
return
|
|
583
|
+
}
|
|
584
|
+
const { root } = resolved
|
|
585
|
+
const now = new Date()
|
|
586
|
+
|
|
587
|
+
if (target !== undefined) {
|
|
588
|
+
const [pageName, frameName, ...rest] = target.split('/')
|
|
589
|
+
if (!pageName || !frameName || rest.length > 0) {
|
|
590
|
+
process.exitCode = refuse(
|
|
591
|
+
{
|
|
592
|
+
ok: false,
|
|
593
|
+
reason: 'invalid-name',
|
|
594
|
+
detail: `${target} is not <page>/<frame>`,
|
|
595
|
+
},
|
|
596
|
+
emitJson,
|
|
597
|
+
)
|
|
598
|
+
return
|
|
599
|
+
}
|
|
600
|
+
const outcome = opts.done
|
|
601
|
+
? clearEditing(root, pageName, frameName)
|
|
602
|
+
: markEditing(
|
|
603
|
+
root,
|
|
604
|
+
pageName,
|
|
605
|
+
frameName,
|
|
606
|
+
opts.by ?? (await sessionLabel()),
|
|
607
|
+
now,
|
|
608
|
+
)
|
|
609
|
+
if (!outcome.ok) {
|
|
610
|
+
process.exitCode = refuse(outcome, emitJson)
|
|
611
|
+
return
|
|
612
|
+
}
|
|
613
|
+
} else if (opts.done) {
|
|
614
|
+
process.exitCode = refuse(
|
|
615
|
+
{
|
|
616
|
+
ok: false,
|
|
617
|
+
reason: 'invalid-name',
|
|
618
|
+
detail: '--done needs the <page>/<frame> to clear',
|
|
619
|
+
},
|
|
620
|
+
emitJson,
|
|
621
|
+
)
|
|
622
|
+
return
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const marks = readEditing(root, now)
|
|
626
|
+
if (emitJson) writeJson({ ok: true, editing: marks })
|
|
627
|
+
intro(BANNER)
|
|
628
|
+
if (target !== undefined) {
|
|
629
|
+
logStep(`${target} ${opts.done ? 'cleared' : 'marked'}`)
|
|
630
|
+
}
|
|
631
|
+
if (marks.length === 0) logInfo('No frame is marked as being edited')
|
|
632
|
+
for (const mark of marks) {
|
|
633
|
+
logInfo(`${mark.page}/${mark.frame} ${mark.by} until ${mark.until}`)
|
|
634
|
+
}
|
|
635
|
+
outro()
|
|
636
|
+
},
|
|
637
|
+
)
|
|
638
|
+
|
|
490
639
|
withRoot(
|
|
491
640
|
canvas
|
|
492
641
|
.command('capture')
|
|
@@ -644,6 +793,29 @@ async function runComposite(
|
|
|
644
793
|
return 0
|
|
645
794
|
}
|
|
646
795
|
|
|
796
|
+
async function unlocated(): Promise<Located> {
|
|
797
|
+
return {
|
|
798
|
+
repository: null,
|
|
799
|
+
worktree: null,
|
|
800
|
+
branch: null,
|
|
801
|
+
unresolved: 'git-unavailable',
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* The caller's roster name, or a generic label when the environment names no
|
|
807
|
+
* session or the roster holds no row for it, as in a sandbox or a CI run.
|
|
808
|
+
*/
|
|
809
|
+
async function sessionLabel(): Promise<string> {
|
|
810
|
+
const identity = callerIdentity()
|
|
811
|
+
if (identity.sessionId === null && identity.pid === null) return 'a session'
|
|
812
|
+
/* The label needs the name alone, so skip the git probe each row's branch costs. */
|
|
813
|
+
const report = await resolveSessions({ locate: unlocated })
|
|
814
|
+
if (report.kind === 'absent') return 'a session'
|
|
815
|
+
const self = selfOf(report.sessions, identity)
|
|
816
|
+
return self.kind === 'self' ? self.session.name : 'a session'
|
|
817
|
+
}
|
|
818
|
+
|
|
647
819
|
/** NaN for a value that is not a number, which the content module refuses. */
|
|
648
820
|
function parsePosition(raw: string | undefined, fallback: number): number {
|
|
649
821
|
if (raw === undefined) return fallback
|
|
@@ -698,6 +870,11 @@ async function runServe(
|
|
|
698
870
|
if (tokens.source === 'none') logWarn(tokens.notice)
|
|
699
871
|
else if (tokens.source === 'installed') {
|
|
700
872
|
for (const file of tokens.files) logInfo(file)
|
|
873
|
+
for (const face of tokens.dropped ?? []) {
|
|
874
|
+
logWarn(
|
|
875
|
+
`${face.sheet}: dropped the face at ${face.file} (${face.reason})`,
|
|
876
|
+
)
|
|
877
|
+
}
|
|
701
878
|
} else logInfo('this toolkit’s own token module')
|
|
702
879
|
logStep('Stop')
|
|
703
880
|
logInfo('Ctrl-C')
|
package/src/commands/claude.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { join, resolve } from 'node:path'
|
|
|
5
5
|
import type { Command } from 'commander'
|
|
6
6
|
import { execa } from 'execa'
|
|
7
7
|
import { singleLine } from '@/commands/upgrade'
|
|
8
|
-
import { gitEnv } from '@/git
|
|
8
|
+
import { gitEnv } from '@/git/env'
|
|
9
9
|
import { claudeChain, pendingEntries, planGitignore } from '@/claude/gitignore'
|
|
10
10
|
import {
|
|
11
11
|
matchInstall,
|
|
@@ -24,8 +24,11 @@ import { listSeeds, readSeedContents } from '@/claude/seeds-list'
|
|
|
24
24
|
import {
|
|
25
25
|
auditExitCode,
|
|
26
26
|
auditSkills,
|
|
27
|
+
CONTENTS_SECTION,
|
|
28
|
+
CONTENTS_THRESHOLD,
|
|
27
29
|
CORPORA,
|
|
28
30
|
DESCRIPTION_LIMIT,
|
|
31
|
+
LEDGER_SKILLS,
|
|
29
32
|
PRACTICE_LEDGER,
|
|
30
33
|
PRACTICE_SECTIONS,
|
|
31
34
|
PRACTICE_SKILLS,
|
|
@@ -41,7 +44,12 @@ import {
|
|
|
41
44
|
scanRouting,
|
|
42
45
|
} from '@/claude/routing'
|
|
43
46
|
import { type DriftReport, readDrift } from '@/claude/skills-drift'
|
|
44
|
-
import {
|
|
47
|
+
import { familyKeys, SKILL_FAMILIES } from '@/claude/skills-families'
|
|
48
|
+
import {
|
|
49
|
+
type FamilyGrouping,
|
|
50
|
+
groupByFamily,
|
|
51
|
+
listSkills,
|
|
52
|
+
} from '@/claude/skills-list'
|
|
45
53
|
import {
|
|
46
54
|
type ReachRefusal,
|
|
47
55
|
type ReachReport,
|
|
@@ -61,12 +69,12 @@ import {
|
|
|
61
69
|
serializeSettings,
|
|
62
70
|
writeSettings,
|
|
63
71
|
} from '@/claude/settings'
|
|
64
|
-
import { copyPreservingMode } from '@/copy'
|
|
72
|
+
import { copyPreservingMode } from '@/sync/copy'
|
|
65
73
|
import { execScript } from '@/exec'
|
|
66
74
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/project-root'
|
|
67
75
|
import { recordDir } from '@/record-root'
|
|
68
76
|
import { SURFACE_ENTRIES, surfaceDir } from '@/surface-root'
|
|
69
|
-
import { isDirectory, resolveTarget } from '@/
|
|
77
|
+
import { isDirectory, resolveTarget } from '@/targets/validate'
|
|
70
78
|
import { injectGitignore, pruneGitignore } from '@/tooling/inject'
|
|
71
79
|
import {
|
|
72
80
|
frameError,
|
|
@@ -93,6 +101,7 @@ interface SeedsListOptions {
|
|
|
93
101
|
interface SkillsListOptions {
|
|
94
102
|
readonly json?: boolean
|
|
95
103
|
readonly names?: boolean
|
|
104
|
+
readonly byFamily?: boolean
|
|
96
105
|
}
|
|
97
106
|
|
|
98
107
|
interface SkillsAuditOptions {
|
|
@@ -356,8 +365,12 @@ export function register(program: Command): void {
|
|
|
356
365
|
.command('list')
|
|
357
366
|
.description('List the plugin skills shipped under claude/skills/')
|
|
358
367
|
.helpOption('-h, --help', 'Show this help message')
|
|
359
|
-
.option(
|
|
368
|
+
.option(
|
|
369
|
+
'--json',
|
|
370
|
+
'Emit JSON with each skill and the ordered family vocabulary',
|
|
371
|
+
)
|
|
360
372
|
.option('--names', 'Only list skill names, one per line')
|
|
373
|
+
.option('--by-family', 'Group the listing under each family')
|
|
361
374
|
.addHelpText(
|
|
362
375
|
'after',
|
|
363
376
|
[
|
|
@@ -365,6 +378,8 @@ export function register(program: Command): void {
|
|
|
365
378
|
'Notes:',
|
|
366
379
|
' Internal skills under .claude/skills/ are excluded, since they',
|
|
367
380
|
' never install into a target project.',
|
|
381
|
+
' Each skill carries the family its frontmatter declares under',
|
|
382
|
+
' metadata.family, and --json lists the vocabulary as families.',
|
|
368
383
|
'',
|
|
369
384
|
].join('\n'),
|
|
370
385
|
)
|
|
@@ -767,7 +782,9 @@ function runSkillsList(opts: SkillsListOptions): number {
|
|
|
767
782
|
|
|
768
783
|
if (opts.json) {
|
|
769
784
|
if (mismatch !== undefined) logWarn(mismatch)
|
|
770
|
-
process.stdout.write(
|
|
785
|
+
process.stdout.write(
|
|
786
|
+
`${JSON.stringify({ skills: listings, families: SKILL_FAMILIES })}\n`,
|
|
787
|
+
)
|
|
771
788
|
return 0
|
|
772
789
|
}
|
|
773
790
|
|
|
@@ -781,14 +798,34 @@ function runSkillsList(opts: SkillsListOptions): number {
|
|
|
781
798
|
|
|
782
799
|
intro('canon claude')
|
|
783
800
|
if (mismatch !== undefined) logWarn(mismatch)
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
801
|
+
if (opts.byFamily) {
|
|
802
|
+
reportByFamily(groupByFamily(listings))
|
|
803
|
+
} else {
|
|
804
|
+
logStep('Plugin skills')
|
|
805
|
+
for (const listing of listings) {
|
|
806
|
+
logInfo(listing.name)
|
|
807
|
+
}
|
|
787
808
|
}
|
|
788
809
|
outro()
|
|
789
810
|
return 0
|
|
790
811
|
}
|
|
791
812
|
|
|
813
|
+
/**
|
|
814
|
+
* One step per family in vocabulary order. A skill with a missing or unknown
|
|
815
|
+
* family takes a trailing step rather than vanishing, so the view still
|
|
816
|
+
* accounts for every listed skill.
|
|
817
|
+
*/
|
|
818
|
+
function reportByFamily(grouping: FamilyGrouping): void {
|
|
819
|
+
for (const group of grouping.groups) {
|
|
820
|
+
logStep(`${group.group} (${group.key})`)
|
|
821
|
+
for (const name of group.skills) logInfo(name)
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (grouping.unassigned.length === 0) return
|
|
825
|
+
logStep('No known family')
|
|
826
|
+
for (const name of grouping.unassigned) logWarn(name)
|
|
827
|
+
}
|
|
828
|
+
|
|
792
829
|
/**
|
|
793
830
|
* Measures the cwd for the same reason the audit does, and takes the ref as a
|
|
794
831
|
* required argument with no default. `HEAD` would be the only defensible one and
|
|
@@ -1398,6 +1435,8 @@ async function runSkillsAudit(
|
|
|
1398
1435
|
reportRequirementShape(report)
|
|
1399
1436
|
reportProvenance(report)
|
|
1400
1437
|
reportPracticeShape(report)
|
|
1438
|
+
reportReferenceContents(report)
|
|
1439
|
+
reportFamily(report)
|
|
1401
1440
|
reportUnmeasured()
|
|
1402
1441
|
outro()
|
|
1403
1442
|
}
|
|
@@ -1421,13 +1460,18 @@ async function runSkillsAudit(
|
|
|
1421
1460
|
requirementSections: report.requirementSections,
|
|
1422
1461
|
datedProvenance: report.datedProvenance,
|
|
1423
1462
|
practiceShape: report.practiceShape,
|
|
1463
|
+
referenceContents: report.referenceContents,
|
|
1464
|
+
family: report.family,
|
|
1424
1465
|
},
|
|
1425
1466
|
checkpoints: {
|
|
1426
1467
|
descriptionLimit: DESCRIPTION_LIMIT,
|
|
1427
1468
|
requirementSections: REQUIREMENT_SECTIONS,
|
|
1428
1469
|
corpora: CORPORA,
|
|
1429
1470
|
practiceSkills: PRACTICE_SKILLS,
|
|
1471
|
+
ledgerSkills: LEDGER_SKILLS,
|
|
1430
1472
|
practiceSections: PRACTICE_SECTIONS,
|
|
1473
|
+
contentsThreshold: CONTENTS_THRESHOLD,
|
|
1474
|
+
families: familyKeys(),
|
|
1431
1475
|
},
|
|
1432
1476
|
})}\n`,
|
|
1433
1477
|
)
|
|
@@ -1626,10 +1670,10 @@ function reportProvenance(report: SkillsAudit): void {
|
|
|
1626
1670
|
function reportPracticeShape(report: SkillsAudit): void {
|
|
1627
1671
|
logStep('Practice shape')
|
|
1628
1672
|
logInfo(
|
|
1629
|
-
`A listed practice skill closes with ${PRACTICE_SECTIONS.map((section) => `## ${section}`).join(', ')}, and carries ${PRACTICE_LEDGER}.`,
|
|
1673
|
+
`A listed practice skill closes with ${PRACTICE_SECTIONS.map((section) => `## ${section}`).join(', ')}, and every skill on the wider ledger list carries ${PRACTICE_LEDGER}.`,
|
|
1630
1674
|
)
|
|
1631
1675
|
logInfo(
|
|
1632
|
-
`
|
|
1676
|
+
`Both lists are kept here and name ${plural(PRACTICE_SKILLS.length, 'practice skill')} and ${plural(LEDGER_SKILLS.length, 'ledger skill')}, so a skill outside ${SHIPPED_CORPUS} is never read.`,
|
|
1633
1677
|
)
|
|
1634
1678
|
|
|
1635
1679
|
if (report.practiceShape.length === 0) {
|
|
@@ -1643,6 +1687,45 @@ function reportPracticeShape(report: SkillsAudit): void {
|
|
|
1643
1687
|
reportFindings(report.practiceShape)
|
|
1644
1688
|
}
|
|
1645
1689
|
|
|
1690
|
+
/** Reports without failing the run, the same judgment the practice shape is. */
|
|
1691
|
+
function reportReferenceContents(report: SkillsAudit): void {
|
|
1692
|
+
logStep('Reference contents')
|
|
1693
|
+
logInfo(
|
|
1694
|
+
`A reference over ${CONTENTS_THRESHOLD} lines opens with a ## ${CONTENTS_SECTION} list, matched exactly outside fences.`,
|
|
1695
|
+
)
|
|
1696
|
+
|
|
1697
|
+
if (report.referenceContents.length === 0) {
|
|
1698
|
+
logInfo('Every long reference opens with a contents list.')
|
|
1699
|
+
return
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
logWarn(
|
|
1703
|
+
`${plural(report.referenceContents.length, 'long reference')} with no contents list`,
|
|
1704
|
+
)
|
|
1705
|
+
reportFindings(report.referenceContents)
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
/**
|
|
1709
|
+
* Reports without failing the verb, the split the practice shape takes. The
|
|
1710
|
+
* Skill family stage of `canon gate run` is what fails a push on it.
|
|
1711
|
+
*/
|
|
1712
|
+
function reportFamily(report: SkillsAudit): void {
|
|
1713
|
+
logStep('Family')
|
|
1714
|
+
logInfo(
|
|
1715
|
+
`A skill under ${SHIPPED_CORPUS} declares metadata.family, one of ${familyKeys().join(', ')}.`,
|
|
1716
|
+
)
|
|
1717
|
+
|
|
1718
|
+
if (report.family.length === 0) {
|
|
1719
|
+
logInfo('Every shipped skill declares a known family.')
|
|
1720
|
+
return
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
logWarn(
|
|
1724
|
+
`${plural(report.family.length, 'skill')} with a missing or unknown family`,
|
|
1725
|
+
)
|
|
1726
|
+
reportFindings(report.family)
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1646
1729
|
/**
|
|
1647
1730
|
* Stated on every run, including the run where everything above passed. A
|
|
1648
1731
|
* report that lists only what it measured reads as a verdict on the standard
|
package/src/commands/design.ts
CHANGED
|
@@ -8,20 +8,23 @@ import {
|
|
|
8
8
|
} from '@/design/adapter'
|
|
9
9
|
import { buildDesignCss } from '@/design/css'
|
|
10
10
|
import { HAND_DRAWN_FONT_FACES } from '@/design/fonts'
|
|
11
|
+
import { addProjectFace, listProjectFaces } from '@/design/project-fonts'
|
|
11
12
|
import { renderDesignDoc } from '@/design/render'
|
|
12
13
|
import { DESIGN_BASE_CSS, DESIGN_DOCUMENT, regenDesign } from '@/design/regen'
|
|
13
14
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/project-root'
|
|
14
15
|
import { creationRel, SCRATCH } from '@/record-root'
|
|
15
16
|
import { surfaceDir } from '@/surface-root'
|
|
16
17
|
import { recordStamp, runDomainSync } from '@/sync/engine'
|
|
17
|
-
import { resolveTarget } from '@/
|
|
18
|
+
import { isDirectory, resolveTarget } from '@/targets/validate'
|
|
18
19
|
import { intro, logAdd, logError, logInfo, logWarn, outro, palette } from '@/ui'
|
|
19
20
|
|
|
20
21
|
export function register(program: Command): void {
|
|
21
22
|
const design = program
|
|
22
23
|
.command('design')
|
|
23
24
|
.helpOption('-h, --help', 'Show this help message')
|
|
24
|
-
.description(
|
|
25
|
+
.description(
|
|
26
|
+
'Design system commands (regen, css, render, install, sync, fonts)',
|
|
27
|
+
)
|
|
25
28
|
|
|
26
29
|
design
|
|
27
30
|
.command('regen')
|
|
@@ -172,6 +175,143 @@ export function register(program: Command): void {
|
|
|
172
175
|
{ protectedRoot: PROJECT_ROOT },
|
|
173
176
|
)
|
|
174
177
|
})
|
|
178
|
+
|
|
179
|
+
registerFonts(design)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const FONTS_DIR = join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR, 'fonts')
|
|
183
|
+
|
|
184
|
+
interface FontsRefused {
|
|
185
|
+
readonly ok: false
|
|
186
|
+
readonly reason: string
|
|
187
|
+
readonly detail: string
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function writeJson(record: unknown): void {
|
|
191
|
+
process.stdout.write(`${JSON.stringify(record)}\n`)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function refuseFonts(
|
|
195
|
+
title: string,
|
|
196
|
+
refusal: FontsRefused,
|
|
197
|
+
emitJson: boolean,
|
|
198
|
+
): number {
|
|
199
|
+
if (emitJson) writeJson(refusal)
|
|
200
|
+
intro(title)
|
|
201
|
+
logError(refusal.detail)
|
|
202
|
+
outro()
|
|
203
|
+
return 1
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** A target that is a directory, or the refusal naming the path given. */
|
|
207
|
+
function fontsTarget(target: string): string | FontsRefused {
|
|
208
|
+
const resolved = resolve(target)
|
|
209
|
+
if (!isDirectory(resolved)) {
|
|
210
|
+
return {
|
|
211
|
+
ok: false,
|
|
212
|
+
reason: 'no-target',
|
|
213
|
+
detail: `Target directory not found: ${target}`,
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return resolved
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function registerFonts(design: Command): void {
|
|
220
|
+
const fonts = design
|
|
221
|
+
.command('fonts')
|
|
222
|
+
.helpOption('-h, --help', 'Show this help message')
|
|
223
|
+
.description(`Read and add the project's own faces under ${FONTS_DIR}/`)
|
|
224
|
+
.addHelpText(
|
|
225
|
+
'after',
|
|
226
|
+
[
|
|
227
|
+
'',
|
|
228
|
+
`Faces are declared as @font-face rules in ${join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR)}/fonts.css,`,
|
|
229
|
+
'which the canvas embeds into every frame. Sync never writes the folder.',
|
|
230
|
+
'',
|
|
231
|
+
].join('\n'),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
fonts
|
|
235
|
+
.command('list')
|
|
236
|
+
.helpOption('-h, --help', 'Show this help message')
|
|
237
|
+
.description('List each face the project override sheets declare')
|
|
238
|
+
.argument('[target]', 'Target directory', '.')
|
|
239
|
+
.option('--json', 'Emit the record on stdout')
|
|
240
|
+
.action((target: string, opts: { json?: boolean }) => {
|
|
241
|
+
const title = 'canon design fonts list'
|
|
242
|
+
const resolved = fontsTarget(target)
|
|
243
|
+
if (typeof resolved !== 'string') {
|
|
244
|
+
process.exitCode = refuseFonts(title, resolved, Boolean(opts.json))
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
const faces = listProjectFaces(resolved)
|
|
248
|
+
if (opts.json) writeJson({ ok: true, faces })
|
|
249
|
+
intro(title)
|
|
250
|
+
if (faces.length === 0) logInfo(`No faces declared under ${FONTS_DIR}/`)
|
|
251
|
+
for (const face of faces) {
|
|
252
|
+
const line = `${face.family} ${face.weight} ${face.style}: ${face.file} in ${face.sheet}`
|
|
253
|
+
if (face.present) logInfo(line)
|
|
254
|
+
else logWarn(`${line} (${face.problem ?? 'missing'})`)
|
|
255
|
+
}
|
|
256
|
+
outro()
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
fonts
|
|
260
|
+
.command('add')
|
|
261
|
+
.helpOption('-h, --help', 'Show this help message')
|
|
262
|
+
.description(
|
|
263
|
+
`Copy a woff2, woff, ttf, or otf face into ${FONTS_DIR}/ and declare it`,
|
|
264
|
+
)
|
|
265
|
+
.argument('<file>', 'Font file to copy')
|
|
266
|
+
.argument('[target]', 'Target directory', '.')
|
|
267
|
+
.requiredOption('--family <name>', 'Family name the face declares')
|
|
268
|
+
.option('--weight <n>', "Weight, or a range such as '100 900'", '400')
|
|
269
|
+
.option('--style <style>', 'normal or italic', 'normal')
|
|
270
|
+
.option('--json', 'Emit the record on stdout')
|
|
271
|
+
.action(
|
|
272
|
+
(
|
|
273
|
+
file: string,
|
|
274
|
+
target: string,
|
|
275
|
+
opts: { family: string; weight: string; style: string; json?: boolean },
|
|
276
|
+
) => {
|
|
277
|
+
const title = 'canon design fonts add'
|
|
278
|
+
const emitJson = Boolean(opts.json)
|
|
279
|
+
const resolved = fontsTarget(target)
|
|
280
|
+
if (typeof resolved !== 'string') {
|
|
281
|
+
process.exitCode = refuseFonts(title, resolved, emitJson)
|
|
282
|
+
return
|
|
283
|
+
}
|
|
284
|
+
if (resolved === PROJECT_ROOT) {
|
|
285
|
+
process.exitCode = refuseFonts(
|
|
286
|
+
title,
|
|
287
|
+
{
|
|
288
|
+
ok: false,
|
|
289
|
+
reason: 'toolkit-root',
|
|
290
|
+
detail:
|
|
291
|
+
'Cannot run against toolkit root. Files here are the source of truth.',
|
|
292
|
+
},
|
|
293
|
+
emitJson,
|
|
294
|
+
)
|
|
295
|
+
return
|
|
296
|
+
}
|
|
297
|
+
const outcome = addProjectFace(resolved, resolve(file), {
|
|
298
|
+
family: opts.family,
|
|
299
|
+
weight: opts.weight,
|
|
300
|
+
style: opts.style,
|
|
301
|
+
})
|
|
302
|
+
if (!outcome.ok) {
|
|
303
|
+
process.exitCode = refuseFonts(title, outcome, emitJson)
|
|
304
|
+
return
|
|
305
|
+
}
|
|
306
|
+
if (emitJson) writeJson(outcome)
|
|
307
|
+
intro(title)
|
|
308
|
+
logAdd(join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR, outcome.file))
|
|
309
|
+
logInfo(
|
|
310
|
+
`Declared ${outcome.family} ${outcome.weight} ${outcome.style} in ${outcome.sheet}`,
|
|
311
|
+
)
|
|
312
|
+
outro()
|
|
313
|
+
},
|
|
314
|
+
)
|
|
175
315
|
}
|
|
176
316
|
|
|
177
317
|
/**
|
package/src/commands/feedback.ts
CHANGED
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
deriveTitle,
|
|
8
8
|
missingField,
|
|
9
9
|
missingFieldMessage,
|
|
10
|
-
} from '@/
|
|
10
|
+
} from '@/feedback/body'
|
|
11
11
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/project-root'
|
|
12
12
|
import { creationRel } from '@/record-root'
|
|
13
|
-
import { createGithubIssue } from '@/github'
|
|
14
|
-
import { issueFailureMessage } from '@/github-format'
|
|
13
|
+
import { createGithubIssue } from '@/feedback/github'
|
|
14
|
+
import { issueFailureMessage } from '@/feedback/github-format'
|
|
15
15
|
import { frameError, frameSuccess, logWarn, palette } from '@/ui'
|
|
16
16
|
|
|
17
17
|
function readStdin(): Promise<string> {
|
package/src/commands/gov.ts
CHANGED
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
} from '@/gov/test-order'
|
|
54
54
|
import { recordStamp, runDomainSync } from '@/sync/engine'
|
|
55
55
|
import { writeChainStamp } from '@/sync/stamp'
|
|
56
|
-
import { resolveTarget } from '@/
|
|
56
|
+
import { resolveTarget } from '@/targets/validate'
|
|
57
57
|
import {
|
|
58
58
|
intro,
|
|
59
59
|
isNonInteractive,
|
package/src/commands/hooks.ts
CHANGED
package/src/commands/indexes.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { $ } from 'bun'
|
|
|
4
4
|
import type { Command } from 'commander'
|
|
5
5
|
import { buildIndexCatalog } from '@/indexes/list'
|
|
6
6
|
import { exitCodeFor, type RegenResult, regenOne } from '@/indexes/regen'
|
|
7
|
-
import { gitEnv } from '@/git
|
|
7
|
+
import { gitEnv } from '@/git/env'
|
|
8
8
|
import { findIndexedAncestor, isIgnored, listIndexes } from '@/indexes/walk'
|
|
9
9
|
import { intro, logAdd, logInfo, logStep, logWarn, outro } from '@/ui'
|
|
10
10
|
|
package/src/commands/init.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { applyInitOptions, flagsProvided } from '@/init/flags'
|
|
|
5
5
|
import { type InitFlags, parseSkip, planInit } from '@/init/plan'
|
|
6
6
|
import { runDomains } from '@/init/run'
|
|
7
7
|
import { buildSteps } from '@/init/steps'
|
|
8
|
-
import { resolveTarget } from '@/
|
|
8
|
+
import { resolveTarget } from '@/targets/validate'
|
|
9
9
|
import { intro, logInfo, logStep, logWarn, outro, palette, select } from '@/ui'
|
|
10
10
|
|
|
11
11
|
interface InitOptions {
|
package/src/commands/intake.ts
CHANGED