beehaven 0.8.27 → 0.8.33
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/dist/agents-md-text.js +64 -0
- package/dist/browser-login.js +14 -4
- package/dist/build-channel.js +2 -2
- package/dist/claude-bridge.js +12 -9
- package/dist/clearly.js +6 -4
- package/dist/cli.js +27 -8
- package/dist/commands/agents-md.js +118 -0
- package/dist/commands/daemon-cmd.js +2 -0
- package/dist/commands/help.js +21 -0
- package/dist/commands/self-update.js +32 -5
- package/dist/commands/workspace.js +22 -5
- package/dist/daemon-client.js +10 -6
- package/dist/daemon-entry.js +1 -0
- package/dist/daemon-process.js +125 -0
- package/dist/daemon.js +131 -62
- package/dist/dashboard.js +118 -6
- package/dist/ipc-auth.js +3 -1
- package/dist/ipc-client.js +7 -6
- package/dist/ipc-path.js +92 -0
- package/dist/ipc-server.js +33 -33
- package/dist/npm-update.js +138 -0
- package/dist/relay-presets.js +3 -4
- package/dist/setup-service.js +9 -4
- package/dist/verb-surface.js +1 -0
- package/dist/watcher.js +9 -23
- package/dist/windows-hide.js +77 -0
- package/package.json +1 -1
- package/scripts/sync-skills.mjs +6 -0
- package/skills/agent-doodle-space/SKILL.md +1 -1
- package/skills/agent-home/SKILL.md +1 -1
- package/skills/beehaven-cli/SKILL.md +12 -0
- package/skills/brand-identity/SKILL.md +37 -14
- package/skills/clearly-agent/SKILL.md +24 -4
- package/skills/clearly-canvas/SKILL.md +88 -11
- package/skills/clearly-canvas/authoring.md +61 -10
- package/skills/clearly-canvas/example.mjs +72 -69
- package/skills/clearly-canvas/review.mjs +106 -12
- package/skills/clearly-docs/SKILL.md +151 -0
- package/skills/clearly-init/SKILL.md +135 -0
- package/skills/clearly-workflows/SKILL.md +90 -0
- package/skills/clearly-workspace/SKILL.md +1 -1
- package/skills/codebase-map/SKILL.md +1 -1
- package/skills/design-craft/SKILL.md +14 -6
- package/skills/design-craft/references.md +95 -0
- package/skills/index.json +48 -12
- package/skills/layout-systems/SKILL.md +14 -11
- package/skills/pair-on-canvas/SKILL.md +1 -1
- package/skills/sticker-pack/SKILL.md +132 -0
- package/skills/visualize/SKILL.md +188 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: brand-identity
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
4
|
+
Needs a terminal with the beehaven CLI (Claude Code, Codex, Gemini CLI); in a chat with only the Clearly connector, say so and use the clearly_* tools instead.
|
|
5
|
+
Design the requested logo or brand identity on a Clearly canvas —
|
|
5
6
|
brief, mark, wordmark, lockups and clear space, palette, type system,
|
|
6
7
|
applications, and a spec board someone else can build from. Use when asked
|
|
7
8
|
for a brand, a logo, an identity, a rebrand, a visual system, brand
|
|
@@ -13,10 +14,14 @@ description: >-
|
|
|
13
14
|
|
|
14
15
|
# brand-identity — a system, not a picture of a logo
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
Match the user's scope. For a logo concept, deliver the editable mark/wordmark, primary and
|
|
18
|
+
one-color use, a small-size check, and the requested application. A logo plus landing page does
|
|
19
|
+
not require merchandise, storefronts or a complete guideline deck. Add those when requested or
|
|
20
|
+
when a concrete use in the brief requires them.
|
|
21
|
+
|
|
22
|
+
For a complete identity request, the deliverable is a system someone else can build with:
|
|
23
|
+
symbol, wordmark, palette, typography, applications and guidelines. Sections 6–8 describe that
|
|
24
|
+
larger scope; they are optional for a narrow concept.
|
|
20
25
|
|
|
21
26
|
Read **`design-craft`** first or alongside — grid, type scale, colour roles and the studio
|
|
22
27
|
pass are assumed here.
|
|
@@ -60,15 +65,31 @@ handover. A mark of hand-placed béziers does not, and it shows.
|
|
|
60
65
|
| **Counter-form** | the shape is the NEGATIVE space between forms | clever marks that survive one colour |
|
|
61
66
|
| **Modular** | one unit repeated/rotated on a grid | systems, networks, collectives |
|
|
62
67
|
|
|
63
|
-
**Build it
|
|
68
|
+
**Build it from native layers, every number derived from the construction** — the way an
|
|
69
|
+
identity designer works in Figma, so each part of the mark stays a named, editable layer in the
|
|
70
|
+
brand colour (never one generated or hand-written SVG):
|
|
64
71
|
|
|
65
72
|
```jsonc
|
|
66
|
-
{"
|
|
67
|
-
"
|
|
73
|
+
{"batch":[
|
|
74
|
+
{"action":"frame.create","args":{"name":"Mark","x":120,"y":120,"w":240,"h":240}},
|
|
75
|
+
{"action":"canvas.create-node","args":{"type":"ellipse","name":"mark/ring","parentId":"Mark",
|
|
76
|
+
"x":20,"y":20,"w":200,"h":200,"fill":"#1B4DFF"}},
|
|
77
|
+
{"action":"canvas.create-node","args":{"type":"ellipse","name":"mark/counter","parentId":"Mark",
|
|
78
|
+
"x":70,"y":70,"w":100,"h":100,"fill":"#FFFFFF"}},
|
|
79
|
+
{"action":"vector.create","args":{"name":"mark/blade","parentId":"Mark","closed":true,"fill":"#1B4DFF",
|
|
80
|
+
"points":[{"x":120,"y":20},{"x":220,"y":120},{"x":120,"y":120}]}},
|
|
81
|
+
{"action":"canvas.group","args":{"ids":["mark/ring","mark/counter","mark/blade"],"name":"mark"}}
|
|
82
|
+
]}
|
|
68
83
|
```
|
|
69
84
|
|
|
70
|
-
|
|
71
|
-
|
|
85
|
+
Here R = 100: the counter is R/2, the blade's corners sit on the circle. Curves are
|
|
86
|
+
`vector.create` points with `hIn`/`hOut` control points (absolute coordinates) placed where the
|
|
87
|
+
construction says; a quarter-circle's handle sits 0.552·R from its anchor. A counter-form is a
|
|
88
|
+
ground-colour shape layered on top; `vector.boolean` makes a true cut-out when an editor is open.
|
|
89
|
+
Raw SVG (`type:"svg"`) is only for importing a mark the client already has.
|
|
90
|
+
|
|
91
|
+
⚠ **Wordmarks are real text nodes, or outlined paths** — and `<text>` inside an imported `svg`
|
|
92
|
+
node does NOT render headlessly (no system fonts are loaded).
|
|
72
93
|
|
|
73
94
|
**Test the mark against these before going further. A mark that fails any of them is not done:**
|
|
74
95
|
|
|
@@ -93,7 +114,9 @@ good. If it does not work in flat black, the shape is wrong and the gradient is
|
|
|
93
114
|
- ⚠ **A wordmark is always tracked tighter than body text.** At display size, `letterSpacing`
|
|
94
115
|
−1 to −4. Then fix the specific pairs the font gets wrong (an uppercase A next to a V, a
|
|
95
116
|
T next to a lowercase o).
|
|
96
|
-
- **
|
|
117
|
+
- **For a full identity, define this fixed set.** For a concept, deliver the requested lockup
|
|
118
|
+
plus the mark-only and one-color forms needed for its smallest use. Additional lockups are
|
|
119
|
+
optional unless the brief asks for them:
|
|
97
120
|
|
|
98
121
|
```
|
|
99
122
|
primary mark + wordmark, horizontal ← the default
|
|
@@ -225,11 +248,11 @@ Run `design-craft`'s studio pass, plus these identity-specific ones:
|
|
|
225
248
|
```
|
|
226
249
|
□ Rendered the mark at 24px and LOOKED at it
|
|
227
250
|
□ Mark works in flat black, flat white, and knocked out
|
|
228
|
-
□ Every lockup has stated clear space and minimum size
|
|
251
|
+
□ Every delivered lockup has stated clear space and minimum size
|
|
229
252
|
□ Palette has a dark-ground variant and role sentences
|
|
230
253
|
□ Type scale has NUMBERS, not just face names
|
|
231
|
-
□
|
|
232
|
-
□ Misuse section exists
|
|
254
|
+
□ Requested applications at real proportions (4–6 for a full identity; the requested surface for a concept)
|
|
255
|
+
□ Misuse section exists for a full identity; a concise use note is enough for a logo concept
|
|
233
256
|
□ Put the mark beside the competitor named in UNLIKE — still distinct?
|
|
234
257
|
□ Can someone build a new asset from this board without asking a question?
|
|
235
258
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clearly-agent
|
|
3
|
-
description: Work in a Clearly workspace AS an agent — sign in with an identity, resume a session, read your brief (what changed since you were last here, your recents, your unfiled drafts), and understand whose work you are creating. TRIGGER on the first `beehaven` call of any session, on "Not an agent" / "agent login" refusals, and when the user asks "who am I acting as", "what was I doing", "what have I made", "why can't the agent see this", "why is my work invisible", or "run this as a different agent". Read this BEFORE clearly-canvas or clearly-workspace — both need an identity and neither will work without one.
|
|
3
|
+
description: Needs a terminal with the beehaven CLI (Claude Code, Codex, Gemini CLI); in a chat with only the Clearly connector, say so and use the clearly_* tools instead. Work in a Clearly workspace AS an agent — sign in with an identity, resume a session, read your brief (what changed since you were last here, your recents, your unfiled drafts), and understand whose work you are creating. TRIGGER on the first `beehaven` call of any session, on "Not an agent" / "agent login" refusals, and when the user asks "who am I acting as", "what was I doing", "what have I made", "why can't the agent see this", "why is my work invisible", or "run this as a different agent". Read this BEFORE clearly-canvas or clearly-workspace — both need an identity and neither will work without one.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# clearly-agent — who you are, and what that makes your work
|
|
@@ -190,6 +190,19 @@ task changes a product's UI, the composition comes FIRST: build the screen and i
|
|
|
190
190
|
`canvas.review` it, link it to the ticket (`work-link {ticketId, kind:"design", refKind:"composition",
|
|
191
191
|
refId}`), then implement. `clearly-canvas` §0 has the details.
|
|
192
192
|
|
|
193
|
+
No brand yet (`brand-tokens` answers `brand-not-found`) for a real company? Ask the person for their
|
|
194
|
+
website rather than inventing a palette, then:
|
|
195
|
+
|
|
196
|
+
1. `beehaven call brand-import '{"url":"theirsite.com","dryRun":true}'` — colours by role, faces, logos,
|
|
197
|
+
voice and shape, each with its reason in `provenance`. Tell the person what you read.
|
|
198
|
+
2. Ask what to call the brand (`suggestedName` is what the site calls itself — a suggestion, not a default).
|
|
199
|
+
3. `beehaven call brand-import '{"url":"theirsite.com","name":"<their answer>"}'` saves it (the read is
|
|
200
|
+
reused; the first brand becomes the workspace default). Without `name` nothing is saved:
|
|
201
|
+
`brand-name-required`.
|
|
202
|
+
|
|
203
|
+
`brandId` + `apply:["colors","type"]` refreshes an existing brand as a new version instead. Licensed faces
|
|
204
|
+
come back set in the closest free one — `faces` says which.
|
|
205
|
+
|
|
193
206
|
## When a write is refused
|
|
194
207
|
|
|
195
208
|
`agent-denied-create` / `-update` / `-delete` mean your **capability matrix** said no. It covers the
|
|
@@ -203,6 +216,11 @@ governance. Each resource's delete cell is `none`, `own`, or `all`; `own` means
|
|
|
203
216
|
`created_by: agent:<your-id>`. Missing or legacy author data is not yours. Permanent deletion is
|
|
204
217
|
human-only; agent deletes use a recoverable archive, tombstone, or checkpoint.
|
|
205
218
|
|
|
219
|
+
Removing canvas layers is an **update**, including `canvas.delete`, block removal, and placed
|
|
220
|
+
design layers. You may remove layers from any visible canvas within your edit scope, regardless
|
|
221
|
+
of its author. The server requires an undo checkpoint first. Deleting or archiving the whole
|
|
222
|
+
canvas still follows delete-own/delete-all (CAN2-128).
|
|
223
|
+
|
|
206
224
|
Only agents whose owner is currently a workspace owner or admin can use admin or delete-all. The
|
|
207
225
|
server checks this on every call: if your owner is demoted, your scope drops to write/delete-own.
|
|
208
226
|
After an owner is promoted again, a human must explicitly re-grant the higher scope.
|
|
@@ -215,15 +233,17 @@ owner/admin-owned agent can be granted it. Check yours before a destructive step
|
|
|
215
233
|
beehaven call agent-capabilities-get '{}' # { scope, matrix, summary }
|
|
216
234
|
```
|
|
217
235
|
|
|
218
|
-
⚠ `permission_scope: 'write'` lets you
|
|
219
|
-
|
|
236
|
+
⚠ `permission_scope: 'write'` lets you archive/remove only your own workspace items; editing layers
|
|
237
|
+
inside an editable canvas follows the update rule above. A permission refusal is the contract
|
|
238
|
+
working, not a bug. ⚠ You cannot change permissions — yours or another agent's;
|
|
220
239
|
ask the owner.
|
|
221
240
|
|
|
222
241
|
## Traps that cost real time
|
|
223
242
|
|
|
224
243
|
- ⚠ **`beehaven env` first.** `prod` and `staging` are different databases and `--env` does not
|
|
225
244
|
exist on `call` — the daemon *is* the env. Every number is meaningless if you are on the wrong one.
|
|
226
|
-
- ⚠ **
|
|
245
|
+
- ⚠ **Verify a deploy by the response's runtime version.** Allow propagation and retry read-only
|
|
246
|
+
checks; do not restart the user's daemon to force a resident DO onto a new version.
|
|
227
247
|
- ⚠⚠ **Check the `as <agent>` on your first call.** An identity archived in this workspace still
|
|
228
248
|
mints (identities are account-level), but the workspace refuses its session. Current CLIs say so
|
|
229
249
|
(`⚠ Signed in, but this workspace refused …`, exit 1) and then refuse every call as that
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clearly-canvas
|
|
3
3
|
description: >-
|
|
4
|
+
Needs a terminal with the beehaven CLI (Claude Code, Codex, Gemini CLI); in a chat with only the Clearly connector, say so and use the clearly_* tools instead.
|
|
4
5
|
Design and revise editable compositions on a Clearly canvas using the beehaven
|
|
5
6
|
CLI: posters, campaigns, decks, page mockups, diagrams, spatial reviews, and
|
|
6
7
|
project plans built from LIVE workspace objects (boards, tickets, documents,
|
|
@@ -19,22 +20,34 @@ The deliverable is a composition that communicates a specific idea at its intend
|
|
|
19
20
|
viewing size, with editable, well-named layers. Successful RPCs prove that nodes were
|
|
20
21
|
stored. A rendered image you have inspected is the evidence for visual quality.
|
|
21
22
|
|
|
23
|
+
Use the same working method as a designer in Figma: artboards, named editable layers,
|
|
24
|
+
text styles, reusable components, auto-layout and constraints; explicit responsive states;
|
|
25
|
+
then inspect the pixels and refine. Read `authoring.md` and discover the current catalog
|
|
26
|
+
before assuming an operation is missing. Typography defaults to Auto; use `140%` or `24px`
|
|
27
|
+
for explicit line heights. Keep unsupported capabilities and unverified rendering visible
|
|
28
|
+
in the handoff; a familiar workflow does not prove every Figma feature is implemented.
|
|
29
|
+
|
|
22
30
|
For a small correction, keep the existing direction and make the smallest useful edit.
|
|
23
31
|
For a new composition or substantial redesign, use the workflow below.
|
|
24
32
|
|
|
33
|
+
Keep the requested scope. A landing concept with a logo needs its page layouts and a usable
|
|
34
|
+
logo; add application boards or a full guideline system only when the brief calls for them.
|
|
35
|
+
Read only relevant references. Save large tool responses once and print compact summaries.
|
|
36
|
+
|
|
25
37
|
## The studio bar — what "done" means, every time
|
|
26
38
|
|
|
27
39
|
Load **`design-craft`** before any new visual work: grid, type scale, colour roles,
|
|
28
40
|
spacing, optical correction, the studio pass. It ships beside this skill; `layout-systems`
|
|
29
41
|
covers multi-artboard grids. This skill covers the canvas mechanics.
|
|
30
42
|
|
|
31
|
-
A composition is done when every requested artboard meets all
|
|
43
|
+
A composition is done when every requested artboard meets all five conditions:
|
|
32
44
|
|
|
33
45
|
1. **`canvas.review` verdict is `clean` or `look`.** `fix` means a probable defect
|
|
34
46
|
remains: text colliding or covered, contrast under WCAG (4.5:1 body, 3:1 display),
|
|
35
47
|
type below the artboard's legible floor, missing media, text overflowing its box,
|
|
36
|
-
placeholder copy. Fix it.
|
|
37
|
-
`
|
|
48
|
+
placeholder copy. Fix it. For an intentional finding, use
|
|
49
|
+
`accept:[{check,ids:[node IDs],reason}]`. Accepted findings stay visible and return `look`.
|
|
50
|
+
Legacy `ignore` can suppress multiple checks and is not an unconditional pass.
|
|
38
51
|
2. **Every `look` finding was looked at**: type-size and palette sprawl, near-miss
|
|
39
52
|
alignment, copy against the trim, text over imagery. Act on it or say why not.
|
|
40
53
|
3. **You inspected the rendered PNG** against design-craft's studio pass, covering what no
|
|
@@ -42,6 +55,12 @@ A composition is done when every requested artboard meets all four conditions:
|
|
|
42
55
|
one accent, orphans, consistency.
|
|
43
56
|
4. **The first read works at delivery size.** At thumbnail size, the thing that should
|
|
44
57
|
win does win.
|
|
58
|
+
5. **The document behaves as a design.** Inspect its frame tree: sections and UI containers
|
|
59
|
+
own their contents and background fills; rows, stacks and grids use live auto layout
|
|
60
|
+
with deliberate Hug/Fill/Fixed sizing. Resize a representative container and lengthen
|
|
61
|
+
its copy on a duplicate, then verify reflow and containment. Keep intentional artwork
|
|
62
|
+
positioned inside named artwork frames. Record these checks separately from visual QA;
|
|
63
|
+
`canvas.review` does not prove hierarchy or reflow.
|
|
45
64
|
|
|
46
65
|
A new composition almost always needs at least one revision after its first render. If
|
|
47
66
|
the pass finds nothing, look again at the thumbnail. If there is still nothing, say what
|
|
@@ -54,8 +73,9 @@ build from them — redrawing a button the library already has is how designs dr
|
|
|
54
73
|
product they describe.
|
|
55
74
|
|
|
56
75
|
```sh
|
|
57
|
-
beehaven call brand-tokens '{}'
|
|
58
|
-
beehaven call
|
|
76
|
+
beehaven call brand-tokens '{"compact":true}' # roles without repeated CSS/prose
|
|
77
|
+
beehaven call brand-import '{"url":"theirsite.com","dryRun":true}' # no brand yet? read it off their website
|
|
78
|
+
beehaven call component-list '{"query":"<kind>","compact":true}' # IDs, dimensions and prop names
|
|
59
79
|
beehaven call component-instantiate '{"compositionId":"<id>","instances":[
|
|
60
80
|
{"id":"<component>","x":96,"y":200,"variant":"Light"},
|
|
61
81
|
{"id":"<component>","x":96,"y":280,"variant":"Light","props":{"label":"Save changes"}}]}'
|
|
@@ -68,8 +88,9 @@ beehaven call component-instantiate '{"compositionId":"<id>","instances":[
|
|
|
68
88
|
`component-create` (or `{ fromCompositionId, nodeId }` to save one you drew).
|
|
69
89
|
- Component node coordinates are relative to the component ROOT, even under an inner
|
|
70
90
|
frame — the opposite of `canvas.create-node`, where x/y follow `parentId`.
|
|
71
|
-
-
|
|
72
|
-
and
|
|
91
|
+
- For Clearly product UI, use its brand kit. For a separate client, use that client's kit
|
|
92
|
+
and supplied assets. A requested new client identity is scoped to that composition;
|
|
93
|
+
it does not change the workspace's default brand.
|
|
73
94
|
|
|
74
95
|
**UX design before implementation.** When the work is a change to a product's UI, the
|
|
75
96
|
composition is the design the code will answer to: show the real states (empty, loading,
|
|
@@ -103,10 +124,46 @@ can read and edit artifact records, while canvas-specific actions use the CLI.
|
|
|
103
124
|
beehaven env
|
|
104
125
|
beehaven connect home
|
|
105
126
|
beehaven agent login <name> --label "Design <artifact>" --client cli
|
|
106
|
-
beehaven call canvas-perceive '{"compositionId":"<id>","
|
|
127
|
+
beehaven call canvas-perceive '{"compositionId":"<id>","outline":true}'
|
|
107
128
|
beehaven call canvas-catalog '{"query":"create-node"}'
|
|
108
129
|
```
|
|
109
130
|
|
|
131
|
+
Read a canvas the way you read a repository: `canvas-perceive {outline:true}` is `tree` (artboards,
|
|
132
|
+
sections, layer counts, first copy, EMPTY sections — a few hundred bytes); `{frame:"<id or name>"}`
|
|
133
|
+
opens one frame like a file (its layers indented, positions relative to their parent);
|
|
134
|
+
`{find:"Start free"}` is `grep` (copy, layer names or `#hex`, with each match's frame path). Use
|
|
135
|
+
`format:"json"` only when you need every field of every node. Every `canvas-act` write returns
|
|
136
|
+
`diagnostics` — a lint of the artboards it touched (text overflow, collisions, covered text,
|
|
137
|
+
contrast) — treat them like compiler errors and fix them in the next batch. `canvas.review` is still
|
|
138
|
+
the pixel check and the ticket gate.
|
|
139
|
+
|
|
140
|
+
A canvas is planned like a git repository: its own plan board, a WORK TICKET for the request, and
|
|
141
|
+
COMMITS — one ticket per coherent layer or section of a larger change.
|
|
142
|
+
`design-start {title, brandId?}` makes a PRIVATE DRAFT canvas, bound to the brand, with its private
|
|
143
|
+
plan board and the work ticket, and returns `{ compositionId, ticketId, ticketKey, boardId, brand }`.
|
|
144
|
+
Same title again returns the same draft. Nothing is shared until it is filed:
|
|
145
|
+
`design-file {compositionId, projectId | projectTitle}` moves the canvas — plan board and every
|
|
146
|
+
ticket with it — into the project the person chose and sends the work ticket to in-review. Ask which
|
|
147
|
+
project unless they named one; a close-but-different title answers `similar-projects` with
|
|
148
|
+
candidates. Repeat-safe.
|
|
149
|
+
Plan a larger change before drawing, the way you would split a big code change into commits:
|
|
150
|
+
`design-plan {compositionId, commits: ["Grid, type and colour styles", "Nav", "Hero", …]}` (drafts
|
|
151
|
+
and filed canvases alike) adds ordered commit tickets under the work ticket. `sections: true` uses
|
|
152
|
+
the landing-page set (set up frames and styles, nav bar, hero, highlights, offer, story, call to
|
|
153
|
+
action, footer, mobile, states); `phases: true` and a `brief` add the studio method (brief, research,
|
|
154
|
+
structure, direction, design, review) — load the `design-process` skill. Order commits so each
|
|
155
|
+
builds on the last and can be reviewed alone. Build ONE commit per canvas-act batch that ends with
|
|
156
|
+
`canvas.review` of the artboard and carries
|
|
157
|
+
`"ticket":{"id":"<key>","status":"done","resolution":"<what changed>"}` — it lands only if that
|
|
158
|
+
review is clean or look; `result.ticket` says whether it did, and the ticket logs the canvas
|
|
159
|
+
revision and the layers the commit changed. Auto-layout, gradients, shadows, drawing and placeholders:
|
|
160
|
+
see "Technique" in [authoring.md](authoring.md).
|
|
161
|
+
|
|
162
|
+
`composition-board-get {compositionId}` reads the plan back. `design-start` with a project, ticket or
|
|
163
|
+
`phases` still sets up planned work directly (kept for one release).
|
|
164
|
+
For an existing task, reuse its ticket/project. Check one unknown action with
|
|
165
|
+
`beehaven explain <action>` or a filtered catalog; do not download the entire registry.
|
|
166
|
+
|
|
110
167
|
Use the composition supplied by the user. If none is named, inspect recent titles and
|
|
111
168
|
context; create a clearly titled composition for new work instead of modifying an
|
|
112
169
|
arbitrary recent canvas. File shared work into its project.
|
|
@@ -161,8 +218,11 @@ hand-author hundreds of coordinates in a chat message.
|
|
|
161
218
|
Check contrast on the actual ground. Use the user's real brand assets.
|
|
162
219
|
- Choose relevant imagery, a meaningful diagram, a product view or a deliberate
|
|
163
220
|
typographic treatment. Decorative blobs and random stock photos do not prove a
|
|
164
|
-
product claim.
|
|
165
|
-
|
|
221
|
+
product claim. Draw marks, icons, illustrations and diagrams yourself from native
|
|
222
|
+
layers (shapes, vector.create pen paths, text, groups), the way a designer works in
|
|
223
|
+
Figma, so every part stays named and editable. Raster generation suits photographic
|
|
224
|
+
imagery when an image tool is available. Raw SVG (an svg node, or a generated SVG)
|
|
225
|
+
is for importing an existing file or a requested SVG, never the default.
|
|
166
226
|
- Define repeated components once. Vary composition where the content changes.
|
|
167
227
|
A deck of identical cards has little rhythm even when every card aligns.
|
|
168
228
|
- Keep important copy and layers editable. Do not flatten the whole composition
|
|
@@ -188,6 +248,10 @@ For a single page, establish the complete hierarchy before polishing small detai
|
|
|
188
248
|
Use a batch for each coherent build or revision, with descriptive unique layer names.
|
|
189
249
|
Parent content to its artboard. Inspect every operation result and rollback status.
|
|
190
250
|
Save your builder and returned IDs so revisions are targeted and reproducible.
|
|
251
|
+
Check `ignoredFields`, `rejectedFields`, `warnings`, `outcome` and `canvasChanges` as well as
|
|
252
|
+
`ok/count`. `matched` is not `updated`. An unchanged or partly ignored request does not prove
|
|
253
|
+
the intended edit happened. Read `composition-detail {includeScene:true}` from its top-level
|
|
254
|
+
`nodes`; never treat a missing response field as an empty scene. Keep executed payloads immutable.
|
|
191
255
|
|
|
192
256
|
⚠ **Batch, never loop.** One `canvas-act` batch of hundreds of steps is one scene read,
|
|
193
257
|
persisted every 50 steps, and the workspace stays responsive for everyone in it while it
|
|
@@ -225,6 +289,12 @@ It invokes `canvas.review` on one persisted snapshot and returns:
|
|
|
225
289
|
type and palette sprawl, near-miss edges, trim crowding, text over imagery;
|
|
226
290
|
- the placeholder/overflow audit, measured text fit, and a preview PNG.
|
|
227
291
|
|
|
292
|
+
For several artboards, write their IDs/names as a JSON array and use:
|
|
293
|
+
`node <skill-directory>/review.mjs --many <composition-id> <ids.json> <output-directory>`.
|
|
294
|
+
This uses `canvas.review-many`: one scene read, separate findings per artboard and compact
|
|
295
|
+
preview handles. Review only artboards changed since their verified snapshot. The helper versions
|
|
296
|
+
existing output paths so before/after evidence is retained.
|
|
297
|
+
|
|
228
298
|
The helper prints the verdict and every finding. Work until the verdict is `clean` or
|
|
229
299
|
`look`, as described in the studio bar above. If the installed worker lacks `canvas.review`,
|
|
230
300
|
use a real frame ID with `--perceive` for a preview-only check and run the text measurement
|
|
@@ -232,9 +302,16 @@ and audit separately. A failed or missing render means visual verification is in
|
|
|
232
302
|
|
|
233
303
|
```sh
|
|
234
304
|
# A deliberate finding — say why in the handoff:
|
|
235
|
-
beehaven call canvas-act '{"compositionId":"<id>","action":"canvas.review","args":{"ids":["<frame>"],"
|
|
305
|
+
beehaven call canvas-act '{"compositionId":"<id>","action":"canvas.review","args":{"ids":["<frame>"],"accept":[{"check":"text-over-image","ids":["<text-id>","<image-id>"],"reason":"Intentional type over this photograph; rendered contrast was inspected."}]}}'
|
|
236
306
|
```
|
|
237
307
|
|
|
308
|
+
Asset storage is a reference-aware pipeline: an SVG may have `svgRef` instead of inline markup.
|
|
309
|
+
Do not shrink or recreate it just because the inline field is absent. Replace it with
|
|
310
|
+
`canvas.update-nodes {ids, patch:{svg:<complete markup>}}`; references are managed by the action.
|
|
311
|
+
Use `canvas.fonts` before choosing an unfamiliar family/weight. Fallback metrics are not exact.
|
|
312
|
+
Use `canvas.editor-state {requireLive:true,includePixels:true}` to verify the responding editor.
|
|
313
|
+
An agent camera and a navigation delivery count do not prove the person's view was framed.
|
|
314
|
+
|
|
238
315
|
Inspect the actual image and identify concrete defects, not generic praise:
|
|
239
316
|
|
|
240
317
|
| Lens | What to judge |
|
|
@@ -10,8 +10,8 @@ Use a local builder and pass JSON through `@file` or stdin. Do not interpolate c
|
|
|
10
10
|
SVG or code into shell strings. Here is a minimal native-node pattern; replace its
|
|
11
11
|
visual decisions with the brief's system:
|
|
12
12
|
|
|
13
|
-
For
|
|
14
|
-
It demonstrates
|
|
13
|
+
For desktop, mobile and dark examples, inspect [example.mjs](example.mjs).
|
|
14
|
+
It demonstrates nested flow containers, Hug/Fill sizing and framed artwork; it writes a payload
|
|
15
15
|
without making remote calls. Run `node <skill-directory>/example.mjs <composition-id>`.
|
|
16
16
|
Use its construction approach, not its fictional brand or aesthetic, for other briefs.
|
|
17
17
|
|
|
@@ -21,18 +21,22 @@ const compositionId = process.argv[2];
|
|
|
21
21
|
const grid = { w: 1440, h: 900, margin: 88, gap: 24 };
|
|
22
22
|
const color = { paper: '#F3F0E8', ink: '#172824', accent: '#CB482F' };
|
|
23
23
|
const type = {
|
|
24
|
-
display: { family: 'Inter', size: 88, fontWeight: 700, lineHeight:
|
|
25
|
-
body: { family: 'Inter', size: 24, fontWeight: 400, lineHeight:
|
|
24
|
+
display: { family: 'Inter', size: 88, fontWeight: 700, lineHeight: '105%', letterSpacing: -2 },
|
|
25
|
+
body: { family: 'Inter', size: 24, fontWeight: 400, lineHeight: '140%' },
|
|
26
26
|
};
|
|
27
27
|
const batch = [];
|
|
28
28
|
const add = (action, args) => batch.push({ action, args });
|
|
29
29
|
add('frame.create', { name: '01-opening', x: 0, y: 0, w: grid.w, h: grid.h, fill: color.paper });
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
add('frame.create', { name: 'hero-copy', parentId: '01-opening', w: 740, h: 400, fill: 'transparent' });
|
|
31
|
+
const text = (name, copy, role) => add('canvas.create-node', {
|
|
32
|
+
name, type: 'text', parentId: 'hero-copy', w: 740,
|
|
32
33
|
text: copy, fill: color.ink, ...type[role],
|
|
33
34
|
});
|
|
34
|
-
text('opening-title', 'Ideas take
|
|
35
|
-
text('opening-deck', 'An editable visual system for the next chapter.',
|
|
35
|
+
text('opening-title', 'Ideas take shape here.', 'display');
|
|
36
|
+
text('opening-deck', 'An editable visual system for the next chapter.', 'body');
|
|
37
|
+
add('canvas.update-nodes', { ids: ['opening-title', 'opening-deck'], patch: { layoutSizingH: 'fill' } });
|
|
38
|
+
add('canvas.auto-layout', { id: 'hero-copy', direction: 'v', gap: 24, sizingH: 'fixed', sizingV: 'hug' });
|
|
39
|
+
add('canvas.auto-layout', { id: '01-opening', direction: 'v', gap: 64, padding: grid.margin, sizingH: 'fixed', sizingV: 'hug' });
|
|
36
40
|
// Continue with the brief's central visual, supporting evidence and footer.
|
|
37
41
|
writeFileSync('/tmp/canvas-build.json', JSON.stringify({ compositionId, batch }));
|
|
38
42
|
```
|
|
@@ -49,8 +53,21 @@ do not blindly resend only skipped operations. Mixed live/headless actions may h
|
|
|
49
53
|
different rollback behavior. Use deterministic layer names and returned IDs to avoid
|
|
50
54
|
duplicate content during retries.
|
|
51
55
|
|
|
56
|
+
Also check ignored/rejected fields, warnings, mutation outcome and actual changed IDs. A matched
|
|
57
|
+
node or `ok:true` receipt alone is not proof of an update. The bundled `assertReceipt` helper can
|
|
58
|
+
reject partial drops; `requireChange:true` rejects an unexpected no-op. A deliberate replay may
|
|
59
|
+
be unchanged and should reuse its previous evidence instead of recreating nodes.
|
|
60
|
+
Keep executed payloads and returned-ID manifests separate from regenerated plans.
|
|
61
|
+
|
|
52
62
|
## Node shape and coordinates
|
|
53
63
|
|
|
64
|
+
Choose ownership before coordinates: page → section → row/stack/grid → content. Put
|
|
65
|
+
the container's background, border and radius on its frame. Auto layout owns positions
|
|
66
|
+
in content flow; use Hug for content height and Fill for flexible width. Keep deliberate
|
|
67
|
+
overlays and illustrations inside artwork frames. A native editable layer alone does
|
|
68
|
+
not establish a usable document structure. Frames also make scoped perception cheaper:
|
|
69
|
+
read the outline and the section you are editing instead of a full scene dump.
|
|
70
|
+
|
|
54
71
|
Fields are flat: `{name,type,x,y,w,h,text,size,family,fontWeight,fill,...}`.
|
|
55
72
|
Use `text` for copy, `size` for type size, numeric `fontWeight`, and `w`/`h` for bounds.
|
|
56
73
|
Create normalizes hex colours; raw stored scenes use RGBA arrays in 0..1.
|
|
@@ -71,12 +88,27 @@ Create normalizes hex colours; raw stored scenes use RGBA arrays in 0..1.
|
|
|
71
88
|
moves/resizes use the catalog's frame/arrangement/scale actions; do not assume a patch
|
|
72
89
|
reflows children.
|
|
73
90
|
- Build backgrounds before foregrounds. Use `canvas.order` to change stacking.
|
|
91
|
+
|
|
92
|
+
For create/update geometry, `coordinateSpace:"world"` or `"parent"` makes the intent explicit.
|
|
93
|
+
Default behavior remains compatible with the rules above. Receipts include normalized world
|
|
94
|
+
bounds and parent offsets where available. Template coordinates remain relative to their root.
|
|
95
|
+
An SVG's bytes may be stored in `svgRef` once it exceeds the inline limit; this is valid artwork,
|
|
96
|
+
not a missing node. Replacing `svg` clears and rebuilds its reference automatically. Never patch
|
|
97
|
+
`svgRef` manually or guess its storage URL. Image `fit` is explicitly `contain` or `cover`.
|
|
74
98
|
- Name nodes uniquely; use returned IDs where names collide. Parent content to its
|
|
75
99
|
frame so movement, selection, clipping and reviews can treat it as one artifact.
|
|
76
100
|
- Give an intended stroke both `stroke` and `strokeWidth`. Zero explicitly removes it.
|
|
77
101
|
|
|
78
102
|
## Typography
|
|
79
103
|
|
|
104
|
+
Line height defaults to **Auto**, from the font itself. Use `lineHeight:"140%"` for a
|
|
105
|
+
percentage of font size or `lineHeight:"24px"` for fixed leading. Numeric values in old
|
|
106
|
+
scenes remain multipliers (`1.4` = `140%`); new designs should carry explicit units.
|
|
107
|
+
Changing font size scales % leading and leaves px leading fixed. Paragraph spacing is
|
|
108
|
+
`paragraphSpacing` in px after a hard newline, never a soft wrap. In a fixed-height
|
|
109
|
+
box, `vAlign:"middle"` centers the line boxes; `"bottom"` anchors their bottom. Do not
|
|
110
|
+
compensate with spaces, empty lines or hand-tuned y offsets.
|
|
111
|
+
|
|
80
112
|
For prose, set `w` and omit `h` to enable auto-height. Omit both axes only for short
|
|
81
113
|
single-line labels whose width should hug content. A fixed box sets that axis explicitly;
|
|
82
114
|
it does not guarantee text will clip safely. Headless auto-height is an estimate from
|
|
@@ -86,7 +118,7 @@ then inspect the rendered result in the editor.
|
|
|
86
118
|
```json
|
|
87
119
|
{"compositionId":"<id>","action":"canvas.measure-text","args":{
|
|
88
120
|
"text":"Ideas take shape here.","family":"Inter","size":88,"fontWeight":700,
|
|
89
|
-
"letterSpacing":-2,"lineHeight":
|
|
121
|
+
"letterSpacing":-2,"lineHeight":"105%","maxWidth":740}}
|
|
90
122
|
```
|
|
91
123
|
|
|
92
124
|
Use measured `height`/`lineCount` to place the next block. Measure the exact copy, font,
|
|
@@ -106,8 +138,27 @@ and tokens when relevant. Constraints reflow children on frame resize; they do n
|
|
|
106
138
|
a static canvas into a responsive website. Design explicit mobile artboards when the
|
|
107
139
|
deliverable requires them, with content order and hierarchy reconsidered for the width.
|
|
108
140
|
|
|
141
|
+
## Technique
|
|
142
|
+
|
|
143
|
+
- CONTAINERS: page sections, cards, sidebars and toolbars are named frames that own their content and background fill. Use live auto-layout for content rows, stacks and grids, with explicit Hug/Fill/Fixed sizing; position overlays and artwork deliberately within their owning frames. A rectangle behind sibling text is not a container. Verify the frame tree, resize a representative container and lengthen its copy on a duplicate before completion; record reflow checks separately from pixel review.
|
|
144
|
+
- FIGMA WORKFLOW: approach this canvas as a designer working in Figma. Read the brand and component library; compose artboards from named editable frames, text, shapes and component instances; use auto-layout, constraints, styles and variables; create deliberate desktop/mobile and light/dark states; inspect at delivery size, iterate, then review the final edit. Discover the current canvas-catalog before assuming a familiar Figma operation is unavailable. Its headlessActions identify what runs without an open editor; live-only actions need an editor. Report an unsupported capability accurately rather than inventing an operation or claiming universal feature parity.
|
|
145
|
+
|
|
146
|
+
- TYPOGRAPHY: lineHeight defaults to "auto", using the resolved font metrics. Author percentages as "140%" and absolute leading as "24px"; legacy numeric 1.4 still means 140%. Percentage leading follows font size; px leading stays fixed until the Scale tool scales the artwork. paragraphSpacing is px between hard-newline paragraphs, never soft wraps. For Auto width omit w/h; for Auto height set w and omit h; for a fixed box set w/h. Explicit layoutSizingH/V "fixed" or "fill" overrides legacy autoWidth/autoHeight. align is left|center|right|justify; vAlign is top|middle|bottom and applies to fixed-height boxes. Measure exact copy/font/weight/width using canvas.measure-text, then inspect the pixels; do not center text with spaces or arbitrary y offsets.
|
|
147
|
+
|
|
148
|
+
The same rules the in-app assistant works to (canvas-catalog returns them as `technique`).
|
|
149
|
+
|
|
150
|
+
- AUTO-LAYOUT: rows, stacks and grids are a frame whose children you create in reading order, then canvas.auto-layout { id, direction: "h" | "v" | "grid", gap, padding, align, justify, hug }. hug:false keeps the frame size; justify "space-between" | "space-around" | "space-evenly" are the Auto gaps; align:"baseline" lines up text in a row. Grids take columns, rows, columnGap, rowGap, columnSizes / rowSizes ("fill", "2fr", "hug", px). wrap:true flows into new rows; give Fill cards a minW so they wrap where you mean. Child settings go on the child via canvas.update-nodes: layoutSizingH/V "fill" | "hug" | "fixed", minW / maxW / minH / maxH, gridColumn / gridRow / gridColumnSpan, layoutPositioning:"absolute". The frame stays live: children created into it (parentId) flow in. Spacing variables: canvas.variable { op: "bind", ids, field, name }.
|
|
151
|
+
- GRADIENTS: gradient { kind, angle, stops: [{ offset, color }] } replaces the solid fill. angle is the direction the colour travels: 0 = left to right, 90 = top to bottom, 45 = top-left to bottom-right (not CSS degrees). Use two or three stops from the brand palette, and keep text off a busy gradient or check its contrast in canvas.review.
|
|
152
|
+
- SHADOWS AND BLUR: effects on any node. A soft card shadow is { type: "drop-shadow", x: 0, y: 4, blur: 16, spread: 0, color: "#0000001F" }; frosted glass is { type: "background-blur", blur: 16 }. Never fake a shadow with an extra rectangle.
|
|
153
|
+
- DRAWING: build every mark, icon, illustration and diagram shape from native layers, as a designer does in Figma, never as one generated SVG file. Primitives are canvas.create-node rect and ellipse; curves are pen paths, vector.create { name, parentId, points: [{ x, y, hIn?: { x, y }, hOut?: { x, y } }], closed, fill or stroke, strokeWidth }, where hIn/hOut are absolute control points: use few anchors with smooth handles. It also takes d (SVG path data, converted to native editable points) or shape: petal|circle|polygon|star|arc|spiral with cx, cy and sizes; strokeCap/strokeJoin apply. Reshape in place with canvas.update-nodes { ids, patch: { points | d | shape } }. Draw a repeated part once: canvas.repeat { id, count, around | cx, cy } turns one petal into a flower; canvas.rotate { ids, angle, cx, cy }; canvas.boolean { ids, op: "union" | "subtract" | "intersect" | "exclude" } (exact, editable operands). Work back to front: ground, big silhouettes in flat brand colours, then features, then details and highlights; check the silhouette in canvas.review before detailing. Name layers by part ("fox/ear-left"), group each figure with canvas.group { ids, name } and set overlap with canvas.order { ids, op }. Keep one stroke weight per drawing. Photographic or painterly imagery is a placed raster. Raw SVG stays supported but is never the default: when an SVG is asked for, write the markup yourself as an svg node, canvas.create-node { type: "svg", name, w, h, svg } with <svg viewBox="0 0 W H"> matching w and h, or import existing markup the same way; never an SVG generation pipeline.
|
|
154
|
+
- COMPUTED GEOMETRY: shapes from math (radial petals, spirals, grids) are computed and drawn in ONE call: canvas-act { compositionId, script } runs JavaScript with geo.petal/circle/arc/star/polygon/spiral/smooth/rotate/radial/grid/bounds (degrees, 0 = 3 o'clock, clockwise) and a read-only scene list, then applies the { action, args } steps it returns. Never copy numbers from one tool result into another call.
|
|
155
|
+
- SHEETS: several concepts or variants go on canvas.sheet { name, title, subtitle, cards or count, cols, cardW, cardH }: a live wrap grid of card frames that own their captions, so rows never overlap. Draw into a card with parentId = its id.
|
|
156
|
+
- MEASURE: answer spacing, overlap and alignment questions with canvas.measure { frame } or { ids } and quote its numbers, never from memory or a preview.
|
|
157
|
+
- PLACEHOLDERS: until real imagery exists, draw a native placeholder at the final size in a muted brand tone, never a flat accent block: a rect with the slot radius plus a simple motif (an ellipse sun, a vector.create mountain), grouped with canvas.group and named "<section> image placeholder", with any label in its own text node.
|
|
158
|
+
- SECTIONS: one frame per page section, named exactly as its ticket says, inside the page artboard. Build a section in one canvas-act batch that ends with canvas.review of the artboard and carries ticket: { id: "<its key>", status: "done", resolution: "<what changed>" }. The ticket moves only when that review is clean or look; result.ticket says whether it did. Then start the next section.
|
|
159
|
+
|
|
109
160
|
Use `arrow.create {from,to,routing,label}` for connected diagrams, so arrows remain bound
|
|
110
|
-
when nodes move.
|
|
161
|
+
when nodes move. Draw custom vector details natively (shapes, vector.create pen paths); raw SVG only imports an existing file. Keep labels as
|
|
111
162
|
native text so they remain editable and measurable.
|
|
112
163
|
|
|
113
164
|
Use `canvas.place {kind,id,x,y,w,h,name,parentId?}` to put a workspace object (document,
|