@clearlysh/beehaven 0.8.31 → 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 +6 -1
- package/dist/build-channel.js +2 -2
- package/dist/cli.js +18 -0
- package/dist/commands/agents-md.js +118 -0
- package/dist/commands/help.js +21 -0
- package/dist/daemon.js +24 -10
- package/dist/dashboard.js +118 -6
- package/dist/ipc-server.js +11 -8
- package/dist/verb-surface.js +1 -0
- package/package.json +1 -1
- package/skills/agent-doodle-space/SKILL.md +1 -1
- package/skills/agent-home/SKILL.md +1 -1
- package/skills/brand-identity/SKILL.md +1 -0
- package/skills/clearly-agent/SKILL.md +11 -4
- package/skills/clearly-canvas/SKILL.md +15 -1
- package/skills/clearly-canvas/authoring.md +38 -11
- package/skills/clearly-canvas/example.mjs +72 -69
- package/skills/clearly-workflows/SKILL.md +1 -0
- package/skills/clearly-workspace/SKILL.md +1 -1
- package/skills/codebase-map/SKILL.md +1 -1
- package/skills/design-craft/SKILL.md +9 -6
- package/skills/index.json +13 -13
- package/skills/layout-systems/SKILL.md +14 -11
- package/skills/pair-on-canvas/SKILL.md +1 -1
- package/skills/sticker-pack/SKILL.md +1 -1
- package/skills/visualize/SKILL.md +1 -1
|
@@ -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
|
|
@@ -216,6 +216,11 @@ governance. Each resource's delete cell is `none`, `own`, or `all`; `own` means
|
|
|
216
216
|
`created_by: agent:<your-id>`. Missing or legacy author data is not yours. Permanent deletion is
|
|
217
217
|
human-only; agent deletes use a recoverable archive, tombstone, or checkpoint.
|
|
218
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
|
+
|
|
219
224
|
Only agents whose owner is currently a workspace owner or admin can use admin or delete-all. The
|
|
220
225
|
server checks this on every call: if your owner is demoted, your scope drops to write/delete-own.
|
|
221
226
|
After an owner is promoted again, a human must explicitly re-grant the higher scope.
|
|
@@ -228,15 +233,17 @@ owner/admin-owned agent can be granted it. Check yours before a destructive step
|
|
|
228
233
|
beehaven call agent-capabilities-get '{}' # { scope, matrix, summary }
|
|
229
234
|
```
|
|
230
235
|
|
|
231
|
-
⚠ `permission_scope: 'write'` lets you
|
|
232
|
-
|
|
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;
|
|
233
239
|
ask the owner.
|
|
234
240
|
|
|
235
241
|
## Traps that cost real time
|
|
236
242
|
|
|
237
243
|
- ⚠ **`beehaven env` first.** `prod` and `staging` are different databases and `--env` does not
|
|
238
244
|
exist on `call` — the daemon *is* the env. Every number is meaningless if you are on the wrong one.
|
|
239
|
-
- ⚠ **
|
|
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.
|
|
240
247
|
- ⚠⚠ **Check the `as <agent>` on your first call.** An identity archived in this workspace still
|
|
241
248
|
mints (identities are account-level), but the workspace refuses its session. Current CLIs say so
|
|
242
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,6 +20,13 @@ 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
|
|
|
@@ -32,7 +40,7 @@ Load **`design-craft`** before any new visual work: grid, type scale, colour rol
|
|
|
32
40
|
spacing, optical correction, the studio pass. It ships beside this skill; `layout-systems`
|
|
33
41
|
covers multi-artboard grids. This skill covers the canvas mechanics.
|
|
34
42
|
|
|
35
|
-
A composition is done when every requested artboard meets all
|
|
43
|
+
A composition is done when every requested artboard meets all five conditions:
|
|
36
44
|
|
|
37
45
|
1. **`canvas.review` verdict is `clean` or `look`.** `fix` means a probable defect
|
|
38
46
|
remains: text colliding or covered, contrast under WCAG (4.5:1 body, 3:1 display),
|
|
@@ -47,6 +55,12 @@ A composition is done when every requested artboard meets all four conditions:
|
|
|
47
55
|
one accent, orphans, consistency.
|
|
48
56
|
4. **The first read works at delivery size.** At thumbnail size, the thing that should
|
|
49
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.
|
|
50
64
|
|
|
51
65
|
A new composition almost always needs at least one revision after its first render. If
|
|
52
66
|
the pass finds nothing, look again at the thumbnail. If there is still nothing, say what
|
|
@@ -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
|
```
|
|
@@ -57,6 +61,13 @@ Keep executed payloads and returned-ID manifests separate from regenerated plans
|
|
|
57
61
|
|
|
58
62
|
## Node shape and coordinates
|
|
59
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
|
+
|
|
60
71
|
Fields are flat: `{name,type,x,y,w,h,text,size,family,fontWeight,fill,...}`.
|
|
61
72
|
Use `text` for copy, `size` for type size, numeric `fontWeight`, and `w`/`h` for bounds.
|
|
62
73
|
Create normalizes hex colours; raw stored scenes use RGBA arrays in 0..1.
|
|
@@ -90,6 +101,14 @@ not a missing node. Replacing `svg` clears and rebuilds its reference automatica
|
|
|
90
101
|
|
|
91
102
|
## Typography
|
|
92
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
|
+
|
|
93
112
|
For prose, set `w` and omit `h` to enable auto-height. Omit both axes only for short
|
|
94
113
|
single-line labels whose width should hug content. A fixed box sets that axis explicitly;
|
|
95
114
|
it does not guarantee text will clip safely. Headless auto-height is an estimate from
|
|
@@ -99,7 +118,7 @@ then inspect the rendered result in the editor.
|
|
|
99
118
|
```json
|
|
100
119
|
{"compositionId":"<id>","action":"canvas.measure-text","args":{
|
|
101
120
|
"text":"Ideas take shape here.","family":"Inter","size":88,"fontWeight":700,
|
|
102
|
-
"letterSpacing":-2,"lineHeight":
|
|
121
|
+
"letterSpacing":-2,"lineHeight":"105%","maxWidth":740}}
|
|
103
122
|
```
|
|
104
123
|
|
|
105
124
|
Use measured `height`/`lineCount` to place the next block. Measure the exact copy, font,
|
|
@@ -121,12 +140,20 @@ deliverable requires them, with content order and hierarchy reconsidered for the
|
|
|
121
140
|
|
|
122
141
|
## Technique
|
|
123
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
|
+
|
|
124
148
|
The same rules the in-app assistant works to (canvas-catalog returns them as `technique`).
|
|
125
149
|
|
|
126
|
-
- AUTO-LAYOUT: rows
|
|
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 }.
|
|
127
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.
|
|
128
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.
|
|
129
|
-
- 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,
|
|
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.
|
|
130
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.
|
|
131
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.
|
|
132
159
|
|
|
@@ -1,78 +1,81 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
2
|
+
/** Three editable page states. Writes JSON only; it never calls a workspace. */
|
|
3
3
|
import { writeFileSync } from 'node:fs';
|
|
4
4
|
|
|
5
5
|
const [compositionId, output = '/tmp/fieldwork-build.json'] = process.argv.slice(2);
|
|
6
6
|
if (!compositionId) throw new Error('Usage: node example.mjs <composition-id> [output.json]');
|
|
7
|
-
const grid = { w: 1440, h: 900, margin: 88, gutter: 80 };
|
|
8
|
-
const ink = '#172824', paper = '#F2F0E7', orange = '#C84A2E', muted = '#58685E';
|
|
9
7
|
const batch = [];
|
|
10
8
|
const op = (action, args) => batch.push({ action, args });
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const rule = (p, y, color) => rect(p, `rule-${y}`, grid.margin, y, grid.w - grid.margin * 2, 1, color);
|
|
23
|
-
const masthead = (p, index, color) => {
|
|
24
|
-
text(p, 'brand', 'FIELDWORK', grid.margin, 52, 400, 20, color, 700, { letterSpacing: 2 });
|
|
25
|
-
text(p, 'series', 'DESIGN NOTES / VOL. 01', 912, 54, 440, 14, color, 400, { letterSpacing: 1 });
|
|
26
|
-
text(p, 'folio', 'STUDIO PRACTICE', grid.margin, 828, 900, 14, color, 400, { letterSpacing: 1 });
|
|
27
|
-
text(p, 'page', String(index).padStart(2, '0'), 1304, 828, 48, 14, color, 400, { align: 'right' });
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// Brief: show how one simple visual idea becomes a coherent editorial system.
|
|
31
|
-
// Hierarchy: statement → geometric proof → compact practical explanation.
|
|
32
|
-
// Motif: two fields meet to make a third; repeated with a different function on each slide.
|
|
33
|
-
const cover = 'fieldwork-01';
|
|
34
|
-
frame(cover, 0, paper); masthead(cover, 1, ink); rule(cover, 104, ink);
|
|
35
|
-
text(cover, 'eyebrow', 'A NOTE ON MAKING', 88, 168, 560, 16, orange, 700, { letterSpacing: 2 });
|
|
36
|
-
text(cover, 'title', 'Make room\nfor the idea.', 80, 228, 810, 108, ink, 700, { letterSpacing: -4, lineHeight: 1.02 });
|
|
37
|
-
text(cover, 'intro', 'Good design begins with a point of view.\nThe system gives it room to grow.', 88, 538, 740, 25, muted);
|
|
38
|
-
circle(cover, 'disc', 977, 233, 350, orange);
|
|
39
|
-
rect(cover, 'field', 916, 385, 270, 270, ink);
|
|
40
|
-
rect(cover, 'intersection', 977, 385, 209, 198, paper, { radius: 0 });
|
|
41
|
-
text(cover, 'motif-caption', '01 / TWO FIELDS, ONE IDEA', 920, 696, 420, 14, muted, 400, { letterSpacing: 1 });
|
|
42
|
-
rule(cover, 782, ink);
|
|
43
|
-
|
|
44
|
-
const method = 'fieldwork-02';
|
|
45
|
-
frame(method, 1, ink); masthead(method, 2, paper); rule(method, 104, '#607369');
|
|
46
|
-
text(method, 'title', 'One idea.\nMany expressions.', 80, 164, 1120, 92, paper, 700, { letterSpacing: -3, lineHeight: 1.04 });
|
|
47
|
-
text(method, 'intro', 'Keep the visual logic.\nChange what the content needs.', 952, 380, 400, 24, '#C7CFC4');
|
|
48
|
-
const concepts = [
|
|
49
|
-
{ x: 88, title: '01 / EMPHASIS', body: 'Let one thing lead.', kind: 0 },
|
|
50
|
-
{ x: 520, title: '02 / RELATIONSHIP', body: 'Make the connection visible.', kind: 1 },
|
|
51
|
-
{ x: 952, title: '03 / RHYTHM', body: 'Repeat with a reason.', kind: 2 },
|
|
52
|
-
];
|
|
53
|
-
for (const c of concepts) {
|
|
54
|
-
const y = 518;
|
|
55
|
-
if (c.kind === 0) { circle(method, 'emphasis', c.x, y, 152, orange); circle(method, 'quiet', c.x + 192, y + 92, 60, paper); }
|
|
56
|
-
if (c.kind === 1) { rect(method, 'relation-field', c.x, y + 20, 148, 120, paper); circle(method, 'relation-disc', c.x + 80, y, 152, orange); }
|
|
57
|
-
if (c.kind === 2) for (let i = 0; i < 4; i++) rect(method, `rhythm-${i}`, c.x + i * 78, y + i * 20, 48, 152 - i * 20, i === 3 ? orange : paper);
|
|
58
|
-
text(method, `label-${c.kind}`, c.title, c.x, 714, 380, 16, paper, 700, { letterSpacing: 1 });
|
|
59
|
-
text(method, `body-${c.kind}`, c.body, c.x, 748, 380, 20, '#C7CFC4');
|
|
9
|
+
const fillWidth = id => op('canvas.update-nodes', { ids: [id], patch: { layoutSizingH: 'fill' } });
|
|
10
|
+
// Page, section, row, card and button share this container contract.
|
|
11
|
+
function flow(id, parentId, box, layout, children) {
|
|
12
|
+
// Enable flow before adding children so reading order is creation order.
|
|
13
|
+
op('frame.create', { id, name: id, parentId, fill: 'transparent', ...box,
|
|
14
|
+
autoLayout: { direction: 'v', gap: 24, padding: 0, ...layout },
|
|
15
|
+
layoutSizingH: layout.sizingH ?? 'fixed', layoutSizingV: layout.sizingV ?? 'hug' });
|
|
16
|
+
children(id);
|
|
17
|
+
op('canvas.auto-layout', { id, direction: 'v', gap: 24, padding: 0,
|
|
18
|
+
sizingH: 'fixed', sizingV: 'hug', ...layout });
|
|
19
|
+
return id;
|
|
60
20
|
}
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
});
|
|
21
|
+
function text(parentId, name, copy, w, size, fill, extra = {}) {
|
|
22
|
+
const id = parentId + '/' + name;
|
|
23
|
+
op('canvas.create-node', { id, name, parentId, type: 'text', w, text: copy,
|
|
24
|
+
size, family: 'Inter', fill, lineHeight: 'auto', ...extra });
|
|
25
|
+
fillWidth(id);
|
|
26
|
+
return id;
|
|
27
|
+
}
|
|
28
|
+
function page(id, x, mobile = false, dark = false) {
|
|
29
|
+
const w = mobile ? 390 : 1440, pad = mobile ? 24 : 80, inner = w - pad * 2;
|
|
30
|
+
const ink = dark ? '#F2F0E7' : '#172824', ground = dark ? '#172824' : '#F2F0E7';
|
|
31
|
+
flow(id, undefined, { x, y: 0, w, h: 1000, fill: ground }, { gap: 64, padding: pad }, p => {
|
|
32
|
+
flow(p + '/navigation', p, { w: inner, h: 48 }, { direction: 'h', align: 'center', justify: 'space-between' }, nav => {
|
|
33
|
+
text(nav, 'brand', 'FIELDWORK', inner - 140, 20, ink, { fontWeight: 700 });
|
|
34
|
+
text(nav, 'edition', 'STUDIO NOTES', 140, 14, ink);
|
|
35
|
+
op('canvas.update-nodes', { ids: [nav + '/edition'], patch: { layoutSizingH: 'fixed' } });
|
|
36
|
+
});
|
|
37
|
+
fillWidth(p + '/navigation');
|
|
38
|
+
flow(p + '/hero', p, { w: inner, h: 420 }, { direction: mobile ? 'v' : 'h', gap: 48 }, hero => {
|
|
39
|
+
const copyWidth = mobile ? inner : 740;
|
|
40
|
+
flow(hero + '/copy', hero, { w: copyWidth, h: 400 }, { gap: 24 }, copy => {
|
|
41
|
+
text(copy, 'eyebrow', 'A NOTE ON MAKING', copyWidth, 14, ink, { letterSpacing: 1.5 });
|
|
42
|
+
text(copy, 'title', 'Make room for the idea.', copyWidth, mobile ? 48 : 88, ink,
|
|
43
|
+
{ fontWeight: 700, letterSpacing: -2, lineHeight: '105%' });
|
|
44
|
+
text(copy, 'description', 'A shared direction. An editable system. Room for the next idea.', copyWidth, 22, ink, { lineHeight: '145%' });
|
|
45
|
+
flow(copy + '/action', copy, { w: 240, h: 56, fill: ink, radius: 8 },
|
|
46
|
+
{ direction: 'h', padding: 16, align: 'center' }, button => {
|
|
47
|
+
text(button, 'label', 'Explore the studio', 208, 16, ground, { align: 'center' });
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
fillWidth(hero + '/copy');
|
|
51
|
+
// Art-directed coordinates belong inside an owning artwork frame.
|
|
52
|
+
const art = hero + '/artwork', aw = mobile ? inner : 400;
|
|
53
|
+
op('frame.create', { id: art, name: 'Artwork / two fields', parentId: hero, w: aw, h: 320, fill: '#C84A2E' });
|
|
54
|
+
op('canvas.create-node', { id: art + '/disc', name: 'Disc', type: 'ellipse', parentId: art, x: 24, y: 24, w: 220, h: 220, fill: '#F2F0E7' });
|
|
55
|
+
op('canvas.create-node', { id: art + '/field', name: 'Field', type: 'rect', parentId: art, x: 116, y: 136, w: 196, h: 160, fill: '#172824' });
|
|
56
|
+
});
|
|
57
|
+
fillWidth(p + '/hero');
|
|
58
|
+
flow(p + '/features', p, { w: inner, h: 220 }, { direction: 'grid', columns: mobile ? 1 : 3,
|
|
59
|
+
rows: mobile ? 3 : 1, rowSizes: mobile ? ['hug', 'hug', 'hug'] : ['hug'], gap: 24, rowGap: 24 }, grid => {
|
|
60
|
+
for (const [name, title, body] of [
|
|
61
|
+
['type', 'Give ideas a voice.', 'Type scales and wraps with the available space.'],
|
|
62
|
+
['space', 'Keep room to grow.', 'Content owns its height. Related layers move together.'],
|
|
63
|
+
['review', 'Make the next edit.', 'Resize a card and extend its copy to check the system.'],
|
|
64
|
+
]) {
|
|
65
|
+
const card = grid + '/' + name, cw = mobile ? inner : (inner - 48) / 3;
|
|
66
|
+
flow(card, grid, { w: cw, h: 180, fill: dark ? '#294337' : '#FFFFFF', radius: 12 }, { gap: 16, padding: 24 }, c => {
|
|
67
|
+
text(c, 'title', title, cw - 48, 24, ink, { fontWeight: 600 });
|
|
68
|
+
text(c, 'body', body, cw - 48, 18, ink, { lineHeight: '145%' });
|
|
69
|
+
});
|
|
70
|
+
fillWidth(card);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
fillWidth(p + '/features');
|
|
74
|
+
text(p, 'footer', 'FIELDWORK / A SYSTEM READY FOR CHANGE', inner, 14, ink, { letterSpacing: 1 });
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
page('01-desktop', 0);
|
|
78
|
+
page('02-mobile', 1520, true);
|
|
79
|
+
page('03-dark', 1990, false, true);
|
|
77
80
|
writeFileSync(output, JSON.stringify({ compositionId, batch }, null, 2) + '\n');
|
|
78
|
-
process.stdout.write(
|
|
81
|
+
process.stdout.write(output + ': ' + batch.length + ' operations\n');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clearly-workflows
|
|
3
3
|
description: >-
|
|
4
|
+
Best with the beehaven CLI (semantic search and write-back); with only the Clearly connector, search with clearly_grep and record decisions with clearly_create.
|
|
4
5
|
Use the Clearly workspace as a COMPANY BRAIN — search the org's accumulated
|
|
5
6
|
context (decisions, facts, prompts, docs), write conclusions back so the next
|
|
6
7
|
agent inherits them instead of re-deriving them, and inherit the team's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clearly-workspace
|
|
3
|
-
description: Understand and audit a Clearly workspace from the terminal — what it holds (documents, projects, boards, tickets, thoughts, files, agents), who authored what, and which known data defects are present. Run `survey.mjs` for the whole picture in one command. TRIGGER when the user asks "what is in this workspace", "how big is this workspace", "audit / survey / check the workspace", "what have my agents made", "is anything broken in here", "who created these", or before any cleanup, migration or backfill — the survey is what tells you whether a repair is needed and whether it worked. NOT for editing documents (use `document-*`) or drawing on a canvas (use clearly-canvas).
|
|
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. Understand and audit a Clearly workspace from the terminal — what it holds (documents, projects, boards, tickets, thoughts, files, agents), who authored what, and which known data defects are present. Run `survey.mjs` for the whole picture in one command. TRIGGER when the user asks "what is in this workspace", "how big is this workspace", "audit / survey / check the workspace", "what have my agents made", "is anything broken in here", "who created these", or before any cleanup, migration or backfill — the survey is what tells you whether a repair is needed and whether it worked. NOT for editing documents (use `document-*`) or drawing on a canvas (use clearly-canvas).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# clearly-workspace — know what you are standing in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: codebase-map
|
|
3
|
-
description: Walk a code repository and draw a living ARCHITECTURE MAP of it on a Clearly spatial canvas — modules as frames (sized by LOC, colored by layer), key files as nodes, imports/dependencies as arrows — so the big pieces, how they depend on each other, and where the complexity sits all read at a glance. Load this when the user says "map / diagram / visualize this codebase / repo / architecture", "how is this project structured", "draw the dependency graph", "give me an architecture overview", or when you're onboarding to an unfamiliar repo and need to see its shape fast.
|
|
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. Walk a code repository and draw a living ARCHITECTURE MAP of it on a Clearly spatial canvas — modules as frames (sized by LOC, colored by layer), key files as nodes, imports/dependencies as arrows — so the big pieces, how they depend on each other, and where the complexity sits all read at a glance. Load this when the user says "map / diagram / visualize this codebase / repo / architecture", "how is this project structured", "draw the dependency graph", "give me an architecture overview", or when you're onboarding to an unfamiliar repo and need to see its shape fast.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
> **⚠ CANVAS WORK GOES THROUGH THE CLI, NOT AN MCP TOOL.** Anything written
|
|
@@ -114,8 +114,9 @@ divided by the ratio. Sizes that share a ratio look related; sizes picked by han
|
|
|
114
114
|
make them obviously different in class (a grotesque with a serif), never two neighbours.
|
|
115
115
|
- **Measure: 45–75 characters.** At 16px in a normal grotesque that is roughly **360–600px**.
|
|
116
116
|
Set the text node's `w` to hold that, not to fill the column.
|
|
117
|
-
- **Line height
|
|
118
|
-
**
|
|
117
|
+
- **Line height defaults to Auto**, using the font's metrics. When tuning it deliberately,
|
|
118
|
+
use **140–160%** for body, **125–135%** for subheads, and **95–105%** for display type.
|
|
119
|
+
Author explicit units (`lineHeight:"140%"` or `"24px"`); percentage leading follows font size.
|
|
119
120
|
- ⚠⚠ **TRACK DISPLAY TYPE NEGATIVE.** Type designed at 16px is far too loose at 120px.
|
|
120
121
|
Above ~40px use `letterSpacing: -1` to `-4`; above ~120px, −3 to −6. **Uppercase and small
|
|
121
122
|
labels go the other way: +1 to +3.** This one adjustment does more for perceived quality
|
|
@@ -250,8 +251,8 @@ only to show that a review happened.
|
|
|
250
251
|
|
|
251
252
|
**A 1080×1350 social post**
|
|
252
253
|
```
|
|
253
|
-
margin 72 · display 96–140 (weight 800, tracking −3, lineHeight
|
|
254
|
-
body 20–24 (weight 500, lineHeight
|
|
254
|
+
margin 72 · display 96–140 (weight 800, tracking −3, lineHeight "100%")
|
|
255
|
+
body 20–24 (weight 500, lineHeight "150%", w ≤ 560)
|
|
255
256
|
caption 16 (weight 600, tracking +1.5, uppercase)
|
|
256
257
|
rule 2–3px accent · footer block bottom-aligned at 1350 − 72 − blockHeight
|
|
257
258
|
```
|
|
@@ -265,7 +266,7 @@ Content column ≤ 1200 wide even though the slide is 1920 — full width is unr
|
|
|
265
266
|
|
|
266
267
|
**A 1440 web hero**
|
|
267
268
|
```
|
|
268
|
-
margin 96 · content max 1200 · headline 64–88 (tracking −2, lineHeight
|
|
269
|
+
margin 96 · content max 1200 · headline 64–88 (tracking −2, lineHeight "105%")
|
|
269
270
|
sub 20–24 (muted ink, w ≤ 640) · CTA 48–56 tall, 24–32 horizontal padding, radius 8 or full
|
|
270
271
|
```
|
|
271
272
|
|
|
@@ -273,7 +274,9 @@ sub 20–24 (muted ink, w ≤ 640) · CTA 48–56 tall, 24–32 horizontal paddi
|
|
|
273
274
|
```
|
|
274
275
|
padding 24–32 · radius 10–16 · gap between cards ≥ 2× padding
|
|
275
276
|
title 20–24/600 · body 15–16/400 muted · one accent element maximum
|
|
276
|
-
|
|
277
|
+
Use a filled frame that owns the card's contents. Apply auto layout with this padding
|
|
278
|
+
and a deliberate content gap; let text hug its height. Rectangles serve artwork,
|
|
279
|
+
swatches and rules. A background rectangle with sibling text does not form a card.
|
|
277
280
|
```
|
|
278
281
|
|
|
279
282
|
---
|
package/skills/index.json
CHANGED
|
@@ -17,21 +17,21 @@
|
|
|
17
17
|
"project-plans.md",
|
|
18
18
|
"review.mjs"
|
|
19
19
|
],
|
|
20
|
-
"sha": "
|
|
20
|
+
"sha": "5daf296f2bdf65e6"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"name": "agent-home",
|
|
24
24
|
"files": [
|
|
25
25
|
"SKILL.md"
|
|
26
26
|
],
|
|
27
|
-
"sha": "
|
|
27
|
+
"sha": "e1d18e7518ff4b65"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"name": "agent-doodle-space",
|
|
31
31
|
"files": [
|
|
32
32
|
"SKILL.md"
|
|
33
33
|
],
|
|
34
|
-
"sha": "
|
|
34
|
+
"sha": "1e1911e6d8784476"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"name": "design-craft",
|
|
@@ -39,35 +39,35 @@
|
|
|
39
39
|
"SKILL.md",
|
|
40
40
|
"references.md"
|
|
41
41
|
],
|
|
42
|
-
"sha": "
|
|
42
|
+
"sha": "d11f0c45c93c9dea"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"name": "layout-systems",
|
|
46
46
|
"files": [
|
|
47
47
|
"SKILL.md"
|
|
48
48
|
],
|
|
49
|
-
"sha": "
|
|
49
|
+
"sha": "27151a50e3bdb27a"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"name": "brand-identity",
|
|
53
53
|
"files": [
|
|
54
54
|
"SKILL.md"
|
|
55
55
|
],
|
|
56
|
-
"sha": "
|
|
56
|
+
"sha": "366139b11ff11b58"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"name": "pair-on-canvas",
|
|
60
60
|
"files": [
|
|
61
61
|
"SKILL.md"
|
|
62
62
|
],
|
|
63
|
-
"sha": "
|
|
63
|
+
"sha": "1d79147baa8c232d"
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"name": "codebase-map",
|
|
67
67
|
"files": [
|
|
68
68
|
"SKILL.md"
|
|
69
69
|
],
|
|
70
|
-
"sha": "
|
|
70
|
+
"sha": "4a4af2229b68827d"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"name": "clearly-workspace",
|
|
@@ -75,28 +75,28 @@
|
|
|
75
75
|
"SKILL.md",
|
|
76
76
|
"survey.mjs"
|
|
77
77
|
],
|
|
78
|
-
"sha": "
|
|
78
|
+
"sha": "3a3e6fa6e3cf8717"
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
"name": "clearly-agent",
|
|
82
82
|
"files": [
|
|
83
83
|
"SKILL.md"
|
|
84
84
|
],
|
|
85
|
-
"sha": "
|
|
85
|
+
"sha": "c20b255224221342"
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
"name": "visualize",
|
|
89
89
|
"files": [
|
|
90
90
|
"SKILL.md"
|
|
91
91
|
],
|
|
92
|
-
"sha": "
|
|
92
|
+
"sha": "88bb6e94fb37c337"
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"name": "sticker-pack",
|
|
96
96
|
"files": [
|
|
97
97
|
"SKILL.md"
|
|
98
98
|
],
|
|
99
|
-
"sha": "
|
|
99
|
+
"sha": "74af254817a134d6"
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
102
|
"name": "clearly-docs",
|
|
@@ -117,6 +117,6 @@
|
|
|
117
117
|
"files": [
|
|
118
118
|
"SKILL.md"
|
|
119
119
|
],
|
|
120
|
-
"sha": "
|
|
120
|
+
"sha": "b9622f21173bab0d"
|
|
121
121
|
}
|
|
122
122
|
]
|
|
@@ -47,7 +47,7 @@ that lost one. If you have four items, ask whether one is really a different thi
|
|
|
47
47
|
```
|
|
48
48
|
margin 8–10% of the short edge (1080 → 88–108; A3 → 280–350)
|
|
49
49
|
display 12–20% of the HEIGHT (1350 → 160–270px), weight 700–900, tracking −3 to −6,
|
|
50
|
-
lineHeight
|
|
50
|
+
lineHeight "92%"–"100%"
|
|
51
51
|
supporting 2–3% of height credits, date, venue — deliberately small
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -105,7 +105,7 @@ content column ≤ 1200 even though the slide is 1920
|
|
|
105
105
|
## Landing page / hero — 1440 wide (design), content max 1200
|
|
106
106
|
|
|
107
107
|
```
|
|
108
|
-
margin 96 · headline 64–88 (tracking −2, lineHeight
|
|
108
|
+
margin 96 · headline 64–88 (tracking −2, lineHeight "105%") · sub 20–24 muted, w ≤ 640
|
|
109
109
|
CTA 48–56 tall, 24–32 horizontal padding · section spacing 96–160 vertical
|
|
110
110
|
```
|
|
111
111
|
|
|
@@ -124,7 +124,7 @@ CTA 48–56 tall, 24–32 horizontal padding · section spacing 96–160 vertica
|
|
|
124
124
|
|
|
125
125
|
```
|
|
126
126
|
margin: outer 10%, inner (gutter side) 12–14% — asymmetric, because the binding eats it
|
|
127
|
-
columns 2–3 for A4 body · measure 45–75ch · body 10–11pt (≈42–46px at 300dpi), lineHeight
|
|
127
|
+
columns 2–3 for A4 body · measure 45–75ch · body 10–11pt (≈42–46px at 300dpi), lineHeight "145%"
|
|
128
128
|
```
|
|
129
129
|
|
|
130
130
|
- **Asymmetric margins are the mark of real editorial.** Equal margins all round read as a
|
|
@@ -141,9 +141,9 @@ columns 2–3 for A4 body · measure 45–75ch · body 10–11pt (≈42–46px a
|
|
|
141
141
|
## Cards, tables and dense UI
|
|
142
142
|
|
|
143
143
|
- **Card padding 24–32, radius 10–16, gap between cards ≥ 2× padding.**
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
- **Cards are filled frames.** Parent labels, icons and controls to the card; use auto
|
|
145
|
+
layout for its content. Build rows and grids from these cards, with deliberate
|
|
146
|
+
Hug/Fill/Fixed sizing. Reserve rectangles for decorative shapes, swatches and rules.
|
|
147
147
|
- **In tables, align numbers RIGHT and use tabular figures.** Left-aligned numbers of
|
|
148
148
|
different lengths cannot be compared, which is the only reason the table exists.
|
|
149
149
|
- **Zebra striping OR rules, never both.** Ideally neither — space is enough at ≥12px row padding.
|
|
@@ -153,10 +153,13 @@ columns 2–3 for A4 body · measure 45–75ch · body 10–11pt (≈42–46px a
|
|
|
153
153
|
## Building it on the canvas
|
|
154
154
|
|
|
155
155
|
```jsonc
|
|
156
|
-
// ONE batch.
|
|
157
|
-
{"action":"frame.create","args":{"
|
|
158
|
-
{"action":"canvas.create-node","args":{"name":"
|
|
159
|
-
"
|
|
156
|
+
// ONE batch. A content stack owns its fill and children; the layout computes positions.
|
|
157
|
+
{"action":"frame.create","args":{"id":"card","name":"Feature card","w":360,"h":200,"fill":"#FFFFFF"}}
|
|
158
|
+
{"action":"canvas.create-node","args":{"name":"Feature title","type":"text","parentId":"card",
|
|
159
|
+
"w":312,"text":"Make room for the idea","size":28,"fontWeight":600,"lineHeight":"auto"}}
|
|
160
|
+
{"action":"canvas.create-node","args":{"name":"Feature detail","type":"text","parentId":"card",
|
|
161
|
+
"w":312,"text":"Keep every layer ready for the next edit.","size":16,"lineHeight":"145%"}}
|
|
162
|
+
{"action":"canvas.auto-layout","args":{"id":"card","direction":"v","gap":16,"padding":24,"sizingH":"fixed","sizingV":"hug"}}
|
|
160
163
|
```
|
|
161
164
|
|
|
162
165
|
- ⚠ **Omit `h` on text** — it hugs its wrapped content. Pin `h` only when a later element's
|
|
@@ -180,5 +183,5 @@ columns 2–3 for A4 body · measure 45–75ch · body 10–11pt (≈42–46px a
|
|
|
180
183
|
| Deck | too many words; title states the topic instead of the argument; full-width text |
|
|
181
184
|
| Landing | subhead runs full width; two competing CTAs; sections evenly spaced |
|
|
182
185
|
| Editorial | symmetric margins; no baseline grid; unbroken columns |
|
|
183
|
-
| Cards |
|
|
186
|
+
| Cards | background and contents lack a shared frame; layout breaks when copy grows |
|
|
184
187
|
| **All** | **an exact 50/50 split, and four type sizes where three would do** |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pair-on-canvas
|
|
3
|
-
description: Use a Clearly canvas as mission control for a coding task — read the spec the human placed on the board, do the work in the repo, and report progress, diffs, and next steps back as cards they steer by inking. Load this when the user says "work the task on my canvas", "take this from the board", "what's on my Clearly canvas", "pick up the spec", "let's pair on the canvas", or whenever a human is directing your coding work spatially instead of in a chat thread.
|
|
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. Use a Clearly canvas as mission control for a coding task — read the spec the human placed on the board, do the work in the repo, and report progress, diffs, and next steps back as cards they steer by inking. Load this when the user says "work the task on my canvas", "take this from the board", "what's on my Clearly canvas", "pick up the spec", "let's pair on the canvas", or whenever a human is directing your coding work spatially instead of in a chat thread.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
> **⚠ CANVAS WORK GOES THROUGH THE CLI, NOT AN MCP TOOL.** Anything written
|