@erclx/canon 5.38.0 → 5.40.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 +5 -5
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +12 -9
- package/claude/skills/auto-ship/SKILL.md +43 -23
- package/claude/skills/backlog-triage/SKILL.md +62 -53
- package/claude/skills/backlog-triage/references/apply.md +69 -0
- package/claude/skills/build-in-slices/SKILL.md +8 -4
- package/claude/skills/canon-cli/SKILL.md +5 -1
- package/claude/skills/canon-feedback/SKILL.md +18 -8
- package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
- package/claude/skills/canvas-board/SKILL.md +37 -18
- package/claude/skills/ci-workflow/SKILL.md +5 -4
- package/claude/skills/code-craft/SKILL.md +10 -6
- package/claude/skills/codebase-layout/SKILL.md +3 -5
- package/claude/skills/context-fold/REQUIREMENT.md +4 -4
- package/claude/skills/context-fold/SKILL.md +42 -23
- package/claude/skills/context-fold/references/context-refresh.md +4 -3
- package/claude/skills/context-fold/references/context.md +79 -64
- package/claude/skills/create-rule/SKILL.md +7 -3
- package/claude/skills/create-skill/SKILL.md +27 -7
- package/claude/skills/create-skill/references/skill-reference.md +41 -17
- package/claude/skills/decision-escalate/SKILL.md +8 -5
- package/claude/skills/deploy-app/SKILL.md +1 -1
- package/claude/skills/deprecation-migration/SKILL.md +12 -4
- package/claude/skills/design-taste/SKILL.md +17 -11
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
- package/claude/skills/docs-sync/SKILL.md +17 -6
- package/claude/skills/docs-sync/references/docs.md +54 -21
- package/claude/skills/docs-sync/references/readme.md +32 -8
- package/claude/skills/document-health/SKILL.md +3 -4
- package/claude/skills/draft-and-pick/SKILL.md +73 -47
- package/claude/skills/draft-doc/SKILL.md +9 -4
- package/claude/skills/draft-doc/references/context.md +4 -4
- package/claude/skills/draft-doc/references/docs.md +1 -0
- package/claude/skills/draft-doc/references/wiki.md +3 -2
- package/claude/skills/draft-figure/SKILL.md +9 -7
- package/claude/skills/draft-identity/SKILL.md +24 -52
- package/claude/skills/draft-identity/references/card-route.md +46 -0
- package/claude/skills/draft-ready/SKILL.md +19 -7
- package/claude/skills/draft-screencast/SKILL.md +6 -112
- package/claude/skills/draft-screencast/references/beats-template.md +119 -0
- package/claude/skills/draft-slides/SKILL.md +9 -7
- package/claude/skills/draft-slides/references/deck.md +183 -0
- package/claude/skills/git-branch/SKILL.md +3 -3
- package/claude/skills/git-commit/SKILL.md +5 -3
- package/claude/skills/git-followup/SKILL.md +16 -9
- package/claude/skills/git-issue/SKILL.md +6 -5
- package/claude/skills/git-pr/SKILL.md +56 -44
- package/claude/skills/git-pr/references/evidence.md +2 -2
- package/claude/skills/git-pr/references/final-command.md +1 -1
- package/claude/skills/git-pr/references/labels.md +1 -1
- package/claude/skills/git-pr/references/publish.md +1 -1
- package/claude/skills/git-ship/SKILL.md +43 -34
- package/claude/skills/git-ship/references/ci-watch.md +31 -0
- package/claude/skills/git-split/SKILL.md +28 -100
- package/claude/skills/git-split/references/independent.md +40 -0
- package/claude/skills/git-split/references/stacked.md +73 -0
- package/claude/skills/git-stage/SKILL.md +9 -7
- package/claude/skills/git-worktree/SKILL.md +27 -49
- package/claude/skills/git-worktree/references/cleanup.md +55 -0
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/markdown-craft/references/markdown.md +82 -53
- package/claude/skills/plan-feature/SKILL.md +52 -46
- package/claude/skills/plan-feature/references/batches.md +46 -0
- package/claude/skills/plan-groundwork/SKILL.md +60 -74
- package/claude/skills/plan-groundwork/references/output.md +48 -0
- package/claude/skills/plan-intake/SKILL.md +28 -21
- package/claude/skills/plan-intake-answer/SKILL.md +14 -13
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +31 -11
- package/claude/skills/review-address/SKILL.md +76 -158
- package/claude/skills/review-address/references/rebase-only.md +34 -0
- package/claude/skills/review-craft/SKILL.md +27 -11
- package/claude/skills/review-pr/SKILL.md +91 -40
- package/claude/skills/review-ui/SKILL.md +63 -37
- package/claude/skills/review-ui/references/hosted-preview.md +30 -0
- package/claude/skills/role-orchestrator/SKILL.md +105 -74
- package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-planner/SKILL.md +66 -64
- package/claude/skills/role-reviewer/SKILL.md +57 -46
- package/claude/skills/role-worker/SKILL.md +68 -63
- package/claude/skills/search-craft/SKILL.md +7 -5
- package/claude/skills/session-compact/SKILL.md +16 -11
- package/claude/skills/session-map/SKILL.md +31 -10
- package/claude/skills/session-relay/SKILL.md +32 -65
- package/claude/skills/session-resume/SKILL.md +18 -13
- package/claude/skills/session-worktree/SKILL.md +70 -42
- package/claude/skills/systematic-debugging/SKILL.md +6 -1
- package/claude/skills/target-check/SKILL.md +13 -6
- package/claude/skills/target-setup/SKILL.md +39 -27
- package/claude/skills/task-board/SKILL.md +68 -60
- package/claude/skills/task-board/references/board.md +1 -1
- package/claude/skills/task-board/references/create-report.md +36 -0
- package/claude/skills/task-board/references/tasks.md +1 -1
- package/claude/skills/task-complete/SKILL.md +20 -18
- package/claude/skills/teach-workspace/SKILL.md +61 -33
- package/claude/skills/test-craft/SKILL.md +2 -1
- package/claude/skills/test-first/SKILL.md +15 -9
- package/claude/skills/ui-checklist/SKILL.md +18 -16
- package/claude/skills/ux-audit/SKILL.md +9 -10
- package/claude/skills/ux-measure/SKILL.md +23 -19
- package/claude/skills/video-craft/SKILL.md +15 -7
- package/claude/skills/write-human/SKILL.md +9 -1
- package/claude/skills/youtube-transcripts/SKILL.md +2 -1
- package/docs/agents/audits.md +61 -60
- package/docs/agents/context-audit.md +40 -58
- package/docs/agents/index.md +11 -61
- package/docs/agents/indexes.md +25 -29
- package/docs/agents/install-and-sync.md +125 -235
- package/docs/agents/markdown-audit.md +54 -96
- package/docs/agents/migrate.md +41 -16
- package/docs/agents/output-shape.md +60 -45
- package/docs/agents/overview.md +36 -12
- package/docs/agents/records.md +37 -79
- package/docs/agents/sessions-transfer.md +26 -70
- package/docs/agents/targets.md +25 -77
- package/docs/target/index.md +0 -1
- package/docs/target/migrations.md +57 -66
- package/docs/target/projects.md +36 -78
- package/docs/target/scenarios.md +9 -19
- package/docs/target/sync.md +27 -68
- package/docs/workflow/ai-workflow.md +22 -68
- package/docs/workflow/operating-model.md +32 -186
- package/docs/workflow/parallel-features.md +29 -66
- package/docs/workflow/skill-map-on-request.md +22 -24
- package/docs/workflow/skill-map.md +72 -76
- package/docs/workflow/visual-design-workflow.md +25 -118
- package/docs/workflow/zshrc-aliases.md +18 -37
- package/package.json +1 -1
- package/src/canvas/client/inspector/fields.css +4 -0
- package/src/canvas/index.html +6 -0
- package/src/claude/skills-reach.ts +2 -2
- package/src/cli/ui.ts +3 -1
- package/src/commands/canvas.ts +23 -0
- package/src/commands/capture.ts +14 -0
- package/src/commands/claude.ts +14 -1
- package/src/commands/context.ts +106 -7
- package/src/commands/demo.ts +22 -0
- package/src/commands/deps.ts +6 -0
- package/src/commands/driver.ts +28 -2
- package/src/commands/gov.ts +52 -18
- package/src/commands/hooks.ts +63 -0
- package/src/commands/intake.ts +17 -0
- package/src/commands/labels.ts +38 -5
- package/src/commands/markdown.ts +169 -32
- package/src/commands/pr.ts +160 -43
- package/src/commands/records.ts +8 -0
- package/src/commands/secrets.ts +6 -0
- package/src/commands/sessions.ts +8 -0
- package/src/commands/tasks.ts +52 -0
- package/src/commands/teach.ts +13 -0
- package/src/commands/upstream.ts +25 -1
- package/src/commands/worktrees.ts +5 -0
- package/src/context/audit.ts +274 -5
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/folders.ts +1 -1
- package/src/context/gate.ts +23 -7
- package/src/context/shape-gated.ts +30 -0
- package/src/counts/scan.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/gate/boundaries.ts +4 -1
- package/src/gate/measures.ts +16 -191
- package/src/gate/stages.ts +14 -30
- package/src/git/env.ts +6 -0
- package/src/hooks/reply-links.ts +110 -0
- package/src/markdown/density.ts +258 -0
- package/src/markdown/gate.ts +57 -18
- package/src/markdown/reference-shape.ts +103 -0
- package/src/markdown/scope.ts +162 -0
- package/src/markdown/structure.ts +9 -59
- package/src/pr/lift.ts +153 -19
- package/src/pr/painted.ts +87 -0
- package/src/roots/record.ts +18 -1
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/headless/run.ts +3 -2
- package/src/sandbox/headless/watch.ts +3 -4
- package/src/shipped/references.ts +1 -1
- package/src/slides/convert/master.ts +3 -0
- package/src/sync/format.ts +46 -0
- package/src/sync/stamp.ts +6 -0
- package/tooling/astro/reference.md +2 -2
- package/tooling/base/reference.md +1 -1
- package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/tooling/go/reference.md +1 -1
- package/tooling/nextjs/reference.md +1 -1
- package/tooling/php/reference.md +1 -1
- package/tooling/python/reference.md +1 -1
- package/tooling/vite-react/reference.md +1 -1
- package/tooling/web/reference.md +1 -1
- package/docs/agents/canvas.md +0 -86
- package/docs/agents/capture.md +0 -65
- package/docs/agents/census.md +0 -23
- package/docs/agents/commands.md +0 -154
- package/docs/agents/comments.md +0 -34
- package/docs/agents/context-audit-checks.md +0 -90
- package/docs/agents/context-classify.md +0 -101
- package/docs/agents/counts.md +0 -74
- package/docs/agents/demo.md +0 -140
- package/docs/agents/docs.md +0 -27
- package/docs/agents/drift-surfaces.md +0 -201
- package/docs/agents/driver.md +0 -103
- package/docs/agents/gate.md +0 -90
- package/docs/agents/gov-detect.md +0 -47
- package/docs/agents/hooks.md +0 -58
- package/docs/agents/intake.md +0 -81
- package/docs/agents/key-changes.md +0 -116
- package/docs/agents/label-coverage.md +0 -86
- package/docs/agents/markdown-audit-weight.md +0 -81
- package/docs/agents/pr-evidence-layout.md +0 -70
- package/docs/agents/pr-evidence.md +0 -273
- package/docs/agents/pr-frames.md +0 -131
- package/docs/agents/pr-lift.md +0 -132
- package/docs/agents/pr-local.md +0 -111
- package/docs/agents/pr-preview.md +0 -155
- package/docs/agents/pr-reads.md +0 -111
- package/docs/agents/pr-tick.md +0 -72
- package/docs/agents/records-push.md +0 -61
- package/docs/agents/records-stale.md +0 -40
- package/docs/agents/records-validate.md +0 -57
- package/docs/agents/restated.md +0 -83
- package/docs/agents/routing.md +0 -61
- package/docs/agents/rule-citations.md +0 -90
- package/docs/agents/sandbox.md +0 -126
- package/docs/agents/scripting.md +0 -142
- package/docs/agents/sessions.md +0 -128
- package/docs/agents/skills-audit.md +0 -120
- package/docs/agents/skills-reach.md +0 -64
- package/docs/agents/slides.md +0 -176
- package/docs/agents/state-scoped-risk.md +0 -105
- package/docs/agents/superseded.md +0 -85
- package/docs/agents/tasks-archive.md +0 -83
- package/docs/agents/tasks-plans.md +0 -152
- package/docs/agents/tasks-validate.md +0 -133
- package/docs/agents/tasks.md +0 -123
- package/docs/agents/teach-authoring.md +0 -118
- package/docs/agents/teach.md +0 -157
- package/docs/agents/test-order.md +0 -58
- package/docs/agents/upstream.md +0 -94
- package/docs/agents/worktrees.md +0 -118
- package/docs/target/standards-moved.md +0 -34
- package/src/markdown/growth.ts +0 -43
|
@@ -6,15 +6,13 @@ category: Workflow
|
|
|
6
6
|
|
|
7
7
|
# Zshrc aliases for Claude Code
|
|
8
8
|
|
|
9
|
-
Claude Code auto-discovers the toolkit plugin
|
|
9
|
+
Claude Code auto-discovers the toolkit plugin inside the toolkit repository. Outside it, the `clp` aliases pass `--plugin-dir` explicitly.
|
|
10
10
|
|
|
11
11
|
## The aliases
|
|
12
12
|
|
|
13
|
-
`bun run bootstrap`
|
|
13
|
+
`bun run bootstrap` appends this block to `~/.zshrc` between the two marker comments and sets `TOOLKIT` to the cloned path. A re-run skips a block it finds and never updates it. To pick up a newer alias, delete the marked block and re-run, or paste the new lines in.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
A block installed by hand before the managed one has no markers. Bootstrap detects that case through the `alias clp=` line instead, warns, and leaves the block untouched rather than appending a second copy. To switch over, delete the hand-rolled block and re-run the bootstrap.
|
|
15
|
+
A hand-written block without markers is detected through its `alias clp=` line, and bootstrap warns and leaves it. Delete it and re-run to switch.
|
|
18
16
|
|
|
19
17
|
```zsh
|
|
20
18
|
# >>> canon aliases >>>
|
|
@@ -34,46 +32,29 @@ alias clpac='clpa --cwd .'
|
|
|
34
32
|
# <<< canon aliases <<<
|
|
35
33
|
```
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
To opt out, delete the block between the two markers. Bootstrap re-adds it on the next run, so skip that step by running `bun install` and `bun link` yourself instead.
|
|
40
|
-
|
|
41
|
-
The block itself works unchanged in bash, and what differs is the file it goes in and who writes it. Paste it into `~/.bashrc` by hand, since `bun run bootstrap` appends to `~/.zshrc` alone and a run from a bash shell installs nothing that shell reads. Bash re-checks the first word of an alias expansion the way zsh does, so the `cl` and `clp` chains below still inherit their base, and the `bun install` and `bun link` step above is the opt-out either shell takes.
|
|
35
|
+
To opt out, delete the block and run `bun install` and `bun link` yourself. Bash takes the block unchanged in `~/.bashrc`, pasted by hand. Bootstrap writes `~/.zshrc` alone.
|
|
42
36
|
|
|
43
37
|
## What each one does
|
|
44
38
|
|
|
45
|
-
`cl`, `clw`, and `cls` carry no explicit plugin dir and start a fresh session. Use them inside the toolkit repository, where Claude Code auto-discovers the plugin from `claude/.claude-plugin/plugin.json`. Loading `--plugin-dir` on top of auto-discovery registers every skill twice and produces duplicate entries in the slash command list.
|
|
46
|
-
|
|
47
|
-
`clr` and `clc` resume a session rather than launching one, so auto-discovery never fires for them. A resume restores whatever plugin registration the session started with and recomputes nothing, which a bare `claude --resume` demonstrated by holding a stale registration through a full process restart until `--plugin-dir` was passed on the resume itself.
|
|
48
|
-
|
|
49
39
|
- `cl`: plain session in the current directory
|
|
50
|
-
- `clr`: opens the `/resume` picker
|
|
51
|
-
- `clc`:
|
|
52
|
-
- `clw`: creates a worktree under `.claude/worktrees/<name>/` on a fresh branch and starts a
|
|
53
|
-
- `cls`: pins the session to Sonnet
|
|
40
|
+
- `clr`: opens the `/resume` picker for the current directory. `clr auth` filters to sessions containing "auth".
|
|
41
|
+
- `clc`: resumes the most recent session for the current directory, no picker
|
|
42
|
+
- `clw`: creates a worktree under `.claude/worktrees/<name>/` on a fresh branch and starts a session there, as in `clw feat-auth`
|
|
43
|
+
- `cls`: pins the session to Sonnet
|
|
54
44
|
|
|
55
|
-
The `clp` family
|
|
45
|
+
The `clp` family loads the plugin explicitly.
|
|
56
46
|
|
|
57
|
-
- `clp`: session with the toolkit plugin loaded
|
|
58
|
-
- `clpc`:
|
|
47
|
+
- `clp`: session with the toolkit plugin loaded
|
|
48
|
+
- `clpc`: resumes the most recent session with the plugin loaded
|
|
59
49
|
- `clps`: `clp` pinned to Sonnet
|
|
60
|
-
- `clpa`: opens the agent view with the plugin loaded,
|
|
61
|
-
- `clpac`: the same view filtered to
|
|
50
|
+
- `clpa`: opens the agent view with the plugin loaded, across every directory
|
|
51
|
+
- `clpac`: the same view filtered to the current directory
|
|
62
52
|
|
|
63
53
|
## When to use which
|
|
64
54
|
|
|
65
|
-
Use `cl`
|
|
66
|
-
|
|
67
|
-
Use `clp` in any other repository where you want the toolkit skills available. Without the flag, those repos do not load the plugin.
|
|
68
|
-
|
|
69
|
-
Use `cls` or `clps` to save Opus usage on routine sessions. Switch mid-session with `/model` to avoid restarting.
|
|
70
|
-
|
|
71
|
-
Use `clw <name>` for features that will take more than one session. A worktree isolates the branch, the transcripts, and the `/resume` history. See [Claude Code and git worktrees](../../wiki/claude/worktrees.md) for the worktree mechanism, and [Parallel features](parallel-features.md) for fan-out rules.
|
|
72
|
-
|
|
73
|
-
Use `clc` to resume the last session without a picker. Use `clr` when you have several sessions and need to pick by name or recency. Reach for `clpc` over `clc` wherever the resumed session needs the plugin, inside the toolkit repository as well as outside it, since neither resume re-runs discovery.
|
|
74
|
-
|
|
75
|
-
Use `clpa` to see what is running across every directory, and `clpac` when only the current project matters.
|
|
76
|
-
|
|
77
|
-
## Why not a function
|
|
55
|
+
Use `cl` inside the toolkit repository and `clp` in any other repository that needs the toolkit skills. A resume does not reload the plugin, so use `clpc` over `clc` wherever the resumed session needs it.
|
|
78
56
|
|
|
79
|
-
|
|
57
|
+
- Use `cls` or `clps` for routine sessions, and `/model` to switch mid-session
|
|
58
|
+
- Use `clw <name>` for features that take more than one session. See [Claude Code and git worktrees](../../wiki/claude/worktrees.md) and [Parallel features](parallel-features.md).
|
|
59
|
+
- Use `clc` to resume without a picker and `clr` to pick by name
|
|
60
|
+
- Use `clpa` for every directory and `clpac` for the current project
|
package/package.json
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* The inspector's own rules. Every value reads a chrome token, the same set
|
|
3
3
|
* shell.css reads. Each field's glyph sits inside its box, so two fields share
|
|
4
4
|
* a row without a label column eating the width.
|
|
5
|
+
*
|
|
6
|
+
* These rules share one class namespace with shell.css, where the Theme tab
|
|
7
|
+
* owns `.token`, so a new class here takes its own prefix, as `.token-option`
|
|
8
|
+
* does.
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
.inspector-section {
|
package/src/canvas/index.html
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>Canvas</title>
|
|
7
|
+
<!--
|
|
8
|
+
Bun's bundler resolves every href and src here at start. A root-relative
|
|
9
|
+
route the server answers, such as /api/icon.svg, fails with "Could not
|
|
10
|
+
resolve" and leaves / serving an empty 200, so main.tsx points the icon
|
|
11
|
+
at it on load.
|
|
12
|
+
-->
|
|
7
13
|
<link rel="icon" href="data:," />
|
|
8
14
|
<link rel="stylesheet" href="./client/shell.css" />
|
|
9
15
|
</head>
|
|
@@ -13,8 +13,8 @@ import { SURFACE_ROOTS } from '@/roots/surface'
|
|
|
13
13
|
* `src/`, `scripts/`, and bare `docs/` are deliberately absent. A body naming
|
|
14
14
|
* one of those is describing the reader's own tree, so listing them would
|
|
15
15
|
* report a correct citation on every run and bury the defect this measures.
|
|
16
|
-
* `docs/agents/` is the exception, being the
|
|
17
|
-
* here alone.
|
|
16
|
+
* `docs/agents/` is the exception, being the reference pages for verbs run by
|
|
17
|
+
* hand, which exist here alone.
|
|
18
18
|
*
|
|
19
19
|
* The context folder carries both surface-root spellings, since this list
|
|
20
20
|
* decides whether a shipped body names this repository's own tree and a body
|
package/src/cli/ui.ts
CHANGED
|
@@ -162,6 +162,8 @@ export async function select<Value>(opts: {
|
|
|
162
162
|
message: string
|
|
163
163
|
options: { value: Value; label: string; hint?: string }[]
|
|
164
164
|
nonInteractiveDefault?: boolean
|
|
165
|
+
/** Replaces the "Pass an argument" clause of the TTY refusal. */
|
|
166
|
+
ttyHint?: string
|
|
165
167
|
}): Promise<Value> {
|
|
166
168
|
const { message, options } = opts
|
|
167
169
|
const { GREEN, GREY, NC, RED, WHITE } = palette(process.stderr)
|
|
@@ -196,7 +198,7 @@ export async function select<Value>(opts: {
|
|
|
196
198
|
return new Promise<Value>((resolve) => {
|
|
197
199
|
if (!process.stdin.isTTY) {
|
|
198
200
|
process.stderr.write(
|
|
199
|
-
`${GREY}│${NC} ${RED}✗${NC} ${message} requires a TTY. Pass an argument or set CANON_NON_INTERACTIVE=1.\n${GREY}└${NC}\n`,
|
|
201
|
+
`${GREY}│${NC} ${RED}✗${NC} ${message} requires a TTY. ${opts.ttyHint ?? 'Pass an argument'} or set CANON_NON_INTERACTIVE=1.\n${GREY}└${NC}\n`,
|
|
200
202
|
)
|
|
201
203
|
process.exit(1)
|
|
202
204
|
}
|
package/src/commands/canvas.ts
CHANGED
|
@@ -77,6 +77,11 @@ const CLIENT_DEPS = ['preact', '@preact/signals'] as const
|
|
|
77
77
|
* the bundler then answers `/` with an empty page rather than an error. The
|
|
78
78
|
* caller passes the package root the binary runs from, never the served
|
|
79
79
|
* project's, so a global install serving a target finds its own copies.
|
|
80
|
+
*
|
|
81
|
+
* `Bun.resolveSync` and `createRequire(...).resolve` fall back to Bun's global
|
|
82
|
+
* install cache when no ancestor of the starting directory holds a
|
|
83
|
+
* `node_modules`, so a presence check from such a directory passes where the
|
|
84
|
+
* bundler fails. The package root always sits under one.
|
|
80
85
|
*/
|
|
81
86
|
export function missingClientDeps(from: string): Refused | undefined {
|
|
82
87
|
const missing = CLIENT_DEPS.filter((name) => {
|
|
@@ -161,6 +166,24 @@ export function register(program: Command): void {
|
|
|
161
166
|
'it, and layout.json beside them holds each frame box. Edit a frame by',
|
|
162
167
|
'editing its file, and an open canvas reloads that frame.',
|
|
163
168
|
'',
|
|
169
|
+
'Reasons, on stderr or in the JSON record:',
|
|
170
|
+
' no-root no .canon/canvas/ folder under the root',
|
|
171
|
+
' no-page, no-frame the target is not on disk',
|
|
172
|
+
' invalid-name a name or target breaks the page or frame form',
|
|
173
|
+
' invalid-size a width or height is not a whole number of pixels',
|
|
174
|
+
' invalid-position an x or y is not a whole number',
|
|
175
|
+
' exists the page or frame is already there',
|
|
176
|
+
' malformed-layout layout.json does not read as a frame map',
|
|
177
|
+
' busy another write holds the page',
|
|
178
|
+
' invalid-address an element address is not a path of positions',
|
|
179
|
+
' address-mismatch the file builds elements the address does not',
|
|
180
|
+
' stale-address the file changed since the address was served',
|
|
181
|
+
' invalid-edit an edit key or value is not one the writer takes',
|
|
182
|
+
' not-text-only text targets an element holding other elements',
|
|
183
|
+
' missing-client-deps preact or @preact/signals does not resolve, so run bun install',
|
|
184
|
+
' no-server no canvas server answers at the address',
|
|
185
|
+
' capture-failed a frame did not render, with the font or browser reason',
|
|
186
|
+
'',
|
|
164
187
|
'Examples:',
|
|
165
188
|
' canon canvas serve',
|
|
166
189
|
' canon canvas page add drafts',
|
package/src/commands/capture.ts
CHANGED
|
@@ -58,6 +58,20 @@ export function register(program: Command): void {
|
|
|
58
58
|
'--width <px>',
|
|
59
59
|
'Viewport width in pixels, so a media query resolves at that width',
|
|
60
60
|
)
|
|
61
|
+
.addHelpText(
|
|
62
|
+
'after',
|
|
63
|
+
[
|
|
64
|
+
'',
|
|
65
|
+
'The selector has no default, since the element to crop to belongs to the',
|
|
66
|
+
'page. Each element holding text inside it must resolve its first font',
|
|
67
|
+
'family, and a generic keyword such as monospace or system-ui fails,',
|
|
68
|
+
'since it resolves differently on each machine. The user agent sets',
|
|
69
|
+
'monospace on pre, code, kbd, and samp, so each needs its own',
|
|
70
|
+
'font-family. --width takes one whole number and sets the viewport, so',
|
|
71
|
+
'run it once per breakpoint with its own --out.',
|
|
72
|
+
'',
|
|
73
|
+
].join('\n'),
|
|
74
|
+
)
|
|
61
75
|
.action(
|
|
62
76
|
async (
|
|
63
77
|
source: string,
|
package/src/commands/claude.ts
CHANGED
|
@@ -319,8 +319,13 @@ export function register(program: Command): void {
|
|
|
319
319
|
' 0 the file was read',
|
|
320
320
|
' 1 refused, with the reason on stderr',
|
|
321
321
|
'',
|
|
322
|
+
'Reasons:',
|
|
323
|
+
' no-claude-md the tree has no always-loaded file',
|
|
324
|
+
' no-rules no path-scoped rule under .claude/rules/, so every path would',
|
|
325
|
+
' report as uncovered',
|
|
326
|
+
'',
|
|
322
327
|
'Reports rather than gates. Whether a bullet belongs in a rule is the',
|
|
323
|
-
'judgment canon/context/context-model
|
|
328
|
+
'judgment canon/context/context-model.md states, and naming a path is evidence for it',
|
|
324
329
|
'rather than the answer.',
|
|
325
330
|
'',
|
|
326
331
|
'Examples:',
|
|
@@ -432,6 +437,8 @@ export function register(program: Command): void {
|
|
|
432
437
|
' 1 refused, with the reason on stderr',
|
|
433
438
|
' 2 a skill folder carries no REQUIREMENT.md',
|
|
434
439
|
'',
|
|
440
|
+
'Refuses when neither claude/skills/ nor .claude/skills/ resolves.',
|
|
441
|
+
'',
|
|
435
442
|
'Only a missing REQUIREMENT.md sets a failing exit code. Name, description,',
|
|
436
443
|
'folder, and requirement-section findings are advisory.',
|
|
437
444
|
'',
|
|
@@ -460,6 +467,10 @@ export function register(program: Command): void {
|
|
|
460
467
|
' 0 history was read, whether or not a body moved',
|
|
461
468
|
' 1 the question could not be answered, with the reason on stderr',
|
|
462
469
|
'',
|
|
470
|
+
'Refuses on an absent shipped corpus, an absent repository, and a ref',
|
|
471
|
+
'matching no commit, each with its own reason. A target loading the',
|
|
472
|
+
'plugin from a marketplace cache has no history, so it refuses there.',
|
|
473
|
+
'',
|
|
463
474
|
'A moved body means the file changed, not that a session holds a stale',
|
|
464
475
|
'copy. Passing a ref older than the oldest load over-reports, which is',
|
|
465
476
|
'the safe direction. Confirm a name by reading the body.',
|
|
@@ -502,6 +513,8 @@ export function register(program: Command): void {
|
|
|
502
513
|
' 1 refused, with the reason on stderr',
|
|
503
514
|
' 2 at least one citation is unqualified',
|
|
504
515
|
'',
|
|
516
|
+
'Refuses a tree carrying neither claude/skills/ nor .claude/skills/.',
|
|
517
|
+
'',
|
|
505
518
|
'Reports rather than gates. A toolkit-scoped instruction is sometimes',
|
|
506
519
|
'meant for a session in this repository, so the verdict is a reading',
|
|
507
520
|
'and the repair is to name the owner in the sentence.',
|
package/src/commands/context.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolve } from 'node:path'
|
|
1
|
+
import { join, relative, resolve } from 'node:path'
|
|
2
2
|
import type { Command } from 'commander'
|
|
3
3
|
import {
|
|
4
4
|
type ContextAuditRefusal,
|
|
@@ -12,14 +12,22 @@ import {
|
|
|
12
12
|
matchesSiblings,
|
|
13
13
|
measureFolders,
|
|
14
14
|
extraSections,
|
|
15
|
+
GOTCHA_CAP,
|
|
16
|
+
LAYOUT_BULLET_CAP,
|
|
17
|
+
LAYOUT_PARAGRAPH_CAP,
|
|
15
18
|
missingSections,
|
|
19
|
+
OTHER_FOLDERS,
|
|
16
20
|
PROVENANCE_FOLDER,
|
|
17
21
|
ALLOWED_SECTIONS_BY_FOLDER,
|
|
18
22
|
REQUIRED_SECTIONS,
|
|
19
23
|
REQUIRED_SECTIONS_BY_FOLDER,
|
|
20
24
|
requiredSections,
|
|
25
|
+
RETIRED_SECTIONS_BY_FOLDER,
|
|
26
|
+
shapeFindings,
|
|
21
27
|
type ExtraSectionFinding,
|
|
22
28
|
type SectionFinding,
|
|
29
|
+
type ShapeFinding,
|
|
30
|
+
type ShapeIssue,
|
|
23
31
|
} from '@/context/audit'
|
|
24
32
|
import { auditCitations, type CitationReport } from '@/context/citations'
|
|
25
33
|
import {
|
|
@@ -49,6 +57,8 @@ import {
|
|
|
49
57
|
resolveFolders,
|
|
50
58
|
} from '@/context/folders'
|
|
51
59
|
import { isGating } from '@/context/gate'
|
|
60
|
+
import { isShapeGated, SHAPE_GATED_FOLDERS } from '@/context/shape-gated'
|
|
61
|
+
import { currentWorktreeRoot } from '@/git/worktree'
|
|
52
62
|
import {
|
|
53
63
|
isOverWordCap,
|
|
54
64
|
measureRequirements,
|
|
@@ -103,7 +113,7 @@ export function register(program: Command): void {
|
|
|
103
113
|
.option('--citations-only', 'Run the gating citation check alone')
|
|
104
114
|
.option(
|
|
105
115
|
'--gate',
|
|
106
|
-
'Also fail on a missing required section or index drift, the findings that are facts',
|
|
116
|
+
'Also fail on a missing required section, an H2 outside the set, a shape break in a gated folder, or index drift, the findings that are facts',
|
|
107
117
|
)
|
|
108
118
|
.addHelpText(
|
|
109
119
|
'after',
|
|
@@ -118,10 +128,13 @@ export function register(program: Command): void {
|
|
|
118
128
|
'stating a word cap gates past it, on any run except',
|
|
119
129
|
'--citations-only, which never measures it. A record stating no',
|
|
120
130
|
'cap is reported and never gated. --gate widens the gate to the',
|
|
121
|
-
'
|
|
122
|
-
'
|
|
123
|
-
'requires Overview and Layout
|
|
124
|
-
'
|
|
131
|
+
'findings that are facts rather than judgments: a missing',
|
|
132
|
+
'required section, an H2 outside the closed set, and index drift.',
|
|
133
|
+
'A context entry requires Overview and Layout and allows Gotchas.',
|
|
134
|
+
'A shape break, such as a Decisions section or a sixth gotcha, is',
|
|
135
|
+
'reported everywhere and gated only under a shape-gated folder.',
|
|
136
|
+
'Entry length, reference form, table, and provenance are',
|
|
137
|
+
'judgments under both.',
|
|
125
138
|
'',
|
|
126
139
|
'Depth and bullet weight are stated over every markdown file rather',
|
|
127
140
|
'than over a context entry, so `canon markdown audit` measures them.',
|
|
@@ -644,6 +657,15 @@ async function runAudit(
|
|
|
644
657
|
const drift = gateOnly ? [] : await auditIndexes(folders)
|
|
645
658
|
const sections = gateOnly ? [] : missingSections(root, folders, entries)
|
|
646
659
|
const extras = gateOnly ? [] : extraSections(entries)
|
|
660
|
+
// The gated prefixes name paths from the repository root, while an entry's
|
|
661
|
+
// path runs from the audit root, which is a seed tree's own root when one is
|
|
662
|
+
// passed. Resolving here keeps a seed tree listed under its toolkit path.
|
|
663
|
+
const top = gateOnly ? root : await currentWorktreeRoot(root)
|
|
664
|
+
const shape = gateOnly
|
|
665
|
+
? []
|
|
666
|
+
: shapeFindings(entries, (rel) =>
|
|
667
|
+
isShapeGated(relative(top, join(root, rel))),
|
|
668
|
+
)
|
|
647
669
|
const length = gateOnly ? undefined : lengthFindings(entries)
|
|
648
670
|
// Absent under `--citations-only` and null when the project carries no
|
|
649
671
|
// record. A run that never looked and a project with nothing to look at are
|
|
@@ -658,6 +680,7 @@ async function runAudit(
|
|
|
658
680
|
reportCitations(citations, cited)
|
|
659
681
|
reportReferenceForm(entries, folders)
|
|
660
682
|
reportSections(sections, extras, folders)
|
|
683
|
+
reportShape(shape)
|
|
661
684
|
reportLength(length ?? [])
|
|
662
685
|
reportTables(entries)
|
|
663
686
|
reportProvenance(entries, folders)
|
|
@@ -696,6 +719,7 @@ async function runAudit(
|
|
|
696
719
|
length,
|
|
697
720
|
missingSections: sections,
|
|
698
721
|
extraSections: extras,
|
|
722
|
+
shapeFindings: shape,
|
|
699
723
|
indexDrift: drift,
|
|
700
724
|
// Null says the run opened the project and found no record, which a
|
|
701
725
|
// target that never wrote one is entitled to. Absent says the run
|
|
@@ -711,6 +735,11 @@ async function runAudit(
|
|
|
711
735
|
// caller without an error.
|
|
712
736
|
requiredSectionsByFolder: REQUIRED_SECTIONS_BY_FOLDER,
|
|
713
737
|
allowedSectionsByFolder: ALLOWED_SECTIONS_BY_FOLDER,
|
|
738
|
+
retiredSectionsByFolder: RETIRED_SECTIONS_BY_FOLDER,
|
|
739
|
+
gotchaCap: GOTCHA_CAP,
|
|
740
|
+
layoutBulletCap: LAYOUT_BULLET_CAP,
|
|
741
|
+
layoutParagraphCap: LAYOUT_PARAGRAPH_CAP,
|
|
742
|
+
shapeGatedFolders: SHAPE_GATED_FOLDERS,
|
|
714
743
|
},
|
|
715
744
|
})}\n`,
|
|
716
745
|
)
|
|
@@ -722,6 +751,7 @@ async function runAudit(
|
|
|
722
751
|
requirements !== undefined && isOverWordCap(requirements),
|
|
723
752
|
sections,
|
|
724
753
|
extraSections: extras,
|
|
754
|
+
shape,
|
|
725
755
|
drift,
|
|
726
756
|
widened,
|
|
727
757
|
})
|
|
@@ -958,7 +988,7 @@ function reportSections(
|
|
|
958
988
|
logInfo(
|
|
959
989
|
`The set is closed: ${Object.entries(ALLOWED_SECTIONS_BY_FOLDER)
|
|
960
990
|
.map(([name, set]) => `canon/${name}/ allows ${set.join(', ')}`)
|
|
961
|
-
.join('. ')} as H2.
|
|
991
|
+
.join('. ')} as H2. A folder is an H3 under Layout.`,
|
|
962
992
|
)
|
|
963
993
|
|
|
964
994
|
if (extras.length === 0) {
|
|
@@ -974,6 +1004,75 @@ function reportSections(
|
|
|
974
1004
|
)
|
|
975
1005
|
}
|
|
976
1006
|
|
|
1007
|
+
/** Characters of a paragraph the report quotes, enough to find it by. */
|
|
1008
|
+
const QUOTE_WIDTH = 60
|
|
1009
|
+
|
|
1010
|
+
function clip(text: string): string {
|
|
1011
|
+
return text.length > QUOTE_WIDTH ? `${text.slice(0, QUOTE_WIDTH)}...` : text
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
/** How each shape break reads in the report. */
|
|
1015
|
+
function readIssue(issue: ShapeIssue): string {
|
|
1016
|
+
switch (issue.kind) {
|
|
1017
|
+
case 'retired-section':
|
|
1018
|
+
return `retired section: ${issue.text}`
|
|
1019
|
+
case 'gotcha-count':
|
|
1020
|
+
return `${issue.count ?? 0} gotchas, past ${GOTCHA_CAP}`
|
|
1021
|
+
case 'gotcha-heading':
|
|
1022
|
+
return `heading inside Gotchas: ${issue.text}`
|
|
1023
|
+
case 'gotcha-paragraph':
|
|
1024
|
+
return `paragraph inside Gotchas: ${clip(issue.text)}`
|
|
1025
|
+
case 'layout-heading':
|
|
1026
|
+
return `Layout H3 titled neither a path nor ${OTHER_FOLDERS}: ${issue.text}`
|
|
1027
|
+
case 'layout-bullets':
|
|
1028
|
+
return `${issue.count ?? 0} bullets under ${issue.text}, past ${LAYOUT_BULLET_CAP}`
|
|
1029
|
+
case 'layout-paragraphs':
|
|
1030
|
+
return `${issue.count ?? 0} paragraphs under ${issue.text}, past ${LAYOUT_PARAGRAPH_CAP}`
|
|
1031
|
+
case 'layout-depth':
|
|
1032
|
+
return `heading below H3 under Layout: ${issue.text}`
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* Names each entry breaking the section shape, gated ones first, and states
|
|
1038
|
+
* which prefixes gate on every run, since an empty gated list and a corpus that
|
|
1039
|
+
* conforms would otherwise print the same report.
|
|
1040
|
+
*/
|
|
1041
|
+
function reportShape(shape: readonly ShapeFinding[]): void {
|
|
1042
|
+
logStep('Shape')
|
|
1043
|
+
|
|
1044
|
+
logInfo(
|
|
1045
|
+
SHAPE_GATED_FOLDERS.length === 0
|
|
1046
|
+
? 'No folder is shape-gated yet, so every shape break reports and none gates.'
|
|
1047
|
+
: `Gated under --gate: ${SHAPE_GATED_FOLDERS.join(', ')}. A break elsewhere reports and never gates.`,
|
|
1048
|
+
)
|
|
1049
|
+
|
|
1050
|
+
if (shape.length === 0) {
|
|
1051
|
+
logInfo('Every entry holds the section shape.')
|
|
1052
|
+
return
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
const gated = shape.filter((finding) => finding.gated)
|
|
1056
|
+
if (gated.length > 0) {
|
|
1057
|
+
logWarn(
|
|
1058
|
+
`${gated.length} gated ${gated.length === 1 ? 'entry' : 'entries'} breaking the shape`,
|
|
1059
|
+
)
|
|
1060
|
+
}
|
|
1061
|
+
logInfo(
|
|
1062
|
+
`${shape.length} ${shape.length === 1 ? 'entry' : 'entries'} breaking the shape in all`,
|
|
1063
|
+
)
|
|
1064
|
+
pipeOutput(
|
|
1065
|
+
[...gated, ...shape.filter((finding) => !finding.gated)]
|
|
1066
|
+
.map(
|
|
1067
|
+
(finding) =>
|
|
1068
|
+
`${finding.rel}${finding.gated ? ' gated' : ''}\n${finding.issues
|
|
1069
|
+
.map((issue) => ` :${issue.line} ${readIssue(issue)}`)
|
|
1070
|
+
.join('\n')}`,
|
|
1071
|
+
)
|
|
1072
|
+
.join('\n'),
|
|
1073
|
+
)
|
|
1074
|
+
}
|
|
1075
|
+
|
|
977
1076
|
/** How each question reads in the report, in the standard's own order. */
|
|
978
1077
|
const QUESTION_LABEL: Record<LengthQuestion, string> = {
|
|
979
1078
|
domain: 'one domain',
|
package/src/commands/demo.ts
CHANGED
|
@@ -76,6 +76,12 @@ export function register(program: Command): void {
|
|
|
76
76
|
'wait condition, and the timing a beat lacks, and the timing is a',
|
|
77
77
|
'starting point you tune, which is why a recompile refuses to overwrite.',
|
|
78
78
|
'',
|
|
79
|
+
'Reasons:',
|
|
80
|
+
' draft-missing no file at the draft path',
|
|
81
|
+
' draft-unreadable no beat sheet in the draft, or a sheet with no beats',
|
|
82
|
+
' plan-exists a plan is already there and --force was not passed',
|
|
83
|
+
' plan-unresolved a URL or a target is still empty, named field by field',
|
|
84
|
+
'',
|
|
79
85
|
'Exit codes:',
|
|
80
86
|
' 0 a plan was written',
|
|
81
87
|
' 1 refused, with the reason on stderr',
|
|
@@ -114,9 +120,20 @@ export function register(program: Command): void {
|
|
|
114
120
|
'Writes mp4 beside the webm when ffmpeg is on PATH, and skips it',
|
|
115
121
|
`otherwise without failing the run. Install it with: ${INSTALL_CONVERTER}`,
|
|
116
122
|
'',
|
|
123
|
+
'Beside the webm it writes <video>.timeline.json, an entries array with',
|
|
124
|
+
'one entry per step carrying index, kind, and startMs and endMs from the',
|
|
125
|
+
'first frame. A click, fill, or hover entry adds box, the target in',
|
|
126
|
+
'viewport pixels. The still is the hero beat, or the last beat.',
|
|
127
|
+
'',
|
|
117
128
|
'A gif is opt-in behind --gif, since it is far larger than the webm',
|
|
118
129
|
'and only a host that strips video needs one. GitHub is that host.',
|
|
119
130
|
'',
|
|
131
|
+
'Reasons:',
|
|
132
|
+
' no-output-requested --no-video with --no-still, which would write nothing',
|
|
133
|
+
' plan-unreadable the plan is not JSON, or a step names a kind nothing drives',
|
|
134
|
+
' browser-missing the browser binary is not installed',
|
|
135
|
+
' engine-missing the browser package did not resolve',
|
|
136
|
+
'',
|
|
120
137
|
'Exit codes:',
|
|
121
138
|
' 0 the recording and the still were written',
|
|
122
139
|
' 1 refused, with the reason on stderr',
|
|
@@ -149,6 +166,11 @@ export function register(program: Command): void {
|
|
|
149
166
|
'Needs ffmpeg on PATH, the same binary demo run already shells to for',
|
|
150
167
|
`mp4 and gif conversion. Install it with: ${INSTALL_CONVERTER}`,
|
|
151
168
|
'',
|
|
169
|
+
'Reasons:',
|
|
170
|
+
' video-missing no file at the video path',
|
|
171
|
+
' converter-missing ffmpeg is not on PATH, so nothing was extracted',
|
|
172
|
+
' extraction-failed ffmpeg exited non-zero, with its stderr in the message',
|
|
173
|
+
'',
|
|
152
174
|
'Exit codes:',
|
|
153
175
|
' 0 frames were written',
|
|
154
176
|
' 1 refused, with the reason on stderr',
|
package/src/commands/deps.ts
CHANGED
|
@@ -56,6 +56,12 @@ export function register(program: Command): void {
|
|
|
56
56
|
' 1 refused, with the reason on stderr',
|
|
57
57
|
' 2 at least one advisory was published',
|
|
58
58
|
'',
|
|
59
|
+
'Reasons:',
|
|
60
|
+
' no-manifest no package.json in the project',
|
|
61
|
+
' no-lockfile dependencies were never resolved, so install before auditing',
|
|
62
|
+
' no-record the lookup returned no record that parses, as an unreachable',
|
|
63
|
+
' index does',
|
|
64
|
+
'',
|
|
59
65
|
'Examples:',
|
|
60
66
|
' canon deps audit',
|
|
61
67
|
' canon deps audit --json',
|
package/src/commands/driver.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { Command } from 'commander'
|
|
|
4
4
|
import { INSTALL_BROWSER, isEngineMissing } from '@/browser/engine'
|
|
5
5
|
import type { DriverRefusal } from '@/driver/drive'
|
|
6
6
|
import { describeViewport } from '@/driver/probes/viewport'
|
|
7
|
-
import { PROBE_NAMES, readDriverPlan } from '@/driver/steps'
|
|
7
|
+
import { PROBE_NAMES, readDriverPlan, type ProbeName } from '@/driver/steps'
|
|
8
8
|
import type { PlanRefusal } from '@/driver/steps'
|
|
9
9
|
import {
|
|
10
10
|
intro,
|
|
@@ -55,6 +55,15 @@ const DRIVE_REFUSALS: Record<DriverRefusal, string> = {
|
|
|
55
55
|
'drive-failed': 'The drive failed against a reachable page.',
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const PROBE_NOTES: Record<ProbeName, string> = {
|
|
59
|
+
focus: 'keyboard focus that changes nothing visible, read after a Tab press',
|
|
60
|
+
details:
|
|
61
|
+
'a details panel off the viewport or a row under the tap minimum, read open',
|
|
62
|
+
'diagram-geometry':
|
|
63
|
+
'an SVG label outside its frame, covered by a fill, or on another label',
|
|
64
|
+
'diagram-strokes': 'an SVG label a stroke crosses, in either paint order',
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
export function register(program: Command): void {
|
|
59
68
|
program
|
|
60
69
|
.command('drive')
|
|
@@ -103,7 +112,24 @@ export function register(program: Command): void {
|
|
|
103
112
|
` ${INSTALL_BROWSER}`,
|
|
104
113
|
'',
|
|
105
114
|
'Probes:',
|
|
106
|
-
...PROBE_NAMES.map(
|
|
115
|
+
...PROBE_NAMES.map(
|
|
116
|
+
(name) => ` ${name.padEnd(18)}${PROBE_NOTES[name]}`,
|
|
117
|
+
),
|
|
118
|
+
'',
|
|
119
|
+
'Reasons:',
|
|
120
|
+
' no-run-file nothing readable at the run path',
|
|
121
|
+
' unreadable-plan the run file is not valid JSON',
|
|
122
|
+
' no-steps the run names no step',
|
|
123
|
+
' no-probes the run names an empty probe list',
|
|
124
|
+
' unknown-probe the run names a probe this build does not ship',
|
|
125
|
+
' bad-step a step is missing what the driver needs to perform it',
|
|
126
|
+
' no-viewport the run declares no viewport',
|
|
127
|
+
' no-width the viewport has no width to wrap at',
|
|
128
|
+
' no-heights the viewport names no height, which is never defaulted',
|
|
129
|
+
' engine-missing the browser engine is not installed in this project',
|
|
130
|
+
' browser-missing the engine is installed and its browser binary is not',
|
|
131
|
+
' server-unreachable nothing answered at the URL, so no state was reached',
|
|
132
|
+
' drive-failed the drive failed against a reachable page',
|
|
107
133
|
'',
|
|
108
134
|
'Step kinds:',
|
|
109
135
|
' click <target> press the first element the selector matches',
|