pmx-canvas 0.9.3 → 0.11.0

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 (237) hide show
  1. package/.github/extensions/pmx-canvas/runtime.json +1 -1
  2. package/.github/extensions/pmx-canvas/tools.json +9418 -2016
  3. package/CHANGELOG.md +54 -1
  4. package/dist/canvas/chunks/abnfDiagram-N423BO3Z-p8dtp6va.js +1 -0
  5. package/dist/canvas/chunks/architecture-TIHT7OUA-9tffvpsv.js +1 -0
  6. package/dist/canvas/chunks/architectureDiagram-T3A2C74G-5jhmxrzf.js +36 -0
  7. package/dist/canvas/chunks/blockDiagram-VBNYF7ZC-pw1fa9yb.js +132 -0
  8. package/dist/canvas/chunks/c4Diagram-5PPSVZJV-x07nq0tt.js +10 -0
  9. package/dist/canvas/chunks/classDiagram-JCYQIIEL-nc6g5x1r.js +1 -0
  10. package/dist/canvas/chunks/classDiagram-v2-OCEON4UE-0qnbpwvh.js +1 -0
  11. package/dist/canvas/chunks/cose-bilkent-JH36ORCC-nm39npq0.js +1 -0
  12. package/dist/canvas/chunks/cynefin-VYW2F7L2-ys8p46ts.js +1 -0
  13. package/dist/canvas/chunks/cynefinDiagram-MW4NZA55-vdxrwahz.js +62 -0
  14. package/dist/canvas/chunks/dagre-VZM6K2ZE-bqdm7wpd.js +4 -0
  15. package/dist/canvas/chunks/diagram-7IWD3JNH-gs5gpr93.js +30 -0
  16. package/dist/canvas/chunks/diagram-B4RE2ZJO-cgwjg47s.js +3 -0
  17. package/dist/canvas/chunks/diagram-LBJQPF4R-w3vahpav.js +24 -0
  18. package/dist/canvas/chunks/diagram-Q27KOJAE-42837z6h.js +24 -0
  19. package/dist/canvas/chunks/diagram-UB23O5K3-4fz83q59.js +41 -0
  20. package/dist/canvas/chunks/ebnfDiagram-BXEA7PRR-zphtgegj.js +1 -0
  21. package/dist/canvas/chunks/erDiagram-JOGREHBK-zvbbdxp4.js +85 -0
  22. package/dist/canvas/chunks/eventmodeling-45OFAUF4-v9q6dn4c.js +1 -0
  23. package/dist/canvas/chunks/flowDiagram-UKHOOZJN-yrr5z8tc.js +1 -0
  24. package/dist/canvas/chunks/ganttDiagram-PKOTCBZU-282jzycm.js +292 -0
  25. package/dist/canvas/chunks/gitGraph-TEB2WS4Q-kdwb8m0a.js +1 -0
  26. package/dist/canvas/chunks/gitGraphDiagram-DS77QQ5N-vqqy6p1b.js +106 -0
  27. package/dist/canvas/chunks/index-0rk4gp1g.js +2 -0
  28. package/dist/canvas/chunks/index-194m3hc3.js +2 -0
  29. package/dist/canvas/chunks/index-1r72hdzb.js +301 -0
  30. package/dist/canvas/chunks/index-353m7b0p.js +2 -0
  31. package/dist/canvas/chunks/index-3cy1bzwh.js +2 -0
  32. package/dist/canvas/chunks/index-5tv8v1hk.js +1 -0
  33. package/dist/canvas/chunks/index-6ceya556.js +332 -0
  34. package/dist/canvas/chunks/index-6qmsnxwy.js +4 -0
  35. package/dist/canvas/chunks/index-d3b3gqe9.js +2 -0
  36. package/dist/canvas/chunks/index-fjtdggjn.js +2 -0
  37. package/dist/canvas/chunks/index-g3pwnqeb.js +2 -0
  38. package/dist/canvas/chunks/index-gf4e0et4.js +2 -0
  39. package/dist/canvas/chunks/index-hj99nz1f.js +1 -0
  40. package/dist/canvas/chunks/index-nprm96xp.js +16 -0
  41. package/dist/canvas/chunks/index-qj8fxwsf.js +2 -0
  42. package/dist/canvas/chunks/index-r2fyc9w1.js +89 -0
  43. package/dist/canvas/chunks/index-rft2hcz5.js +2 -0
  44. package/dist/canvas/chunks/index-rh7nv68n.js +2 -0
  45. package/dist/canvas/chunks/index-s4j678gj.js +2 -0
  46. package/dist/canvas/chunks/index-tb1wf525.js +179 -0
  47. package/dist/canvas/chunks/index-vv56h019.js +2 -0
  48. package/dist/canvas/chunks/index-w2mra17t.js +207 -0
  49. package/dist/canvas/chunks/index-wgv7en21.js +232 -0
  50. package/dist/canvas/chunks/index-yw8h9vha.js +157 -0
  51. package/dist/canvas/chunks/info-DKCQHKI2-wpzs6sz3.js +1 -0
  52. package/dist/canvas/chunks/infoDiagram-6WML65LV-v1yvggqj.js +2 -0
  53. package/dist/canvas/chunks/ishikawaDiagram-WSZJBQD7-5hnq1a9p.js +70 -0
  54. package/dist/canvas/chunks/journeyDiagram-NVQOT4AX-zjcffveh.js +139 -0
  55. package/dist/canvas/chunks/kanban-definition-27J2QSJJ-dakqtfp1.js +89 -0
  56. package/dist/canvas/chunks/katex-dmg8k4zm.js +257 -0
  57. package/dist/canvas/chunks/mermaid.core-j2geswrd.js +12 -0
  58. package/dist/canvas/chunks/mindmap-definition-FAOFIHXS-142xhr3k.js +96 -0
  59. package/dist/canvas/chunks/packet-7NZHBO7P-xn439f0s.js +1 -0
  60. package/dist/canvas/chunks/pegDiagram-VL7TDLO6-5wvk7vsd.js +1 -0
  61. package/dist/canvas/chunks/pie-RZYD4A2V-0kf16rwh.js +1 -0
  62. package/dist/canvas/chunks/pieDiagram-7S7Q4E2Y-ztdhwycc.js +39 -0
  63. package/dist/canvas/chunks/quadrantDiagram-CIZ2JOQS-c5p9gmg6.js +7 -0
  64. package/dist/canvas/chunks/radar-I7S5WNFK-0g2pz36t.js +1 -0
  65. package/dist/canvas/chunks/railroad-3IZDKUUU-fcaran6j.js +1 -0
  66. package/dist/canvas/chunks/railroad-abnf-AHOZXSZD-wgdya41q.js +1 -0
  67. package/dist/canvas/chunks/railroad-ebnf-EBAXGLYW-gy07a4ka.js +1 -0
  68. package/dist/canvas/chunks/railroad-peg-LSFZ7HO6-ewk6wtkh.js +1 -0
  69. package/dist/canvas/chunks/railroadDiagram-AXF67PYL-xkmqkjwf.js +1 -0
  70. package/dist/canvas/chunks/requirementDiagram-LRYGKXZP-9wm2dyaw.js +84 -0
  71. package/dist/canvas/chunks/sankeyDiagram-W5VNT64P-2w19etgb.js +40 -0
  72. package/dist/canvas/chunks/sequenceDiagram-SI44F4Z6-0jn0vwmz.js +162 -0
  73. package/dist/canvas/chunks/sizeCapture-X5ZJPWSS-x75epwdq.js +1 -0
  74. package/dist/canvas/chunks/stateDiagram-OKZ733FA-schjpy6d.js +1 -0
  75. package/dist/canvas/chunks/stateDiagram-v2-UEYNNEHI-k8sfp2e7.js +1 -0
  76. package/dist/canvas/chunks/swimlanes-SLNWSIFB-gkw4xce3.js +1 -0
  77. package/dist/canvas/chunks/swimlanesDiagram-ULZ7WXOC-nqysw67j.js +8 -0
  78. package/dist/canvas/chunks/timeline-definition-Z64GVDOM-x7nkcy01.js +120 -0
  79. package/dist/canvas/chunks/treeView-QDETBFTQ-cesw6gp0.js +1 -0
  80. package/dist/canvas/chunks/treemap-6X3UGDF4-zdv4knp9.js +1 -0
  81. package/dist/canvas/chunks/vennDiagram-T6HMQDX7-x8dqn9yf.js +34 -0
  82. package/dist/canvas/chunks/wardley-OPB4EBWU-44pdddez.js +1 -0
  83. package/dist/canvas/chunks/wardleyDiagram-T6FBY63Y-t1j52t9r.js +78 -0
  84. package/dist/canvas/chunks/xychartDiagram-ELKLHX3M-38t16pme.js +7 -0
  85. package/dist/canvas/global.css +389 -229
  86. package/dist/canvas/index.js +141 -211
  87. package/dist/canvas/mcp-app.html +4205 -554
  88. package/dist/canvas/mermaid-entry.js +338 -338
  89. package/dist/canvas/surface-theme.css +6 -6
  90. package/dist/json-render/index.css +1 -1
  91. package/dist/json-render/index.js +49 -49
  92. package/dist/types/client/canvas/BarHint.d.ts +5 -3
  93. package/dist/types/client/canvas/CanvasNode.d.ts +0 -11
  94. package/dist/types/client/canvas/EdgeLayer.d.ts +1 -2
  95. package/dist/types/client/canvas/auto-fit.d.ts +4 -5
  96. package/dist/types/client/mermaid-entry.d.ts +1 -2
  97. package/dist/types/client/mermaid-render.d.ts +1 -0
  98. package/dist/types/client/nodes/BoardNode.d.ts +1 -1
  99. package/dist/types/client/nodes/ExtAppFrame.d.ts +7 -90
  100. package/dist/types/client/nodes/McpAppNode.d.ts +1 -25
  101. package/dist/types/client/nodes/MermaidNode.d.ts +1 -8
  102. package/dist/types/client/nodes/ViewerFrame.d.ts +29 -0
  103. package/dist/types/client/nodes/ViewerHost.d.ts +6 -0
  104. package/dist/types/client/nodes/iframe-document-url.d.ts +3 -9
  105. package/dist/types/client/nodes/primitive-copy.d.ts +5 -0
  106. package/dist/types/client/nodes/use-iframe-content-height.d.ts +1 -1
  107. package/dist/types/client/nodes/use-surface-frame.d.ts +4 -6
  108. package/dist/types/client/nodes/viewer-runtime-state.d.ts +2 -1
  109. package/dist/types/client/state/canvas-store.d.ts +3 -1
  110. package/dist/types/client/state/intent-bridge.d.ts +1 -0
  111. package/dist/types/client/state/presentation.d.ts +17 -6
  112. package/dist/types/json-render/server.d.ts +2 -1
  113. package/dist/types/mcp/canvas-access.d.ts +1 -12
  114. package/dist/types/mcp/resource-subscriptions.d.ts +7 -0
  115. package/dist/types/mcp/server.d.ts +2 -0
  116. package/dist/types/server/ax-wait.d.ts +1 -0
  117. package/dist/types/server/canvas-operations.d.ts +1 -0
  118. package/dist/types/server/canvas-state.d.ts +2 -0
  119. package/dist/types/server/index.d.ts +11 -6
  120. package/dist/types/server/operations/http.d.ts +10 -0
  121. package/dist/types/server/operations/index.d.ts +2 -2
  122. package/dist/types/server/operations/invoker.d.ts +4 -3
  123. package/dist/types/server/operations/mcp-contracts.d.ts +20 -0
  124. package/dist/types/server/operations/mcp.d.ts +2 -0
  125. package/dist/types/server/operations/ops/batch.d.ts +1 -0
  126. package/dist/types/server/operations/ops/boards.d.ts +0 -1
  127. package/dist/types/server/operations/registry.d.ts +2 -2
  128. package/dist/types/server/operations/types.d.ts +12 -2
  129. package/dist/types/server/server.d.ts +2 -0
  130. package/dist/types/server/tour-control.d.ts +13 -3
  131. package/dist/types/server/webpage-node.d.ts +1 -0
  132. package/dist/types/shared/ax-surface-protocol.d.ts +0 -9
  133. package/dist/types/shared/tour.d.ts +8 -0
  134. package/docs/api-reference.md +2 -2
  135. package/docs/cli.md +1 -1
  136. package/docs/design/Chrome.dc.html +32 -6
  137. package/docs/design/Types1.dc.html +3 -2
  138. package/docs/design/Types2.dc.html +1 -1
  139. package/docs/design/Types3.dc.html +1 -1
  140. package/docs/design/Zoom.dc.html +37 -60
  141. package/docs/design/canvas.json +1 -1
  142. package/docs/design.md +169 -4
  143. package/docs/http-api.md +82 -1
  144. package/docs/mcp.md +101 -21
  145. package/docs/node-types.md +38 -3
  146. package/docs/plans/plan-009-tech-debt-backlog.md +2 -2
  147. package/docs/plans/plan-019-post-0.9-roadmap.md +402 -13
  148. package/docs/product-vision-2026-09.md +9 -0
  149. package/docs/sdk.md +5 -2
  150. package/package.json +2 -2
  151. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
  152. package/plugins/pmx-canvas/plugin.json +1 -1
  153. package/plugins/pmx-canvas/runtime.json +1 -1
  154. package/plugins/pmx-canvas/tools.json +9418 -2016
  155. package/skills/pmx-canvas/SKILL.md +19 -21
  156. package/skills/pmx-canvas/references/full-reference.md +44 -6
  157. package/skills/pmx-canvas/references/installing-pmx-canvas.md +7 -7
  158. package/skills/published-consumer-e2e/scripts/run-published-consumer-e2e.sh +3 -5
  159. package/src/client/canvas/BarHint.tsx +6 -3
  160. package/src/client/canvas/CanvasNode.tsx +34 -47
  161. package/src/client/canvas/CanvasViewport.tsx +6 -7
  162. package/src/client/canvas/ContextMenu.tsx +63 -3
  163. package/src/client/canvas/EdgeLayer.tsx +365 -169
  164. package/src/client/canvas/ExpandedNodeOverlay.tsx +1 -2
  165. package/src/client/canvas/Presentation.tsx +53 -3
  166. package/src/client/canvas/ToolRail.tsx +2 -0
  167. package/src/client/canvas/TopBar.tsx +24 -9
  168. package/src/client/canvas/auto-fit.ts +9 -11
  169. package/src/client/canvas/canvas-area.ts +1 -1
  170. package/src/client/canvas/use-focus-trap.ts +6 -1
  171. package/src/client/mermaid-entry.ts +6 -20
  172. package/src/client/mermaid-render.ts +39 -0
  173. package/src/client/nodes/AxStepControls.tsx +45 -69
  174. package/src/client/nodes/BoardNode.tsx +65 -9
  175. package/src/client/nodes/ContextNode.tsx +88 -396
  176. package/src/client/nodes/ExtAppFrame.tsx +283 -1462
  177. package/src/client/nodes/FileNode.tsx +92 -81
  178. package/src/client/nodes/HtmlNode.tsx +8 -36
  179. package/src/client/nodes/LedgerNode.tsx +31 -17
  180. package/src/client/nodes/MarkdownNode.tsx +8 -17
  181. package/src/client/nodes/McpAppNode.tsx +48 -154
  182. package/src/client/nodes/MermaidNode.tsx +80 -69
  183. package/src/client/nodes/PromptNode.tsx +12 -14
  184. package/src/client/nodes/ResponseNode.tsx +8 -6
  185. package/src/client/nodes/StatusNode.tsx +22 -7
  186. package/src/client/nodes/StatusSummary.tsx +5 -3
  187. package/src/client/nodes/TraceNode.tsx +8 -8
  188. package/src/client/nodes/ViewerFrame.tsx +262 -0
  189. package/src/client/nodes/ViewerHost.tsx +41 -0
  190. package/src/client/nodes/WebpageNode.tsx +22 -24
  191. package/src/client/nodes/iframe-document-url.ts +20 -27
  192. package/src/client/nodes/primitive-copy.ts +97 -0
  193. package/src/client/nodes/use-iframe-content-height.ts +34 -10
  194. package/src/client/nodes/use-surface-frame.ts +22 -11
  195. package/src/client/nodes/viewer-runtime-state.ts +41 -35
  196. package/src/client/state/canvas-store.ts +18 -12
  197. package/src/client/state/intent-bridge.ts +1 -0
  198. package/src/client/state/presentation.ts +135 -15
  199. package/src/client/state/sse-bridge.ts +18 -19
  200. package/src/client/theme/global.css +389 -229
  201. package/src/client/theme/surface-theme.css +6 -6
  202. package/src/json-render/charts/tufte-components.tsx +44 -2
  203. package/src/json-render/renderer/index.css +62 -2
  204. package/src/json-render/renderer/index.tsx +31 -7
  205. package/src/json-render/server.ts +3 -2
  206. package/src/mcp/canvas-access.ts +6 -47
  207. package/src/mcp/resource-subscriptions.ts +181 -0
  208. package/src/mcp/server.ts +185 -219
  209. package/src/server/ax-wait.ts +21 -6
  210. package/src/server/board-export.ts +35 -24
  211. package/src/server/canvas-geometry.ts +1 -0
  212. package/src/server/canvas-operations.ts +6 -2
  213. package/src/server/canvas-state.ts +5 -0
  214. package/src/server/demo-state.json +106 -100
  215. package/src/server/html-primitives.ts +3 -9
  216. package/src/server/html-surface.ts +8 -0
  217. package/src/server/index.ts +30 -12
  218. package/src/server/operations/http.ts +69 -21
  219. package/src/server/operations/index.ts +8 -1
  220. package/src/server/operations/invoker.ts +53 -5
  221. package/src/server/operations/mcp-contracts.ts +354 -0
  222. package/src/server/operations/mcp.ts +153 -18
  223. package/src/server/operations/ops/ax-await.ts +18 -10
  224. package/src/server/operations/ops/ax-read.ts +2 -0
  225. package/src/server/operations/ops/ax-timeline.ts +2 -2
  226. package/src/server/operations/ops/batch.ts +27 -8
  227. package/src/server/operations/ops/boards.ts +1 -3
  228. package/src/server/operations/ops/nodes.ts +18 -3
  229. package/src/server/operations/ops/viewport.ts +11 -9
  230. package/src/server/operations/registry.ts +24 -4
  231. package/src/server/operations/types.ts +16 -2
  232. package/src/server/server.ts +17 -59
  233. package/src/server/tour-control.ts +66 -6
  234. package/src/server/webpage-node.ts +9 -4
  235. package/src/shared/ax-surface-protocol.ts +0 -11
  236. package/src/shared/content-height-reporter.ts +4 -3
  237. package/src/shared/tour.ts +8 -0
package/docs/design.md CHANGED
@@ -87,8 +87,8 @@ Components reference tokens only. Raw colour values live only in the theme files
87
87
  - Tints are derived — `color-mix(in srgb, var(--c-pin) 12%, transparent)` — so the 22 alpha
88
88
  copies, `--c-warn-alt` and `--c-glow-accent` go.
89
89
  - `--c-thinking` becomes `--c-agent`.
90
- - **Kinds carry no colour.** Type icons use `--c-muted`; the glyph tells the kind, plus the kind
91
- word on zoomed-out tiles (Zoom board). Minimap rects and group-chip kind dots are neutral, and
90
+ - **Kinds carry no colour.** Type icons use `--c-muted`; the glyph tells the kind.
91
+ Minimap rects and group-chip kind dots are neutral, and
92
92
  only meaning colours mark them (pinned, agent at work). `KIND_COLOR`, `--kind-accent` and
93
93
  `--c-purple` go. Nine kind hues cannot all stay clear of ten meaning colours in nine themes,
94
94
  and every hue a kind borrows is one a meaning loses.
@@ -141,7 +141,7 @@ the same change.
141
141
  | [`Flows.dc.html`](design/Flows.dc.html) | Data lineage with staleness, what a finding rests on, opening a group | 3, 5 |
142
142
  | [`Uses.dc.html`](design/Uses.dc.html) | One relation layer for research, dependencies, decisions and agent flows | 3 |
143
143
  | [`Types1.dc.html`](design/Types1.dc.html)–[`Types3.dc.html`](design/Types3.dc.html) | Every node type, today vs proposed | 0, 4 |
144
- | [`Zoom.dc.html`](design/Zoom.dc.html) | Fit-all readability when frames are unmounted | 4 |
144
+ | [`Zoom.dc.html`](design/Zoom.dc.html) | Native spatial scaling at every zoom, maintainer override 2026-10-25 | 4 |
145
145
  | [`Pane600.dc.html`](design/Pane600.dc.html) | Home and a board at the narrow end, 600 px | all |
146
146
  | [`Vision.dc.html`](design/Vision.dc.html) | How each design area maps to the vision, and the open decisions | — |
147
147
 
@@ -377,7 +377,7 @@ workflow. A demo of existing features must not be used to claim full sketch pari
377
377
  | **1. Context made visible** — its curation evaluation moved to the end of the plan (2026-10-19) | Part 1 bet, moves 0a, 2, 7 | Surface `context_reads` (already recorded since 0.7.0: who read, which nodes were delivered) per node and per board as read / not read / changed since read, using revisions; who pinned; activity lens and session receipt from presence activity and revisions; board pins (`board_pins`, tiered brief, `canvas_board pin/unpin`) and Home's pinned-boards section | What the agent did with context, Nodes in context, Board pins, Home (Folders) | From the board alone, a person can answer "did the agent read what I pinned, and is its copy current?" The evaluation in `docs/evals/` reads the same data |
378
378
  | **2. Connected memory views** — implemented, verification gates apply | Moves 0, 14 | One board/card projection for Home, links/backlinks, brief discovery and `canvas://graph{?focus,depth}`; saved wiki ID bindings, direct cross-board card edges, previous-board chains, persisted Map positions | Home Map, Home Graph (deviations below) | Map and Graph are generated from the library; orphans visible; works at 600 px and in a full window |
379
379
  | **3. Relations layer** | Moves 0, 1, 13 | Edge `reason` and an open `kind` with a per-board vocabulary; relations carried in the brief's text form; "derived from" with staleness from provenance and recipes; relation queries for the inspector | Relations, Lineage, One relation layer | Hovering a node explains each link; a changed source turns downstream nodes amber; the agent's brief includes relations |
380
- | **4. Frame host and viewers** | Moves 5, 9 | One frame host passing the full theme tokens; json-render defaults to the canvas theme with an opt-out for design experiments; zoomed-out cards for unmounted frames | Node types 1–3, Zoomed out | No viewer draws its own background; 20 portals mount no more frames than none; fit-all is readable |
380
+ | **4. Frame host and viewers** | Moves 5, 9 | One frame host passing the full theme tokens; json-render defaults to the canvas theme with an opt-out for design experiments; native proportional canvas at every zoom | Node types 1–3, Zoom | Viewers use the canvas palette and fill their authored space; approaching a viewer mounts it automatically and retains its state when panning away; no alternate grid or lifetime preview cap |
381
381
  | **5. Agent output and groups as pages** | Moves 3, 0 | Work items, gates and asks as nodes; make board / inline board; opening a group keeps its outside links | One relation layer (agent flow), Lineage (open a group) | Agent output is styled by the same shell and tokens; a group opened as a board shows its outside stubs |
382
382
  | **Later: hosted version** | Part 4 (moved from Part 3, 2026-10-19) | Read-only link, comments, second writer, accounts and roles; org → team → personal scopes with configurable categories and per-user pins; built once for the ChatGPT Sites and later Cloudflare editions | HomeTeam is the earlier two-root look ahead; updated scope/category drawings are required before building, retaining explicit publication and locked cards for unreadable boards | Exports and shared views inherit the tokens; a viewer sees the same meaning colours; nothing personal reaches a wider audience without explicit publication |
383
383
 
@@ -630,6 +630,171 @@ curation evaluation after its remaining features. Local categories and lifecycle
630
630
  without a model; Jev-style classification is optional longer-term assistance, not a dependency
631
631
  of Wave 3 or the org/team/personal structure.
632
632
 
633
+ ## 0.11 implementation notes
634
+
635
+ Chrome §9–10 and Types1–3 drive the section-heading, header, typography and viewer
636
+ pass. Fit and focus reserve a 44 px screen-space top lane. JSON viewers inherit the
637
+ named canvas palette; only duplicate root titles disappear. Mermaid renders inline.
638
+ File-header metadata may clip within its own text container, but Reload and AX
639
+ evidence actions and their hover/focus hints stay outside that clip (Types1).
640
+ The maintainer's 2026-10-25 decision supersedes the earlier reading-flow footer:
641
+ **Set as README** lives only in the card's ⋯ menu, becoming **Remove as README**
642
+ for the current README. The agent normally assigns it; this menu is the human override.
643
+ The designated card keeps a quiet, always-visible **README** word in its header,
644
+ including heading-display Markdown. It uses neutral metadata ink, not pin blue or
645
+ selection styling; the title yields before this identifier truncates.
646
+ Ordinary Markdown keeps its visible **Edit** action; heading display has no footer.
647
+ Chrome and Types1 reflect this decision. The menu takes keyboard focus, supports
648
+ arrows and Tab, and restores the opener on activation or Escape.
649
+ **Present** explains saved tours versus group-derived stops on hover and keyboard
650
+ focus, with an accessible description. The narrow ⋯ menu shows the same explanation
651
+ in flow below Present rather than clipping a floating tooltip. Chrome records the
652
+ owner's exact copy; no tour behavior changes. Its saved-tour instruction says
653
+ **ask your agent to define the stops**, not that a visual human tour editor exists.
654
+ During presentation, **Back** and **Next** sit beside **Exit presentation** at
655
+ the top-right, following the existing shared server cursor. The owner's final
656
+ placement decision puts instructions only in each button's hover/focus tooltip:
657
+ Previous stop (← / ↑), Next stop (→ / ↓ / Space), Exit presentation (Esc).
658
+ There is no lower-left instruction panel. Unavailable end buttons remain focusable
659
+ for their descriptions. Node/rectangle fitting reserves the controls' measured
660
+ height; explicit camera targets and deterministic recordings remain unchanged.
661
+ HTML primitives put **Copy JSON** in the card's ⋯ menu, not their inner header;
662
+ **Copy prompt** is removed. JSON comes from the current mounted document, including
663
+ unsaved interactive edits, through the nonce-bound sandbox bridge. Unloaded or
664
+ replaced documents and denied clipboard access report failure, not stale data or
665
+ success. Raw HTML and the custom presentation primitive have no JSON-export menu
666
+ action. Primitive-specific Copy diff, Copy SVG and similar controls stay in place.
667
+ The maintainer's 2026-10-25 correction rejects the experimental CSS zoom, content
668
+ enlargement and alternate overview. The original world matrix scales cards,
669
+ embedded contents, groups and connections proportionally at every zoom. Only title
670
+ text grows, up to 1.2× inside a fixed 22 px header line. Header controls, padding and
671
+ body space stay fixed in world pixels; enlarging the whole header would resize the
672
+ iframe viewport and reflow charts while zooming. Card bodies never counter-scale.
673
+ All cards share the same stacking and input boundary. A separate
674
+ ext-app portal was rejected in review because it covered higher cards, bypassed
675
+ pan gestures, and disappeared during presentation. The common world also owns
676
+ clipping when a dock resizes the canvas. Headed Linux WebKit reproduced CSS zoom
677
+ shrinking the iframe's internal layout and retaining stale dimensions through
678
+ zoom transitions. Restoring the matrix keeps inner widths stable in the same probe.
679
+ Native WKWebView compositor health remains unverified, not established by that result.
680
+ Automatic previews mount on first approach at any scale, then retain their
681
+ documents to preserve arbitrary app state. The rejected lifetime cap starved later
682
+ board regions. Memory now grows with visited viewers. Visible viewers start loading
683
+ automatically without a shared bootstrap queue or per-card clicks. A slow document
684
+ does not hold another card's loading slot.
685
+ Each loading replacement temporarily coexists with its painted document.
686
+
687
+ The demo gives ordinary standalone charts the full authored card height instead
688
+ of imposing a smaller plot-height cap. Compact chart types keep compact cards:
689
+ the 36 px sparkline sits in a 120 px card, four dot-plot rows in 240 px, three bullet
690
+ rows in 260 px, and the slopegraph in 300 px. These are demo authoring choices,
691
+ not enforced sizes on user cards. Explicit chart `height` still caps content,
692
+ independently of `nodeHeight`. Dashboard and form stacks explicitly use stretch
693
+ alignment; the catalog's start-aligned default is unchanged, as are compact action
694
+ buttons. Work-item controls must fit their authored cards without accidental
695
+ overflow or truncated status. Enlarging the demo to 440×300 did not meet that
696
+ requirement and is not acceptance evidence. The card body now scrolls only its
697
+ content when needed; step controls and Edit share one fixed footer row. The full
698
+ status word takes priority over the title. Steering input and send button wrap
699
+ together. Expanded documents keep their sticky footer. The demo returns to a
700
+ 240 px height, with 360 and 440 px widths exercised in both Chromium and WebKit.
701
+ Bodies still shrink proportionally.
702
+
703
+ Static exports use the same embedded chart layout and named palettes, retain
704
+ heading display, and match the live 37 px card header. Fonts and shared palette
705
+ CSS are embedded for offline use. Saved positions, sizes and specs are unchanged;
706
+ live work controls are intentionally absent. Export is a separate acceptance
707
+ surface, not established by live canvas checks. Close slopegraph labels separate
708
+ without moving data endpoints; short same-ink leaders retain their association
709
+ (Types3). An explicitly overcrowded chart still requires adequate authored height.
710
+
711
+ Relation labels keep their curve midpoint when clear. Otherwise the pill and its
712
+ hit area move together to nearby open space, avoiding cards, group headers,
713
+ connection handles and earlier labels. A dashed leader in the relation's ink
714
+ ties it back to the curve. Card positions, curve routing and stacking do not
715
+ change. Font measurements determine pill width. Dense boards can still require
716
+ panning to a displaced label; labels remain hidden below the existing 35% floor.
717
+
718
+ `ViewerHost` owns preview admission, without a second positioning or recovery path.
719
+ `RefreshingViewerFrame` owns document loading, the painted replacement handoff and
720
+ Retry. HTML readiness and the ext-app protocol use that host; JSON additionally
721
+ restores its viewer-local state before promotion. The ext-app adapter no longer
722
+ has a separate paint/recovery ladder. Document preparation failures do not fall
723
+ back to another transport that the embedding probe already rejected.
724
+ Ext-app protocol bootstrap runs once after initialization, or after the loaded
725
+ document's bounded notification-only bootstrap interval. The host waits for
726
+ input/result delivery and paint before declaring it ready; bootstrap errors use
727
+ the same Retry as other loading failures.
728
+ Webpages show cached text until an explicit live-preview request; Mermaid
729
+ and native board thumbnails render inline. Mermaid's inline
730
+ and standalone/export renderers share their palette, serialization and sanitizer.
731
+ Inline rendering uses Mermaid's strict security mode and DOMPurify, including
732
+ sanitized `foreignObject` labels, instead of the old diagram iframe sandbox.
733
+ Mermaid is the exception to the static-import rule: the SPA loads it on the first
734
+ diagram, using hashed chunks from the same server. A six-Markdown-card cold-boot
735
+ probe requested only the entry and its small shared chunk, not Mermaid's 3.46 MB.
736
+ With Bun 1.4.4, headed Chromium 145, 4× CPU throttling and five alternating fresh
737
+ contexts per variant, the baseline median was 1,423.9 ms and the candidate median
738
+ 1,349.1 ms to six populated cards plus two animation frames. Ranges overlap
739
+ (1,277.3–1,484.7 ms versus 1,315.2–1,510.1 ms), so this is not a speedup claim.
740
+ The baseline is 0.10.0 rebuilt with the same compiler; both variants use current
741
+ CSS and local intercepted responses, not a network or native-host benchmark.
742
+ Reproduce with `DISPLAY=:99 node scripts/benchmark-canvas-boot.mjs <disposable-server-url> <baseline-index.js>`.
743
+ The populated-board check uses `scripts/benchmark-populated-canvas.mjs`, the same
744
+ 70-card fixture and 18% camera, headed Chromium 145 at 1440×900, and three cold-cache
745
+ loads plus three warm reloads per build, with other browsers and tests stopped.
746
+ All 33 visible viewers rendered. The final comparison found baseline 0.10.0 at
747
+ 6.71–7.67 s cold and 7.17–7.32 s warm; the candidate took 7.59–8.19 s cold and
748
+ 8.00–8.39 s warm. This remains a loading cost, not an orb-only explanation or a
749
+ speedup. Main-page long tasks totalled 4.43–4.87 s on the candidate versus
750
+ 3.46–4.20 s on baseline. Each chart document contains about 1.49 MB decoded
751
+ (baseline 1.47 MB). Parent Resource Timing alone misses baseline iframe bytes
752
+ and can duplicate candidate navigation bytes; do not compare or sum those totals.
753
+ The script records frame resources separately. Removing the provisional four-document queue produced overlapping
754
+ completion ranges and a later first viewer; the simpler independent loading path
755
+ avoids cross-card blocking, not a claimed performance win. Warm-load aborted
756
+ presence requests are recorded separately from viewer failures; no viewer failed.
757
+ At the default 52% camera there are no visible iframe viewers. The candidate's
758
+ board appeared in 0.67–0.70 s cold and 0.52–0.65 s warm versus baseline's
759
+ 1.08–1.32 s and 1.06–1.36 s. That measures deferred offscreen work, not faster
760
+ viewer rendering. Local document responses were 2–6 ms. Portal-URL checks use
761
+ Amp's local hairpin forwarding inside this orb, so they do not measure external
762
+ portal transport or the user's connection. These are instrumented local readiness
763
+ timings, not native paint latency. Linux WebKit's full fit-all load exceeded this orb's memory limit
764
+ on both baseline and candidate; narrower populated-row checks are separate evidence.
765
+ The self-contained MCP App cannot fetch those chunks: its document includes
766
+ Mermaid and grows from about 1.32 MB to 4.78 MB uncompressed. This is an introduced delivery
767
+ cost, not eliminated debt or measured native performance. Keeping one renderer
768
+ and an offline-capable MCP document is the tradeoff; native boot remains unmeasured.
769
+ The bundle audit found one Mermaid core, one shared renderer and one DOMPurify,
770
+ not an embedded copy of the standalone viewer. The old standalone Mermaid bundle
771
+ already weighed 3,492,157 bytes; moving its renderer inline brings that dependency
772
+ tree into the self-contained MCP host. The dependency graph contains different
773
+ major versions of `marked`, `layout-base` and `cose-base` required by Mermaid's
774
+ renderers; forcing aliases would not be a safe deduplication. Inspect the graph
775
+ with `bun build src/client/mcp-app/index.tsx --target=browser --format=iife --minify --metafile=/tmp/mcp-meta.json --outfile=/tmp/mcp.js`.
776
+ Removing the payload from MCP startup requires a different script-delivery/CSP
777
+ contract or a reduced diagram catalog, rather than deleting a duplicate host.
778
+ Static export checks separately cover all twelve graph variants, compact plots,
779
+ all nine named themes and 600, 1024 and 1920 px widths in headed Chromium.
780
+ The populated 70-card export matches live saved geometry and renders offline
781
+ without HTTP(S) requests; bounded Linux WebKit checks cover the compact chart
782
+ section and dashboard. Linked boards and live MCP apps retain honest unavailable
783
+ placeholders. Arbitrary user HTML can still contain external requests.
784
+
785
+ There is no threshold-triggered grid or list. Zoom's revised drawing keeps the
786
+ same positions, sizes, groups, connections and native content at every scale.
787
+ Fit-all is for orientation; zoom or expand to read details. The earlier overview's
788
+ scrolling and overlay-clearance fixes are superseded by its complete removal.
789
+
790
+ Visual audit: Harbor headings use the drawing's 20 px semibold `#e6eef7` on
791
+ `#081524` (15.69:1). The initial dim capture had the existing relation-focus
792
+ highlight active, which applies 0.35 opacity to unrelated cards; Escape clears
793
+ that view state. A neighboring card outside a 600 px viewport is spatially
794
+ clipped, not internally truncated: focusing it restores the complete title.
795
+ Expanded pin hints remain while their button has keyboard `:focus-visible`, even
796
+ after pointer movement; Tab away dismisses the hint after its fade transition.
797
+
633
798
  ## Definition of done for any design work
634
799
 
635
800
  1. It is drawn in the proposal canvas first, at 600 px and at full-window width.
package/docs/http-api.md CHANGED
@@ -3,6 +3,37 @@
3
3
  REST endpoints for all canvas operations + an SSE event stream. Works from
4
4
  any language. Default base URL: `http://localhost:4313`.
5
5
 
6
+ ## Operation cancellation and progress (0.10)
7
+
8
+ Registry-backed operation routes use the request's abort signal. Disconnecting
9
+ stops supported AX waits, cancels webpage fetching and prevents later batch
10
+ operations from starting. Completed writes remain. Cancellation is cooperative:
11
+ external app builds/runtime calls and local WebView captures cannot be interrupted
12
+ mid-call. A standalone cancelled operation returns HTTP 499 with
13
+ `{ "ok": false, "cancelled": true, "error": "Operation cancelled." }` when the
14
+ connection still permits a response. An interrupted batch retains completed
15
+ `results` and `refs` in its partial-failure body and adds `cancelled: true`.
16
+ Disconnected clients must inspect state before retrying; they may never receive
17
+ that body. Cancellation is not rollback.
18
+
19
+ Send `Accept: application/x-ndjson` to opt into batch and supported AX wait progress
20
+ over the operation response stream. Each newline-delimited JSON frame is one of:
21
+
22
+ ```json
23
+ {"type":"progress","progress":{"progress":1,"total":3,"message":"node.add"}}
24
+ {"type":"result","status":200,"body":{"ok":true,"results":[],"refs":{}}}
25
+ ```
26
+
27
+ The examples show frame shapes, not one complete batch. The terminal `result`
28
+ frame carries the ordinary operation status and body; the stream's HTTP 200 does
29
+ not establish operation success. Without this header, routes keep their ordinary
30
+ JSON status/body. Early validation errors may still be ordinary JSON. The
31
+ in-process and HTTP operation invokers accept optional `{ signal, onProgress }`;
32
+ the HTTP invoker negotiates this stream only when given a progress callback.
33
+
34
+ AX wait routes accept `timeoutMs` as well as the direct-HTTP `waitMs` parameter;
35
+ `timeoutMs` takes precedence when both are supplied.
36
+
6
37
  ## Knowledge lifecycle data (plan 017 slice 1)
7
38
 
8
39
  The slice-1 data contract now also drives the workbench, due engine and qualified agent context.
@@ -186,9 +217,15 @@ content auto-height or indirect parent-group reflow after editing a child.
186
217
  update and are included in snapshots/undo. They are board-wide writes under a scope fence.
187
218
  - `POST /api/canvas/tour/go` with `{ "stop": 2 }` or `{ "step": "next" | "previous" }`
188
219
  (plus optional `"present": false`) moves the shared tour cursor →
189
- `{ ok, index, total, stop }`; 400 when the stop does not exist or the board has no stops.
220
+ `{ ok, index, total, stop, catalogEpoch, boardGeneration, sequence }`;
221
+ 400 when the stop does not exist or the board has no stops.
190
222
  Broadcasts `canvas-tour-step`; idle workbenches start presenting unless `present` is false.
223
+ Response and event share the same monotonically increasing `sequence` within the
224
+ server's `catalogEpoch`. Viewers accept only newer steps for their current epoch
225
+ and board generation, so delayed echoes cannot rewind or replay the camera.
191
226
  - `POST /api/canvas/tour/exit` leaves presentation in every viewer (`canvas-tour-exit`).
227
+ Returns `{ ok, catalogEpoch, boardGeneration, sequence }`; the event shares that
228
+ identity and the step sequence, so an old exit cannot dismiss a newer presentation.
192
229
  - `POST /api/canvas/camera/move` with exactly one of `nodeId`, `rect: { x, y, width, height }`
193
230
  or `viewport: { x, y, scale }`, plus optional `duration`, `easing`, `padding`, `pullback`
194
231
  → `{ ok, stop, viewport }`. Broadcasts `canvas-camera-move`; browsers ease to the target in
@@ -198,6 +235,29 @@ content auto-height or indirect parent-group reflow after editing a child.
198
235
  Tour steps and camera moves are navigation: no undo entry, no agent-presence write, no
199
236
  scope-fence check.
200
237
 
238
+ `tour/go` and `tour/exit` accept optional `presenter: { clientId, intent,
239
+ catalogEpoch, boardGeneration }`. The workbench assigns each document a random ID
240
+ and each gesture an increasing positive safe-integer intent. The server rejects
241
+ an old activation or an intent no newer than that document's accepted watermark
242
+ with `{ ok: true, superseded: true }`, without moving the cursor or emitting an event.
243
+ A structurally valid newer command supersedes older ones even if its stop is missing.
244
+ This lets Present proceed while an earlier Exit request is stalled, without that
245
+ late Exit stopping the restart. Resume reads cannot outlive their originating intent.
246
+
247
+ This is latest-intent-wins, not FIFO: reversed relative Next requests can coalesce.
248
+ Different documents, including a reload, remain independent; unfenced agent calls
249
+ and other documents still act in server arrival order. Reload is not cancellation
250
+ of an old document's pending request. A board activation retains at most 4096
251
+ document IDs, refusing new IDs with 409 rather than evicting an ordering record.
252
+ Switching boards resets that limit; requests stamped with the old activation still
253
+ cannot apply. The SDK exposes the same fence through `goToTourStop(step,
254
+ { presenter })` and `exitTour(presenter)`; fenced go may return `{ superseded: true }`.
255
+
256
+ Presentation's Back/Next buttons share this cursor with keyboard and agent navigation.
257
+ They sit beside Exit at the top; hover/focus tooltips show the shortcuts. Node and
258
+ rectangle targets fit below those controls, while explicit viewport targets remain
259
+ exact. Presentation does not change the saved board viewport.
260
+
201
261
  The [tour model and recording walkthrough](cli.md#tour-and-presentation) describes
202
262
  targets, duration, easing, padding, and pullback. Open `/workbench?present=1` to hide
203
263
  chrome; camera movement is local to that viewer. Recording writes local files via
@@ -357,6 +417,14 @@ stored once per file. Live MCP apps become placeholders; local file contents
357
417
  are left out unless `includeFiles` is true. Files are written to `exports/`
358
418
  beside the database. Built-app files are only embedded when they are regular,
359
419
  bounded-size files inside the board's owned `.pmx-canvas/artifacts/` directory.
420
+ Exports retain saved card positions and sizes, heading display, and the board's
421
+ named theme. Charts and dashboards use embedded card layout without repeating
422
+ the shell title; explicit chart heights remain unchanged. Viewer bundles, palette
423
+ CSS and shell fonts are embedded. Read-only exports omit live work controls.
424
+ When running from source, run `bun run build` before exporting. Export requires
425
+ the complete built viewer assets, `surface-theme.css`, and the font files referenced
426
+ by `global.css`; the installed package includes them. A missing asset tree is not
427
+ a supported text-only export mode.
360
428
  The preview manifest lists card links, remote images, and statically visible
361
429
  network destinations in embedded HTML. Imported source-linked Markdown is also
362
430
  excluded unless `includeDerivedText=true`, independently of `includeFiles`;
@@ -431,6 +499,13 @@ opening that board or changing where writes go. This is supported by
431
499
  return 404. Omit `board` to read the active board. Live AX session/delivery reads
432
500
  and fixed MCP resources continue to describe the open board.
433
501
 
502
+ The workbench's `POST /api/canvas/update` accepts `{updates: [{id, position?, size?,
503
+ collapsed?, zIndex?}], expectedBoardId?, recordHistory?}`. `zIndex` is finite and
504
+ persists stacking without changing geometry. The workbench raises a group and its
505
+ children together, keeping the frame below its children. Title-bar gestures save
506
+ stacking and geometry together on release. Layout notifications and reloads retain
507
+ that order.
508
+
434
509
  ```bash
435
510
  # Get canvas state
436
511
  curl http://localhost:4313/api/canvas/state
@@ -582,6 +657,10 @@ hosted MCP App still refuses file-linked edits. This is not a crash-recovery dis
582
657
  Replacing a JSON-render node's `spec` preserves its current title; include `title`
583
658
  to rename it explicitly. A new authored spec still resets the viewer's local drafts.
584
659
 
660
+ Markdown nodes accept `data: { "display": "heading" | "card" }` on creation and
661
+ update. Heading display removes the card frame and uses its title as a section
662
+ label; it does not alter content, position, or pin membership.
663
+
585
664
  Mermaid nodes accept `data: { "fit": "contain" | "none" }` on both
586
665
  `POST /api/canvas/node` and `PATCH /api/canvas/node/:id`. The default, `contain`,
587
666
  shrinks overflowing diagrams without changing aspect ratio; `none` keeps 100%
@@ -1263,6 +1342,8 @@ all consume this stream. Auto-reconnect with exponential backoff.
1263
1342
 
1264
1343
  The direct workbench's `connected` snapshot renews its per-process
1265
1344
  `workbenchToken` (also embedded in boot HTML) over both SSE and polling.
1345
+ It is followed by `boards-changed` before the layout, so later tour commands
1346
+ already have a board identity even when the separate catalog HTTP read is delayed.
1266
1347
  A same-bundle daemon restart does not reload the page or discard an open draft.
1267
1348
  Registered writes and file saves marked as workbench calls with a supplied stale capability
1268
1349
  return 409 until reconnect renews it; they are never silently recorded as agent
package/docs/mcp.md CHANGED
@@ -1,10 +1,92 @@
1
1
  # MCP reference
2
2
 
3
- PMX Canvas ships an MCP stdio server with **24 tools**, **15 static canvas
3
+ PMX Canvas ships an MCP stdio server with **25 tools**, **15 static canvas
4
4
  resources**, and two canvas resource templates, plus per-skill resources at
5
5
  `canvas://skills/<name>` and the `skill://{name}/{+path}` template. The server emits
6
- `notifications/resources/updated` when canvas state changes — humans pin
7
- nodes in the browser, agents are notified immediately.
6
+ `notifications/resources/updated` to subscribed connections when canvas state changes.
7
+ This uses MCP SDK v1, not SDK v2.
8
+
9
+ ## Operation help (0.10)
10
+
11
+ Call `canvas_help {}` for the sorted registry names exposed through MCP, then
12
+ `canvas_help { op: "node.add" }` for one operation's public `tool`, `description`
13
+ and JSON `inputSchema`. The schema includes required fields, public field names
14
+ and constant routing selectors (`action`, and `kind` for gates). For example,
15
+ `ax.approval.request` maps to `canvas_ax_gate` with `kind: "approval"`,
16
+ `action: "request"` and the optional `approvalAction` field.
17
+
18
+ Text contains the JSON result; structured content wraps it in `{ result }`.
19
+ Unknown names, internal/human-only operations and non-registry tools such as
20
+ `canvas_screenshot` return text-only `isError`; use `tools/list` for those tools.
21
+ Help reads registry metadata only: it never starts a canvas, writes state, records
22
+ a content read or advances a cursor. It is read-only and idempotent.
23
+
24
+ Help derives its schema and guidance from the operation registry, not from live
25
+ board state. Handlers still enforce conditional requirements and authorization.
26
+ Existing input schemas stay in `tools/list`; help does not enable lazy discovery
27
+ in hosts. Repeated equivalent output branches are grouped within each tool,
28
+ preserving operation/payload validation and partial-error receipts.
29
+
30
+ ## Tool results and effect hints (0.10)
31
+
32
+ All 25 tools advertise an object `outputSchema`. Registry-dispatched tools return
33
+ `structuredContent.result = { operation, outcome, data }`. `operation` names the
34
+ dispatched action (for example `node.add`), `outcome` is `success`, `error` or
35
+ `partial`, and `data` is the existing compact tool result. Prose results use
36
+ `data.message`. Exceptions use `operation: null`, `outcome: "error"` and
37
+ `data.message`; this does not guarantee that nothing changed before the exception.
38
+ Batch failures retain completed `results` and `refs`, with `partial` when at least
39
+ one entry completed. Check both `isError` and the outcome before using a result.
40
+
41
+ The three handwritten tools keep direct structured objects: `canvas_ax_interaction`
42
+ returns its accepted interaction, `canvas_ingest_activity` its event and reaction
43
+ records, and `canvas_screenshot` capture metadata alongside model-visible image
44
+ content. Their errors are text-only `isError` replies. Existing model-facing text
45
+ and compact/full projections remain unchanged; structured results do not introduce
46
+ additional full-card or UI payloads. Inspect the advertised schema for each tool.
47
+
48
+ All tools declare `readOnlyHint`, `destructiveHint`, `idempotentHint` and
49
+ `openWorldHint`. Composite hints cover every action, not only their read actions.
50
+ `canvas_query` is not read-only because context reads can advance a durable
51
+ consumer cursor. Hints describe effects; they grant no permission or retry guarantee.
52
+
53
+ ## Cancellation and progress (0.10)
54
+
55
+ MCP cancellation reaches the operation layer in both local and daemon-attached
56
+ connections. Supported AX waits release their listeners and timers immediately;
57
+ batches stop before the next operation and keep completed writes. Webpage fetches
58
+ receive the signal and stop before writing fetched content after cancellation.
59
+ Cancellation does not roll back a created node or other completed mutations.
60
+ If webpage creation already committed, its receipt retains `fetch.cancelled: true`.
61
+ External app builds/runtime calls and local WebView captures are not interruptible
62
+ mid-call; do not treat cancellation as proof that those side effects stopped.
63
+
64
+ Calls supplying `_meta.progressToken` receive `notifications/progress` at batch
65
+ entry boundaries and supported AX wait start/completion, with `progress`, optional
66
+ `total`, optional `message` and the same token. This works over the daemon bridge
67
+ as well as local stdio. No token means
68
+ no progress notifications. A host that aborts its connection may not receive a
69
+ partial result; inspect canvas state before retrying. See the
70
+ [HTTP streaming contract](http-api.md#operation-cancellation-and-progress-010).
71
+
72
+ ## Resource subscriptions (0.10)
73
+
74
+ The server advertises `resources.subscribe`. Send `resources/subscribe` with an
75
+ exact live URI, then `resources/unsubscribe` to stop. Subscriptions belong to the
76
+ connection and disappear on close; reconnecting clients must subscribe again.
77
+
78
+ Live resources are `canvas://layout`, `boards`, `summary`, `context`, `graph`,
79
+ `spatial-context`, `history`, `code-graph`, `pinned-context`, `ax`, `ax-context`,
80
+ `ax-timeline`, `ax-work`, `ax-pending-steering` and `ax-delivery` (each with the
81
+ `canvas://` prefix). Parameterized context and graph URIs are supported, for example
82
+ `canvas://context?consumer=my-agent&budget=3000`; notifications echo the exact
83
+ subscribed URI. Static schema and bundled skill resources do not support subscriptions.
84
+
85
+ Notifications invalidate cached data, not deliver it. Read the resource when needed.
86
+ They can be broader than the underlying change, and daemon reconnection invalidates
87
+ subscribed resources to cover missed events. Notification delivery does not record
88
+ a context read or advance a consumer cursor. Explicit `resources/read` works without
89
+ subscriptions, including on hosts that do not use this capability.
8
90
 
9
91
  > **Consolidation complete (plan-006/008).** The MCP surface shrank from 84
10
92
  > tools to 22: 16 action-discriminated **composites** (recommended — see
@@ -64,6 +146,10 @@ tour: { stops: [...] } }` persists an ordered tour; `tour: null` resets it.
64
146
  presents a stop in the workbench, `"tour-exit"` leaves presentation, and
65
147
  `canvas_view { action: "move", nodeId | rect | viewport, duration, easing, padding, pullback }`
66
148
  eases the camera. None of these enter undo history.
149
+ `tour-go` and `tour-exit` also accept the optional document `presenter` fence
150
+ described in [HTTP board tours](http-api.md#board-tours). Superseded requests return
151
+ `{ ok: true, superseded: true }` with no delivery or event. Ordinary agent calls
152
+ omit it and retain shared arrival-order navigation.
67
153
  See the [tour model and CLI walkthrough](cli.md#tour-and-presentation) for stop
68
154
  fields. Recording is a local CLI operation; no remote recording/file-writing
69
155
  tool is added.
@@ -83,12 +169,12 @@ Add to your agent's MCP config:
83
169
  }
84
170
  ```
85
171
 
86
- The canvas auto-starts on first tool call.
172
+ The canvas auto-starts on first canvas operation, not on `canvas_help`.
87
173
 
88
174
  ## Private MCP App preview
89
175
 
90
176
  `pmx-canvas --mcp-app` runs a **separate, experimental stdio profile**; the
91
- 24-tool `--mcp` profile above is unchanged. Build from this checkout first:
177
+ 25-tool `--mcp` profile above is separate. Build from this checkout first:
92
178
 
93
179
  ```bash
94
180
  bun run build
@@ -358,7 +444,7 @@ Single-card and layout reads record delivered content, not incident relations.
358
444
  Use a complete graph or brief relation entry to acknowledge those relations.
359
445
  Reads never mark full card content read or
360
446
  switch the workbench. Pull needed cards in full separately.
361
- No new tool is added: the tool count stays 24.
447
+ These reads add no tools beyond the catalog listed above.
362
448
 
363
449
  Library search is `canvas_query { action: "search", query: "auth", scope:
364
450
  "library" }`. It returns board/card IDs and never switches the active board.
@@ -431,6 +517,10 @@ into `persistFile: true` with both preconditions and top-level `content` to save
431
517
  workspace `.md` file and card together. In this mode, `data` accepts only the `rendered` preview;
432
518
  refused saves change neither. See [the file-save contract](http-api.md#nodes).
433
519
 
520
+ For Markdown nodes, `canvas_node` actions `add` and `update` accept
521
+ `data: { display: "heading" | "card" }`. Heading display uses the existing title
522
+ and content as a frameless section label, without changing pin membership.
523
+
434
524
  For Mermaid nodes, `canvas_node` actions `add` and `update` accept
435
525
  `data: { fit: "contain" | "none" }`. Contain is the default, shrinking overflow
436
526
  uniformly; none keeps 100% with scrolling. Use Open as site for 100% without
@@ -491,13 +581,14 @@ agent intends to publish its own cursor or attention target.
491
581
 
492
582
  ## Standalone tools
493
583
 
494
- 6 tools that intentionally stay outside the composites — folding them would
584
+ 7 tools that intentionally stay outside the composites — folding them would
495
585
  hurt (distinct callers, binary payloads, trust-boundary or execution-intent
496
586
  semantics). See [Migration reference](#migration-reference) below for the
497
587
  legacy tools the composites replaced.
498
588
 
499
589
  | Tool | Description |
500
590
  |------|-------------|
591
+ | `canvas_help` | List MCP registry operations or fetch one operation's public arguments and guidance (`op` optional); no canvas access |
501
592
  | `canvas_batch` | Run a batch of canvas operations with `$ref` support |
502
593
  | `canvas_pin_nodes` | Pin nodes to include in agent context (`nodeIds`, `mode` set/add/remove, optional `reason` shown to the human) |
503
594
  | `canvas_invoke_command` | Invoke a registry command (`pmx.plan`, `pmx.execute`, `pmx.promote-context`, `pmx.summarize`, `pmx.review`); records a `command` agent-event, unknown names rejected |
@@ -703,20 +794,9 @@ interaction against the node's effective capabilities.
703
794
 
704
795
  ## Change notifications
705
796
 
706
- The MCP server emits `notifications/resources/updated` whenever canvas state
707
- changes:
708
-
709
- - Pin changes notify `canvas://pinned-context`, `canvas://ax`, and `canvas://ax-context`
710
- - AX focus changes notify `canvas://ax` and `canvas://ax-context`
711
- - Canvas-bound AX mutations (work items, approval gates, review annotations,
712
- host capability) notify `canvas://ax`, `canvas://ax-work`, and `canvas://ax-context`
713
- - AX timeline mutations (agent-events, evidence, steering) notify
714
- `canvas://ax-timeline` and `canvas://ax-context`
715
- - All mutations notify `canvas://layout`, `canvas://summary`,
716
- `canvas://spatial-context`, `canvas://history`, `canvas://code-graph`, and `canvas://graph`
717
-
718
- This closes the human-to-agent loop: spatial curation in the browser becomes
719
- an immediate signal in the agent's context.
797
+ Notifications require an explicit subscription to each live resource URI. See
798
+ [Resource subscriptions](#resource-subscriptions-010) for connection lifetime,
799
+ reconnection and broad cache invalidation. Receiving a notification is not a content read.
720
800
 
721
801
  ## Codex App Adapter
722
802
 
@@ -1,9 +1,9 @@
1
1
  # Node types
2
2
 
3
- `board` is a native text-only link. Set `data.boardId` to the durable target ID. Its header pin pins the
3
+ `board` is a native link with a lightweight board thumbnail. Set `data.boardId` to the durable target ID. Its header pin pins the
4
4
  linked board into the agent's working set (`canvas_board { action: "pin" }`), not the portal card.
5
5
  Titles resolve from that ID, so renames and folder moves are safe; deleted
6
- targets render explicitly as missing. It is not an iframe or a cross-board card
6
+ targets render explicitly as missing, with **Link to board…** to choose a replacement. It is not an iframe or a cross-board card
7
7
  edge. Static exports lock the card and intentionally do not embed the target
8
8
  title or summary, so exporting this board does not disclose another board.
9
9
 
@@ -32,7 +32,7 @@ see [MCP tools](mcp.md), [HTTP API](http-api.md), and [SDK](sdk.md).
32
32
  | `html` | Self-contained HTML/JS in a sandboxed iframe |
33
33
  | `web-artifact` | Bundled React/Tailwind artifact (full single-file app) |
34
34
  | `group` | Spatial container/frame around other nodes |
35
- | `board` | Text-only link to another board, with its README summary and navigation |
35
+ | `board` | Lightweight thumbnail link to another board, with its README summary and navigation |
36
36
 
37
37
  Creation applies per-type frame defaults and readability minimums. When a
38
38
  dimension is defaulted or clamped, HTTP and MCP create responses include a
@@ -48,6 +48,11 @@ response warns about the distinction.
48
48
  Thread node types `prompt` and `response` exist internally for agent
49
49
  conversation rendering and are not created through public APIs.
50
50
 
51
+ The spatial board and its content scale proportionally at every zoom, without
52
+ switching layouts. Iframe previews mount automatically near the viewport and
53
+ remain mounted to preserve arbitrary app state. There is no lifetime preview cap;
54
+ memory use grows with the viewers visited. Board links and Mermaid render inline.
55
+
51
56
  Full node reads expose server-owned `createdBy`, `lastEditedBy`, and
52
57
  `contentRevision`. Authors distinguish human, agent, system, and unknown;
53
58
  legacy nodes remain unknown. The revision advances on semantic content changes,
@@ -73,6 +78,15 @@ that fits the work — each step adds capability and bundle weight.
73
78
 
74
79
  ## Markdown tasks
75
80
 
81
+ Use **Display as heading** in a Markdown card's context menu for a frameless section
82
+ label. Its title becomes the heading and its content remains below it. **Display as card**
83
+ restores the frame; this does not change the content or context pins. Agents can set
84
+ `data.display` to `"heading"` or `"card"` through ordinary node creation or updates.
85
+ **Set as README** in the card's ⋯ menu designates the board's existing README field;
86
+ the current README instead offers **Remove as README** to clear it. A quiet **README**
87
+ word stays visible in the designated card's header, including heading display.
88
+ **Edit** stays visible below ordinary Markdown. Heading display has no footer.
89
+
76
90
  Tick a task directly on its card, including quoted and nested tasks. A card click changes
77
91
  only that task's `[ ]` or `[x]` marker, preserving the rest of the source exactly.
78
92
  Task-shaped text in code examples and raw HTML checkboxes are not Markdown task controls.
@@ -119,6 +133,9 @@ different type by extension:
119
133
 
120
134
  ## Mermaid nodes
121
135
 
136
+ Diagrams render inline with the canvas palette, rather than in an iframe. Invalid
137
+ source shows a visible error and **Retry**. Native WebKit hosts remain best-effort.
138
+
122
139
  Mermaid diagrams default to `data.fit: "contain"`: when the diagram overflows
123
140
  the available body, it shrinks uniformly until the entire diagram fits. Small
124
141
  diagrams stay at 100%; aspect ratio, labels, and edges are preserved, in both
@@ -216,6 +233,12 @@ with the server's transport, tool name, and arguments.
216
233
 
217
234
  ## json-render nodes
218
235
 
236
+ Embedded dashboards and charts inherit all nine named canvas themes. Their root
237
+ card fills the viewer without an extra panel or shadow. A root title identical to
238
+ the canvas card title is hidden; distinct authored titles and descriptions remain.
239
+ Theme changes preserve viewer-local inputs. A failed replacement keeps the last
240
+ painted document and offers **Retry** instead of repeatedly reloading it.
241
+
219
242
  `json-render` nodes turn structured JSON specs into rendered UI panels
220
243
  (dashboards, tables, forms, cards) without writing HTML. PMX Canvas ships the
221
244
  [`@json-render/*`](https://www.npmjs.com/package/@json-render/core) 0.21.0 runtime
@@ -372,6 +395,10 @@ Fitting waits for local or remote human grabs to end. A growing ungrouped,
372
395
  screen-unpinned card moves downward if needed to leave a 24px gap from neighboring
373
396
  cards, without moving those neighbors. A relocation records one undo step for
374
397
  both size and position; height-only adjustments do not add undo entries.
398
+ Repeated measurements from the same document do not reverse Undo or a smaller
399
+ height set by another writer. Changed content dimensions, width or chrome can
400
+ fit again. Replacing or reopening the viewer starts a fresh measurement, so this
401
+ suppression does not survive reload, collapse/reopen or a board switch.
375
402
  Grouped or screen-pinned cards retain their positions. Collapsed cards and cards
376
403
  marked `strictSize` or `userResized` are not automatically resized. Hosted MCP
377
404
  apps and webpage viewers do not use this authored-content fitting behavior.
@@ -431,6 +458,14 @@ component gallery, interaction prototype, flowchart, SVG illustration set,
431
458
  presentation, explainer, status report, incident report, triage board, config
432
459
  editor, or prompt tuner.
433
460
 
461
+ The card's ⋯ menu offers **Copy JSON** for primitives with JSON export (all except
462
+ the custom `presentation` template). It copies the mounted document's current
463
+ state, including interactive edits, rather than the original server data.
464
+ Open the viewer first; unavailable/reloading content or denied clipboard access
465
+ shows a failure message. Copy prompt and the shared inner-header copy buttons are
466
+ removed. Primitive-specific actions such as Copy diff and Copy SVG remain.
467
+ Ordinary HTML nodes do not receive this menu item.
468
+
434
469
  Omitted fields may use the template's examples. Explicit empty arrays, empty
435
470
  strings, or `null` mean “show nothing”: the field's section, heading, and
436
471
  dependent controls are omitted rather than replaced with sample content.