@polderlabs/bizar 4.4.8 → 4.4.10
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/config/skills/glyph/SKILL.md +94 -206
- package/package.json +1 -1
|
@@ -1,275 +1,163 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: glyph
|
|
3
|
-
description: Create
|
|
4
|
-
version:
|
|
3
|
+
description: Create visual glyphs at `artifacts/<slug>/` for plans, recaps, design proposals, postmortems, handoffs. Glyphs should be compact and visual — one screen, dense info, no walls of text. This skill enforces that.
|
|
4
|
+
version: 4
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Glyphs
|
|
7
|
+
# Glyphs
|
|
8
8
|
|
|
9
|
-
A **glyph** is
|
|
10
|
-
|
|
11
|
-
## When to create a glyph
|
|
12
|
-
|
|
13
|
-
- **Design proposal** — you're proposing a new component, system, or workflow
|
|
14
|
-
- **Decision recap** — multiple options were considered; one was chosen; the reasoning matters
|
|
15
|
-
- **Postmortem** — something broke; here's the timeline and root cause
|
|
16
|
-
- **Implementation plan** — breaking down a non-trivial feature into phases
|
|
17
|
-
- **Handoff** — work moving from one agent to another
|
|
18
|
-
|
|
19
|
-
If it's a one-line fix, don't make a glyph. If it's a 5-minute edit, don't make a glyph. Glyphs are for work that needs visible structure.
|
|
20
|
-
|
|
21
|
-
## File structure
|
|
9
|
+
A **glyph** is an MDX file the dashboard renders with a comment-pin overlay and right-click menu. Three files per glyph:
|
|
22
10
|
|
|
23
11
|
```
|
|
24
12
|
artifacts/<slug>/
|
|
25
|
-
├── meta.json
|
|
26
|
-
├── artifact.mdx
|
|
27
|
-
└── comments.json
|
|
13
|
+
├── meta.json ← title, status, author, created
|
|
14
|
+
├── artifact.mdx ← source of truth
|
|
15
|
+
└── comments.json ← free-placed pins (mutable)
|
|
28
16
|
```
|
|
29
17
|
|
|
30
|
-
Two locations
|
|
31
|
-
1. **Per-project:** `<projectRoot>/.bizar/artifacts/<slug>/`
|
|
32
|
-
2. **Global:** `~/.config/opencode/artifacts/<slug>/`
|
|
33
|
-
|
|
34
|
-
The dashboard uses whichever exists. The project's `artifacts/<slug>/` is preferred when running inside a worktree.
|
|
18
|
+
Two locations: `<projectRoot>/.bizar/artifacts/` (preferred) and `~/.config/opencode/artifacts/` (global).
|
|
35
19
|
|
|
36
20
|
## Frontmatter
|
|
37
21
|
|
|
38
22
|
```yaml
|
|
39
23
|
---
|
|
40
24
|
title: "Short, action-oriented title"
|
|
41
|
-
brief: "One sentence
|
|
25
|
+
brief: "One sentence."
|
|
42
26
|
status: draft | review | shipped | archived
|
|
43
27
|
kind: plan | postmortem | recap | design
|
|
44
28
|
---
|
|
45
29
|
```
|
|
46
30
|
|
|
47
|
-
The
|
|
48
|
-
|
|
49
|
-
## Block vocabulary
|
|
50
|
-
|
|
51
|
-
```mdx
|
|
52
|
-
<RichText id="...">markdown content (headings, lists, code blocks, etc.)</RichText>
|
|
31
|
+
## The 6 rules — read this first, every time
|
|
53
32
|
|
|
54
|
-
|
|
33
|
+
These are non-negotiable. The existing 357-line v3-to-v4-consolidation glyph is a cautionary tale — don't write that one.
|
|
55
34
|
|
|
56
|
-
|
|
35
|
+
### Rule 1 — One screen
|
|
57
36
|
|
|
58
|
-
|
|
59
|
-
id="..."
|
|
60
|
-
items={[
|
|
61
|
-
{ id: "i1", label: "...", checked: true },
|
|
62
|
-
{ id: "i2", label: "...", checked: false }
|
|
63
|
-
]}
|
|
64
|
-
/>
|
|
37
|
+
A glyph MUST fit on one screen of the dashboard (≈ 1000px tall at desktop width). Long glyphs are skimmed and abandoned. If you can't fit the work in 5-10 blocks, you're covering too much. Break the work into multiple glyphs, one per phase.
|
|
65
38
|
|
|
66
|
-
|
|
67
|
-
id="..."
|
|
68
|
-
columns={["A", "B"]}
|
|
69
|
-
rows={[["x", "y"], ["p", "q"]]}
|
|
70
|
-
/>
|
|
39
|
+
### Rule 2 — One idea per block
|
|
71
40
|
|
|
72
|
-
|
|
73
|
-
id="..."
|
|
74
|
-
tabs={[
|
|
75
|
-
{ id: "t1", label: "file.ts", language: "typescript", code: "...", caption: "..." }
|
|
76
|
-
]}
|
|
77
|
-
/>
|
|
41
|
+
If a block covers two ideas, split it. Each block is a single visual unit. The dashboard groups blocks into sections by id prefix — use that.
|
|
78
42
|
|
|
79
|
-
|
|
80
|
-
id="..."
|
|
81
|
-
title="..."
|
|
82
|
-
question="..."
|
|
83
|
-
options={[
|
|
84
|
-
{ id: "a", label: "...", detail: "...", recommended: true }
|
|
85
|
-
]}
|
|
86
|
-
/>
|
|
43
|
+
### Rule 3 — RichText is glue, not body
|
|
87
44
|
|
|
88
|
-
|
|
89
|
-
id="..."
|
|
90
|
-
questions={[
|
|
91
|
-
{ id: "q1", label: "...", kind: "choice|text|multi", options: ["A", "B"] }
|
|
92
|
-
]}
|
|
93
|
-
/>
|
|
45
|
+
RichText is for 1-3 sentence transitions between visual blocks. NEVER use RichText for the actual content. If you find yourself writing 4+ sentences in a RichText, switch to:
|
|
94
46
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
]}
|
|
101
|
-
/>
|
|
47
|
+
- **A table** if you're listing things with attributes
|
|
48
|
+
- **A decision** if you're explaining why one option won
|
|
49
|
+
- **A file tree** if you're listing changes
|
|
50
|
+
- **A stat** if you're highlighting a number
|
|
51
|
+
- **A workflow** if you're describing a sequence
|
|
102
52
|
|
|
103
|
-
|
|
104
|
-
id="..."
|
|
105
|
-
steps={[
|
|
106
|
-
{ id: "s1", label: "...", type: "task|decision|note" }
|
|
107
|
-
]}
|
|
108
|
-
connections={[
|
|
109
|
-
{ from: "s1", to: "s2", label: "yes" }
|
|
110
|
-
]}
|
|
111
|
-
/>
|
|
53
|
+
### Rule 4 — Lead with visuals
|
|
112
54
|
|
|
113
|
-
|
|
114
|
-
id="..."
|
|
115
|
-
title="..."
|
|
116
|
-
x={40} y={120} w={280} h={180}
|
|
117
|
-
html="<div class='mockup-card'>...</div>"
|
|
118
|
-
/>
|
|
55
|
+
The first block after the title/headline should be a visual: a Stat, a Callout, or a Table. Never open with a long RichText. The user decides in 5 seconds whether to keep scrolling based on the visual.
|
|
119
56
|
|
|
120
|
-
|
|
121
|
-
id="..."
|
|
122
|
-
title="..."
|
|
123
|
-
dataHtml="<svg>...</svg>"
|
|
124
|
-
dataCss=".diagram-node { fill: var(--bg-1); }"
|
|
125
|
-
/>
|
|
126
|
-
```
|
|
57
|
+
### Rule 5 — One headline callout
|
|
127
58
|
|
|
128
|
-
|
|
59
|
+
Use `<Callout tone="success|danger">` once, near the top, as the TL;DR. Everything else supports it.
|
|
129
60
|
|
|
130
|
-
|
|
61
|
+
### Rule 6 — Truncate hints, not bodies
|
|
131
62
|
|
|
132
|
-
|
|
133
|
-
| --- | --- |
|
|
134
|
-
| `RichText` | none (children are markdown) |
|
|
135
|
-
| `Callout` | none; optional `tone: 'info' \| 'warn' \| 'success' \| 'danger'` (default: info) |
|
|
136
|
-
| `Stat` | `label: string`, `value: string \| number`; optional `trend`, `hint` |
|
|
137
|
-
| `Checklist` | `items: Array<{ id, label, checked }>` |
|
|
138
|
-
| `Table` | `columns: string[]`, `rows: string[][]` (each row is a cell array) |
|
|
139
|
-
| `CodeTabs` | `tabs: Array<{ id, label, language, code, caption? }>` |
|
|
140
|
-
| `Decision` | `options: Array<{ id, label, detail, recommended? }>`; optional `title`, `question` |
|
|
141
|
-
| `OpenQuestions` | `questions: Array<{ id, label, kind, options? }>` |
|
|
142
|
-
| `FileTree` | `entries: Array<{ path, change, note? }>` where `change ∈ {added, modified, removed, renamed}` |
|
|
143
|
-
| `Diff` | `before: string`, `after: string`; optional `filename`, `language`, `mode` |
|
|
144
|
-
| `Workflow` | `steps: Array<{ id, label, type }>`; optional `connections` |
|
|
145
|
-
| `Mockup` | `html: string`; optional `title`, `x`, `y`, `w`, `h` |
|
|
146
|
-
| `Diagram` | `dataHtml: string`; optional `title`, `dataCss` |
|
|
63
|
+
Stat `hint` props should be 1 short clause. Long hints mean the value needs to be a different block.
|
|
147
64
|
|
|
148
|
-
##
|
|
65
|
+
## The block vocabulary — minimal reference
|
|
149
66
|
|
|
150
|
-
|
|
67
|
+
| Block | What it shows | Required `data` |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `<RichText>` | 1-3 sentences of glue | none |
|
|
70
|
+
| `<Callout tone>` | Boxed TL;DR | none (tone defaults to info) |
|
|
71
|
+
| `<Stat label value trend hint />` | Big number + label | `label`, `value` |
|
|
72
|
+
| `<Checklist items />` | Checkbox list | `items: [{id,label,checked}]` |
|
|
73
|
+
| `<Table columns rows />` | Tabular data | `columns: []`, `rows: [[]]` |
|
|
74
|
+
| `<CodeTabs tabs />` | Tabbed code | `tabs: [{id,label,language,code}]` |
|
|
75
|
+
| `<Decision title question options />` | Multi-option choice | `options: [{id,label,detail,recommended?}]` |
|
|
76
|
+
| `<OpenQuestions questions />` | Unanswered questions | `questions: [{id,label,kind,options?}]` |
|
|
77
|
+
| `<FileTree title entries />` | File-by-file changes | `entries: [{path,change,note?}]` |
|
|
78
|
+
| `<Diff before after filename language mode />` | Before/after | `before`, `after` |
|
|
79
|
+
| `<Workflow steps connections />` | Node graph | `steps: [{id,label,type}]` |
|
|
80
|
+
| `<Mockup title x y w h html />` | Inline UI mockup | `html` |
|
|
81
|
+
| `<Diagram title dataHtml dataCss />` | Inline SVG | `dataHtml` |
|
|
151
82
|
|
|
152
|
-
|
|
83
|
+
Every block needs a unique `id`. RichText + Callout use open/close tags (markdown body); everything else is self-closing.
|
|
153
84
|
|
|
154
|
-
|
|
85
|
+
## Skeleton
|
|
155
86
|
|
|
156
87
|
```mdx
|
|
157
|
-
|
|
158
|
-
|
|
88
|
+
<RichText id="overview">
|
|
89
|
+
## What this is
|
|
159
90
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
<RichText id="x">Run the installer to bootstrap.</RichText>
|
|
163
|
-
```
|
|
91
|
+
One sentence the reader can't miss.
|
|
92
|
+
</RichText>
|
|
164
93
|
|
|
165
|
-
|
|
94
|
+
<Stat id="headline" label="X shipped" value="7" trend="flat" hint="across v3.22 → v4.4.7" />
|
|
166
95
|
|
|
167
|
-
|
|
96
|
+
<Callout id="tldr" tone="success">
|
|
97
|
+
One-sentence TL;DR.
|
|
98
|
+
</Callout>
|
|
168
99
|
|
|
169
|
-
|
|
100
|
+
<Table
|
|
101
|
+
id="releases"
|
|
102
|
+
columns={["v", "what", "fix"]}
|
|
103
|
+
rows={[
|
|
104
|
+
["3.22", "unified", "—"],
|
|
105
|
+
["4.4.1", "bg fix", "process exit crash"],
|
|
106
|
+
]}
|
|
107
|
+
/>
|
|
170
108
|
|
|
171
|
-
|
|
172
|
-
|
|
109
|
+
<FileTree
|
|
110
|
+
id="files"
|
|
111
|
+
title="Files changed"
|
|
112
|
+
entries={[
|
|
113
|
+
{ path: "cli/provision.mjs", change: "added", note: "unified provisioner" },
|
|
114
|
+
]}
|
|
115
|
+
/>
|
|
173
116
|
```
|
|
174
117
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
**Rule of thumb:** keep string values brace-free. If you must use `{...}` in a note, escape or rephrase.
|
|
178
|
-
|
|
179
|
-
### 3. Trailing commas in arrays used to be a phantom-element bug
|
|
118
|
+
## The 5 things that break a glyph
|
|
180
119
|
|
|
181
|
-
|
|
120
|
+
These shipped as bugs. Read before writing.
|
|
182
121
|
|
|
183
|
-
|
|
122
|
+
### 1. Backticks inside attribute strings
|
|
184
123
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
`change` must be exactly one of: `added`, `modified`, `removed`, `renamed`. Anything else (including the empty string or `null`) makes `FILE_CHANGE[e.change]` return `undefined` and the renderer crashes with "can't access property 'bg' of undefined".
|
|
188
|
-
|
|
189
|
-
```mdx
|
|
190
|
-
<!-- WRONG -->
|
|
191
|
-
{ path: "src/foo.ts", change: null, note: "..." }
|
|
192
|
-
{ path: "src/foo.ts", change: "", note: "..." }
|
|
124
|
+
The parser scans for `` ` `` and breaks. Use straight quotes or rephrase:
|
|
193
125
|
|
|
194
|
-
<!-- RIGHT -->
|
|
195
|
-
{ path: "src/foo.ts", change: "modified", note: "..." }
|
|
196
|
-
{ path: "src/foo.ts", change: "added", note: "..." }
|
|
197
126
|
```
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
### 5. MDX heading with `<N`
|
|
202
|
-
|
|
203
|
-
A heading like `## Mobile (under 768px)` is fine. But `## Mobile <768px` breaks the MDX validator because `<7` looks like a malformed JSX tag. Always escape or rephrase:
|
|
204
|
-
|
|
205
|
-
```mdx
|
|
206
|
-
## Mobile (under 768px) <!-- fine -->
|
|
207
|
-
## Mobile: under 768px <!-- fine -->
|
|
208
|
-
## Mobile < 768px <!-- fine but ugly -->
|
|
127
|
+
WRONG: Run `bizar install` to bootstrap.
|
|
128
|
+
RIGHT: Run 'bizar install' to bootstrap.
|
|
209
129
|
```
|
|
210
130
|
|
|
211
|
-
###
|
|
131
|
+
### 2. Braces inside string values
|
|
212
132
|
|
|
213
|
-
|
|
133
|
+
The brace counter doesn't know about strings. `{` / `}` in notes still bump depth. Keep note strings brace-free.
|
|
214
134
|
|
|
215
|
-
###
|
|
135
|
+
### 3. `FileTree` `change` must be exact
|
|
216
136
|
|
|
217
|
-
|
|
137
|
+
`added | modified | removed | renamed`. Empty string or `null` crashes on `t.bg`. Default to `modified` with a `note` when unclear.
|
|
218
138
|
|
|
219
|
-
|
|
220
|
-
<!-- self-closing -->
|
|
221
|
-
<Stat id="x" label="..." value="..." />
|
|
139
|
+
### 4. Duplicate block ids
|
|
222
140
|
|
|
223
|
-
|
|
224
|
-
<RichText id="x">markdown content here</RichText>
|
|
225
|
-
<Callout id="x" tone="warn">important message</Callout>
|
|
226
|
-
```
|
|
141
|
+
Comment pins and error reporting key off ids. Two blocks with the same id collide.
|
|
227
142
|
|
|
228
|
-
###
|
|
143
|
+
### 5. `## Heading <768px`
|
|
229
144
|
|
|
230
|
-
The parser
|
|
145
|
+
The parser sees `<7` as a malformed JSX tag. Use parentheses or colons.
|
|
231
146
|
|
|
232
|
-
##
|
|
147
|
+
## Validate before shipping
|
|
233
148
|
|
|
234
|
-
```
|
|
235
|
-
{
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
"created": "2026-06-26T20:30:00.000Z",
|
|
241
|
-
"lastEdited": "2026-06-26T20:30:00.000Z"
|
|
242
|
-
}
|
|
149
|
+
```bash
|
|
150
|
+
node -e "import('./bizar-dash/src/server/glyphs/mdx-compiler.mjs').then(m => { \
|
|
151
|
+
const fs = require('node:fs'); \
|
|
152
|
+
const out = m.compileGlyphMdxSync(fs.readFileSync('artifacts/<slug>/artifact.mdx','utf8')); \
|
|
153
|
+
console.log('blocks:', out.blocks.length, 'errors:', out.errors.length); \
|
|
154
|
+
})"
|
|
243
155
|
```
|
|
244
156
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
## Validation workflow
|
|
248
|
-
|
|
249
|
-
Before committing a glyph:
|
|
250
|
-
|
|
251
|
-
1. Run the compiler against your MDX:
|
|
252
|
-
```bash
|
|
253
|
-
node -e "import('./bizar-dash/src/server/glyphs/mdx-compiler.mjs').then(m => { const fs = require('node:fs'); const src = fs.readFileSync('artifacts/<slug>/artifact.mdx', 'utf8'); const out = m.compileGlyphMdxSync(src); console.log('blocks:', out.blocks.length, 'errors:', out.errors); out.errors.forEach(e => console.error(' line', e.line, ':', e.message)); })"
|
|
254
|
-
```
|
|
255
|
-
This catches parser bugs (missing tags, malformed attrs, etc.) before they hit the dashboard.
|
|
256
|
-
|
|
257
|
-
2. Visually inspect the rendered output by hitting `GET /api/artifacts/<slug>/render`. The response is the compiled JSON the React renderer consumes. Look for blocks with missing data fields — those will show up as `data: {}` or `data: []`.
|
|
258
|
-
|
|
259
|
-
3. Open the glyph in the dashboard. v4.4.8+ shows a red error banner at the top of the canvas if any block failed to render. The banner lists every block error AND every compiler warning.
|
|
260
|
-
|
|
261
|
-
## How to view in the dashboard
|
|
262
|
-
|
|
263
|
-
Glyphs are rendered at `/artifacts/<slug>`. The dashboard shows them with:
|
|
264
|
-
- **Section grouping** — by block id prefix (e.g. all blocks with ids starting `overview_` go into the "Overview" section)
|
|
265
|
-
- **Comment pin overlay** — right-click anywhere to add a comment
|
|
266
|
-
- **Floating toolbar** — Send to agent, share, fullscreen
|
|
267
|
-
- **Error banner** — v4.4.8+: red banner at the top with block render errors and compiler warnings. The page is no longer blank when something fails — you'll see exactly which block crashed and why.
|
|
268
|
-
- **Status badge** — `draft | review | shipped | archived`. `shipped` locks editing.
|
|
157
|
+
Also check yourself: does it fit on one screen? Are there any 4-sentence RichText blocks? Are the stats/tables/file trees doing the heavy lifting? If not, rewrite.
|
|
269
158
|
|
|
270
159
|
## See also
|
|
271
160
|
|
|
272
|
-
- `bizar-dash/src/
|
|
273
|
-
- `bizar-dash/src/
|
|
274
|
-
- `bizar-dash/src/web/views/glyphs/
|
|
275
|
-
- `artifacts/sample-plan-login/` — a complete worked example
|
|
161
|
+
- `bizar-dash/src/server/glyphs/mdx-compiler.mjs` — parser
|
|
162
|
+
- `bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx` — React renderer (has error banner)
|
|
163
|
+
- `bizar-dash/src/web/views/glyphs/components.tsx` — block implementations
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polderlabs/bizar",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.10",
|
|
4
4
|
"description": "Norse-pantheon multi-agent system for opencode — 13 agents across 4 cost tiers with cost-aware routing, plans, and a configurable agent harness. v4 ships as a single npm package bundling the dashboard server, opencode plugin, and typed SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|