pmx-canvas 0.8.2 → 0.9.1

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 (338) hide show
  1. package/.github/extensions/pmx-canvas/runtime.json +1 -1
  2. package/.github/extensions/pmx-canvas/tools.json +601 -22
  3. package/CHANGELOG.md +59 -0
  4. package/Readme.md +131 -532
  5. package/dist/canvas/global.css +2724 -476
  6. package/dist/canvas/index.js +168 -107
  7. package/dist/canvas/mcp-app.html +2899 -596
  8. package/dist/json-render/index.js +20 -20
  9. package/dist/types/client/canvas/BarHint.d.ts +12 -2
  10. package/dist/types/client/canvas/BoardLinkDialog.d.ts +3 -1
  11. package/dist/types/client/canvas/BoardPinButton.d.ts +10 -0
  12. package/dist/types/client/canvas/BoardSwitcher.d.ts +1 -1
  13. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  14. package/dist/types/client/canvas/CommandBar.d.ts +3 -4
  15. package/dist/types/client/canvas/ConnectionBanner.d.ts +2 -1
  16. package/dist/types/client/canvas/ContextChip.d.ts +3 -0
  17. package/dist/types/client/canvas/CrossBoardReferences.d.ts +5 -0
  18. package/dist/types/client/canvas/EdgeLayer.d.ts +14 -3
  19. package/dist/types/client/canvas/EmptyState.d.ts +4 -4
  20. package/dist/types/client/canvas/HomeGraphView.d.ts +2 -0
  21. package/dist/types/client/canvas/HomeMapView.d.ts +1 -0
  22. package/dist/types/client/canvas/HomeReviewView.d.ts +6 -0
  23. package/dist/types/client/canvas/HomeView.d.ts +9 -7
  24. package/dist/types/client/canvas/KnowledgeDialog.d.ts +4 -0
  25. package/dist/types/client/canvas/LifecycleChrome.d.ts +5 -0
  26. package/dist/types/client/canvas/LifecycleFields.d.ts +7 -0
  27. package/dist/types/client/canvas/LifecyclePanel.d.ts +1 -0
  28. package/dist/types/client/canvas/MemoryInspector.d.ts +7 -0
  29. package/dist/types/client/canvas/NearPinLayer.d.ts +14 -0
  30. package/dist/types/client/canvas/NodeContextMark.d.ts +40 -7
  31. package/dist/types/client/canvas/RelationPresetsDialog.d.ts +4 -0
  32. package/dist/types/client/canvas/RelationsPanel.d.ts +4 -0
  33. package/dist/types/client/canvas/SessionPanel.d.ts +2 -0
  34. package/dist/types/client/canvas/canvas-area.d.ts +1 -1
  35. package/dist/types/client/canvas/graph-geometry.d.ts +27 -0
  36. package/dist/types/client/canvas/graph-model.d.ts +37 -0
  37. package/dist/types/client/canvas/memory-layout.d.ts +23 -0
  38. package/dist/types/client/canvas/use-chrome-height.d.ts +2 -0
  39. package/dist/types/client/canvas/use-focus-trap.d.ts +1 -0
  40. package/dist/types/client/canvas/use-memory-graph.d.ts +8 -0
  41. package/dist/types/client/canvas/use-pan-zoom.d.ts +4 -1
  42. package/dist/types/client/icons.d.ts +0 -10
  43. package/dist/types/client/nodes/AxStepControls.d.ts +1 -1
  44. package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +4 -4
  45. package/dist/types/client/nodes/MarkdownNode.d.ts +5 -1
  46. package/dist/types/client/nodes/McpAppNode.d.ts +4 -4
  47. package/dist/types/client/nodes/viewer-runtime-state.d.ts +1 -1
  48. package/dist/types/client/state/boards-store.d.ts +81 -9
  49. package/dist/types/client/state/canvas-store.d.ts +14 -1
  50. package/dist/types/client/state/context-chip-store.d.ts +22 -0
  51. package/dist/types/client/state/context-status-store.d.ts +35 -0
  52. package/dist/types/client/state/human-store.d.ts +2 -1
  53. package/dist/types/client/state/intent-bridge.d.ts +11 -8
  54. package/dist/types/client/state/knowledge-store.d.ts +22 -0
  55. package/dist/types/client/state/near-pin-store.d.ts +44 -1
  56. package/dist/types/client/state/presence-store.d.ts +4 -4
  57. package/dist/types/client/state/presentation.d.ts +28 -0
  58. package/dist/types/client/state/relation-store.d.ts +10 -0
  59. package/dist/types/client/state/session-store.d.ts +41 -2
  60. package/dist/types/client/state/workspace-settings.d.ts +7 -0
  61. package/dist/types/client/types.d.ts +13 -1
  62. package/dist/types/client/utils/keyboard.d.ts +2 -0
  63. package/dist/types/client/utils/time-ago.d.ts +4 -0
  64. package/dist/types/mcp/context-uri-template.d.ts +3 -1
  65. package/dist/types/server/agent-presence.d.ts +10 -3
  66. package/dist/types/server/ax-context.d.ts +1 -1
  67. package/dist/types/server/canvas-db.d.ts +30 -7
  68. package/dist/types/server/canvas-operations.d.ts +24 -2
  69. package/dist/types/server/canvas-provenance.d.ts +22 -2
  70. package/dist/types/server/canvas-serialization.d.ts +2 -0
  71. package/dist/types/server/canvas-state.d.ts +93 -15
  72. package/dist/types/server/canvas-validation.d.ts +1 -1
  73. package/dist/types/server/context-brief.d.ts +94 -6
  74. package/dist/types/server/context-reads.d.ts +33 -7
  75. package/dist/types/server/edit-summary.d.ts +20 -0
  76. package/dist/types/server/index.d.ts +71 -10
  77. package/dist/types/server/knowledge-lifecycle.d.ts +221 -0
  78. package/dist/types/server/lifecycle-status.d.ts +10 -0
  79. package/dist/types/server/memory-graph.d.ts +9 -0
  80. package/dist/types/server/mutation-history.d.ts +2 -0
  81. package/dist/types/server/operations/ops/ax-shared.d.ts +1 -1
  82. package/dist/types/server/operations/ops/boards.d.ts +2 -1
  83. package/dist/types/server/operations/ops/lifecycle.d.ts +2 -0
  84. package/dist/types/server/operations/ops/memory-graph.d.ts +2 -0
  85. package/dist/types/server/operations/ops/nodes.d.ts +5 -0
  86. package/dist/types/server/operations/ops/query.d.ts +23 -0
  87. package/dist/types/server/operations/registry.d.ts +1 -0
  88. package/dist/types/server/placement.d.ts +7 -0
  89. package/dist/types/server/scope-fence.d.ts +2 -1
  90. package/dist/types/server/spatial-analysis.d.ts +6 -3
  91. package/dist/types/server/tour-control.d.ts +32 -0
  92. package/dist/types/server/wiki-links.d.ts +14 -0
  93. package/dist/types/server/workbench-auth.d.ts +2 -0
  94. package/dist/types/shared/agent-context.d.ts +2 -0
  95. package/dist/types/shared/agent-presence.d.ts +15 -12
  96. package/dist/types/shared/auto-arrange.d.ts +1 -0
  97. package/dist/types/shared/boards.d.ts +4 -4
  98. package/dist/types/shared/knowledge-lifecycle.d.ts +41 -0
  99. package/dist/types/shared/knowledge-presets.d.ts +6 -0
  100. package/dist/types/shared/lifecycle-status.d.ts +24 -0
  101. package/dist/types/shared/memory-graph.d.ts +53 -0
  102. package/dist/types/shared/relations.d.ts +68 -0
  103. package/dist/types/shared/semantic-attention.d.ts +2 -0
  104. package/dist/types/shared/tour.d.ts +38 -0
  105. package/dist/types/shared/workspace-settings.d.ts +11 -0
  106. package/docs/RELEASE.md +21 -3
  107. package/docs/adr-001-bun-only-runtime.md +7 -1
  108. package/docs/adr-002-shared-product-separate-runtimes.md +93 -0
  109. package/docs/api-reference.md +109 -0
  110. package/docs/ax-host-adapter-contract.md +1 -1
  111. package/docs/ax-state-contract.md +5 -4
  112. package/docs/cli.md +153 -15
  113. package/docs/demos/pmx-canvas-demo.mp4 +0 -0
  114. package/docs/design/AgentContext.dc.html +3 -3
  115. package/docs/design/BoardPins.dc.html +37 -22
  116. package/docs/design/Categories.dc.html +208 -0
  117. package/docs/design/CategoryEditor.dc.html +33 -0
  118. package/docs/design/Chrome.dc.html +52 -9
  119. package/docs/design/ContextChip.dc.html +224 -0
  120. package/docs/design/ContextChip600.dc.html +136 -0
  121. package/docs/design/EmptyState.dc.html +45 -0
  122. package/docs/design/Flows.dc.html +23 -1
  123. package/docs/design/HeaderMarks.dc.html +183 -0
  124. package/docs/design/Home.dc.html +19 -1
  125. package/docs/design/HomeGraph.dc.html +86 -202
  126. package/docs/design/HomeMap.dc.html +23 -1
  127. package/docs/design/HomeTeam.dc.html +32 -14
  128. package/docs/design/Lifecycle.dc.html +22 -0
  129. package/docs/design/Lifecycle600.dc.html +18 -0
  130. package/docs/design/LifecycleVariants.dc.html +157 -0
  131. package/docs/design/LinkAuthorship.dc.html +139 -0
  132. package/docs/design/LinksChanged.dc.html +203 -0
  133. package/docs/design/LinksOptions.dc.html +137 -0
  134. package/docs/design/LinksOptions600.dc.html +134 -0
  135. package/docs/design/NearPin.dc.html +9 -10
  136. package/docs/design/Pane600.dc.html +4 -3
  137. package/docs/design/Relations.dc.html +3 -2
  138. package/docs/design/Restore.dc.html +152 -0
  139. package/docs/design/SeeChange.dc.html +267 -0
  140. package/docs/design/Uses.dc.html +12 -6
  141. package/docs/design/canvas.json +146 -19
  142. package/docs/design.md +449 -16
  143. package/docs/environment.md +0 -1
  144. package/docs/evals/curation-effect.md +128 -0
  145. package/docs/http-api.md +459 -37
  146. package/docs/mcp.md +146 -18
  147. package/docs/node-types.md +58 -3
  148. package/docs/plans/design-gaps-2026-10-08.md +53 -0
  149. package/docs/plans/plan-009-tech-debt-backlog.md +379 -0
  150. package/docs/plans/plan-016-context-made-visible-wave-1.md +150 -5
  151. package/docs/plans/plan-017-knowledge-categories-and-lifecycle.md +175 -0
  152. package/docs/plans/plan-018-connected-memory-wave-2.md +594 -0
  153. package/docs/plans/plan-019-post-0.9-roadmap.md +198 -0
  154. package/docs/product-context-vision-2026-09.md +17 -1
  155. package/docs/product-vision-2026-09.md +1082 -43
  156. package/docs/product-vision-review-2026-09.md +13 -1
  157. package/docs/screenshots/workbench-live-dark.png +0 -0
  158. package/docs/screenshots/workbench-live-light.png +0 -0
  159. package/docs/sdk.md +62 -2
  160. package/package.json +1 -1
  161. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
  162. package/plugins/pmx-canvas/plugin.json +1 -1
  163. package/plugins/pmx-canvas/runtime.json +1 -1
  164. package/plugins/pmx-canvas/tools.json +601 -22
  165. package/skills/pmx-canvas/SKILL.md +216 -42
  166. package/skills/pmx-canvas/evals/evals.json +224 -0
  167. package/skills/pmx-canvas/references/full-reference.md +120 -21
  168. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
  169. package/skills/pmx-canvas/references/importing-context.md +132 -0
  170. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  171. package/skills/pmx-canvas/references/tours-and-recording.md +16 -1
  172. package/skills/pmx-canvas-testing/SKILL.md +20 -0
  173. package/src/cli/agent.ts +2 -0
  174. package/src/cli/commands/ax.ts +12 -0
  175. package/src/cli/commands/boards.ts +88 -11
  176. package/src/cli/commands/edges.ts +28 -0
  177. package/src/cli/commands/groups.ts +7 -0
  178. package/src/cli/commands/nodes.ts +1 -0
  179. package/src/cli/commands/query.ts +34 -2
  180. package/src/cli/commands/record.ts +199 -48
  181. package/src/cli/index.ts +6 -1
  182. package/src/client/App.tsx +177 -70
  183. package/src/client/canvas/AttentionHistory.tsx +0 -2
  184. package/src/client/canvas/BarHint.tsx +40 -2
  185. package/src/client/canvas/BoardCopyDialog.tsx +1 -1
  186. package/src/client/canvas/BoardFolderDialog.tsx +7 -7
  187. package/src/client/canvas/BoardLinkDialog.tsx +138 -33
  188. package/src/client/canvas/BoardPinButton.tsx +33 -0
  189. package/src/client/canvas/BoardSwitcher.tsx +26 -40
  190. package/src/client/canvas/CanvasNode.tsx +360 -237
  191. package/src/client/canvas/CanvasViewport.tsx +45 -7
  192. package/src/client/canvas/CommandBar.tsx +29 -23
  193. package/src/client/canvas/CommandPalette.tsx +5 -12
  194. package/src/client/canvas/ConnectionBanner.tsx +3 -3
  195. package/src/client/canvas/ContextChip.tsx +296 -0
  196. package/src/client/canvas/ContextMenu.tsx +63 -5
  197. package/src/client/canvas/CrossBoardReferences.tsx +60 -0
  198. package/src/client/canvas/EdgeLayer.tsx +339 -76
  199. package/src/client/canvas/EmptyState.tsx +33 -18
  200. package/src/client/canvas/ExpandedNodeOverlay.tsx +72 -40
  201. package/src/client/canvas/ExternalWriters.tsx +57 -42
  202. package/src/client/canvas/HomeGraphView.tsx +942 -0
  203. package/src/client/canvas/HomeMapView.tsx +641 -0
  204. package/src/client/canvas/HomeReviewView.tsx +167 -0
  205. package/src/client/canvas/HomeView.tsx +687 -160
  206. package/src/client/canvas/IntentLayer.tsx +19 -12
  207. package/src/client/canvas/KnowledgeDialog.tsx +488 -0
  208. package/src/client/canvas/LifecycleChrome.tsx +133 -0
  209. package/src/client/canvas/LifecycleFields.tsx +91 -0
  210. package/src/client/canvas/LifecyclePanel.tsx +543 -0
  211. package/src/client/canvas/MemoryInspector.tsx +104 -0
  212. package/src/client/canvas/Minimap.tsx +3 -3
  213. package/src/client/canvas/NearPinLayer.tsx +187 -0
  214. package/src/client/canvas/NodeContextMark.tsx +175 -97
  215. package/src/client/canvas/Presentation.tsx +23 -57
  216. package/src/client/canvas/RelationPresetsDialog.tsx +413 -0
  217. package/src/client/canvas/RelationsPanel.tsx +82 -0
  218. package/src/client/canvas/SelectionBar.tsx +3 -6
  219. package/src/client/canvas/SessionPanel.tsx +90 -50
  220. package/src/client/canvas/SessionReceipt.tsx +311 -39
  221. package/src/client/canvas/ShortcutOverlay.tsx +1 -1
  222. package/src/client/canvas/SnapshotPanel.tsx +27 -36
  223. package/src/client/canvas/ToolRail.tsx +367 -192
  224. package/src/client/canvas/TopBar.tsx +354 -124
  225. package/src/client/canvas/canvas-area.ts +10 -3
  226. package/src/client/canvas/graph-geometry.ts +195 -0
  227. package/src/client/canvas/graph-model.ts +254 -0
  228. package/src/client/canvas/memory-layout.ts +106 -0
  229. package/src/client/canvas/use-chrome-height.ts +20 -0
  230. package/src/client/canvas/use-focus-trap.ts +31 -5
  231. package/src/client/canvas/use-memory-graph.ts +58 -0
  232. package/src/client/canvas/use-node-drag.ts +2 -1
  233. package/src/client/canvas/use-pan-zoom.ts +64 -7
  234. package/src/client/icons.tsx +0 -63
  235. package/src/client/mcp-app/style.css +0 -6
  236. package/src/client/nodes/AxStepControls.tsx +74 -50
  237. package/src/client/nodes/BoardNode.tsx +5 -1
  238. package/src/client/nodes/ContextNode.tsx +18 -11
  239. package/src/client/nodes/ExtAppFrame.tsx +6 -3
  240. package/src/client/nodes/FileNode.tsx +46 -42
  241. package/src/client/nodes/HtmlNode.tsx +32 -0
  242. package/src/client/nodes/ImageNode.tsx +1 -1
  243. package/src/client/nodes/InlineFormatBar.tsx +6 -9
  244. package/src/client/nodes/InlineMarkdownEditor.tsx +56 -17
  245. package/src/client/nodes/MarkdownNode.tsx +377 -109
  246. package/src/client/nodes/McpAppNode.tsx +50 -20
  247. package/src/client/nodes/MdFormatBar.tsx +21 -18
  248. package/src/client/nodes/PromptNode.tsx +1 -1
  249. package/src/client/nodes/ResponseNode.tsx +1 -1
  250. package/src/client/nodes/viewer-runtime-state.ts +54 -22
  251. package/src/client/state/attention-bridge.ts +64 -15
  252. package/src/client/state/boards-store.ts +193 -39
  253. package/src/client/state/canvas-store.ts +99 -12
  254. package/src/client/state/context-chip-store.ts +70 -0
  255. package/src/client/state/context-status-store.ts +53 -0
  256. package/src/client/state/human-store.ts +13 -7
  257. package/src/client/state/intent-bridge.ts +51 -30
  258. package/src/client/state/knowledge-store.ts +43 -0
  259. package/src/client/state/near-pin-store.ts +115 -6
  260. package/src/client/state/presence-store.ts +7 -10
  261. package/src/client/state/presentation.ts +91 -0
  262. package/src/client/state/relation-store.ts +81 -0
  263. package/src/client/state/session-store.ts +144 -18
  264. package/src/client/state/sse-bridge.ts +235 -32
  265. package/src/client/state/workspace-settings.ts +11 -0
  266. package/src/client/theme/global.css +2724 -476
  267. package/src/client/types.ts +12 -0
  268. package/src/client/utils/keyboard.ts +10 -0
  269. package/src/client/utils/time-ago.ts +14 -0
  270. package/src/json-render/renderer/index.tsx +31 -0
  271. package/src/mcp/canvas-app.ts +12 -2
  272. package/src/mcp/context-uri-template.ts +7 -4
  273. package/src/mcp/server.ts +63 -41
  274. package/src/mcp/workbench-app.ts +39 -6
  275. package/src/server/agent-presence.ts +128 -28
  276. package/src/server/ax-context.ts +27 -13
  277. package/src/server/board-export.ts +12 -1
  278. package/src/server/canvas-db.ts +331 -42
  279. package/src/server/canvas-operations.ts +195 -83
  280. package/src/server/canvas-provenance.ts +53 -22
  281. package/src/server/canvas-serialization.ts +2 -0
  282. package/src/server/canvas-state.ts +950 -122
  283. package/src/server/canvas-validation.ts +9 -2
  284. package/src/server/context-brief.ts +345 -38
  285. package/src/server/context-reads.ts +178 -30
  286. package/src/server/demo-state.json +355 -24
  287. package/src/server/edit-summary.ts +74 -0
  288. package/src/server/html-surface.ts +8 -1
  289. package/src/server/index.ts +181 -11
  290. package/src/server/knowledge-lifecycle.ts +304 -0
  291. package/src/server/lifecycle-status.ts +232 -0
  292. package/src/server/memory-graph.ts +166 -0
  293. package/src/server/mutation-history.ts +18 -6
  294. package/src/server/operations/composites.ts +32 -11
  295. package/src/server/operations/http.ts +7 -2
  296. package/src/server/operations/index.ts +4 -0
  297. package/src/server/operations/mcp.ts +26 -1
  298. package/src/server/operations/ops/ax-presence.ts +1 -1
  299. package/src/server/operations/ops/ax-read.ts +57 -6
  300. package/src/server/operations/ops/ax-timeline.ts +28 -2
  301. package/src/server/operations/ops/backup.ts +5 -3
  302. package/src/server/operations/ops/batch.ts +35 -4
  303. package/src/server/operations/ops/boards.ts +188 -47
  304. package/src/server/operations/ops/canvas-wire.ts +31 -1
  305. package/src/server/operations/ops/edges.ts +36 -2
  306. package/src/server/operations/ops/groups.ts +6 -1
  307. package/src/server/operations/ops/lifecycle.ts +262 -0
  308. package/src/server/operations/ops/memory-graph.ts +45 -0
  309. package/src/server/operations/ops/nodes.ts +107 -24
  310. package/src/server/operations/ops/query.ts +281 -68
  311. package/src/server/operations/ops/snapshots.ts +73 -1
  312. package/src/server/operations/ops/validate.ts +5 -1
  313. package/src/server/operations/ops/viewport.ts +97 -3
  314. package/src/server/operations/registry.ts +74 -25
  315. package/src/server/placement.ts +29 -0
  316. package/src/server/scope-fence.ts +78 -6
  317. package/src/server/server.ts +115 -16
  318. package/src/server/spatial-analysis.ts +48 -23
  319. package/src/server/tour-control.ts +82 -0
  320. package/src/server/wiki-links.ts +137 -0
  321. package/src/server/workbench-auth.ts +11 -0
  322. package/src/shared/agent-context.ts +3 -0
  323. package/src/shared/agent-presence.ts +15 -15
  324. package/src/shared/auto-arrange.ts +2 -0
  325. package/src/shared/boards.ts +4 -4
  326. package/src/shared/knowledge-lifecycle.ts +22 -0
  327. package/src/shared/knowledge-presets.ts +80 -0
  328. package/src/shared/lifecycle-status.ts +26 -0
  329. package/src/shared/memory-graph.ts +74 -0
  330. package/src/shared/relations.ts +98 -0
  331. package/src/shared/semantic-attention.ts +15 -1
  332. package/src/shared/tour.ts +23 -5
  333. package/src/shared/workspace-settings.ts +13 -0
  334. package/dist/types/client/canvas/ContextPinBar.d.ts +0 -1
  335. package/dist/types/client/canvas/FocusFieldLayer.d.ts +0 -1
  336. package/dist/types/client/canvas/kind-colors.d.ts +0 -3
  337. package/dist/types/server/agent-context.d.ts +0 -22
  338. package/src/client/canvas/ContextPinBar.tsx +0 -25
@@ -4,7 +4,7 @@ Use this reference when the `pmx-canvas` skill is installed but the `pmx-canvas`
4
4
 
5
5
  ## Prerequisites and version
6
6
 
7
- The examples pin **PMX Canvas 0.8.2**, which requires **Bun >=1.4.2** even when
7
+ The examples pin **PMX Canvas 0.9.1**, which requires **Bun >=1.4.2** even when
8
8
  installed through npm: the CLI runs through Bun, not Node. Check `bun --version`
9
9
  first. If missing or older, follow the [Bun installation instructions](https://bun.sh/docs/installation)
10
10
  with the user's authorization. Ensure Bun is on the MCP host's PATH as well as the
@@ -17,11 +17,11 @@ in `SKILL.md`. Do not pair newer checkout guidance with an older runtime unknowi
17
17
  ## Install from npm
18
18
 
19
19
  ```bash
20
- npm install -g pmx-canvas@0.8.2
20
+ npm install -g pmx-canvas@0.9.1
21
21
  pmx-canvas --version
22
22
  ```
23
23
 
24
- Without a global install, use `bunx pmx-canvas@0.8.2` in place of `pmx-canvas` in
24
+ Without a global install, use `bunx pmx-canvas@0.9.1` in place of `pmx-canvas` in
25
25
  the commands below. Do not use unpinned `bunx pmx-canvas` for a version-specific check.
26
26
 
27
27
  ## Choose the workspace and target
@@ -91,7 +91,7 @@ discards empty env values, remove `PMX_CANVAS_URL` from its launch environment i
91
91
  "mcpServers": {
92
92
  "canvas": {
93
93
  "command": "bunx",
94
- "args": ["pmx-canvas@0.8.2", "--mcp"],
94
+ "args": ["pmx-canvas@0.9.1", "--mcp"],
95
95
  "env": {
96
96
  "PMX_CANVAS_WORKSPACE_ROOT": "/absolute/path/to/project",
97
97
  "PMX_CANVAS_PORT": "14313",
@@ -135,7 +135,7 @@ Amp executes, not only on the user's laptop. Merge this into that workspace's
135
135
  "amp.mcpServers": {
136
136
  "canvas": {
137
137
  "command": "bunx",
138
- "args": ["pmx-canvas@0.8.2", "--mcp"],
138
+ "args": ["pmx-canvas@0.9.1", "--mcp"],
139
139
  "includeTools": ["canvas_*"],
140
140
  "env": {
141
141
  "PMX_CANVAS_WORKSPACE_ROOT": "/absolute/path/to/project",
@@ -169,7 +169,7 @@ The agent must not run this approval itself or move the command to global settin
169
169
  `--mcp-config` to bypass workspace trust. Approval authorizes execution of this MCP
170
170
  command; it is not a new Canvas import consent or permission to mutate arbitrary boards.
171
171
  After approval, reload MCP connections (`reload_mcp` in Amp) and require `connected`.
172
- Discover `canvas` tools with `tool_search`; for the full unfiltered 0.8.2 server there
172
+ Discover `canvas` tools with `tool_search`; for the full unfiltered 0.9.1 server there
173
173
  are 24 tools. If still absent, inspect the server status, command/PATH and target instead
174
174
  of reinstalling blindly. See [Amp MCP documentation](https://ampcode.com/docs/customize/mcp).
175
175
 
@@ -19,10 +19,11 @@ Persist a tour with `canvas_view { action: "set-tour", tour: { stops: [...] } }`
19
19
  ```
20
20
 
21
21
  - `nodeId` may identify a card or group. Its persisted position and size determine the camera.
22
+ - `rect` is a world-space box `{ x, y, width, height }` (top-left corner plus size).
22
23
  - An explicit viewport is `{ x, y, scale }`, with positive `scale`. Translation is screen-space:
23
24
  `screen = world * scale + offset`.
24
25
  - `duration` is transition time in seconds (default 1; zero jumps). Valid values are 0–3600.
25
- - `padding` is screen pixels around a node target (default 40).
26
+ - `padding` is screen pixels around a node or rect target (default 40).
26
27
  - `easing` is `linear`, `ease-in-out` (default), or `ease-out`.
27
28
  - `pullback` is 0–4 (default 0). It zooms out during the move without changing either endpoint.
28
29
  - A tour contains at most 1000 stops.
@@ -39,6 +40,20 @@ ID. A saved `{ "stops": [] }` intentionally has no stops; it does not enable gro
39
40
  Preserve the tour of each board when working across boards and target the intended board before
40
41
  setting or reading it.
41
42
 
43
+ ## Drive a tour
44
+
45
+ The server holds one in-memory tour cursor, tied to the board it was started on (a tour on another board replaces it). `canvas_view { action: "tour-go", stop: 0 }`
46
+ starts presenting in open workbenches; `step: "next" | "previous"` moves relative to wherever the
47
+ audience is (a human's arrow keys move the same cursor) and clamps at the ends. Pass
48
+ `present: false` to move only viewers already presenting. `canvas_view { action: "tour-exit" }`
49
+ leaves presentation everywhere. `get-tour` reports `position` (the current stop, or null).
50
+
51
+ `canvas_view { action: "move", nodeId | rect | viewport, duration, easing, padding, pullback }`
52
+ eases the camera without a tour. Outside a presentation the end camera becomes the board
53
+ viewport. Tour steps and moves never enter undo history, never count as agent writes, and are
54
+ allowed under a scope fence. Viewers with reduced motion jump instead of animating; a
55
+ deterministic capture ignores both.
56
+
42
57
  ## Capture prerequisites and behavior
43
58
 
44
59
  Start and verify the matching PMX daemon first: its `/health` workspace and version must match the
@@ -53,6 +53,10 @@ and check `$?`, then read the file.
53
53
  - Test-only changes: run `bun run test` and `bun run test:coverage` if coverage matters
54
54
  - Client/UI/browser interaction changes: run `bun run test:web-canvas`
55
55
  - Cross-stack or non-trivial changes: run `bun run test:all`
56
+ - Bundled skill/documentation-only changes: run
57
+ `bun test tests/unit/bundled-skills.test.ts tests/unit/no-native-tooltips.test.ts`
58
+ and `git diff --check`; inspect public-contract prose against source. No client rebuild or
59
+ full browser suite is needed when executable behavior has not changed.
56
60
  - Before changing browser-visible behavior under `src/client/`: rebuild with `bun run build`
57
61
  Manual browser validation also requires a fresh client bundle. `bun run test:web-canvas`
58
62
  already does this for you.
@@ -146,6 +150,13 @@ Four ways a test silently stops discriminating in this repo:
146
150
  between those assertions. Separately verify a real spec revision resets to authored state,
147
151
  and that local drafts never entered the server spec. See `tests/e2e/json-render-forms.pw.ts`.
148
152
  Eval definitions are not evidence of executing this browser regression or a model benchmark.
153
+ - For viewer refreshes, run `tests/e2e/viewer-refresh-frames.pw.ts`: it delays the runtime-state
154
+ restore beyond document load and checks every captured frame for blank/white flashes in
155
+ Harbor with light/dark OS settings and Daylight with dark OS settings. Keep the frame assertions;
156
+ a settled DOM check cannot prove the handoff stayed painted. Reset canvas-bound work as well as
157
+ nodes between cases. The inert replacement renders behind the active iframe, so select the
158
+ foreground with `iframe:not([inert])`, not `iframe:visible`. Keep capturing until the last
159
+ update is actually in the foreground; a momentary one-iframe count may precede the next poll.
149
160
  - When checking embedded frame fit manually, start from a clean seeded state, rebuild stale bundles,
150
161
  and inspect the actual iframe document in a browser. Server dimensions can look correct while the
151
162
  embedded content is still clipped.
@@ -158,6 +169,15 @@ Four ways a test silently stops discriminating in this repo:
158
169
  - User-facing creation flows must end with the new nodes visible: after the create (plus the
159
170
  skill-mandated focus/fit), a screenshot must show them without any manual pan. A `panned: true`
160
171
  API result alone is not proof — verify the frame is on-screen and unobscured.
172
+ - Layout validation proves node non-overlap, not relation readability. After content settles,
173
+ inspect edge lines, labels, arrowheads and authorship marks at the intended viewing zoom,
174
+ including after auto-arrange; do not prescribe one universal gap.
175
+ - Context/receipt checks must distinguish map delivery (seen links and board read status) from
176
+ full card-content reads. Check one-open stacked See change, clipped-excerpt captions and
177
+ whole-card Undo with a latest-human-edit negative control. Retain a receipt across a board
178
+ switch: snapshot comparison must reopen its owning board, Undo/Unpin must not affect the
179
+ foreign board, and lens marks must use only active-board touches. Check the narrow agent
180
+ initial's counts/lens/panel interaction separately. Use disposable boards for these checks.
161
181
 
162
182
  ## Failure Handling
163
183
 
package/src/cli/agent.ts CHANGED
@@ -52,6 +52,8 @@ Usage:
52
52
 
53
53
  Presentation and capture:
54
54
  pmx-canvas tour get|set Read or persist ordered camera stops
55
+ pmx-canvas tour go <n|next|previous> Present a stop; tour exit leaves presentation
56
+ pmx-canvas camera move --node <id> Ease the camera to a node, --rect or --viewport
55
57
  pmx-canvas record --help Optionally capture the same board tour or live presentation
56
58
 
57
59
  Server:
@@ -397,6 +397,18 @@ cmd(
397
397
  },
398
398
  );
399
399
 
400
+ cmd(
401
+ 'ax reads status',
402
+ 'Read status for a board: its last agent read, per-node reads and revisions, and pin metadata',
403
+ ['pmx-canvas ax reads status', 'pmx-canvas ax reads status --board <board-id>'],
404
+ async (args) => {
405
+ const { flags } = parseFlags(args);
406
+ if (flags.help || flags.h) return showCommandHelp('ax reads status');
407
+
408
+ output(await invokeOperation('ax.reads.status', typeof flags.board === 'string' ? { board: flags.board } : {}));
409
+ },
410
+ );
411
+
400
412
  cmd(
401
413
  'ax work add',
402
414
  'Add a canvas-bound AX work item',
@@ -2,6 +2,55 @@
2
2
 
3
3
  import { cmd, die, getStringFlag, invokeOperation, output, parseFlags, showCommandHelp } from '../shared.js';
4
4
 
5
+ cmd(
6
+ 'board vocabulary',
7
+ 'Set a board relation vocabulary from JSON',
8
+ ['pmx-canvas board vocabulary <id> \'[{"kind":"supports","ink":"supports","directed":true}]\''],
9
+ async (args) => {
10
+ const [id, json] = args;
11
+ if (!id || !json) die('Expected board id and vocabulary JSON.');
12
+ output(await invokeOperation('board.update', { id, relationVocabulary: JSON.parse(json) }));
13
+ },
14
+ );
15
+
16
+ cmd(
17
+ 'board knowledge',
18
+ 'Workspace knowledge actions with a JSON payload',
19
+ [
20
+ 'pmx-canvas board knowledge list',
21
+ 'pmx-canvas board knowledge category-remove \'{"id":"unused-category"}\'',
22
+ 'pmx-canvas board knowledge folder-set \'{"path":"A","categoryId":null,"lifecycleOverride":null}\'',
23
+ ],
24
+ async (args) => {
25
+ const [action, payload = '{}'] = args;
26
+ if (
27
+ ![
28
+ 'list',
29
+ 'category-set',
30
+ 'category-remove',
31
+ 'folder-set',
32
+ 'relation-preset-set',
33
+ 'relation-preset-remove',
34
+ ].includes(action ?? '')
35
+ )
36
+ die('Expected list, category-set, category-remove, folder-set, relation-preset-set or relation-preset-remove.');
37
+ output(await invokeOperation(`knowledge.${action}`, JSON.parse(payload)));
38
+ },
39
+ );
40
+
41
+ cmd(
42
+ 'board lifecycle',
43
+ 'Card lifecycle and audited reviews with a JSON payload',
44
+ ['pmx-canvas board lifecycle get \'{"id":"card"}\''],
45
+ async (args) => {
46
+ const [action, payload = '{}'] = args;
47
+ if (!['get', 'set', 'review', 'restore'].includes(action ?? '')) die('Expected get, set, review or restore.');
48
+ output(
49
+ await invokeOperation(action === 'review' ? 'node.review' : `node.lifecycle-${action}`, JSON.parse(payload)),
50
+ );
51
+ },
52
+ );
53
+
5
54
  cmd('board list', 'List boards, most recently opened first', ['pmx-canvas board list'], async (args) => {
6
55
  const { flags } = parseFlags(args);
7
56
  if (flags.help || flags.h) return showCommandHelp('board list');
@@ -49,14 +98,42 @@ cmd(
49
98
  cmd(
50
99
  'board create',
51
100
  'Create an empty board (use board open with its returned id before writing)',
52
- ['pmx-canvas board create "Q4 planning"', 'pmx-canvas board create "Q4 planning" --category Planning'],
101
+ ['pmx-canvas board create "Q4 planning"', 'pmx-canvas board create "Q4 planning" --folder Planning'],
53
102
  async (args) => {
54
103
  const { positional, flags } = parseFlags(args);
55
104
  if (flags.help || flags.h) return showCommandHelp('board create');
105
+ if ('category' in flags) die('The --category flag was removed.', 'Use --folder <folder> instead.');
56
106
  const name = positional.join(' ').trim();
57
- if (!name) die('Usage: pmx-canvas board create <name> [--category <category>]');
58
- const category = getStringFlag(flags, 'category');
59
- output(await invokeOperation('board.create', { name, ...(category ? { category } : {}) }));
107
+ if (!name) die('Usage: pmx-canvas board create <name> [--folder <folder>]');
108
+ const folder = getStringFlag(flags, 'folder');
109
+ output(await invokeOperation('board.create', { name, ...(folder ? { folder } : {}) }));
110
+ },
111
+ );
112
+
113
+ cmd(
114
+ 'board pin',
115
+ "Pin a board into the agent's working set (its README and pinned cards reach every brief)",
116
+ ['pmx-canvas board pin board-abc123', 'pmx-canvas board pin board-abc123 --reason "Q4 rests on it"'],
117
+ async (args) => {
118
+ const { positional, flags } = parseFlags(args);
119
+ if (flags.help || flags.h) return showCommandHelp('board pin');
120
+ const [id] = positional;
121
+ if (!id || positional.length > 1) die('Usage: pmx-canvas board pin <board-id> [--reason <why>]');
122
+ const reason = getStringFlag(flags, 'reason');
123
+ output(await invokeOperation('board.pin', { id, ...(reason ? { reason } : {}) }));
124
+ },
125
+ );
126
+
127
+ cmd(
128
+ 'board unpin',
129
+ "Remove a board from the agent's working set",
130
+ ['pmx-canvas board unpin board-abc123'],
131
+ async (args) => {
132
+ const { positional, flags } = parseFlags(args);
133
+ if (flags.help || flags.h) return showCommandHelp('board unpin');
134
+ const [id] = positional;
135
+ if (!id || positional.length > 1) die('Usage: pmx-canvas board unpin <board-id>');
136
+ output(await invokeOperation('board.unpin', { id }));
60
137
  },
61
138
  );
62
139
 
@@ -70,15 +147,15 @@ cmd('board rename', 'Rename a board', ['pmx-canvas board rename board-abc123 "Q4
70
147
  });
71
148
 
72
149
  cmd(
73
- 'board category',
74
- 'File a board under a category on Home (--clear removes it)',
75
- ['pmx-canvas board category board-abc123 "Planning"', 'pmx-canvas board category board-abc123 --clear'],
150
+ 'board folder',
151
+ 'File a board under a folder on Home (--clear removes it)',
152
+ ['pmx-canvas board folder board-abc123 "Planning"', 'pmx-canvas board folder board-abc123 --clear'],
76
153
  async (args) => {
77
154
  const { positional, flags } = parseFlags(args);
78
- if (flags.help || flags.h) return showCommandHelp('board category');
155
+ if (flags.help || flags.h) return showCommandHelp('board folder');
79
156
  const [id, ...rest] = positional;
80
- const category = flags.clear ? '' : rest.join(' ').trim();
81
- if (!id || (!category && !flags.clear)) die('Usage: pmx-canvas board category <board-id> <category> | --clear');
82
- output(await invokeOperation('board.update', { id, category }));
157
+ const folder = flags.clear ? '' : rest.join(' ').trim();
158
+ if (!id || (!folder && !flags.clear)) die('Usage: pmx-canvas board folder <board-id> <folder> | --clear');
159
+ output(await invokeOperation('board.update', { id, folder }));
83
160
  },
84
161
  );
@@ -39,18 +39,46 @@ cmd(
39
39
  type,
40
40
  ...(from ? { from } : {}),
41
41
  ...(to ? { to } : {}),
42
+ ...(typeof flags['to-board'] === 'string' ? { toBoardId: flags['to-board'] } : {}),
42
43
  ...(fromSearch ? { fromSearch } : {}),
43
44
  ...(toSearch ? { toSearch } : {}),
44
45
  };
45
46
  if (flags.label && flags.label !== true) body.label = flags.label;
47
+ if (typeof flags.kind === 'string') body.kind = flags.kind;
48
+ if (typeof flags.reason === 'string') body.reason = flags.reason;
46
49
  if (typeof flags.style === 'string') body.style = flags.style;
47
50
  if (flags.animated) body.animated = true;
51
+ for (const [flag, field] of [
52
+ ['destination-board', 'destinationBoardId'],
53
+ ['request-id', 'requestId'],
54
+ ['expected-board', 'expectedBoardId'],
55
+ ] as const) {
56
+ if (typeof flags[flag] === 'string') body[field] = flags[flag];
57
+ }
48
58
 
49
59
  const result = await invokeOperation('edge.add', body);
50
60
  output(result);
51
61
  },
52
62
  );
53
63
 
64
+ cmd(
65
+ 'edge update',
66
+ 'Edit a relation kind, reason, label or appearance',
67
+ ['pmx-canvas edge update <id> --kind supports --reason "Evidence from interviews"'],
68
+ async (args) => {
69
+ const { positional, flags } = parseFlags(args);
70
+ if (flags.help || flags.h) return showCommandHelp('edge update');
71
+ if (!positional[0]) die('Missing edge ID', 'pmx-canvas edge update <id> --kind supports');
72
+ const body: Record<string, unknown> = { id: positional[0] };
73
+ for (const key of ['kind', 'reason', 'label', 'type', 'style']) {
74
+ if (typeof flags[key] === 'string') body[key] = flags[key];
75
+ }
76
+ if (flags['clear-kind']) body.kind = null;
77
+ if (flags['clear-reason']) body.reason = null;
78
+ output(await invokeOperation('edge.update', body));
79
+ },
80
+ );
81
+
54
82
  // ── edge list ────────────────────────────────────────────────
55
83
  cmd('edge list', 'List all edges on the canvas', ['pmx-canvas edge list'], async (args) => {
56
84
  const { flags } = parseFlags(args);
@@ -38,6 +38,13 @@ cmd(
38
38
  if (height !== undefined) body.height = height;
39
39
  if (typeof flags['child-layout'] === 'string') body.childLayout = flags['child-layout'];
40
40
  if (positional.length > 0) body.childIds = positional;
41
+ for (const [flag, field] of [
42
+ ['destination-board', 'destinationBoardId'],
43
+ ['request-id', 'requestId'],
44
+ ['expected-board', 'expectedBoardId'],
45
+ ] as const) {
46
+ if (typeof flags[flag] === 'string') body[field] = flags[flag];
47
+ }
41
48
 
42
49
  const result = await invokeOperation('group.create', body);
43
50
  output(result);
@@ -133,6 +133,7 @@ function summarizeNodeResult(node: Record<string, unknown>): Record<string, unkn
133
133
  ...(node.path !== undefined ? { path: node.path } : {}),
134
134
  ...(node.url !== undefined ? { url: node.url } : {}),
135
135
  ...(node.provenance !== undefined ? { provenance: node.provenance } : {}),
136
+ ...(node.qualification !== undefined ? { qualification: node.qualification } : {}),
136
137
  ...(typeof data.mode === 'string' ? { mode: data.mode } : {}),
137
138
  ...(typeof data.viewerType === 'string' ? { viewerType: data.viewerType } : {}),
138
139
  ...(typeof data.serverName === 'string' ? { serverName: data.serverName } : {}),
@@ -28,7 +28,7 @@ import {
28
28
  cmd(
29
29
  'search',
30
30
  'Search nodes by title or content',
31
- ['pmx-canvas search "design doc"', 'pmx-canvas search --query "TODO"'],
31
+ ['pmx-canvas search "design doc"', 'pmx-canvas search --query "TODO" --folder "Research" --board-id <id>'],
32
32
  async (args) => {
33
33
  const { positional, flags } = parseFlags(args);
34
34
  if (flags.help || flags.h) return showCommandHelp('search');
@@ -36,11 +36,43 @@ cmd(
36
36
  const query = positional[0] || (typeof flags.query === 'string' ? flags.query : '');
37
37
  if (!query) die('Missing search query', 'pmx-canvas search "query"');
38
38
 
39
- const result = await invokeOperation('search', { q: query, ...(flags.library ? { scope: 'library' } : {}) });
39
+ if (flags.scope !== undefined && flags.scope !== 'active' && flags.scope !== 'library')
40
+ die('--scope must be active or library.');
41
+ const result = await invokeOperation('search', {
42
+ q: query,
43
+ ...(flags.scope ? { scope: flags.scope } : flags.library ? { scope: 'library' } : {}),
44
+ ...(typeof flags['board-id'] === 'string' ? { boardId: flags['board-id'] } : {}),
45
+ ...(typeof flags.folder === 'string' ? { folder: flags.folder } : {}),
46
+ ...(typeof flags.limit === 'string' ? { limit: Number(flags.limit) } : {}),
47
+ });
40
48
  output(result);
41
49
  },
42
50
  );
43
51
 
52
+ cmd(
53
+ 'memory-graph',
54
+ 'Explore the board/card relation graph (summary-only)',
55
+ [
56
+ 'pmx-canvas memory-graph',
57
+ 'pmx-canvas memory-graph --focus pins --depth 2',
58
+ 'pmx-canvas memory-graph --projection boards',
59
+ ],
60
+ async (args) => {
61
+ const { flags } = parseFlags(args);
62
+ if (flags.help || flags.h) return showCommandHelp('memory-graph');
63
+ if (flags.depth !== undefined && (typeof flags.depth !== 'string' || !flags.depth.trim())) {
64
+ die('--depth requires an integer from 0 to 4.');
65
+ }
66
+ output(
67
+ await invokeOperation('memory-graph.get', {
68
+ ...(typeof flags.focus === 'string' ? { focus: flags.focus } : {}),
69
+ ...(flags.depth !== undefined ? { depth: Number(flags.depth) } : {}),
70
+ ...(flags.projection !== undefined ? { projection: flags.projection } : {}),
71
+ }),
72
+ );
73
+ },
74
+ );
75
+
44
76
  cmd(
45
77
  'context',
46
78
  'Read the budgeted cross-board context brief',