@polderlabs/bizar 4.4.8 → 4.4.9
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 +78 -206
- package/package.json +1 -1
|
@@ -1,275 +1,147 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: glyph
|
|
3
|
-
description: Create and consume Bizar glyphs — visual
|
|
4
|
-
version:
|
|
3
|
+
description: Create and consume Bizar glyphs — visual artifacts at `artifacts/<slug>/`. Use for plans, recaps, design proposals, postmortems, handoffs. Quick reference for the block vocabulary and the 5 things that actually break a glyph.
|
|
4
|
+
version: 3
|
|
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 are scanned:
|
|
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 are scanned: `<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 blocks at a glance
|
|
53
32
|
|
|
54
|
-
|
|
33
|
+
| Block | What it shows | Required `data` |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `<RichText>` | Prose, lists, code blocks | none — body is markdown |
|
|
36
|
+
| `<Callout tone="info\|warn\|success\|danger">` | Boxed callout | none (tone defaults to info) |
|
|
37
|
+
| `<Stat label value trend hint />` | Big number with trend | `label`, `value` |
|
|
38
|
+
| `<Checklist items={[...]} />` | Checkbox list | `items: [{id,label,checked}]` |
|
|
39
|
+
| `<Table columns rows />` | Tabular data | `columns: []`, `rows: [[]]` |
|
|
40
|
+
| `<CodeTabs tabs />` | Tabbed code blocks | `tabs: [{id,label,language,code}]` |
|
|
41
|
+
| `<Decision title question options />` | Multi-option choice | `options: [{id,label,detail,recommended?}]` |
|
|
42
|
+
| `<OpenQuestions questions />` | Unanswered questions | `questions: [{id,label,kind,options?}]` |
|
|
43
|
+
| `<FileTree title entries />` | File-by-file change list | `entries: [{path,change,note?}]` |
|
|
44
|
+
| `<Diff before after filename language mode />` | Before/after diff | `before`, `after` |
|
|
45
|
+
| `<Workflow steps connections />` | Node graph | `steps: [{id,label,type}]` |
|
|
46
|
+
| `<Mockup title x y w h html />` | Inline UI mockup | `html` |
|
|
47
|
+
| `<Diagram title dataHtml dataCss />` | Inline SVG | `dataHtml` |
|
|
55
48
|
|
|
56
|
-
|
|
49
|
+
Every block needs a unique `id`. `RichText` and `Callout` use open/close tags with markdown children; everything else is self-closing.
|
|
57
50
|
|
|
58
|
-
|
|
59
|
-
id="..."
|
|
60
|
-
items={[
|
|
61
|
-
{ id: "i1", label: "...", checked: true },
|
|
62
|
-
{ id: "i2", label: "...", checked: false }
|
|
63
|
-
]}
|
|
64
|
-
/>
|
|
51
|
+
## Skeleton
|
|
65
52
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
rows={[["x", "y"], ["p", "q"]]}
|
|
70
|
-
/>
|
|
53
|
+
```mdx
|
|
54
|
+
<RichText id="overview">
|
|
55
|
+
## What this covers
|
|
71
56
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
tabs={[
|
|
75
|
-
{ id: "t1", label: "file.ts", language: "typescript", code: "...", caption: "..." }
|
|
76
|
-
]}
|
|
77
|
-
/>
|
|
57
|
+
A one-paragraph summary.
|
|
58
|
+
</RichText>
|
|
78
59
|
|
|
79
|
-
<
|
|
80
|
-
id="..."
|
|
81
|
-
title="..."
|
|
82
|
-
question="..."
|
|
83
|
-
options={[
|
|
84
|
-
{ id: "a", label: "...", detail: "...", recommended: true }
|
|
85
|
-
]}
|
|
86
|
-
/>
|
|
60
|
+
<Stat id="headline" label="X" value="7" trend="flat" />
|
|
87
61
|
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
{ id: "q1", label: "...", kind: "choice|text|multi", options: ["A", "B"] }
|
|
92
|
-
]}
|
|
93
|
-
/>
|
|
62
|
+
<Callout id="warning" tone="warn">
|
|
63
|
+
One important thing.
|
|
64
|
+
</Callout>
|
|
94
65
|
|
|
95
66
|
<FileTree
|
|
96
|
-
id="
|
|
97
|
-
title="
|
|
67
|
+
id="files"
|
|
68
|
+
title="Files changed"
|
|
98
69
|
entries={[
|
|
99
|
-
{ path: "src/foo.ts", change: "
|
|
70
|
+
{ path: "src/foo.ts", change: "modified", note: "why" },
|
|
71
|
+
{ path: "src/bar.ts", change: "added" },
|
|
100
72
|
]}
|
|
101
73
|
/>
|
|
102
74
|
|
|
103
75
|
<Workflow
|
|
104
|
-
id="
|
|
76
|
+
id="flow"
|
|
105
77
|
steps={[
|
|
106
|
-
{ id: "s1", label: "
|
|
78
|
+
{ id: "s1", label: "Step 1", type: "task" },
|
|
79
|
+
{ id: "s2", label: "Step 2", type: "task" },
|
|
107
80
|
]}
|
|
108
81
|
connections={[
|
|
109
|
-
{ from: "s1", to: "s2"
|
|
82
|
+
{ from: "s1", to: "s2" },
|
|
110
83
|
]}
|
|
111
84
|
/>
|
|
112
|
-
|
|
113
|
-
<Mockup
|
|
114
|
-
id="..."
|
|
115
|
-
title="..."
|
|
116
|
-
x={40} y={120} w={280} h={180}
|
|
117
|
-
html="<div class='mockup-card'>...</div>"
|
|
118
|
-
/>
|
|
119
|
-
|
|
120
|
-
<Diagram
|
|
121
|
-
id="..."
|
|
122
|
-
title="..."
|
|
123
|
-
dataHtml="<svg>...</svg>"
|
|
124
|
-
dataCss=".diagram-node { fill: var(--bg-1); }"
|
|
125
|
-
/>
|
|
126
85
|
```
|
|
127
86
|
|
|
128
|
-
##
|
|
129
|
-
|
|
130
|
-
The dashboard validates every block's `data` shape BEFORE rendering. If a field is missing or the wrong type, the block renders an inline error card instead of crashing the whole canvas (v4.4.8+). The same thing happens if a block throws during render — a per-block `ErrorBoundary` catches it.
|
|
131
|
-
|
|
132
|
-
| Block | Required `data` fields |
|
|
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` |
|
|
147
|
-
|
|
148
|
-
## Common pitfalls
|
|
87
|
+
## The 5 things that break a glyph
|
|
149
88
|
|
|
150
|
-
|
|
89
|
+
Read this BEFORE writing. Each one is a real bug we've shipped.
|
|
151
90
|
|
|
152
|
-
### 1. Backticks inside attribute strings
|
|
91
|
+
### 1. Backticks inside attribute strings
|
|
153
92
|
|
|
154
|
-
The
|
|
93
|
+
The parser scans for `` ` `` to delimit template literals. A literal backtick inside a string — even inside double-quotes — closes the surrounding context and breaks parsing.
|
|
155
94
|
|
|
156
|
-
```mdx
|
|
157
|
-
<!-- WRONG: \` inside a string value kills the parser -->
|
|
158
|
-
<RichText id="x">Run \`bizar install\` to bootstrap.</RichText>
|
|
159
|
-
|
|
160
|
-
<!-- RIGHT: use straight quotes or rephrase -->
|
|
161
|
-
<RichText id="x">Run 'bizar install' to bootstrap.</RichText>
|
|
162
|
-
<RichText id="x">Run the installer to bootstrap.</RichText>
|
|
163
95
|
```
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
### 2. The parser counts braces naively (does NOT track strings)
|
|
168
|
-
|
|
169
|
-
The `parseJsxValue` function uses a brace-depth counter that doesn't know about string literals. If you have something like:
|
|
170
|
-
|
|
171
|
-
```mdx
|
|
172
|
-
<FileTree entries={[{ path: "x", change: "added", note: "this {weird} note" }]} />
|
|
96
|
+
WRONG: Run `bizar install` to bootstrap.
|
|
97
|
+
RIGHT: Run 'bizar install' to bootstrap.
|
|
98
|
+
RIGHT: Run the installer to bootstrap.
|
|
173
99
|
```
|
|
174
100
|
|
|
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
|
|
180
|
-
|
|
181
|
-
Before v4.4.8, an array ending with a trailing comma — e.g. `[a, b,]` — caused the parser to call `parseValue` on the closing `]`, which fell through to the bareword-identifier fallback and returned `{__ident: ''}` as a phantom element. The FileTree then had one extra broken entry that crashed the React renderer (`t.bg` on undefined).
|
|
101
|
+
### 2. The parser doesn't track strings when counting braces
|
|
182
102
|
|
|
183
|
-
|
|
103
|
+
`{` and `}` inside string values still increment the brace depth walker. With brace-laden strings the walker terminates at the wrong closing brace and the value gets truncated.
|
|
184
104
|
|
|
185
|
-
|
|
105
|
+
**Rule:** keep string values brace-free. If you must use `{...}` in a note, escape or rephrase.
|
|
186
106
|
|
|
187
|
-
|
|
107
|
+
### 3. `FileTree` `change` field must be exact
|
|
188
108
|
|
|
189
|
-
|
|
190
|
-
<!-- WRONG -->
|
|
191
|
-
{ path: "src/foo.ts", change: null, note: "..." }
|
|
192
|
-
{ path: "src/foo.ts", change: "", note: "..." }
|
|
109
|
+
`change` must be `added` | `modified` | `removed` | `renamed`. Anything else (empty string, `null`, typo) makes the renderer crash on `t.bg`.
|
|
193
110
|
|
|
194
|
-
<!-- RIGHT -->
|
|
195
|
-
{ path: "src/foo.ts", change: "modified", note: "..." }
|
|
196
|
-
{ path: "src/foo.ts", change: "added", note: "..." }
|
|
197
111
|
```
|
|
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 -->
|
|
112
|
+
WRONG: change: null, change: "", change: "Modified"
|
|
113
|
+
RIGHT: change: "modified"
|
|
209
114
|
```
|
|
210
115
|
|
|
211
|
-
|
|
116
|
+
When in doubt, use `modified` with a `note` that explains why.
|
|
212
117
|
|
|
213
|
-
|
|
118
|
+
### 4. Two blocks with the same id
|
|
214
119
|
|
|
215
|
-
|
|
120
|
+
Comment pins and error reporting are keyed by block id. Duplicates collide. Each `id` must be unique within a glyph.
|
|
216
121
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
```mdx
|
|
220
|
-
<!-- self-closing -->
|
|
221
|
-
<Stat id="x" label="..." value="..." />
|
|
122
|
+
### 5. MDX heading with `<N`
|
|
222
123
|
|
|
223
|
-
<!-- with children -->
|
|
224
|
-
<RichText id="x">markdown content here</RichText>
|
|
225
|
-
<Callout id="x" tone="warn">important message</Callout>
|
|
226
124
|
```
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
The parser's JSON-like value reader handles `\\`, `\"`, `\'`, `\n`, `\t`, `\r` inside string literals. Em-dashes (`—`), curly quotes (`""`), and other Unicode characters are fine. Just avoid `\``.
|
|
231
|
-
|
|
232
|
-
## meta.json example
|
|
233
|
-
|
|
234
|
-
```json
|
|
235
|
-
{
|
|
236
|
-
"title": "Chat UI — Complete Rewrite (Gemini-Inspired)",
|
|
237
|
-
"slug": "chat-ui-rewrite",
|
|
238
|
-
"status": "draft",
|
|
239
|
-
"author": "drb0rk",
|
|
240
|
-
"created": "2026-06-26T20:30:00.000Z",
|
|
241
|
-
"lastEdited": "2026-06-26T20:30:00.000Z"
|
|
242
|
-
}
|
|
125
|
+
WRONG: ## Mobile <768px ← <7 looks like a malformed tag
|
|
126
|
+
RIGHT: ## Mobile (under 768px)
|
|
127
|
+
RIGHT: ## Mobile: under 768px
|
|
243
128
|
```
|
|
244
129
|
|
|
245
|
-
|
|
130
|
+
## Validate before shipping
|
|
246
131
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
|
132
|
+
```bash
|
|
133
|
+
node -e "import('./bizar-dash/src/server/glyphs/mdx-compiler.mjs').then(m => { \
|
|
134
|
+
const fs = require('node:fs'); \
|
|
135
|
+
const out = m.compileGlyphMdxSync(fs.readFileSync('artifacts/<slug>/artifact.mdx','utf8')); \
|
|
136
|
+
console.log('blocks:', out.blocks.length, 'errors:', out.errors.length); \
|
|
137
|
+
out.errors.forEach(e => console.error(' line', e.line, ':', e.message)); \
|
|
138
|
+
})"
|
|
139
|
+
```
|
|
262
140
|
|
|
263
|
-
|
|
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.
|
|
141
|
+
If errors > 0, fix the MDX before opening the glyph in the browser. When a block DOES fail in the browser, v4.4.8+ shows a red banner with block id + error message — no more blank screen.
|
|
269
142
|
|
|
270
143
|
## See also
|
|
271
144
|
|
|
272
|
-
- `bizar-dash/src/
|
|
273
|
-
- `bizar-dash/src/
|
|
274
|
-
- `bizar-dash/src/web/views/glyphs/
|
|
275
|
-
- `artifacts/sample-plan-login/` — a complete worked example
|
|
145
|
+
- `bizar-dash/src/server/glyphs/mdx-compiler.mjs` — parser
|
|
146
|
+
- `bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx` — React renderer (has the error banner)
|
|
147
|
+
- `bizar-dash/src/web/views/glyphs/components.tsx` — block component implementations
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polderlabs/bizar",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.9",
|
|
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": {
|