@erclx/canon 5.38.0 → 5.39.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 +1 -1
- 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 +36 -17
- 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 +7 -4
- 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-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 +62 -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-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/create-report.md +36 -0
- 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 +22 -18
- 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/context-audit-checks.md +19 -1
- package/docs/agents/context-audit.md +2 -2
- package/docs/agents/driver.md +1 -1
- package/docs/agents/hooks.md +21 -1
- package/docs/agents/index.md +10 -14
- package/docs/agents/indexes.md +25 -29
- package/docs/agents/install-and-sync.md +124 -235
- package/docs/agents/markdown-audit-density.md +39 -0
- package/docs/agents/markdown-audit-weight.md +9 -7
- package/docs/agents/markdown-audit.md +18 -14
- 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/routing.md +1 -1
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/skills-reach.md +1 -1
- package/docs/agents/targets.md +25 -77
- package/docs/target/migrations.md +1 -1
- package/docs/target/projects.md +2 -2
- package/docs/workflow/ai-workflow.md +2 -2
- package/docs/workflow/parallel-features.md +2 -2
- package/docs/workflow/skill-map.md +1 -1
- package/docs/workflow/visual-design-workflow.md +1 -1
- package/package.json +1 -1
- package/src/commands/claude.ts +1 -1
- package/src/commands/context.ts +106 -7
- package/src/commands/hooks.ts +63 -0
- package/src/commands/markdown.ts +169 -32
- package/src/context/audit.ts +256 -5
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/gate.ts +23 -7
- package/src/context/shape-gated.ts +28 -0
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/gate/measures.ts +15 -190
- package/src/gate/stages.ts +7 -23
- 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 +174 -0
- package/src/markdown/structure.ts +9 -59
- package/src/shipped/references.ts +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/docs/agents/commands.md +0 -154
- package/docs/agents/docs.md +0 -27
- package/docs/agents/drift-surfaces.md +0 -201
- package/docs/agents/gov-detect.md +0 -47
- package/docs/agents/scripting.md +0 -142
- package/src/markdown/growth.ts +0 -43
|
@@ -15,44 +15,58 @@ The candidates live on the local design canvas, the surface `canon:canvas-board`
|
|
|
15
15
|
|
|
16
16
|
- If the request names one answer and asks for it to be built, stop: `❌ This names one answer, so there is nothing to pick between. Use /canon:plan-feature.`
|
|
17
17
|
- If the decision has no visible form, stop: `❌ Nothing to look at. Drafting candidates needs a decision a render can show.`
|
|
18
|
-
- Draft no candidate for a decision the operator has not asked to make
|
|
18
|
+
- Draft no candidate for a decision the operator has not asked to make, since options everywhere spend their attention rather than saving it
|
|
19
19
|
|
|
20
20
|
## Step 1: name the decision and the arms
|
|
21
21
|
|
|
22
22
|
1. State the decision in one sentence, naming what changes between arms and what stays fixed.
|
|
23
|
-
2. Emit the design read in the run's
|
|
24
|
-
3. Derive a kebab slug from that sentence. The first round's
|
|
23
|
+
2. Emit the design read in the run's output, in the form `design-taste` fixes, taking the layer from its ordered catalog. The arms differ at that layer, and a missing read is visible.
|
|
24
|
+
3. Derive a kebab slug from that sentence. The first round's page is `<slug>`, and Step 5 names later rounds `<slug>-2`, `<slug>-3`, and so on.
|
|
25
25
|
4. Write one arm per candidate, each carrying an id, a label, and what the arm costs. An arm with no stated cost is not an option.
|
|
26
26
|
5. Make the current state arm `0`, so the baseline is a candidate rather than an absence. A decision with nothing shipped yet says so and starts at arm `1`.
|
|
27
27
|
6. Stop at three to five arms. Two is a comparison the operator can hold in prose, and past five the pick stops being a look and becomes a sort.
|
|
28
28
|
|
|
29
|
+
Inside a live `plan-groundwork` track, renders land in the track's own `evidence/<slug>/renders/`, since a candidate render is evidence its decision file cites. Everywhere else they land in session scratch.
|
|
30
|
+
|
|
29
31
|
## Step 2: draft the arms as frames on one canvas page
|
|
30
32
|
|
|
31
|
-
Every arm of a round sits as one frame on one canvas page, side by side. The
|
|
33
|
+
Every arm of a round sits as one frame on one canvas page, side by side. The operator judges that page, never a set of separate images compared from memory.
|
|
32
34
|
|
|
33
|
-
1. Start the canvas the way `canon:canvas-board` Step 1 states, unless this run already has
|
|
34
|
-
2. Add the round's page with `canon canvas page add <page> --json` and record
|
|
35
|
-
3. Add each arm
|
|
35
|
+
1. Start the canvas the way `canon:canvas-board` Step 1 states, unless this run already has. Note whether this run started the server, since Step 6 stops only a server this run started.
|
|
36
|
+
2. Add the round's page with `canon canvas page add <page> --json` and record it on the run's list of pages. A name `canvas list` already shows is somebody else's, so take the next free suffix.
|
|
37
|
+
3. Add each arm with `canon canvas frame add <page> arm-<id> --width <px> --height <px> --json`. Step 6's archive keys on the `arm-<id>` names.
|
|
36
38
|
4. Write each arm's whole document to the `path` the add verb reported. From a linked worktree, take the heredoc route `canon:canvas-board` Step 3 gives for a main-root write.
|
|
37
39
|
5. Lay the frames out in one row, in arm order, with `canon canvas frame move <page> arm-<id> --x <px> --y <px> --json`.
|
|
38
40
|
|
|
41
|
+
The `canvas-board` start reads `canon canvas list --json`, serves with `canon canvas serve --json` in the background unless the operator named an address that answers, and checks the shell's body holds a `<script` tag. A refused serve or a blank shell stops the run with its `reason`, and no file stands in for a canvas.
|
|
42
|
+
|
|
43
|
+
Set each frame's width to the one the arm is judged at. A frame renders at its own layout width on the canvas and in a capture alike, so a layout decision needs no device toolbar.
|
|
44
|
+
|
|
39
45
|
### What every frame carries
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
-
|
|
47
|
+
Each frame carries its own label and follows the canvas theme, so the set reads as one comparison.
|
|
48
|
+
|
|
49
|
+
- Label each arm inside its frame with its id and its cost, since the composite capture draws no captions
|
|
50
|
+
- Theme every arm off the `data-theme` attribute the canvas sets on each frame's root, so the theme toggle sets the whole set at once. A set spanning both themes cannot be compared.
|
|
51
|
+
- Give no arm a script that stores a theme and reapplies it on load. It overwrites the toggle, and a fresh browser profile hides the fault.
|
|
44
52
|
|
|
45
|
-
|
|
53
|
+
### Default path and live app
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
55
|
+
A running app under decision takes the live-app branch, and every other decision takes the default path.
|
|
56
|
+
|
|
57
|
+
- Live app: lift the rendered markup and link a copy of the built stylesheet rather than inlining, per `${CLAUDE_SKILL_DIR}/references/live-arms.md`
|
|
58
|
+
- Default path: inline every style, script, and asset. A frame resolves nothing outside its own page folder, so a build step or network font silently drops out.
|
|
59
|
+
- Default path: name a real font first in the stack, one the machine has or the frame embeds, such as the project's own family. A generic keyword such as `system-ui` resolves differently per machine.
|
|
60
|
+
|
|
61
|
+
The capture refuses a frame that would rewrap against a substitute font rather than ship a false comparison. A frame naming no font is refused on whatever the default resolves to.
|
|
50
62
|
|
|
51
63
|
### What varies
|
|
52
64
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- Vary the property the decision is about
|
|
65
|
+
Vary one property across the arms, since a pick cannot say which of three differences decided it.
|
|
66
|
+
|
|
67
|
+
- Vary the property the decision is about. Holding composition fixed and varying color produces five skins of one design, and a palette cannot be picked ahead of the composition it serves.
|
|
68
|
+
- Grey-box the arms when the declared layer sits below typography, per `design-taste`, and say the set is grey-boxed when handing it over
|
|
69
|
+
- Do not grey-box a set judged at composition that carries a finished palette, since the operator looks at the higher layers instead of the question
|
|
56
70
|
|
|
57
71
|
## Step 3: render and hand off
|
|
58
72
|
|
|
@@ -62,63 +76,73 @@ Render the page and look at what came back before handing anything over:
|
|
|
62
76
|
canon canvas capture <page> --composite --json
|
|
63
77
|
```
|
|
64
78
|
|
|
65
|
-
- Point `--out` at `evidence/<slug>/renders/<page>.png` inside a live track, and leave
|
|
66
|
-
- Read the PNG's `path` off the record. The composite shows
|
|
67
|
-
-
|
|
68
|
-
|
|
79
|
+
- Point `--out` at `evidence/<slug>/renders/<page>.png` inside a live track, and leave the scratch default elsewhere. Step 6 archives the picked round alone.
|
|
80
|
+
- Read the PNG's `path` off the record. The composite shows each frame in its default theme, so check the other theme on the live canvas.
|
|
81
|
+
- A capture refusing on a font names the family it read. Take the repair `canon:canvas-board` Step 6 gives and capture again.
|
|
82
|
+
|
|
83
|
+
When `canon canvas capture` refuses for a missing browser binary, report it and name `bunx playwright install chromium` as the repair. Stop the canvas server if this run started it, then stop rather than describe an arm nobody has seen.
|
|
69
84
|
|
|
70
85
|
### Handing over
|
|
71
86
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
87
|
+
Hand over the address rather than a description. Emit the canvas link first on its own line, naming the page, then the PNG path on its own line.
|
|
88
|
+
|
|
89
|
+
- A still answers how a thing looks and none of a hover, a scroll-linked position, or a pace, which the live frame does
|
|
90
|
+
- Never report a visual result you have not looked at, since a claim about appearance with no render behind it is a guess
|
|
91
|
+
- Look to judge rather than to confirm. Name the weakest thing on the page in a sentence, fix it where that sentence would embarrass the work, and say what remains.
|
|
75
92
|
|
|
76
93
|
## Step 4: take the pick
|
|
77
94
|
|
|
78
95
|
Put the choice to the operator through the structured question surface, since a call the operator's preference decides always routes through it rather than through prose.
|
|
79
96
|
|
|
80
|
-
- Emit the link
|
|
81
|
-
- One option per arm, labeled with the arm's id and carrying its cost as the description
|
|
82
|
-
- Rank the recommendation first and mark it `(Recommended)
|
|
83
|
-
- Author the real arms only. The surface appends its own
|
|
97
|
+
- Emit the link ahead of the question call and again in the question's text, since some surfaces render the card alone
|
|
98
|
+
- One option per arm, labeled with the arm's id and carrying its cost as the description
|
|
99
|
+
- Rank the recommendation first and mark it `(Recommended)`
|
|
100
|
+
- Author the real arms only. The surface appends its own free-text and reopen escapes, and a duplicate is rejected.
|
|
84
101
|
|
|
85
102
|
### Taking the answer
|
|
86
103
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
104
|
+
Take no pick on the operator's behalf when two arms are both defensible and the difference is taste. That call is theirs, and a silent one is the failure this skill exists to prevent.
|
|
105
|
+
|
|
106
|
+
Read `canon canvas selection --json` when the answer points at the canvas, such as "the selected one". Resolve it against the record's `page` as well as its `frame`, since every round reuses the `arm-<id>` names.
|
|
107
|
+
|
|
108
|
+
| Selection | Reading |
|
|
109
|
+
| ---------------------------------------------------------------- | ---------------------------------------------- |
|
|
110
|
+
| A frame on the current round's page | The pick |
|
|
111
|
+
| A frame on an earlier round's page | A revert, so name the round back before acting |
|
|
112
|
+
| A fresh element inside a picked frame | A correction Step 5 carries by its `index` |
|
|
113
|
+
| `selection: null`, a page this run did not add, or `stale: true` | No answer, so ask again rather than guess |
|
|
90
114
|
|
|
91
115
|
## Step 5: loop on the pick
|
|
92
116
|
|
|
93
|
-
1. Add each iteration as its own page, recorded on the run's list
|
|
117
|
+
1. Add each iteration as its own page, recorded on the run's list. An overwritten page cannot be reopened, and the losing round stops a correction re-proposing a rejected arm.
|
|
94
118
|
2. Write fresh arms off the pick and return to Step 2 where the correction opens a new question. Revise the one arm's frame where it does not.
|
|
95
119
|
3. Re-render, hand off again, and take the next answer.
|
|
96
|
-
4. Repeat until the operator says it is right.
|
|
120
|
+
4. Repeat until the operator says it is right. A run stopping because the arms stopped differing has stopped early.
|
|
97
121
|
5. Hold the real surface untouched across every iteration. Nothing outside the run's own canvas pages changes until the pick is final.
|
|
98
122
|
|
|
99
123
|
## Step 6: close
|
|
100
124
|
|
|
101
125
|
1. Apply the winning arm to the real surface, in one change.
|
|
102
|
-
2. Close out
|
|
103
|
-
3. Capture the
|
|
104
|
-
4. Resolve `<archive-dir>` as `.canon/picks/<slug>/` against the main worktree root, since shared session scratch resolves there rather than
|
|
105
|
-
5. Delete every page folder on the run's list from under the `content` folder `canon canvas list --json` reports
|
|
126
|
+
2. Close out any document stating the decision as open, in the same change, naming the winner and the arms that stayed defensible. Skip this where nothing stated the decision.
|
|
127
|
+
3. Capture the picked round's frames with `canon canvas capture <page> --out <archive-dir> --json`. Each lands as `arm-<id>.png`, keeping the losing arms as a revert record.
|
|
128
|
+
4. Resolve `<archive-dir>` as `.canon/picks/<slug>/` against the main worktree root, since shared session scratch resolves there rather than in a linked worktree.
|
|
129
|
+
5. Delete every page folder on the run's list from under the `content` folder `canon canvas list --json` reports. Touch no page the run did not add, whatever its name.
|
|
106
130
|
6. Stop the canvas server if this run started it, and leave one the operator started running.
|
|
107
|
-
7. Leave the renders in
|
|
108
|
-
8. Report each page
|
|
109
|
-
9. Report every surface that changed, each on its own line, name the arm
|
|
131
|
+
7. Leave the renders in a live track's `evidence/<slug>/renders/`, since `plan-groundwork` treats evidence as durable.
|
|
132
|
+
8. Report each page whose delete is refused, naming the path for the operator to remove. The pick is applied either way.
|
|
133
|
+
9. Report every surface that changed, each on its own line, name the winning arm by its id and its cost, and report the archive path.
|
|
110
134
|
|
|
111
|
-
|
|
135
|
+
The picked round is the final one unless Step 4 resolved a revert. Archiving any other page lets item 5 delete the winning arm with nothing kept, and a variant left on the canvas is a second design nobody maintains.
|
|
112
136
|
|
|
113
|
-
|
|
137
|
+
## Reading a measurement
|
|
114
138
|
|
|
115
|
-
|
|
139
|
+
A capture proves appearance and a measurement proves a relationship, so reach for the second whenever the claim is a number, such as a contrast ratio, a column width, or a tap target. `canon drive` runs the probes and ships the failure modes each one carries.
|
|
116
140
|
|
|
117
|
-
- Composite alpha before reading a color. A `color-mix` toward transparent resolves to channels plus an alpha, and reading
|
|
118
|
-
- Sample inside the shape. A patch
|
|
119
|
-
- Ask whether a reader would see the thing
|
|
141
|
+
- Composite alpha before reading a color. A `color-mix` toward transparent resolves to channels plus an alpha, and reading them as opaque reports a color nobody sees.
|
|
142
|
+
- Sample inside the shape. A patch at a bounding box corner misses a round control and reads the page behind it.
|
|
143
|
+
- Ask whether a reader would see the thing. A panel sized a healthy 1517 by 639 passed every size check while sitting 1868px above the viewport.
|
|
120
144
|
|
|
121
|
-
`canon drive` reports findings and never gates
|
|
145
|
+
`canon drive` reports findings and never gates. Read its record as evidence for the operator rather than as a filter over the arms, since the probe catalog has not earned the right to drop one.
|
|
122
146
|
|
|
123
147
|
## What this delegates
|
|
124
148
|
|
|
@@ -130,6 +154,8 @@ Cite these rather than restating them. A step reimplemented here rots against th
|
|
|
130
154
|
|
|
131
155
|
### Git and review
|
|
132
156
|
|
|
157
|
+
Commits, review, and the canvas mechanics each have an owner.
|
|
158
|
+
|
|
133
159
|
- `git-stage`, `git-pr`, and `git-followup` carry the commits and the pull request
|
|
134
160
|
- `review-pr` and `review-address` run the review pass
|
|
135
161
|
- `canon:canvas-board` carries the canvas start-and-check sequence, the main-root write route for a frame, and the selection and capture refusals
|
|
@@ -21,8 +21,10 @@ Each kind has one standard and one reference. Load the reference for the resolve
|
|
|
21
21
|
| readme | a `README.md`, at the root or in a folder | `${CLAUDE_SKILL_DIR}/../docs-sync/references/readme.md` | `${CLAUDE_SKILL_DIR}/references/readme.md` |
|
|
22
22
|
|
|
23
23
|
- Read the kind off the destination the request names: a path, a folder, or the document's own name, such as "a context entry" or "a wiki page".
|
|
24
|
-
- Ask which kind when the request names no destination, offering the candidates the subject fits with the likeliest first
|
|
25
|
-
-
|
|
24
|
+
- Ask which kind when the request names no destination, offering the candidates the subject fits with the likeliest first
|
|
25
|
+
- Never default to `docs/` without saying so, since a subject documented in the wrong surface is invisible to the session that looks for it in the right one
|
|
26
|
+
- If no subject is given for any kind but readme, stop: `❌ No subject given. Name what this document should cover.`
|
|
27
|
+
- A README covers the project or the folder it sits in, so its subject is the target path
|
|
26
28
|
|
|
27
29
|
## Read
|
|
28
30
|
|
|
@@ -50,12 +52,13 @@ Settle the path and check the catalog for a collision the way the reference stat
|
|
|
50
52
|
## Confirm
|
|
51
53
|
|
|
52
54
|
- Show the kind, the resolved path, whatever else the reference names for the preview, and the full drafted content before writing.
|
|
53
|
-
- Confirm with the user
|
|
55
|
+
- Confirm with the user, and wait for that answer rather than treating the tool permission dialog as the gate
|
|
56
|
+
- The kind, the placement, and every detection the reference runs are judgment calls with no diff to preview them against, which is why the dialog cannot stand in
|
|
54
57
|
|
|
55
58
|
## Write
|
|
56
59
|
|
|
57
60
|
- Write the file at the confirmed path, creating the folder when it is absent unless the reference narrows that.
|
|
58
|
-
- Run `canon markdown audit <path
|
|
61
|
+
- Run `canon markdown audit <path>` and fix every ban, density, and reference shape finding until a re-run reports none. The whole file is this run's draft, so every finding is its own.
|
|
59
62
|
- Run `canon indexes regen <folder>` on the folder the reference names, so its `index.md` picks up the new document. Skip it where the reference says the kind keeps no catalog.
|
|
60
63
|
|
|
61
64
|
## Response format
|
|
@@ -73,6 +76,8 @@ Settle the path and check the catalog for a collision the way the reference stat
|
|
|
73
76
|
|
|
74
77
|
### After confirmation
|
|
75
78
|
|
|
79
|
+
One line once the file is written and its audit reports nothing.
|
|
80
|
+
|
|
76
81
|
```plaintext
|
|
77
82
|
✅ Drafted: <path>
|
|
78
83
|
```
|
|
@@ -18,13 +18,13 @@ A project the surface move has not reached keeps its context folder under `.clau
|
|
|
18
18
|
## Placement
|
|
19
19
|
|
|
20
20
|
- Read `<context-root>/index.md` and check every title and description it lists against the domain. Stop on a match: `❌ <path> already covers this domain under a different name. Use context-fold to refresh it instead.`
|
|
21
|
-
- Default a brand-new entry to a flat file, `<context-root>/<slug>.md`. A domain starts as one page's worth of narrative, and the standard splits it into a folder only once
|
|
21
|
+
- Default a brand-new entry to a flat file, `<context-root>/<slug>.md`. A domain starts as one page's worth of narrative, and the standard splits it into a folder only once the entry passes the 300-line ceiling, which a fresh domain never does on day one.
|
|
22
22
|
|
|
23
23
|
## Draft
|
|
24
24
|
|
|
25
|
-
- Read the domain's own folders and files well enough to answer the standard's three questions
|
|
26
|
-
- Draft `title` and `description` frontmatter, then `## Overview`, `## Layout`
|
|
27
|
-
- Keep the standard's closed set and order
|
|
25
|
+
- Read the domain's own folders and files well enough to answer the standard's three questions, being what the domain owns, what each folder does now, and which trap a session would hit.
|
|
26
|
+
- Draft `title` and `description` frontmatter, then `## Overview`, `## Layout` with one H3 per working folder and `### Other folders` for the rest, and `## Gotchas` only for a trap true today.
|
|
27
|
+
- Keep the standard's closed set and order of `Overview`, `Layout`, and `Gotchas`, per `context.md` in the `context-fold` skill's references. Write no decision and no history.
|
|
28
28
|
|
|
29
29
|
## Write
|
|
30
30
|
|
|
@@ -21,6 +21,7 @@ description: The guard, placement, draft additions, and regen folder for a brand
|
|
|
21
21
|
## Draft
|
|
22
22
|
|
|
23
23
|
- Draft `title`, `description`, and `category` where one applies, then the page body.
|
|
24
|
+
- Draft a page documenting one command in the docs standard's reference shape, with `kind: reference` in its frontmatter, so `canon markdown audit` checks its sections.
|
|
24
25
|
- Test the page against the standard's four questions: what the surface is, what to run or write, what it refuses, and where to go for the adjacent surface.
|
|
25
26
|
- Take a diagram only through the Mermaid fence the docs standard permits. Never build a hand-drawn diagram-and-capture loop here.
|
|
26
27
|
|
|
@@ -28,7 +28,8 @@ A page failing either is non-conforming even when it satisfies every shape rule
|
|
|
28
28
|
## Placement
|
|
29
29
|
|
|
30
30
|
- Write a page here only when its subject is owned outside this repository. Route anything about how this repository works to `docs/`, `canon/context/`, or a skill body instead.
|
|
31
|
-
- File the page in the `claude` subfolder of the `wiki` folder
|
|
31
|
+
- File the page in the `claude` subfolder of the `wiki` folder
|
|
32
|
+
- Route a subject Anthropic does not own, whether a third-party tool or a vendor-neutral concept, to `docs/` or a skill body rather than adding a second wiki folder for it
|
|
32
33
|
|
|
33
34
|
## Frontmatter
|
|
34
35
|
|
|
@@ -50,7 +51,7 @@ A page failing either is non-conforming even when it satisfies every shape rule
|
|
|
50
51
|
## Shape
|
|
51
52
|
|
|
52
53
|
- Keep a page thin: the `Source:` sentence, an orientation paragraph, and lesson sections. The source owns the reference detail and a paraphrase of it falls behind within days.
|
|
53
|
-
- Apply the lesson test per section
|
|
54
|
+
- Apply the lesson test per section, keeping a fact only when the source page does not state it. Such a fact is a gotcha this project hit, a constraint it relies on, or how it uses the feature.
|
|
54
55
|
- Read the current source before keeping or cutting a section. A fact kept from memory is the drift this shape exists to prevent.
|
|
55
56
|
- Send a session that wants reference detail to the source and fetch it live. The page answers orientation and lessons only.
|
|
56
57
|
- Leave a page with no lessons as the source link and the orientation paragraph. A catalog routes a reader by page, so the stub stays.
|
|
@@ -30,7 +30,7 @@ Apply the standard's bar: a relationship, a boundary, a path, or a before-and-af
|
|
|
30
30
|
|
|
31
31
|
Take the first that matches, and state which path was picked and why in one sentence:
|
|
32
32
|
|
|
33
|
-
1. **A teach lesson**,
|
|
33
|
+
1. **A teach lesson**, a page in a learning workspace's `lessons/` folder: the hand-drawn path, any shape. The renderer cannot load the lesson's hand font, so Mermaid labels measure narrow and clip.
|
|
34
34
|
2. **An architecture view**, meaning the request names system context, components, request flow, data pipeline, or deployment: the architecture set, then the Mermaid path.
|
|
35
35
|
3. **Graph-shaped**, meaning the relationship, boundary, or path is already what a flowchart or sequence diagram expresses: the Mermaid path.
|
|
36
36
|
4. **Anything else**, a spatial or physical arrangement no flowchart reduces to: the hand-drawn path.
|
|
@@ -41,7 +41,7 @@ The standard states this as a render-first policy rather than a ban on any tool-
|
|
|
41
41
|
|
|
42
42
|
Read the reference for the path Step 3 picked and follow it:
|
|
43
43
|
|
|
44
|
-
- Architecture set:
|
|
44
|
+
- Architecture set: shape the view per `${CLAUDE_SKILL_DIR}/references/architecture-set.md`, then draw, render, and read back per `${CLAUDE_SKILL_DIR}/references/mermaid-path.md`
|
|
45
45
|
- Mermaid path: read `${CLAUDE_SKILL_DIR}/references/mermaid-path.md`.
|
|
46
46
|
- Hand-drawn path: read `${CLAUDE_SKILL_DIR}/references/hand-drawn.md`.
|
|
47
47
|
|
|
@@ -50,17 +50,17 @@ Read the reference for the path Step 3 picked and follow it:
|
|
|
50
50
|
- Wrap the drawing in a `<figure>` element with a `<figcaption>` naming what to take from the figure, never what it shows. Let it run wider than the surrounding prose column.
|
|
51
51
|
- On the Mermaid path, run the read-back `mermaid-path.md` states before confirming.
|
|
52
52
|
- On every path, confirm the figure still reads once every color and font it depends on is stripped to its fallback, per the standard's own working-figure bar.
|
|
53
|
-
-
|
|
53
|
+
- On a rendered page, an HTML file a browser loads, the check that counts is the figure in the page, which Step 6 captures on either path. A markdown destination's whole check is the checks above.
|
|
54
54
|
|
|
55
55
|
## Step 6: confirm and write
|
|
56
56
|
|
|
57
|
-
Show the destination path, the decided path, and the full `<figure>` markup before writing. Confirm with the user, since the path decision and the render verdict are judgment calls with no diff to preview
|
|
58
|
-
|
|
59
|
-
Write the figure into the destination document at the location the user named.
|
|
57
|
+
Show the destination path, the decided path, and the full `<figure>` markup before writing. Confirm with the user, since the path decision and the render verdict are judgment calls with no diff to preview, then write the figure where the user named.
|
|
60
58
|
|
|
61
59
|
When the destination is a rendered page, read the `## Capture in the page` section of `${CLAUDE_SKILL_DIR}/references/hand-drawn.md` and run it, on the Mermaid path as well as the hand-drawn one, within the same two correction passes the read-back allows.
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
### Cleaning up
|
|
62
|
+
|
|
63
|
+
Renders and captures under `.canon/tmp/figures/` are verification artifacts. Delete the scratch PNGs, the stamps beside them, and the JSON config once the checks confirm, since only the SVG ships, and keep the `.mmd` source a later refresh redraws from.
|
|
64
64
|
|
|
65
65
|
## Output
|
|
66
66
|
|
|
@@ -75,6 +75,8 @@ Renders and captures under `.canon/tmp/figures/` are verification artifacts, and
|
|
|
75
75
|
|
|
76
76
|
### After confirmation
|
|
77
77
|
|
|
78
|
+
Report the write in this shape.
|
|
79
|
+
|
|
78
80
|
```plaintext
|
|
79
81
|
✅ Drafted figure in <path>
|
|
80
82
|
Render path: <mermaid | architecture | freehand>
|
|
@@ -18,12 +18,12 @@ One identity rendered twice: the same mark sized down to an icon sequence and co
|
|
|
18
18
|
|
|
19
19
|
Read these in parallel, skipping any that do not exist:
|
|
20
20
|
|
|
21
|
-
- `canon/DESIGN.md`: the `## Overview` paragraph and the role intents under `## Colors` and `## Typography`, read
|
|
21
|
+
- `canon/DESIGN.md`: the `## Overview` paragraph and the role intents under `## Colors` and `## Typography`, read as `## Personality` and `## Color` in an older record
|
|
22
22
|
- The stylesheet `canon/DESIGN.md`'s lead names: the color and type values behind those roles
|
|
23
23
|
- `canon/REQUIREMENTS.md`: the `## Personality` paragraph, when `canon/DESIGN.md` carries none
|
|
24
24
|
- `CLAUDE.md`: the project's stated voice, when neither file above carries a personality signal
|
|
25
25
|
|
|
26
|
-
No signal from any of these is not a stop. Draft against a neutral default, and mark each guessed color and type value with a `/* ? verify */` comment beside its declaration in the `.mark` and `.card` markup
|
|
26
|
+
No signal from any of these is not a stop. Draft against a neutral default, and mark each guessed color and type value with a `/* ? verify */` comment beside its declaration in the `.mark` and `.card` markup, since the design document carries no value to tag.
|
|
27
27
|
|
|
28
28
|
## Step 2: detect the icon size sequence
|
|
29
29
|
|
|
@@ -35,13 +35,11 @@ Fall back to the stated default when nothing is detected, since no `tooling/` st
|
|
|
35
35
|
- `180x180`
|
|
36
36
|
- `192x192`, `512x512`
|
|
37
37
|
|
|
38
|
-
This default set is raster-only
|
|
39
|
-
|
|
40
|
-
Announce which of the two decided the sequence.
|
|
38
|
+
This default set is raster-only, and Step 6 writes the vector source at `favicon.svg` on either branch. Announce which of the two decided the sequence.
|
|
41
39
|
|
|
42
40
|
## Step 3: detect the write folder
|
|
43
41
|
|
|
44
|
-
A root-only check
|
|
42
|
+
A root-only check misses a site kept in a subfolder, and a Next project keeps its favicon under the App Router with no `public/` at all. Both would fall through to the root while the announcement reads as detected, so walk one level down and know that convention.
|
|
45
43
|
|
|
46
44
|
Read both, from the project root:
|
|
47
45
|
|
|
@@ -53,18 +51,20 @@ find . -maxdepth 4 \( -name node_modules -o -name .git \) -prune -o -type d -pat
|
|
|
53
51
|
Take the first tier that answers:
|
|
54
52
|
|
|
55
53
|
1. A root `public/` or `static/`.
|
|
56
|
-
2. A `public/` or `static/` one level down, such as `web/public/`.
|
|
57
|
-
3. A `src/app/` folder, at the root or one level down, which is the Next App Router convention
|
|
54
|
+
2. A `public/` or `static/` one level down, such as `web/public/`. Of several, take the shallowest, then the one whose parent holds the project's framework config.
|
|
55
|
+
3. A `src/app/` folder, at the root or one level down, which is the Next App Router convention. Take the folder itself, not a `public/` beside it.
|
|
58
56
|
4. A stack-declared asset folder, where the project's own config names one.
|
|
59
57
|
5. The project root, which is the fallback rather than a detection.
|
|
60
58
|
|
|
61
|
-
Announce which tier decided, naming the tier rather than the path alone
|
|
59
|
+
Announce which tier decided, naming the tier rather than the path alone, so the operator can move the files where the project's convention differs. On tier 5 say the detection found nothing and the root is a fallback.
|
|
62
60
|
|
|
63
61
|
## Step 4: name the decision and the arms
|
|
64
62
|
|
|
65
|
-
Follow `${CLAUDE_SKILL_DIR}/../draft-and-pick/SKILL.md` Step 1, with the decision fixed rather than derived: "the project's logo mark and its composition into the social card." Vary the mark's shape or style across arms, keeping the card's type and layout fixed, per that skill's one-property rule.
|
|
63
|
+
Follow `${CLAUDE_SKILL_DIR}/../draft-and-pick/SKILL.md` Step 1, with the decision fixed rather than derived: "the project's logo mark and its composition into the social card." Vary the mark's shape or style across arms, keeping the card's type and layout fixed, per that skill's one-property rule.
|
|
66
64
|
|
|
67
|
-
|
|
65
|
+
- Draft each arm inside the full 1200x630 card frame, mark and type together, and add its canvas frame at `--width 1200 --height 630`, so one pick settles shape and composition
|
|
66
|
+
- Arm 0 is the current mark when the Step 3 folder already holds a logo file (`favicon.svg`, `favicon.ico`, `logo.svg`, or similar). Arms start at 1 otherwise.
|
|
67
|
+
- Structure every arm as a `.mark` element, the inline SVG alone, nested inside a `.card` element, the full composition, so Step 6 can address either
|
|
68
68
|
|
|
69
69
|
## Step 5: draft, render, pick, and loop
|
|
70
70
|
|
|
@@ -77,56 +77,28 @@ The final icon and card renders below are not arms, so they stay off the canvas.
|
|
|
77
77
|
This step and Step 7 replace `draft-and-pick`'s own Step 6 items 1 and 2, since the pick here produces several final files rather than one applied surface. Its archive capture, its page delete, and its server stop still run, after Step 7.
|
|
78
78
|
|
|
79
79
|
1. Extract the picked arm's `.mark` markup as the final vector source. Write it to `<write-folder>/favicon.svg`.
|
|
80
|
-
2. Under `<dest>/render/`, write one `icon-<w>x<h>.html` page per Step 2 size, carrying the picked `.mark` markup
|
|
81
|
-
3.
|
|
80
|
+
2. Under `<dest>/render/`, write one `icon-<w>x<h>.html` page per Step 2 size, carrying the picked `.mark` markup in an element with the shared class `.render`.
|
|
81
|
+
3. Declare each `.render` element at `<w>/2` by `<h>/2`, since `canon capture` screenshots at a fixed 2x scale and the PNG then lands on the target size.
|
|
82
|
+
4. Declare no font on them. Each holds the mark alone, and `canon capture` skips the font check on an element with no text, where `system-ui` would be refused.
|
|
83
|
+
5. Render the batch:
|
|
82
84
|
|
|
83
85
|
```bash
|
|
84
86
|
canon capture <dest>/render --selector .render --out <write-folder>
|
|
85
87
|
```
|
|
86
88
|
|
|
87
|
-
|
|
89
|
+
6. Report each written file's path and the dimensions `canon capture` printed, confirming each equals its Step 2 target rather than half of it.
|
|
88
90
|
|
|
89
|
-
The card leaves this batch and takes Step 7 instead. An icon is the mark alone
|
|
91
|
+
The card leaves this batch and takes Step 7 instead. An icon is the mark alone and a scratch page renders it faithfully, where the card composes the mark with the project's own type and color, which a scratch page can only copy.
|
|
90
92
|
|
|
91
93
|
## Step 7: write the card as a route and capture it through the server
|
|
92
94
|
|
|
93
|
-
A card captured from a page this run deletes leaves
|
|
95
|
+
A card captured from a page this run deletes leaves a PNG and nothing that produced it, so renaming the project means another pick loop to move one string. Write the composition into a route the project keeps, and capture it through a running server so it reads the real stylesheet, tokens, and fonts.
|
|
94
96
|
|
|
95
|
-
This is Astro-shaped
|
|
97
|
+
This is Astro-shaped for now, because Astro is the one web stack whose config gives a route a structural build exclusion. A project already holding the card route scaffold takes the route path, and everything else takes the page path. Say which one decided, since the two leave the project different things.
|
|
96
98
|
|
|
97
99
|
### The route path
|
|
98
100
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```plaintext
|
|
102
|
-
No card route installed, so the card shipped as a PNG this run.
|
|
103
|
-
`canon tooling sync astro . --write` installs the route, and it replaces every other
|
|
104
|
-
golden config in the astro stack, so run it when you mean to sync the stack.
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Never run that sync to obtain the route. It copies the whole stack over the project's own framework, lint, typescript, and test configs, which is a cost nobody asking for a logo agreed to. Hand-writing the scaffold instead is the other wrong answer, since a copy written here drifts from the one the stack maintains.
|
|
108
|
-
|
|
109
|
-
The scaffold is a second framework config pointing `srcDir` at a folder beside `src/`, the route inside that folder importing the project's global stylesheet and carrying a fixed `<meta>` marker, and a shell check failing a build that carries the marker. Of the route's three consumers, the published build is the only one a check reaches. Read the shape with `canon tooling reference astro`.
|
|
110
|
-
|
|
111
|
-
2. Write the picked arm's `.card` markup into the route's `.card` element, leaving the marker, the stylesheet import and the surrounding document alone. Keep the element at 600x315, half of the 1200x630 target, since the capture's 2x scale factor is fixed and a 1200x630 element captures at 2400x1260.
|
|
112
|
-
|
|
113
|
-
3. Start the card server in the background and read the port off its own output:
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
bun run card:dev
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
It serves under a strict port, so it refuses rather than walking to the next free one. Set `WORKTREE_PORT_OFFSET` by hand and start it again where something already holds that port.
|
|
120
|
-
|
|
121
|
-
4. Capture the route to the write folder, naming the destination PNG rather than a directory, which is what a URL source takes for `--out`:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
canon capture http://localhost:<port>/og-card --selector .card --out <write-folder>/og-image.png
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
5. Stop the server. Report the dimensions `canon capture` printed, confirming 1200x630.
|
|
128
|
-
|
|
129
|
-
A refusal naming a font here is the mechanism working rather than a failure to route around. It says the route asked for a family the machine cannot resolve, which is the same rewrap a published card would have shipped silently.
|
|
101
|
+
Read `${CLAUDE_SKILL_DIR}/references/card-route.md` on reaching this path, for the scaffold check, the message to give when it is missing, and the write, serve, and capture sequence. A project with no scaffold skips it.
|
|
130
102
|
|
|
131
103
|
### The page path
|
|
132
104
|
|
|
@@ -136,13 +108,13 @@ Where the project holds no route to write into, write `og-image.html` into `<des
|
|
|
136
108
|
canon capture <dest>/render/og-image.html --selector .render --out <write-folder>
|
|
137
109
|
```
|
|
138
110
|
|
|
139
|
-
It takes its own call
|
|
111
|
+
It takes its own call because Step 6's batch is already captured by the time this step picks a path. Say that the card shipped as a PNG with no source, and that the project gains one when it grows a route to hold the composition.
|
|
140
112
|
|
|
141
113
|
### Closing the scratch folder and the canvas
|
|
142
114
|
|
|
143
|
-
Delete `<dest>` once both captures land, then close the canvas through `draft-and-pick` Step 6 items 3 to 8, which archive every arm and delete the pages the run added. The route is not a leftover variant
|
|
115
|
+
Delete `<dest>` once both captures land, then close the canvas through `draft-and-pick` Step 6 items 3 to 8, which archive every arm and delete the pages the run added. The route is not a leftover variant, since it holds the arm the operator picked.
|
|
144
116
|
|
|
145
|
-
A project whose card was generated before this route existed keeps its PNG. Say so rather than regenerating it, since
|
|
117
|
+
A project whose card was generated before this route existed keeps its PNG. Say so rather than regenerating it, since the pick loop spends attention on a file nobody complained about, and the next real edit picks up the route.
|
|
146
118
|
|
|
147
119
|
## Response format
|
|
148
120
|
|
|
@@ -162,5 +134,5 @@ Cite these rather than restating them.
|
|
|
162
134
|
|
|
163
135
|
- `draft-and-pick` owns Steps 1 through 5 of the render-and-pick loop, cited above
|
|
164
136
|
- `canon:canvas-board` carries a picked direction into `canon/DESIGN.md`. This skill only reads it.
|
|
165
|
-
- `canon capture` owns the render mechanics, its font refusal, its fixed 2x scale
|
|
137
|
+
- `canon capture` owns the render mechanics, its font refusal, its fixed 2x scale, and its reported dimensions. It reads an `http(s)://` source, where `--out` names the PNG.
|
|
166
138
|
- The `astro` tooling stack owns the card route's scaffold, its second config, and the exclusion check, read with `canon tooling reference astro`. This skill writes into the route and never reshapes it.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Card route path
|
|
3
|
+
description: How draft-identity writes the picked card composition into a project's existing Astro card route and captures it through the card server
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Card route path
|
|
7
|
+
|
|
8
|
+
Applies to Step 7 of `draft-identity` when the project already holds the card route scaffold. A project without it takes the page path in the skill body instead.
|
|
9
|
+
|
|
10
|
+
## The scaffold
|
|
11
|
+
|
|
12
|
+
The scaffold is a second framework config pointing `srcDir` at a folder beside `src/`, a route inside that folder, and a shell check. Read the shape with `canon tooling reference astro`.
|
|
13
|
+
|
|
14
|
+
- The route imports the project's global stylesheet and carries a fixed `<meta>` marker
|
|
15
|
+
- The shell check fails a build that carries the marker
|
|
16
|
+
- Of the route's three consumers, the published build is the only one a check reaches
|
|
17
|
+
|
|
18
|
+
### When the scaffold is missing
|
|
19
|
+
|
|
20
|
+
Check for a `card.config.mjs` with a `card-src/pages/og-card.astro` beside it. Where either is missing, take the page path and leave the install to the operator, saying:
|
|
21
|
+
|
|
22
|
+
```plaintext
|
|
23
|
+
No card route installed, so the card shipped as a PNG this run.
|
|
24
|
+
`canon tooling sync astro . --write` installs the route, and it replaces every other
|
|
25
|
+
golden config in the astro stack, so run it when you mean to sync the stack.
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Never run that sync to obtain the route, since it copies the whole stack over the project's own framework, lint, typescript, and test configs. Never hand-write the scaffold either, since a copy written here drifts from the one the stack maintains.
|
|
29
|
+
|
|
30
|
+
## Writing and capturing the route
|
|
31
|
+
|
|
32
|
+
1. Write the picked arm's `.card` markup into the route's `.card` element, leaving the marker, the stylesheet import, and the surrounding document alone.
|
|
33
|
+
2. Keep the element at 600x315, half the 1200x630 target, since the capture's 2x scale factor is fixed and a 1200x630 element captures at 2400x1260.
|
|
34
|
+
3. Start the card server in the background with `bun run card:dev` and read the port off its own output.
|
|
35
|
+
4. Capture the route, naming the destination PNG rather than a directory, which is what a URL source takes for `--out`.
|
|
36
|
+
5. Stop the server. Report the dimensions `canon capture` printed, confirming 1200x630.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
canon capture http://localhost:<port>/og-card --selector .card --out <write-folder>/og-image.png
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Port and font refusals
|
|
43
|
+
|
|
44
|
+
The card server runs under a strict port, so it refuses rather than walking to the next free one. Where something already holds that port, set `WORKTREE_PORT_OFFSET` by hand and start it again.
|
|
45
|
+
|
|
46
|
+
A capture refusing on a font is the mechanism working rather than a failure to route around. The route asked for a family the machine cannot resolve, which is the rewrap a published card would have shipped silently.
|