pmx-canvas 0.6.3 → 0.6.5

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/Readme.md +27 -6
  3. package/dist/canvas/global.css +90 -4
  4. package/dist/canvas/index.js +93 -91
  5. package/dist/canvas/mermaid-entry.js +258 -258
  6. package/dist/types/cli/agent.d.ts +1 -0
  7. package/dist/types/cli/commands/record.d.ts +12 -0
  8. package/dist/types/client/canvas/FeedbackDialog.d.ts +4 -0
  9. package/dist/types/client/canvas/Presentation.d.ts +13 -0
  10. package/dist/types/client/canvas/use-node-drag.d.ts +2 -1
  11. package/dist/types/client/nodes/McpAppNode.d.ts +24 -1
  12. package/dist/types/client/state/presentation.d.ts +3 -0
  13. package/dist/types/client/types.d.ts +1 -1
  14. package/dist/types/json-render/catalog.d.ts +2 -2
  15. package/dist/types/json-render/server.d.ts +2 -0
  16. package/dist/types/server/canvas-db.d.ts +2 -0
  17. package/dist/types/server/canvas-operations.d.ts +22 -0
  18. package/dist/types/server/canvas-schema.d.ts +1 -0
  19. package/dist/types/server/canvas-state.d.ts +6 -0
  20. package/dist/types/server/canvas-validation.d.ts +3 -0
  21. package/dist/types/server/html-surface.d.ts +1 -1
  22. package/dist/types/server/index.d.ts +4 -0
  23. package/dist/types/server/operations/ops/app.d.ts +2 -0
  24. package/dist/types/server/operations/ops/json-render.d.ts +2 -0
  25. package/dist/types/server/operations/ops/nodes.d.ts +3 -1
  26. package/dist/types/server/web-artifacts.d.ts +3 -0
  27. package/dist/types/shared/tour.d.ts +72 -0
  28. package/docs/cli.md +96 -2
  29. package/docs/http-api.md +79 -4
  30. package/docs/mcp.md +25 -1
  31. package/docs/node-types.md +123 -1
  32. package/docs/product-context-vision-2026-09.md +1 -1
  33. package/docs/product-vision-2026-09.md +135 -42
  34. package/docs/product-vision-review-2026-09.md +277 -0
  35. package/package.json +1 -1
  36. package/skills/pmx-canvas/SKILL.md +19 -4
  37. package/skills/pmx-canvas/evals/evals.json +46 -0
  38. package/skills/pmx-canvas/references/full-reference.md +1 -1
  39. package/skills/pmx-canvas/references/installing-pmx-canvas.md +4 -4
  40. package/src/cli/agent.ts +5 -0
  41. package/src/cli/commands/nodes.ts +10 -0
  42. package/src/cli/commands/record.ts +218 -0
  43. package/src/cli/index.ts +2 -0
  44. package/src/client/App.tsx +7 -1
  45. package/src/client/canvas/AgentPresenceLayer.tsx +1 -1
  46. package/src/client/canvas/CanvasNode.tsx +8 -0
  47. package/src/client/canvas/FeedbackDialog.tsx +86 -0
  48. package/src/client/canvas/IntentLayer.tsx +9 -2
  49. package/src/client/canvas/Presentation.tsx +108 -0
  50. package/src/client/canvas/ToolRail.tsx +225 -189
  51. package/src/client/canvas/TopBar.tsx +28 -2
  52. package/src/client/canvas/use-node-drag.ts +8 -3
  53. package/src/client/mermaid-entry.ts +39 -0
  54. package/src/client/nodes/HtmlNode.tsx +12 -13
  55. package/src/client/nodes/McpAppNode.tsx +105 -13
  56. package/src/client/nodes/MermaidNode.tsx +3 -2
  57. package/src/client/state/intent-store.ts +5 -1
  58. package/src/client/state/presentation.ts +7 -0
  59. package/src/client/state/session-store.ts +3 -0
  60. package/src/client/state/sse-bridge.ts +3 -0
  61. package/src/client/theme/global.css +90 -4
  62. package/src/json-render/server.ts +29 -0
  63. package/src/server/agent-presence.ts +15 -9
  64. package/src/server/canvas-db.ts +15 -0
  65. package/src/server/canvas-operations.ts +115 -22
  66. package/src/server/canvas-schema.ts +10 -0
  67. package/src/server/canvas-state.ts +39 -4
  68. package/src/server/canvas-validation.ts +9 -1
  69. package/src/server/demo-state.json +11 -7
  70. package/src/server/html-primitives.ts +199 -91
  71. package/src/server/html-surface.ts +8 -3
  72. package/src/server/index.ts +12 -0
  73. package/src/server/operations/composites.ts +3 -1
  74. package/src/server/operations/ops/app.ts +10 -0
  75. package/src/server/operations/ops/batch.ts +12 -3
  76. package/src/server/operations/ops/groups.ts +14 -7
  77. package/src/server/operations/ops/json-render.ts +37 -5
  78. package/src/server/operations/ops/nodes.ts +42 -16
  79. package/src/server/operations/ops/viewport.ts +32 -0
  80. package/src/server/operations/registry.ts +6 -0
  81. package/src/server/scope-fence.ts +1 -1
  82. package/src/server/server.ts +9 -6
  83. package/src/server/web-artifacts.ts +9 -2
  84. package/src/server/workboard.ts +3 -3
  85. package/src/shared/tour.ts +87 -0
package/docs/http-api.md CHANGED
@@ -9,6 +9,40 @@ bodies are treated as an empty request. As of 0.4.0 every error response is a
9
9
  JSON envelope of that same shape (`{ ok: false, error }`, status unchanged) —
10
10
  no plain-text errors remain.
11
11
 
12
+ Node-create responses include `sizeAdjustment` when a frame dimension was
13
+ defaulted or raised to its node type's readability floor. It contains the
14
+ `requested` dimensions (`null` when omitted), the final `applied` dimensions,
15
+ and a `reason` (`defaulted`, `clamped-to-minimum`, or
16
+ `defaulted-and-clamped-to-minimum`; groups also use `fit-to-children`). `strictSize: true`
17
+ still bypasses the readability clamp, but omitted dimensions are reported as
18
+ defaulted. MCP create actions return the same size report.
19
+ Updates preserve explicit dimensions without applying creation floors; their
20
+ returned node `size` is the applied size. Omitted update dimensions retain the
21
+ existing size and are not reported as defaulted adjustments.
22
+
23
+ Both group-create routes report defaults or final child-derived dimensions, including
24
+ when children override supplied width/height because x/y were omitted. Explicit manual
25
+ frames retain their existing semantics. Group child replacement reports `fit-to-children`
26
+ when it changes the frame; `group.add` reports the previous frame as `requested` and
27
+ the final frame as `applied`. Reports survive compact/full MCP and batch responses.
28
+ External MCP app creation and web-artifact builds that open a node report their default
29
+ frames too; reusing an existing app node or building without opening does not report a
30
+ creation default. These reports describe the synchronous operation, not later browser
31
+ content auto-height or indirect parent-group reflow after editing a child.
32
+
33
+ ## Board tours
34
+
35
+ - `GET /api/canvas/tour` → `{ tour: { stops: [...] }, derived: boolean }`.
36
+ - `POST /api/canvas/tour` with `{ "tour": { "stops": [...] } }` persists the tour;
37
+ `{ "tour": null }` resets to derived group reading order. Returns `{ "ok": true }`.
38
+ - `GET /api/canvas/state` includes optional `tour`. Tour writes broadcast a layout
39
+ update and are included in snapshots/undo. They are board-wide writes under a scope fence.
40
+
41
+ The [tour model and recording walkthrough](cli.md#tour-and-presentation) describes
42
+ targets, duration, easing, padding, and pullback. Open `/workbench?present=1` to hide
43
+ chrome; camera movement is local to that viewer. Recording writes local files via
44
+ the CLI, not an HTTP job endpoint.
45
+
12
46
  ## Canvas state
13
47
 
14
48
  ```bash
@@ -35,6 +69,10 @@ curl -X POST http://localhost:4313/api/canvas/json-render \
35
69
  -H "Content-Type: application/json" \
36
70
  -d '{"title":"Panel","nodeHeight":280,"spec":{"root":"card","elements":{"card":{"type":"Card","props":{"title":"Live"},"children":[]}}}}'
37
71
 
72
+ # For graph nodes, `height` is the chart's plot height, not the node frame.
73
+ # Set the frame with `nodeHeight` (`heightPx` in the SDK). A graph request that
74
+ # supplies only `height` gets the default frame height and a response warning.
75
+
38
76
  # Validate an HTML primitive without creating a node
39
77
  curl -X POST http://localhost:4313/api/canvas/schema/validate \
40
78
  -H "Content-Type: application/json" \
@@ -70,6 +108,11 @@ A node creation request must resolve a `type` — pass it in the body (`{ "type"
70
108
  ... }`) or as a `?type=` query param. An empty / type-less body returns `400`
71
109
  rather than silently creating a markdown node.
72
110
 
111
+ Mermaid nodes accept `data: { "fit": "contain" | "none" }` on both
112
+ `POST /api/canvas/node` and `PATCH /api/canvas/node/:id`. The default, `contain`,
113
+ shrinks overflowing diagrams without changing aspect ratio; `none` keeps 100%
114
+ with scrolling. [Mermaid sizing and readability](node-types.md#mermaid-nodes).
115
+
73
116
  ### File node content and bytes
74
117
 
75
118
  A `file` node reads its file server-side. Text is stored on the node as
@@ -145,6 +188,31 @@ curl -X DELETE http://localhost:4313/api/canvas/annotation/ann-123
145
188
  Agent-readable context reports annotation IDs, targets, and bounds. Use WebView
146
189
  inspection or screenshots when the drawn shape matters.
147
190
 
191
+ ## Viewport
192
+
193
+ ```bash
194
+ # Set the camera transform (screen = world * scale + {x,y})
195
+ curl -X POST http://localhost:4313/api/canvas/viewport \
196
+ -H "Content-Type: application/json" \
197
+ -d '{"x":64,"y":96,"scale":0.8}'
198
+
199
+ # Fit selected nodes (omit nodeIds to fit the whole canvas)
200
+ curl -X POST http://localhost:4313/api/canvas/fit \
201
+ -H "Content-Type: application/json" \
202
+ -d '{"nodeIds":["node-1"],"width":1200,"height":700}'
203
+
204
+ # Focus without moving the camera
205
+ curl -X POST http://localhost:4313/api/canvas/focus \
206
+ -H "Content-Type: application/json" \
207
+ -d '{"id":"node-1","noPan":true}'
208
+ ```
209
+
210
+ Viewport `x`/`y`, fit `width`/`height`, and fit padding are interpreted against
211
+ the **canvas area**, excluding the tool rail, top bar, and other surrounding
212
+ page chrome—not the full browser window. Camera, fit, and focus-only requests
213
+ do not create or refresh agent writer presence. Use the explicit presence API
214
+ when an agent should publish a cursor or `focusNodeId`.
215
+
148
216
  ## Pins
149
217
 
150
218
  ```bash
@@ -341,13 +409,20 @@ When that session ends (`attached: false`, `session-end`, or the idle expiry)
341
409
  the stream carries one `agent-session-ended` frame:
342
410
 
343
411
  ```json
344
- { "label": "Copilot", "endedAt": "…", "counts": { "items": 4, "done": 3, "vetoed": 1 },
412
+ { "label": "Copilot", "parentAgentId": null, "endedAt": "…", "endedBy": "agent",
413
+ "unchanged": false, "counts": { "items": 4, "done": 3, "cancelled": 1, "rejected": 0, "held": 0 },
345
414
  "snapshot": { "id": "…", "name": "Before session · Copilot · 14:00" } }
346
415
  ```
347
416
 
348
- `items`/`done` count the work items on the board; `vetoed` counts cancelled
349
- items plus rejected or held gates. `snapshot` is null when the board was
350
- empty at attach. The browser renders this as the session receipt; its *View
417
+ `items`/`done` count the work items on the board; cancelled items, rejected
418
+ gates, and held gates have separate counts. `snapshot` is null when the board was
419
+ empty at attach or unchanged at end (the redundant snapshot is removed).
420
+ The browser shows a receipt only for a changed top-level session: `unchanged: true`
421
+ and worker endings (`parentAgentId` set) never open or replace a popup. An empty
422
+ board that stays empty is unchanged too. This only filters the popup: session-end
423
+ events, timeline records, and changed-session snapshots remain available.
424
+ There is at most one receipt, replaced by the next qualifying ending and kept until
425
+ dismissed so restore/diff actions do not disappear on a timer. Its *View
351
426
  diff* is `GET /api/canvas/snapshots/<id>/diff` against that snapshot, and
352
427
  restoring the snapshot undoes the session. Adapters should end their session
353
428
  explicitly so the human gets the receipt promptly rather than after the idle
package/docs/mcp.md CHANGED
@@ -13,6 +13,15 @@ nodes in the browser, agents are notified immediately.
13
13
  > snapshot standalones — each step per [`api-stability.md`](api-stability.md)'s
14
14
  > deprecate-one-minor-before-removal rule. **Prefer the composites.**
15
15
 
16
+ ## Board tours
17
+
18
+ `canvas_view { action: "get-tour" }` returns `{ tour, derived }`, using group
19
+ reading order when there is no saved tour. `canvas_view { action: "set-tour",
20
+ tour: { stops: [...] } }` persists an ordered tour; `tour: null` resets it.
21
+ See the [tour model and CLI walkthrough](cli.md#tour-and-presentation) for stop
22
+ fields. Recording is a local CLI operation; no remote recording/file-writing
23
+ tool is added.
24
+
16
25
  ## Connect
17
26
 
18
27
  Add to your agent's MCP config:
@@ -42,7 +51,7 @@ its `action` to the same operation the legacy tool used, so results are identica
42
51
  | `canvas_edge` | `add` · `update` · `remove` | `canvas_add_edge`, `canvas_update_edge`, `canvas_remove_edge` |
43
52
  | `canvas_group` | `create` · `add` · `ungroup` | `canvas_create_group`, `canvas_group_nodes`, `canvas_ungroup` |
44
53
  | `canvas_history` | `undo` · `redo` | `canvas_undo`, `canvas_redo` |
45
- | `canvas_view` | `arrange` · `focus` · `fit` · `clear` · `remove-annotation` | `canvas_arrange`, `canvas_focus_node`, `canvas_fit_view`, `canvas_clear`, `canvas_remove_annotation` |
54
+ | `canvas_view` | `arrange` · `focus` · `fit` · `clear` · `remove-annotation` · `get-tour` · `set-tour` | `canvas_arrange`, `canvas_focus_node`, `canvas_fit_view`, `canvas_clear`, `canvas_remove_annotation` |
46
55
  | `canvas_query` | `search` · `layout` · `validate` | `canvas_search`, `canvas_get_layout`, `canvas_validate` |
47
56
  | `canvas_webview` | `status` · `start` · `stop` · `resize` · `evaluate` | `canvas_webview_status`, `canvas_webview_start`, `canvas_webview_stop`, `canvas_resize`, `canvas_evaluate` |
48
57
  | `canvas_app` | `open-mcp-app` · `diagram` · `build-artifact` | `canvas_open_mcp_app`, `canvas_add_diagram`, `canvas_build_web_artifact` |
@@ -54,6 +63,11 @@ its `action` to the same operation the legacy tool used, so results are identica
54
63
  | `canvas_intent` | `signal` · `update` · `clear` | _(new — Ghost Cursor of Intent; no legacy standalone tool)_ |
55
64
  | `canvas_snapshot` | `save` · `list` · `restore` · `delete` · `gc` · `diff` | `canvas_snapshot` (legacy save tool), `canvas_list_snapshots`, `canvas_restore`, `canvas_delete_snapshot`, `canvas_gc_snapshots`, `canvas_diff` — removed in v0.4.0 after one deprecated minor |
56
65
 
66
+ For Mermaid nodes, `canvas_node` actions `add` and `update` accept
67
+ `data: { fit: "contain" | "none" }`. Contain is the default, shrinking overflow
68
+ uniformly; none keeps 100% with scrolling. Use Open as site for 100% without
69
+ changing the node setting. [Sizing and readability](node-types.md#mermaid-nodes).
70
+
57
71
  ### `canvas_intent` — Ghost Cursor of Intent
58
72
 
59
73
  Announce the spatial move you are **about** to make so the canvas paints a faint
@@ -92,6 +106,16 @@ fixing `node.update`'s `formatResult` to surface a FAILED refresh as `isError` +
92
106
  fold completed in v0.4.0: `canvas_snapshot { action: "save" | "list" | "restore" |
93
107
  "delete" | "gc" | "diff" }` replaced the 6 deprecated snapshot standalones.
94
108
 
109
+ ### Viewport coordinates
110
+
111
+ `canvas_view { action: "focus" | "fit" }` controls the camera without counting
112
+ as a writer operation or refreshing agent presence. Viewport translation uses
113
+ screen-space canvas-area coordinates (`screen = world * scale + viewport`). Fit
114
+ dimensions and padding likewise refer to the canvas area after excluding the
115
+ tool rail, top bar, and surrounding page chrome—not the full browser window.
116
+ Use `canvas_ax_state { action: "set-presence", cursor, focusNodeId }` when the
117
+ agent intends to publish its own cursor or attention target.
118
+
95
119
  ## Standalone tools
96
120
 
97
121
  6 tools that intentionally stay outside the composites — folding them would
@@ -26,6 +26,17 @@ see [MCP tools](mcp.md), [HTTP API](http-api.md), and [SDK](sdk.md).
26
26
  | `web-artifact` | Bundled React/Tailwind artifact (full single-file app) |
27
27
  | `group` | Spatial container/frame around other nodes |
28
28
 
29
+ Creation applies per-type frame defaults and readability minimums. When a
30
+ dimension is defaulted or clamped, HTTP and MCP create responses include a
31
+ `sizeAdjustment` with requested and applied dimensions plus the reason.
32
+ `strictSize: true` bypasses minimum-size clamping; it does not change defaults
33
+ for omitted dimensions.
34
+
35
+ For `graph` nodes, `height` controls the chart plot inside the viewer.
36
+ `nodeHeight` controls the canvas node frame (`heightPx` is the SDK alias). If
37
+ only `height` is supplied, the frame keeps its default height and the create
38
+ response warns about the distinction.
39
+
29
40
  Thread node types `prompt` and `response` exist internally for agent
30
41
  conversation rendering and are not created through public APIs.
31
42
 
@@ -64,6 +75,34 @@ different type by extension:
64
75
  - **Text files over 2 MB** render truncated with a banner saying so, so a huge
65
76
  log can never exhaust memory.
66
77
 
78
+ ## Mermaid nodes
79
+
80
+ Mermaid diagrams default to `data.fit: "contain"`: when the diagram overflows
81
+ the available body, it shrinks uniformly until the entire diagram fits. Small
82
+ diagrams stay at 100%; aspect ratio, labels, and edges are preserved, in both
83
+ dark and light themes. Resizing a card or expanding it recalculates the fit.
84
+ `strictSize` keeps the requested node geometry while the diagram fits inside it;
85
+ ordinary cards retain their grow-only automatic sizing.
86
+
87
+ Fitting a large diagram makes its text smaller. Use **Expand** for more space,
88
+ or **Open as site** for a 100% natural-size diagram with scrolling. Set
89
+ `data.fit: "none"` to use that natural-size, scrollable view inside the card too.
90
+ This setting is independent of the canvas camera's **Fit view** action.
91
+
92
+ ```ts
93
+ canvas_node({ action: 'add', type: 'mermaid', content: 'flowchart TD; A-->B-->C-->D',
94
+ width: 920, height: 870, strictSize: true, data: { fit: 'contain' } })
95
+ canvas_node({ action: 'update', id: 'node-id', data: { fit: 'none' } })
96
+ ```
97
+
98
+ HTTP uses the same `data` object in `POST /api/canvas/node` and
99
+ `PATCH /api/canvas/node/:id`. CLI creation and updates expose `--fit`:
100
+
101
+ ```bash
102
+ pmx-canvas node add --type mermaid --content 'flowchart TD; A-->B-->C-->D' --fit contain --width 920 --height 870 --strict-size
103
+ pmx-canvas node update node-id --fit none
104
+ ```
105
+
67
106
  ## Image nodes
68
107
 
69
108
  Image nodes display local paths, remote URLs, and data URIs. File-backed and
@@ -137,7 +176,7 @@ with the server's transport, tool name, and arguments.
137
176
 
138
177
  `json-render` nodes turn structured JSON specs into rendered UI panels
139
178
  (dashboards, tables, forms, cards) without writing HTML. PMX Canvas ships the
140
- [`@json-render/*`](https://www.npmjs.com/package/@json-render/core) runtime
179
+ [`@json-render/*`](https://www.npmjs.com/package/@json-render/core) 0.21.0 runtime
141
180
  and component catalog (core + react + shadcn).
142
181
 
143
182
  ```ts
@@ -158,6 +197,56 @@ canvas_render({
158
197
  `outline`. Older saved specs using `label` or status variants such as
159
198
  `success`/`warning` are normalized during validation.
160
199
 
200
+ Specs preserve top-level `state` and element-level `repeat`, `watch`, and
201
+ `slots`. Use `$bindState` with JSON Pointer paths for editable form values;
202
+ `$state` only reads a value. Nested repeats can use `statePath: { "$item": "tasks" }`
203
+ to iterate the current item's tasks. Watchers run after changes, not on mount.
204
+
205
+ **Seed form values through bindings, not literal `value` props.** In shadcn
206
+ 0.21, `Input`, `Textarea`, `Select`, `Radio`, `Slider`, `ToggleGroup`, and
207
+ `Tabs` ignore an unbound `value`; `ButtonGroup` ignores unbound `selected`.
208
+ This includes read-only `$state` expressions. PMX returns a `warnings` array
209
+ from `POST /api/canvas/json-render`, `POST /api/canvas/schema/validate`, and
210
+ `canvas_render` actions `add-json-render` and `validate`. Warnings name the
211
+ element/property; they do not reject or rewrite the spec. PMX does not invent
212
+ state paths because repeated controls and existing actions may need distinct
213
+ or deliberately shared state.
214
+
215
+ ```json
216
+ {
217
+ "root": "postcode",
218
+ "state": { "form": { "postcode": "nw1 6xe" } },
219
+ "elements": {
220
+ "postcode": {
221
+ "type": "Input",
222
+ "props": {
223
+ "label": "Postcode",
224
+ "name": "postcode",
225
+ "value": { "$bindState": "/form/postcode" }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ Inside repeats, use `$bindItem` with seeded item data. `Checkbox`/`Switch`
233
+ honor literal `checked`, `Toggle` honors literal `pressed`, and `Tabs` honors
234
+ `defaultValue` for an uncontrolled initial tab. `Pagination` reads `page`
235
+ directly; `DropdownMenu.value` is an output binding for selection, not a
236
+ displayed selection. These do not require the same ignored-value warning.
237
+ Use two-way bindings whenever edits or form checks must participate in state.
238
+
239
+ Cards keep their body in `children` and accept
240
+ `slots: { header: ['headingId'], footer: ['actionsId'] }`. Slot IDs reference
241
+ entries in `elements`; a custom header replaces the title and description props.
242
+ See the bundled [json-render guide](../skills/json-render-mcp/SKILL.md)
243
+ for a complete state-bound form with watchers and footer actions.
244
+
245
+ Form edits are viewer-local, not saved into the stored spec. Reloading the iframe
246
+ or updating its spec (including streaming patches) resets that state. Finish
247
+ streaming before collecting input, and persist important changes through an
248
+ explicit server interaction.
249
+
161
250
  Elements may carry an `on` map (`on.press`, `on.change`, …) binding events to
162
251
  actions (`{ action, params }`) — built-in actions (`setState`, `pushState`, …) or
163
252
  host-provided handlers. PMX wires AX handlers named after interaction types, so a
@@ -185,9 +274,35 @@ source + per-viewer nonce + node id) and submits it server-side; `json-render` /
185
274
  `graph` viewers are sandboxed surfaces, so caller-supplied `nodeIds` are clamped
186
275
  to the node's own id. See the [MCP reference](mcp.md#node-interactions-capability-gated).
187
276
 
277
+ AX handlers are fire-and-forget: `onSuccess` means local dispatch completed,
278
+ not that the server accepted the operation. Confirm acceptance through AX state
279
+ or timeline before showing a saved state or clearing a draft. The built-in
280
+ `validateForm` action returns without calling `onSuccess`; do not chain submission
281
+ through that callback.
282
+
188
283
  Use `canvas_render { action: "describe-schema" }` / `canvas_render { action:
189
284
  "validate" }` to introspect the component catalog before building a spec.
190
285
 
286
+ ### Automatic sizing of authored iframe cards
287
+
288
+ HTML (except presentation decks), Mermaid, JSON-render, graph, and web-artifact
289
+ cards can grow as their rendered content changes. This changes node geometry;
290
+ **Fit view** only changes the camera. Height measurements include title-bar and
291
+ body padding, grow only up to 1400px, and never change the width. Content beyond
292
+ that limit may still scroll; this is not a general shrink-to-content action.
293
+
294
+ Fitting waits for local or remote human grabs to end. A growing ungrouped,
295
+ screen-unpinned card moves downward if needed to leave a 24px gap from neighboring
296
+ cards, without moving those neighbors. A relocation records one undo step for
297
+ both size and position; height-only adjustments do not add undo entries.
298
+ Grouped or screen-pinned cards retain their positions. Collapsed cards and cards
299
+ marked `strictSize` or `userResized` are not automatically resized. Hosted MCP
300
+ apps and webpage viewers do not use this authored-content fitting behavior.
301
+
302
+ Read the settled node geometry after mounting rather than treating requested
303
+ dimensions as final. Prefer targeted node reads or the CLI's projected layout
304
+ fields over fetching full content merely to check spacing.
305
+
191
306
  ## HTML nodes
192
307
 
193
308
  `html` nodes render a normal self-contained HTML/JS document in a sandboxed iframe.
@@ -235,6 +350,13 @@ component gallery, interaction prototype, flowchart, SVG illustration set,
235
350
  presentation, explainer, status report, incident report, triage board, config
236
351
  editor, or prompt tuner.
237
352
 
353
+ Omitted fields may use the template's examples. Explicit empty arrays, empty
354
+ strings, or `null` mean “show nothing”: the field's section, heading, and
355
+ dependent controls are omitted rather than replaced with sample content.
356
+ Other populated or omitted fields keep their normal behavior. Empty `slides`
357
+ or flow `steps` also omit navigation/run controls; an AX board's live task
358
+ controls remain available when only its optional note is empty.
359
+
238
360
  Two kinds are **live AX control surfaces** rather than static documents, and are
239
361
  the only primitives created with AX enabled:
240
362
 
@@ -1,6 +1,6 @@
1
1
  # Vision extension: boards, personal wiki, and workspace context
2
2
 
3
- **Status:** Proposed for discussion, not an implementation commitment.
3
+ **Status:** Proposed for discussion, not an implementation commitment. **Superseded in part, 2026-09-23:** the maintainer decided that boards are the wiki and that the destination is "share this board" ([vision, move 0 and Part 3](product-vision-2026-09.md); reasoning in the [review](product-vision-review-2026-09.md#design-sketch-boards-are-the-wiki)). The separate entity and revision store, the personal wiki as its own surface, and working-versus-confirmed machinery are not planned; boards, cards and the journal play those roles. Still in force: the publication and audience rules and the threat-model corrections, which apply when sharing reaches a second writer (Part 3), and the validation experiment, run on linked boards instead of a wiki.
4
4
  **Date:** 2026-09-06
5
5
  **Companions:** [Product review](product-review-2026-09.md), [product vision](product-vision-2026-09.md).
6
6
  **Request:** Review the existing vision and explore hosted users building their own wiki by describing their work, with their boards contributing context, and cross-cutting organizational context shared within a workspace. Reuse the logic of the personal/context-frame projects inside pmx-canvas's own store rather than depend on an external wiki.