pmx-canvas 0.8.0 → 0.9.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.
- package/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/.github/extensions/pmx-canvas/tools.json +601 -22
- package/CHANGELOG.md +66 -0
- package/Readme.md +131 -532
- package/dist/canvas/global.css +2759 -510
- package/dist/canvas/index.js +168 -107
- package/dist/canvas/mcp-app.html +2936 -632
- package/dist/json-render/index.css +81 -1
- package/dist/json-render/index.js +20 -20
- package/dist/types/client/canvas/BarHint.d.ts +12 -2
- package/dist/types/client/canvas/BoardLinkDialog.d.ts +3 -1
- package/dist/types/client/canvas/BoardPinButton.d.ts +10 -0
- package/dist/types/client/canvas/BoardSwitcher.d.ts +1 -1
- package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
- package/dist/types/client/canvas/CommandBar.d.ts +3 -4
- package/dist/types/client/canvas/ConnectionBanner.d.ts +2 -1
- package/dist/types/client/canvas/ContextChip.d.ts +3 -0
- package/dist/types/client/canvas/CrossBoardReferences.d.ts +5 -0
- package/dist/types/client/canvas/EdgeLayer.d.ts +14 -3
- package/dist/types/client/canvas/EmptyState.d.ts +4 -4
- package/dist/types/client/canvas/HomeGraphView.d.ts +2 -0
- package/dist/types/client/canvas/HomeMapView.d.ts +1 -0
- package/dist/types/client/canvas/HomeReviewView.d.ts +6 -0
- package/dist/types/client/canvas/HomeView.d.ts +9 -7
- package/dist/types/client/canvas/KnowledgeDialog.d.ts +4 -0
- package/dist/types/client/canvas/LifecycleChrome.d.ts +5 -0
- package/dist/types/client/canvas/LifecycleFields.d.ts +7 -0
- package/dist/types/client/canvas/LifecyclePanel.d.ts +1 -0
- package/dist/types/client/canvas/MemoryInspector.d.ts +7 -0
- package/dist/types/client/canvas/NearPinLayer.d.ts +14 -0
- package/dist/types/client/canvas/NodeContextMark.d.ts +40 -7
- package/dist/types/client/canvas/RelationPresetsDialog.d.ts +4 -0
- package/dist/types/client/canvas/RelationsPanel.d.ts +4 -0
- package/dist/types/client/canvas/SessionPanel.d.ts +2 -0
- package/dist/types/client/canvas/canvas-area.d.ts +1 -1
- package/dist/types/client/canvas/graph-geometry.d.ts +27 -0
- package/dist/types/client/canvas/graph-model.d.ts +37 -0
- package/dist/types/client/canvas/memory-layout.d.ts +23 -0
- package/dist/types/client/canvas/use-chrome-height.d.ts +2 -0
- package/dist/types/client/canvas/use-focus-trap.d.ts +1 -0
- package/dist/types/client/canvas/use-memory-graph.d.ts +8 -0
- package/dist/types/client/canvas/use-pan-zoom.d.ts +4 -1
- package/dist/types/client/icons.d.ts +0 -10
- package/dist/types/client/nodes/AxStepControls.d.ts +1 -1
- package/dist/types/client/nodes/HtmlNode.d.ts +1 -0
- package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +4 -4
- package/dist/types/client/nodes/MarkdownNode.d.ts +5 -1
- package/dist/types/client/nodes/McpAppNode.d.ts +4 -4
- package/dist/types/client/nodes/viewer-runtime-state.d.ts +1 -1
- package/dist/types/client/state/boards-store.d.ts +81 -9
- package/dist/types/client/state/canvas-store.d.ts +14 -1
- package/dist/types/client/state/context-chip-store.d.ts +22 -0
- package/dist/types/client/state/context-status-store.d.ts +35 -0
- package/dist/types/client/state/intent-bridge.d.ts +11 -8
- package/dist/types/client/state/knowledge-store.d.ts +22 -0
- package/dist/types/client/state/near-pin-store.d.ts +44 -1
- package/dist/types/client/state/presence-store.d.ts +4 -4
- package/dist/types/client/state/presentation.d.ts +28 -0
- package/dist/types/client/state/relation-store.d.ts +10 -0
- package/dist/types/client/state/session-store.d.ts +41 -2
- package/dist/types/client/state/workspace-settings.d.ts +7 -0
- package/dist/types/client/types.d.ts +13 -1
- package/dist/types/client/utils/keyboard.d.ts +2 -0
- package/dist/types/client/utils/time-ago.d.ts +4 -0
- package/dist/types/mcp/context-uri-template.d.ts +3 -1
- package/dist/types/server/agent-presence.d.ts +10 -3
- package/dist/types/server/ax-context.d.ts +1 -1
- package/dist/types/server/canvas-db.d.ts +30 -7
- package/dist/types/server/canvas-operations.d.ts +24 -2
- package/dist/types/server/canvas-provenance.d.ts +22 -2
- package/dist/types/server/canvas-serialization.d.ts +2 -0
- package/dist/types/server/canvas-state.d.ts +93 -15
- package/dist/types/server/canvas-validation.d.ts +1 -1
- package/dist/types/server/context-brief.d.ts +94 -6
- package/dist/types/server/context-reads.d.ts +33 -7
- package/dist/types/server/edit-summary.d.ts +20 -0
- package/dist/types/server/index.d.ts +71 -10
- package/dist/types/server/knowledge-lifecycle.d.ts +221 -0
- package/dist/types/server/lifecycle-status.d.ts +10 -0
- package/dist/types/server/memory-graph.d.ts +9 -0
- package/dist/types/server/mutation-history.d.ts +2 -0
- package/dist/types/server/operations/ops/ax-shared.d.ts +1 -1
- package/dist/types/server/operations/ops/boards.d.ts +2 -1
- package/dist/types/server/operations/ops/lifecycle.d.ts +2 -0
- package/dist/types/server/operations/ops/memory-graph.d.ts +2 -0
- package/dist/types/server/operations/ops/nodes.d.ts +5 -0
- package/dist/types/server/operations/ops/query.d.ts +23 -0
- package/dist/types/server/operations/registry.d.ts +1 -0
- package/dist/types/server/placement.d.ts +7 -0
- package/dist/types/server/scope-fence.d.ts +2 -1
- package/dist/types/server/spatial-analysis.d.ts +6 -3
- package/dist/types/server/tour-control.d.ts +32 -0
- package/dist/types/server/wiki-links.d.ts +14 -0
- package/dist/types/server/workbench-auth.d.ts +2 -0
- package/dist/types/shared/agent-context.d.ts +2 -0
- package/dist/types/shared/agent-presence.d.ts +15 -12
- package/dist/types/shared/auto-arrange.d.ts +1 -0
- package/dist/types/shared/boards.d.ts +4 -4
- package/dist/types/shared/knowledge-lifecycle.d.ts +41 -0
- package/dist/types/shared/knowledge-presets.d.ts +6 -0
- package/dist/types/shared/lifecycle-status.d.ts +24 -0
- package/dist/types/shared/memory-graph.d.ts +53 -0
- package/dist/types/shared/relations.d.ts +68 -0
- package/dist/types/shared/semantic-attention.d.ts +2 -0
- package/dist/types/shared/tour.d.ts +38 -0
- package/dist/types/shared/workspace-settings.d.ts +11 -0
- package/docs/RELEASE.md +21 -3
- package/docs/adr-001-bun-only-runtime.md +7 -1
- package/docs/adr-002-shared-product-separate-runtimes.md +93 -0
- package/docs/api-reference.md +109 -0
- package/docs/ax-host-adapter-contract.md +1 -1
- package/docs/ax-state-contract.md +5 -4
- package/docs/cli.md +153 -15
- package/docs/demos/pmx-canvas-demo.mp4 +0 -0
- package/docs/design/AgentContext.dc.html +3 -3
- package/docs/design/BoardPins.dc.html +37 -22
- package/docs/design/Categories.dc.html +208 -0
- package/docs/design/CategoryEditor.dc.html +33 -0
- package/docs/design/Chrome.dc.html +55 -9
- package/docs/design/ContextChip.dc.html +224 -0
- package/docs/design/ContextChip600.dc.html +136 -0
- package/docs/design/EmptyState.dc.html +45 -0
- package/docs/design/Flows.dc.html +23 -1
- package/docs/design/HeaderMarks.dc.html +183 -0
- package/docs/design/Home.dc.html +19 -1
- package/docs/design/HomeGraph.dc.html +86 -202
- package/docs/design/HomeMap.dc.html +23 -1
- package/docs/design/HomeTeam.dc.html +32 -14
- package/docs/design/Lifecycle.dc.html +22 -0
- package/docs/design/Lifecycle600.dc.html +18 -0
- package/docs/design/LifecycleVariants.dc.html +157 -0
- package/docs/design/LinkAuthorship.dc.html +139 -0
- package/docs/design/LinksChanged.dc.html +203 -0
- package/docs/design/LinksOptions.dc.html +137 -0
- package/docs/design/LinksOptions600.dc.html +134 -0
- package/docs/design/NearPin.dc.html +9 -10
- package/docs/design/Pane600.dc.html +4 -3
- package/docs/design/Relations.dc.html +3 -2
- package/docs/design/Restore.dc.html +152 -0
- package/docs/design/SeeChange.dc.html +267 -0
- package/docs/design/Uses.dc.html +12 -6
- package/docs/design/canvas.json +146 -19
- package/docs/design.md +454 -18
- package/docs/environment.md +0 -1
- package/docs/evals/curation-effect.md +128 -0
- package/docs/http-api.md +465 -38
- package/docs/mcp.md +150 -19
- package/docs/node-types.md +58 -3
- package/docs/plans/design-gaps-2026-10-08.md +53 -0
- package/docs/plans/plan-009-tech-debt-backlog.md +379 -0
- package/docs/plans/plan-016-context-made-visible-wave-1.md +150 -5
- package/docs/plans/plan-017-knowledge-categories-and-lifecycle.md +175 -0
- package/docs/plans/plan-018-connected-memory-wave-2.md +594 -0
- package/docs/plans/plan-019-post-0.9-roadmap.md +198 -0
- package/docs/product-context-vision-2026-09.md +17 -1
- package/docs/product-vision-2026-09.md +1082 -43
- package/docs/product-vision-review-2026-09.md +13 -1
- package/docs/screenshots/workbench-live-dark.png +0 -0
- package/docs/screenshots/workbench-live-light.png +0 -0
- package/docs/sdk.md +62 -2
- package/package.json +1 -1
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/plugin.json +1 -1
- package/plugins/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/tools.json +601 -22
- package/skills/pmx-canvas/SKILL.md +234 -43
- package/skills/pmx-canvas/evals/evals.json +62 -0
- package/skills/pmx-canvas/references/ax-html-control-surface.md +6 -0
- package/skills/pmx-canvas/references/full-reference.md +120 -21
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
- package/skills/pmx-canvas/references/importing-context.md +132 -0
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
- package/skills/pmx-canvas/references/tours-and-recording.md +16 -1
- package/skills/pmx-canvas-testing/SKILL.md +20 -0
- package/src/cli/agent.ts +2 -0
- package/src/cli/commands/ax.ts +12 -0
- package/src/cli/commands/boards.ts +87 -11
- package/src/cli/commands/edges.ts +28 -0
- package/src/cli/commands/groups.ts +7 -0
- package/src/cli/commands/nodes.ts +4 -2
- package/src/cli/commands/query.ts +34 -2
- package/src/cli/commands/record.ts +199 -48
- package/src/cli/index.ts +7 -1
- package/src/client/App.tsx +177 -70
- package/src/client/canvas/AttentionHistory.tsx +0 -2
- package/src/client/canvas/BarHint.tsx +40 -2
- package/src/client/canvas/BoardCopyDialog.tsx +1 -1
- package/src/client/canvas/BoardFolderDialog.tsx +7 -7
- package/src/client/canvas/BoardLinkDialog.tsx +138 -33
- package/src/client/canvas/BoardPinButton.tsx +33 -0
- package/src/client/canvas/BoardSwitcher.tsx +26 -40
- package/src/client/canvas/CanvasNode.tsx +360 -237
- package/src/client/canvas/CanvasViewport.tsx +45 -7
- package/src/client/canvas/CommandBar.tsx +29 -23
- package/src/client/canvas/CommandPalette.tsx +5 -12
- package/src/client/canvas/ConnectionBanner.tsx +3 -3
- package/src/client/canvas/ContextChip.tsx +296 -0
- package/src/client/canvas/ContextMenu.tsx +63 -5
- package/src/client/canvas/CrossBoardReferences.tsx +60 -0
- package/src/client/canvas/EdgeLayer.tsx +339 -76
- package/src/client/canvas/EmptyState.tsx +33 -18
- package/src/client/canvas/ExpandedNodeOverlay.tsx +72 -40
- package/src/client/canvas/ExternalWriters.tsx +57 -42
- package/src/client/canvas/HomeGraphView.tsx +942 -0
- package/src/client/canvas/HomeMapView.tsx +641 -0
- package/src/client/canvas/HomeReviewView.tsx +167 -0
- package/src/client/canvas/HomeView.tsx +687 -160
- package/src/client/canvas/IntentLayer.tsx +19 -12
- package/src/client/canvas/KnowledgeDialog.tsx +488 -0
- package/src/client/canvas/LifecycleChrome.tsx +133 -0
- package/src/client/canvas/LifecycleFields.tsx +91 -0
- package/src/client/canvas/LifecyclePanel.tsx +533 -0
- package/src/client/canvas/MemoryInspector.tsx +104 -0
- package/src/client/canvas/Minimap.tsx +3 -3
- package/src/client/canvas/NearPinLayer.tsx +187 -0
- package/src/client/canvas/NodeContextMark.tsx +175 -97
- package/src/client/canvas/Presentation.tsx +23 -57
- package/src/client/canvas/RelationPresetsDialog.tsx +413 -0
- package/src/client/canvas/RelationsPanel.tsx +82 -0
- package/src/client/canvas/SelectionBar.tsx +3 -6
- package/src/client/canvas/SessionPanel.tsx +90 -50
- package/src/client/canvas/SessionReceipt.tsx +311 -39
- package/src/client/canvas/ShortcutOverlay.tsx +1 -1
- package/src/client/canvas/SnapshotPanel.tsx +27 -36
- package/src/client/canvas/ToolRail.tsx +367 -192
- package/src/client/canvas/TopBar.tsx +354 -124
- package/src/client/canvas/canvas-area.ts +10 -3
- package/src/client/canvas/graph-geometry.ts +195 -0
- package/src/client/canvas/graph-model.ts +254 -0
- package/src/client/canvas/memory-layout.ts +106 -0
- package/src/client/canvas/use-chrome-height.ts +20 -0
- package/src/client/canvas/use-focus-trap.ts +31 -5
- package/src/client/canvas/use-memory-graph.ts +58 -0
- package/src/client/canvas/use-node-drag.ts +2 -1
- package/src/client/canvas/use-pan-zoom.ts +64 -7
- package/src/client/icons.tsx +0 -63
- package/src/client/mcp-app/style.css +0 -6
- package/src/client/nodes/AxStepControls.tsx +74 -50
- package/src/client/nodes/BoardNode.tsx +5 -1
- package/src/client/nodes/ContextNode.tsx +18 -11
- package/src/client/nodes/ExtAppFrame.tsx +0 -1
- package/src/client/nodes/FileNode.tsx +46 -42
- package/src/client/nodes/HtmlNode.tsx +44 -2
- package/src/client/nodes/ImageNode.tsx +1 -1
- package/src/client/nodes/InlineFormatBar.tsx +6 -9
- package/src/client/nodes/InlineMarkdownEditor.tsx +56 -17
- package/src/client/nodes/MarkdownNode.tsx +377 -109
- package/src/client/nodes/McpAppNode.tsx +50 -20
- package/src/client/nodes/MdFormatBar.tsx +21 -18
- package/src/client/nodes/PromptNode.tsx +1 -1
- package/src/client/nodes/ResponseNode.tsx +1 -1
- package/src/client/nodes/viewer-runtime-state.ts +54 -22
- package/src/client/state/attention-bridge.ts +64 -15
- package/src/client/state/boards-store.ts +193 -39
- package/src/client/state/canvas-store.ts +99 -12
- package/src/client/state/context-chip-store.ts +70 -0
- package/src/client/state/context-status-store.ts +53 -0
- package/src/client/state/intent-bridge.ts +51 -30
- package/src/client/state/knowledge-store.ts +43 -0
- package/src/client/state/near-pin-store.ts +115 -6
- package/src/client/state/presence-store.ts +7 -10
- package/src/client/state/presentation.ts +91 -0
- package/src/client/state/relation-store.ts +81 -0
- package/src/client/state/session-store.ts +144 -18
- package/src/client/state/sse-bridge.ts +206 -29
- package/src/client/state/workspace-settings.ts +11 -0
- package/src/client/theme/global.css +2759 -510
- package/src/client/types.ts +12 -0
- package/src/client/utils/keyboard.ts +10 -0
- package/src/client/utils/time-ago.ts +14 -0
- package/src/json-render/renderer/index.css +6 -1
- package/src/json-render/renderer/index.tsx +31 -1
- package/src/mcp/canvas-app.ts +12 -2
- package/src/mcp/context-uri-template.ts +7 -4
- package/src/mcp/server.ts +63 -41
- package/src/mcp/workbench-app.ts +39 -6
- package/src/server/agent-presence.ts +128 -28
- package/src/server/ax-context.ts +27 -13
- package/src/server/board-export.ts +12 -1
- package/src/server/canvas-db.ts +331 -42
- package/src/server/canvas-operations.ts +196 -84
- package/src/server/canvas-provenance.ts +53 -22
- package/src/server/canvas-serialization.ts +2 -0
- package/src/server/canvas-state.ts +950 -122
- package/src/server/canvas-validation.ts +9 -2
- package/src/server/context-brief.ts +345 -38
- package/src/server/context-reads.ts +179 -30
- package/src/server/demo-state.json +355 -24
- package/src/server/edit-summary.ts +74 -0
- package/src/server/html-surface.ts +8 -1
- package/src/server/index.ts +203 -13
- package/src/server/knowledge-lifecycle.ts +304 -0
- package/src/server/lifecycle-status.ts +232 -0
- package/src/server/memory-graph.ts +166 -0
- package/src/server/mutation-history.ts +18 -6
- package/src/server/operations/composites.ts +32 -11
- package/src/server/operations/http.ts +7 -2
- package/src/server/operations/index.ts +4 -0
- package/src/server/operations/mcp.ts +32 -1
- package/src/server/operations/ops/ax-presence.ts +1 -1
- package/src/server/operations/ops/ax-read.ts +57 -6
- package/src/server/operations/ops/ax-timeline.ts +28 -2
- package/src/server/operations/ops/backup.ts +5 -3
- package/src/server/operations/ops/batch.ts +35 -4
- package/src/server/operations/ops/boards.ts +188 -47
- package/src/server/operations/ops/canvas-wire.ts +31 -1
- package/src/server/operations/ops/edges.ts +36 -2
- package/src/server/operations/ops/groups.ts +6 -1
- package/src/server/operations/ops/json-render.ts +5 -1
- package/src/server/operations/ops/lifecycle.ts +262 -0
- package/src/server/operations/ops/memory-graph.ts +45 -0
- package/src/server/operations/ops/nodes.ts +107 -24
- package/src/server/operations/ops/query.ts +281 -68
- package/src/server/operations/ops/snapshots.ts +73 -1
- package/src/server/operations/ops/validate.ts +5 -1
- package/src/server/operations/ops/viewport.ts +97 -3
- package/src/server/operations/registry.ts +77 -26
- package/src/server/placement.ts +29 -0
- package/src/server/scope-fence.ts +78 -6
- package/src/server/server.ts +115 -16
- package/src/server/spatial-analysis.ts +48 -23
- package/src/server/tour-control.ts +82 -0
- package/src/server/wiki-links.ts +137 -0
- package/src/server/workbench-auth.ts +11 -0
- package/src/shared/agent-context.ts +3 -0
- package/src/shared/agent-presence.ts +15 -15
- package/src/shared/auto-arrange.ts +2 -0
- package/src/shared/boards.ts +4 -4
- package/src/shared/knowledge-lifecycle.ts +22 -0
- package/src/shared/knowledge-presets.ts +80 -0
- package/src/shared/lifecycle-status.ts +26 -0
- package/src/shared/memory-graph.ts +74 -0
- package/src/shared/relations.ts +98 -0
- package/src/shared/semantic-attention.ts +15 -1
- package/src/shared/tour.ts +23 -5
- package/src/shared/workspace-settings.ts +13 -0
- package/dist/types/client/canvas/ContextPinBar.d.ts +0 -1
- package/dist/types/client/canvas/FocusFieldLayer.d.ts +0 -1
- package/dist/types/client/canvas/kind-colors.d.ts +0 -3
- package/dist/types/server/agent-context.d.ts +0 -22
- package/src/client/canvas/ContextPinBar.tsx +0 -25
|
@@ -384,16 +384,23 @@ draw visual attention to critical paths.
|
|
|
384
384
|
|
|
385
385
|
### Layout: spacing and groups
|
|
386
386
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
387
|
+
Use the smallest clear gap that serves the content and its relationships. Both crowded labels
|
|
388
|
+
and oversized empty channels make a board harder to use.
|
|
389
|
+
|
|
390
|
+
- **Unconnected notes and walkthroughs:** start compact, often a 40–80px clear gap. For a
|
|
391
|
+
280×180 node with a 40px gap, origins are 320px apart horizontally and 220px vertically.
|
|
392
|
+
This is an unconnected-card example, not a minimum for connected cards. Do not reserve
|
|
393
|
+
half a card's width or a large uniform channel where there is no edge.
|
|
394
|
+
- **Connected cards:** provide enough room for the rendered edge line, arrowhead, label and
|
|
395
|
+
authorship marks. Short flow labels may need less room than long explanations. After content settles,
|
|
396
|
+
inspect the rendered relations at the intended viewing zoom, including after auto-arrange.
|
|
397
|
+
`validate` checks node non-overlap, not label/arrowhead clearance or relation readability;
|
|
398
|
+
widen or reroute crowded relations rather than relying on a fixed pixel gap.
|
|
399
|
+
- **After rendering:** use settled card sizes, not just the requested creation heights. Close
|
|
400
|
+
gaps left by automatic shrinking, check the numbered reading order, and frame a readable
|
|
401
|
+
cluster or tour stop. A whole-board fit is orientation, not proof that body text is readable.
|
|
402
|
+
- **Inside a group, apply the same distinction** between compact notes and clear relation
|
|
403
|
+
channels. Groups no longer auto-pack children, so the spacing you set is what the human sees.
|
|
397
404
|
- **Size a group frame larger than its children's bounding box** so the group header — including the
|
|
398
405
|
node-count badge — stays visible and isn't hidden under the top-left child. For an explicit
|
|
399
406
|
(manual) group frame, add margin on every side (≈56px) plus room at the top for the header rather
|
|
@@ -438,15 +445,15 @@ single-purpose tools behind an `action` (and, for `canvas_ax_gate`, a `kind`) di
|
|
|
438
445
|
| Composite | `action` values | What it does |
|
|
439
446
|
|-----------|-----------------|--------------|
|
|
440
447
|
| `canvas_import` | `list` · `read` · `submit` · `unavailable` | Process human-requested imports: inspect metadata/controlled bytes, submit reviewable Markdown with references/warnings/agent description, or report unavailable. Request/cancel/commit are human-only |
|
|
441
|
-
| `canvas_node` | `add` · `get` · `update` · `remove`
|
|
448
|
+
| `canvas_node` | `add` · `get` · `update` · `remove` · `lifecycle-get` · `lifecycle-set` · `review` · `lifecycle-restore` | Node CRUD, lifecycle qualification, evidence-backed review and reversible retirement; retired cards leave active context |
|
|
442
449
|
| `canvas_render` | `describe-schema` · `validate` · `add-json-render` · `stream-json-render` · `add-graph` · `workboard` | Schema introspection, spec dry-run validation, native json-render / graph node creation, and a live AX work-item board |
|
|
443
450
|
| `canvas_edge` | `add` · `update` · `remove` | Connect / edit / disconnect nodes |
|
|
444
451
|
| `canvas_group` | `create` · `add` · `ungroup` | Manage spatial group containers |
|
|
445
452
|
| `canvas_history` | `undo` · `redo` | Time travel through the mutation ring buffer |
|
|
446
|
-
| `canvas_board` | `list` · `get` · `create` · `create-from` · `open` · `update` | Boards
|
|
447
|
-
| `canvas_snapshot` | `save` · `list` · `restore` · `delete` · `gc` · `diff` | Named snapshots: save/list/restore/delete, garbage-collect old ones, diff current canvas vs a snapshot (`diff` takes `snapshot`, not `id`) |
|
|
448
|
-
| `canvas_view` | `arrange` · `focus` · `fit` · `clear` · `remove-annotation` · `get-tour` · `set-tour` | Auto-arrange, pan-to-node, fit viewport, clear the board, delete annotations, read/persist ordered presentation stops (`tour: null` derives group order) |
|
|
449
|
-
| `canvas_query` | `context` · `search` · `layout` · `validate` | Read the budgeted
|
|
453
|
+
| `canvas_board` | `list` · `get` · `create` · `create-from` · `open` · `update` · `pin` · `unpin` · `knowledge-list` · `category-set` · `category-remove` · `folder-set` · `relation-preset-set` · `relation-preset-remove` | Boards and workspace categories/folder properties/shared relation templates; knowledge writes never open a board. Template edits/deletion never rewrite boards or connections. `category-remove` takes `id` and refuses explicit folder assignments, including empty folders; reassign or clear them first. |
|
|
454
|
+
| `canvas_snapshot` | `save` · `list` · `restore` · `restore-node` · `delete` · `gc` · `diff` | Named snapshots: save/list/restore/delete, garbage-collect old ones, diff current canvas vs a snapshot (`diff` takes `snapshot`, not `id`); `restore-node` puts one card (`nodeId`) back to its content in snapshot `id` |
|
|
455
|
+
| `canvas_view` | `arrange` · `focus` · `fit` · `clear` · `remove-annotation` · `get-tour` · `set-tour` · `tour-go` · `tour-exit` · `move` | Auto-arrange, pan-to-node, fit viewport, clear the board, delete annotations, read/persist ordered presentation stops (`tour: null` derives group order), present a stop / exit, ease the camera to a node, rect or viewport (never an undo step) |
|
|
456
|
+
| `canvas_query` | `context` · `graph` · `search` · `layout` · `validate` | Read the budgeted brief or summary-only connected memory graph, find nodes, read full layout, or **`validate`** collisions / containment / dangling edges |
|
|
450
457
|
| `canvas_app` | `open-mcp-app` · `diagram` · `build-artifact` | Hosted MCP apps, the Excalidraw diagram preset, and bundled web artifacts (folds `canvas_open_mcp_app` / `canvas_add_diagram` / `canvas_build_web_artifact`) |
|
|
451
458
|
| `canvas_webview` | `status` · `start` · `stop` · `resize` · `evaluate` | Headless Bun.WebView automation for the workbench (folds the `canvas_webview_*` / `canvas_resize` / `canvas_evaluate` tools) |
|
|
452
459
|
| `canvas_ax_state` | `get` · `set-focus` · `set-policy` · `report-capability` · `presence` · `set-presence` | Read AX state; set AX focus; patch tool/prompt policy (the scope fence is human-set, read-only here); report host capability; read / set agent presence (phase, cursor, focus, attached session) |
|
|
@@ -484,6 +491,88 @@ reads inactive boards without opening them. Board links are native text-only
|
|
|
484
491
|
creation: `prompt`, `response`, `trace`, and `mcp-app` are excluded; README and
|
|
485
492
|
group structure are optional; fresh IDs are allocated; pins, AX state, and
|
|
486
493
|
history are not copied; the source remains unchanged and the new board inactive.
|
|
494
|
+
The new board records `previousBoardId` pointing to its source.
|
|
495
|
+
|
|
496
|
+
### Connected memory (wave 2)
|
|
497
|
+
|
|
498
|
+
Home Folders, Map and Graph, wiki links/backlinks, and brief discovery share one
|
|
499
|
+
board/card projection. Folders are neutral and independent of links. Map uses
|
|
500
|
+
deterministic folder regions and saved draggable SQLite `mapPosition`; board
|
|
501
|
+
update accepts `{ x, y }` or `null` to reset. Graph uses neutral circular clusters,
|
|
502
|
+
not force simulation; labels are in selection details, filters in the shared
|
|
503
|
+
toolbar, with no synthetic Home board, levels, or simulation sliders.
|
|
504
|
+
|
|
505
|
+
Read it with `canvas_query { action: "graph", focus: "pins", depth: 2 }`,
|
|
506
|
+
`canvas://graph{?focus,depth}`, `GET /api/canvas/memory-graph`, SDK
|
|
507
|
+
`getMemoryGraph({ focus, depth })`, or CLI `pmx-canvas memory-graph`. Focus is
|
|
508
|
+
a board ID, a JSON qualified key `["board-id","card-id"]` (or
|
|
509
|
+
`["board-id",null]`), or `pins`; omitted means the library. URL-encode resource
|
|
510
|
+
focus. Depth is an integer 0–4, default 2, traversing undirected links including
|
|
511
|
+
membership. Explicit 0 is valid; empty depth and bare CLI `--depth` are rejected.
|
|
512
|
+
HTTP, SDK and the MCP tool accept `projection: "full" | "boards"` (default `full`);
|
|
513
|
+
CLI uses `--projection full|boards`. The graph resource uses the default full projection.
|
|
514
|
+
Home Map uses compact `boards` summaries, loading depth-2 details on selection.
|
|
515
|
+
Metadata edits and dragging do not refetch relationships; **Refresh** reloads them.
|
|
516
|
+
Cross-board briefs give incoming and outgoing connections readable board/card titles.
|
|
517
|
+
The result has `nodes`, `edges`, `unresolvedLinks: [{ source, ref }]`,
|
|
518
|
+
`focus`, and `depth`. Nodes include qualified `key`, `boardId`, optional `cardId`,
|
|
519
|
+
`kind`, `title`, `summary`, `folder`, `inContext`, and `summaryOnly: true`;
|
|
520
|
+
summaries are capped at 280 characters. Edge projection kinds are `member`,
|
|
521
|
+
`portal`, `wiki`, `card`, and `previous`, with qualified `from`/`to`,
|
|
522
|
+
`source`/`target`, and explicit `missing`. Reads count links seen only when a node's
|
|
523
|
+
incident relations are complete; focused nodes with `linksComplete: false` do
|
|
524
|
+
not acknowledge omitted links. Brief entries with capped or omitted relations also
|
|
525
|
+
carry `linksComplete: false`; near-pin, human, linked README and pinned-board
|
|
526
|
+
summaries do not acknowledge unseen relations. Graph cards and complete brief
|
|
527
|
+
relations carry their captured `linksRevision`, so later writes remain unseen;
|
|
528
|
+
brief delivery is qualified by source board, never by a bare cross-board card ID.
|
|
529
|
+
AX excerpts and annotation anchors, including `canvas://ax-context` and
|
|
530
|
+
`pmx-current-context`, never mark incident relations seen; read a complete graph
|
|
531
|
+
or brief relation entry instead.
|
|
532
|
+
Single-card and layout reads record content delivery, not incident relations.
|
|
533
|
+
Reads never switch boards or record full content reads. Pull cards in full
|
|
534
|
+
when needed. Counts stay 24 tools, 15 static canvas resources; there are now two
|
|
535
|
+
canvas templates, context and graph, besides the skill file template.
|
|
536
|
+
|
|
537
|
+
Markdown save resolves `[[Board]]`, `[[Board#Card]]`, and `|alias` forms into
|
|
538
|
+
server-owned `data.wikiLinks` ID bindings. IDs win; name/title matches must be
|
|
539
|
+
unique. Existing bindings survive renames. Ambiguous/missing links stay explicit
|
|
540
|
+
and never guess or silently retarget. Rendering follows saved bindings: unresolved
|
|
541
|
+
links stay unresolved until an explicit save, and Undo/restore preserves bindings.
|
|
542
|
+
Legacy Markdown without binding metadata gets a one-time persisted backfill;
|
|
543
|
+
saved empty or unresolved records are not reinterpreted on reads.
|
|
544
|
+
Code spans/fences are ignored. A human
|
|
545
|
+
Create dialog for an unresolved board-only link creates exactly the authored
|
|
546
|
+
name and re-saves its source using the captured board/revision, refusing stale
|
|
547
|
+
source writes.
|
|
548
|
+
|
|
549
|
+
Once the board list has loaded, all workbench context-pin writes send the captured
|
|
550
|
+
`expectedBoardId`; a server-side board switch returns 409 instead of changing
|
|
551
|
+
another board's pins. Receipt pin actions require reopening the owning board.
|
|
552
|
+
|
|
553
|
+
Embedded JSON/graph runtime readiness waits up to 10 seconds after document load
|
|
554
|
+
and retries a failed handoff once while retaining the last painted document.
|
|
555
|
+
After another failure, the error toast/history say **Reload to retry**; a later
|
|
556
|
+
healthy authored update can recover. This is not an overall network-load timeout.
|
|
557
|
+
|
|
558
|
+
Native edge add accepts optional `toBoardId`: `from` is on the open source board,
|
|
559
|
+
`to` is a card on the target board. CLI: `pmx-canvas edge add --from <source> --to <target>
|
|
560
|
+
--to-board <board-id> --type references`. The human More menu offers a card
|
|
561
|
+
picker and the source footer shows remote connections. Auto-arrange stays local;
|
|
562
|
+
static export omits remote lines but shows explicit external connection evidence.
|
|
563
|
+
Edges accept open `kind`/`reason`; update null clears them. Boards accept
|
|
564
|
+
`relationVocabulary: [{kind, ink, directed}]`, with six fixed relation inks, never pin/agent/warning
|
|
565
|
+
colours. `derived-from`, `contradicts`, `supersedes` point source → dependent; `depends-on` points
|
|
566
|
+
dependent → prerequisite. Ordinary references/wiki links/portals do not propagate review due.
|
|
567
|
+
Lifecycle reads return qualification, including source observations. Validating dependent cards
|
|
568
|
+
requires `expectedSources` from the evidence checked, plus `expectedContentRevision`; stale or
|
|
569
|
+
unavailable sources refuse. Retired cards leave briefs/pinned context but remain marked in search
|
|
570
|
+
and direct reads. Brief `lifecycle.complete: false` requires rechecking cached cards before reuse;
|
|
571
|
+
empty incomplete lists are not a health claim. Recipe metadata is inert and refresh never validates.
|
|
572
|
+
For human review, Home's Review needed count filters to affected boards, and each Review button
|
|
573
|
+
opens an affected card. More → Review offers one short note and Checked, still correct; Not now
|
|
574
|
+
writes nothing. Settings and history discloses clocks, policies and advanced outcomes. The folder
|
|
575
|
+
tree is navigation, and No review policy is informational rather than an outstanding task.
|
|
487
576
|
|
|
488
577
|
Use `canvas_board { action: "open", id: "<board-id>" }` to open a created or
|
|
489
578
|
existing board before authoring. Verify the returned `activeBoardId`; opening
|
|
@@ -869,7 +958,7 @@ Useful workbench selectors:
|
|
|
869
958
|
the eraser in the rail's Annotate popover; agents can remove a known annotation ID with
|
|
870
959
|
`canvas_view { action: "remove-annotation" }`.
|
|
871
960
|
- Canvas chrome (rail-chrome-v2): `.tool-rail`, `.top-bar` (`.connection-dot`, `.agent-chip`,
|
|
872
|
-
`.gate-badge`, `.context-
|
|
961
|
+
`.gate-badge`, `.context-chip`, `.external-indicator`, `.start-session-btn`),
|
|
873
962
|
`.connection-banner`, `.canvas-region`, `.session-panel`, `.command-bar`, `.selection-bar`,
|
|
874
963
|
`.activity-feed`, `.writers-sheet`, `.session-receipt`, `.snapshot-panel` (the History
|
|
875
964
|
drawer), `.minimap`, `.empty-state`, `.command-palette`, `.expanded-overlay-panel`.
|
|
@@ -1042,6 +1131,9 @@ what the human has set up and what they're focusing on.
|
|
|
1042
1131
|
|
|
1043
1132
|
| Resource | What it provides |
|
|
1044
1133
|
|----------|-----------------|
|
|
1134
|
+
| `canvas://context{?budget,consumer,since}` | Budgeted cross-board map brief with optional durable consumer cursor |
|
|
1135
|
+
| `canvas://graph{?focus,depth}` | Summary-only connected memory projection, library or focused undirected membership-inclusive exploration |
|
|
1136
|
+
| `canvas://boards` | Board library with README summaries, links/backlinks and previews |
|
|
1045
1137
|
| `canvas://pinned-context` | Content of pinned nodes + nearby unpinned neighbors |
|
|
1046
1138
|
| `canvas://schema` | Running-server create schemas and json-render catalog metadata |
|
|
1047
1139
|
| `canvas://layout` | Full canvas state (viewport, nodes, edges) |
|
|
@@ -1165,10 +1257,16 @@ nodes.
|
|
|
1165
1257
|
- **Session receipt:** attaching a session (`set-presence { attached: true }` or a
|
|
1166
1258
|
`session-start` activity) over a non-empty board saves a `Before session · <label> · HH:MM`
|
|
1167
1259
|
snapshot; ending it (`attached: false`, `session-end`, or idle expiry) emits one
|
|
1168
|
-
`agent-session-ended` SSE frame
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1260
|
+
`agent-session-ended` SSE frame with `label`, `endedAt`, `snapshot`, `context` and counts
|
|
1261
|
+
(`items`, `done`, `cancelled`, `rejected`, `held`). Changed top-level endings show a receipt;
|
|
1262
|
+
worker and unchanged endings stay in History, and qualifying endings merge into an open receipt.
|
|
1263
|
+
**See change** opens one stacked Before/After; whole-card Undo preserves geometry and links.
|
|
1264
|
+
Receipt Undo sends `preserveHumanEdits: true` to `restore-node`, so the server skips latest-human
|
|
1265
|
+
edits even when the browser is stale. Agent callers can pass that option to `canvas_snapshot`
|
|
1266
|
+
too: `restored: false, skipped: "human-edit"` is not an undone card. Receipt Unpin only removes
|
|
1267
|
+
its recorded pins, never re-pins them. Reopen a receipt's board before Undo or comparison;
|
|
1268
|
+
Home dismisses it. End your session explicitly so the receipt is prompt. The human's
|
|
1269
|
+
*Start agent session* button is the same attach with `source: "browser"`.
|
|
1172
1270
|
- **Human collaborators / user wins:** every open workbench tab is a presence (`GET
|
|
1173
1271
|
/api/canvas/human-presence`); a node a human is dragging is locked — an agent write to it is
|
|
1174
1272
|
refused with 409 until release (requeue and retry), and a pending explicit intent on it is
|
|
@@ -1340,7 +1438,7 @@ All POST/PATCH endpoints accept `Content-Type: application/json`. Default base U
|
|
|
1340
1438
|
| POST | `/api/canvas/snapshots` | Save snapshot |
|
|
1341
1439
|
| POST | `/api/canvas/snapshots/<id>` | Restore snapshot |
|
|
1342
1440
|
| DELETE | `/api/canvas/snapshots/<id>` | Delete snapshot |
|
|
1343
|
-
| POST | `/api/canvas/context-pins` |
|
|
1441
|
+
| POST | `/api/canvas/context-pins` | Set, add or remove pinned nodes (20 live pins; removal IDs are not capped) |
|
|
1344
1442
|
| GET | `/api/canvas/pinned-context` | Get current pins with neighborhood context |
|
|
1345
1443
|
| GET | `/api/canvas/search?q=...` | Search nodes |
|
|
1346
1444
|
| POST | `/api/canvas/json-render` | Create a native json-render node |
|
|
@@ -1365,6 +1463,7 @@ All POST/PATCH endpoints accept `Content-Type: application/json`. Default base U
|
|
|
1365
1463
|
| POST | `/api/canvas/redo` | Redo |
|
|
1366
1464
|
| GET | `/api/canvas/history` | Mutation history |
|
|
1367
1465
|
| GET | `/api/canvas/code-graph` | File dependency graph |
|
|
1466
|
+
| GET | `/api/canvas/memory-graph` | Summary-only board/card projection; optional focus and depth |
|
|
1368
1467
|
| GET | `/api/workbench/events` | SSE event stream |
|
|
1369
1468
|
|
|
1370
1469
|
## Workflow Patterns
|
|
@@ -47,8 +47,8 @@ panel.
|
|
|
47
47
|
|
|
48
48
|
The extension also reports Copilot's real context window: the SDK's `session.usage_info`
|
|
49
49
|
event (`currentTokens` / `tokenLimit`, root agent only) is posted to the presence as
|
|
50
|
-
`contextUsage`, so the board's
|
|
51
|
-
|
|
50
|
+
`contextUsage`, so the board's context panel names how many tokens Copilot's whole context holds,
|
|
51
|
+
next to what the brief costs.
|
|
52
52
|
|
|
53
53
|
The extension attaches a Copilot session to the canvas when it joins the host session, flips the
|
|
54
54
|
phase to `thinking` on every submitted prompt, and detaches on exit. While attached the workbench
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Importing context
|
|
2
|
+
|
|
3
|
+
Use this workflow when bringing existing context into PMX Canvas from folders, repositories,
|
|
4
|
+
documents, notes, backlogs, structured exports or knowledge bases. It guides organization and
|
|
5
|
+
verification, not a universal file converter or live sync. PDF/Office attachments still require
|
|
6
|
+
the human-consented extraction and review workflow; this guide does not bypass it.
|
|
7
|
+
|
|
8
|
+
## Inspect the source before choosing the structure
|
|
9
|
+
|
|
10
|
+
Inventory the requested scope, file types, existing categories, references and assets. Read
|
|
11
|
+
representative content before mapping it: folder names alone do not establish board boundaries,
|
|
12
|
+
and files may contain several independent items or one argument that should stay together.
|
|
13
|
+
Identify duplicates, historical material, unsupported formats and inaccessible sources. Report
|
|
14
|
+
gaps rather than silently skipping them or claiming extraction succeeded. Keep private context
|
|
15
|
+
within the authorized destination; a folder import is not permission to include credentials.
|
|
16
|
+
|
|
17
|
+
## Choose boards and cards by purpose
|
|
18
|
+
|
|
19
|
+
Categories organize boards; boards hold coherent topics or workflows; cards hold useful content.
|
|
20
|
+
Preserve useful categories and folder context without mechanically copying the directory tree.
|
|
21
|
+
A project folder may become an overview board, a backlog with item cards, and a research board.
|
|
22
|
+
Several small files may belong on one board; a single export may need several boards. Choose
|
|
23
|
+
cards by useful units of meaning, not automatically one per file, heading or data row. Retain
|
|
24
|
+
section context, nested details and useful source ordering when splitting content. These are
|
|
25
|
+
examples, not a fixed taxonomy. Explain consequential grouping choices and make them easy to revise.
|
|
26
|
+
Several boards in one category are fine. Keep an argument together when splitting would lose
|
|
27
|
+
meaning. Group related cards and use the main skill's README and focus guidance for a readable start.
|
|
28
|
+
|
|
29
|
+
Lead each card with the task, item, decision or document section the reader came to find.
|
|
30
|
+
Retain ancestor headings, folder/repository context and source details below that content,
|
|
31
|
+
not as repeated preambles that push every useful item below the card's visible area. Preserve
|
|
32
|
+
meaning and source hierarchy without making the reader expand every card to identify it.
|
|
33
|
+
|
|
34
|
+
## Preserve sources and stable targets
|
|
35
|
+
|
|
36
|
+
Work in an isolated workspace for a test import. Preserve an existing import before replacing
|
|
37
|
+
it, and leave source material unchanged unless editing it was requested. Record source paths,
|
|
38
|
+
URLs or record IDs, revisions where available, and the source-item/section → board/card ID
|
|
39
|
+
mapping so interruptions and retries can reuse created objects instead of duplicating them.
|
|
40
|
+
Distinguish faithful imports from summaries; keep a path back to the original. Capture the active
|
|
41
|
+
board before writes, separately from any explicit destination. Create destination boards and
|
|
42
|
+
cards before rewriting internal references, use returned IDs rather than guessed titles, and
|
|
43
|
+
preserve external links.
|
|
44
|
+
|
|
45
|
+
Create supported static cards, groups and edges on an inactive board with `destinationBoardId`
|
|
46
|
+
without switching the human's view. Static nodes are Markdown, status, context, ledger, trace,
|
|
47
|
+
diff, Mermaid and plain HTML; images, runtime-backed nodes, generated primitives and intents
|
|
48
|
+
are not supported by this path. Updates/removals still require the active board. In a named
|
|
49
|
+
`canvas_batch`, each operation's `args` carries its destination and retry fields; group children
|
|
50
|
+
and edge endpoints can use the existing named references. `toBoardId` independently chooses a
|
|
51
|
+
remote edge endpoint, not the board that owns its source.
|
|
52
|
+
|
|
53
|
+
Assign a stable `requestId` to each logical static node/group/edge creation and retain it in
|
|
54
|
+
the source-to-canvas mapping. Retry with the same input and destination: the durable receipt
|
|
55
|
+
returns the original result after interruption or restart, even if the object was subsequently
|
|
56
|
+
edited or deleted. It does not restore deleted objects. Changed-input reuse conflicts; a new
|
|
57
|
+
intentional creation gets a new ID even when its content is identical. Batch operations commit
|
|
58
|
+
in sequence, not as one all-or-nothing import. Persist the mapping as receipts arrive.
|
|
59
|
+
|
|
60
|
+
`expectedBoardId` guards the active board even with an explicit destination. A stale guard
|
|
61
|
+
means refresh context, not substitute the destination ID or switch the human's view to retry.
|
|
62
|
+
For active-only work, explicitly open the intended board and verify its returned ID first.
|
|
63
|
+
Scope fences and human edit locks remain enforced. If Home is active, list/open a suitable
|
|
64
|
+
board before reading board context; library discovery and background static creation can
|
|
65
|
+
stay on Home. For retrieval, `canvas_query` search accepts intersecting `boardId` and `folder`
|
|
66
|
+
filters. Folder includes slash-boundary descendants; `folder: ""` selects unfiled boards.
|
|
67
|
+
Filters default omitted scope to library, while explicit active scope never widens. Search
|
|
68
|
+
never changes the active board.
|
|
69
|
+
|
|
70
|
+
Use native `references` edges for explicit source links and qualified remote endpoints for
|
|
71
|
+
cross-board cards. Add semantic relations only when the source supports them; record the
|
|
72
|
+
supporting passage or source reference in `reason`. Similar subjects alone do not establish
|
|
73
|
+
dependency, causation or supersession. Follow the main skill's direction rules for dependency kinds.
|
|
74
|
+
|
|
75
|
+
Preserve historical/draft status and source evidence dates. Importing, reading or rendering
|
|
76
|
+
content does not revalidate it. Flag source contradictions separately from conversion errors
|
|
77
|
+
and product bugs; do not silently rewrite uncertain facts or invent validation dates.
|
|
78
|
+
|
|
79
|
+
## Markdown link conversion
|
|
80
|
+
|
|
81
|
+
For content represented as Markdown, use returned IDs in `[[board-id#card-id|label]]` links
|
|
82
|
+
and keep code spans/fences unchanged. In table cells, escape the alias pipe:
|
|
83
|
+
`[[board-id#card-id\|label]]`. Otherwise the table parser can split the link before the wiki
|
|
84
|
+
link parser sees it. Zero unresolved links is not sufficient: compare expected source link
|
|
85
|
+
occurrences with rendered anchors. This is a Markdown rendering concern, not a source-format requirement.
|
|
86
|
+
|
|
87
|
+
## Keep picture bytes out of long Markdown
|
|
88
|
+
|
|
89
|
+
Prefer local asset references over large base64 image strings embedded in Markdown. The
|
|
90
|
+
embedded bytes enlarge layout/render requests; inline pictures remain supported. Choosing
|
|
91
|
+
file-backed assets is a representation choice, not proof that a parser or loading bug is fixed.
|
|
92
|
+
Keep private pictures in the authorized workspace; do not upload them to a public image host.
|
|
93
|
+
|
|
94
|
+
One supported approach is a file-backed image card in the document's board:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{"action":"add","type":"image","content":"assets/diagram.png","title":"System diagram"}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Call `canvas_node` with that payload, then use the returned ID in the document:
|
|
101
|
+
``. Keep the original alt text and connect
|
|
102
|
+
the document to its figure card when useful. This route resolves nodes on the active board:
|
|
103
|
+
keep the image card in the same board, and recheck references after copying or moving cards.
|
|
104
|
+
|
|
105
|
+
Relative image creation paths resolve against the canvas workspace root, not the server's
|
|
106
|
+
launch directory. An absolute path inside that workspace also works. Image creation requires
|
|
107
|
+
opening its destination board; do not send `destinationBoardId` or `requestId` for image nodes.
|
|
108
|
+
The database stores the path, not the file bytes: retain the assets alongside it, update paths
|
|
109
|
+
if relocating the workspace, and verify images in exports rather than assuming the live URL
|
|
110
|
+
is portable.
|
|
111
|
+
|
|
112
|
+
## Verify the imported workspace, not just the API receipts
|
|
113
|
+
|
|
114
|
+
1. Account for each in-scope source item as imported, summarized, intentionally excluded or
|
|
115
|
+
unresolved. Reconcile split items, references and assets with the mapping. Check edge endpoints,
|
|
116
|
+
group containment and collisions with `canvas_query { action: "validate" }`.
|
|
117
|
+
2. Open representative boards for the content actually imported: for example a dense backlog,
|
|
118
|
+
long document, linked table or picture-heavy board. Wait for the correct board and populated
|
|
119
|
+
card bodies, not only titles or HTTP success. Images must load with nonzero natural dimensions.
|
|
120
|
+
3. Wait for the intended card/group bounding rectangle after a camera update. Two animation
|
|
121
|
+
frames do not prove an asynchronous layout update arrived. Inspect screenshots at the
|
|
122
|
+
intended viewing zoom for readable cards, relations, labels and unobscured controls.
|
|
123
|
+
4. Click local and cross-board links; verify the intended card becomes visible. On a disposable
|
|
124
|
+
test service, restart and verify persistence, including pictures. Compare asset bytes when
|
|
125
|
+
changing image representation to confirm originals were preserved.
|
|
126
|
+
5. If loading is slow, measure board-open to rendered-content readiness on repeated equivalent
|
|
127
|
+
workloads. Include a text-only control; record payload sizes, cache conditions and whether
|
|
128
|
+
measurements used a local connection or the user's host. Separate observations from causes.
|
|
129
|
+
|
|
130
|
+
Report coverage, unresolved issues and storage requirements. Distinguish an import workaround
|
|
131
|
+
from a product fix, and a source snapshot from live synchronization. Keep private source paths,
|
|
132
|
+
names and content out of reusable skills and public issue reports.
|
|
@@ -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.
|
|
7
|
+
The examples pin **PMX Canvas 0.9.0**, 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.
|
|
20
|
+
npm install -g pmx-canvas@0.9.0
|
|
21
21
|
pmx-canvas --version
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
Without a global install, use `bunx pmx-canvas@0.
|
|
24
|
+
Without a global install, use `bunx pmx-canvas@0.9.0` 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.
|
|
94
|
+
"args": ["pmx-canvas@0.9.0", "--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.
|
|
138
|
+
"args": ["pmx-canvas@0.9.0", "--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.
|
|
172
|
+
Discover `canvas` tools with `tool_search`; for the full unfiltered 0.9.0 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:
|
package/src/cli/commands/ax.ts
CHANGED
|
@@ -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,41 @@ 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" --
|
|
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');
|
|
56
105
|
const name = positional.join(' ').trim();
|
|
57
|
-
if (!name) die('Usage: pmx-canvas board create <name> [--
|
|
58
|
-
const
|
|
59
|
-
output(await invokeOperation('board.create', { name, ...(
|
|
106
|
+
if (!name) die('Usage: pmx-canvas board create <name> [--folder <folder>]');
|
|
107
|
+
const folder = getStringFlag(flags, 'folder');
|
|
108
|
+
output(await invokeOperation('board.create', { name, ...(folder ? { folder } : {}) }));
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
cmd(
|
|
113
|
+
'board pin',
|
|
114
|
+
"Pin a board into the agent's working set (its README and pinned cards reach every brief)",
|
|
115
|
+
['pmx-canvas board pin board-abc123', 'pmx-canvas board pin board-abc123 --reason "Q4 rests on it"'],
|
|
116
|
+
async (args) => {
|
|
117
|
+
const { positional, flags } = parseFlags(args);
|
|
118
|
+
if (flags.help || flags.h) return showCommandHelp('board pin');
|
|
119
|
+
const [id] = positional;
|
|
120
|
+
if (!id || positional.length > 1) die('Usage: pmx-canvas board pin <board-id> [--reason <why>]');
|
|
121
|
+
const reason = getStringFlag(flags, 'reason');
|
|
122
|
+
output(await invokeOperation('board.pin', { id, ...(reason ? { reason } : {}) }));
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
cmd(
|
|
127
|
+
'board unpin',
|
|
128
|
+
"Remove a board from the agent's working set",
|
|
129
|
+
['pmx-canvas board unpin board-abc123'],
|
|
130
|
+
async (args) => {
|
|
131
|
+
const { positional, flags } = parseFlags(args);
|
|
132
|
+
if (flags.help || flags.h) return showCommandHelp('board unpin');
|
|
133
|
+
const [id] = positional;
|
|
134
|
+
if (!id || positional.length > 1) die('Usage: pmx-canvas board unpin <board-id>');
|
|
135
|
+
output(await invokeOperation('board.unpin', { id }));
|
|
60
136
|
},
|
|
61
137
|
);
|
|
62
138
|
|
|
@@ -70,15 +146,15 @@ cmd('board rename', 'Rename a board', ['pmx-canvas board rename board-abc123 "Q4
|
|
|
70
146
|
});
|
|
71
147
|
|
|
72
148
|
cmd(
|
|
73
|
-
'board
|
|
74
|
-
'File a board under a
|
|
75
|
-
['pmx-canvas board
|
|
149
|
+
'board folder',
|
|
150
|
+
'File a board under a folder on Home (--clear removes it)',
|
|
151
|
+
['pmx-canvas board folder board-abc123 "Planning"', 'pmx-canvas board folder board-abc123 --clear'],
|
|
76
152
|
async (args) => {
|
|
77
153
|
const { positional, flags } = parseFlags(args);
|
|
78
|
-
if (flags.help || flags.h) return showCommandHelp('board
|
|
154
|
+
if (flags.help || flags.h) return showCommandHelp('board folder');
|
|
79
155
|
const [id, ...rest] = positional;
|
|
80
|
-
const
|
|
81
|
-
if (!id || (!
|
|
82
|
-
output(await invokeOperation('board.update', { id,
|
|
156
|
+
const folder = flags.clear ? '' : rest.join(' ').trim();
|
|
157
|
+
if (!id || (!folder && !flags.clear)) die('Usage: pmx-canvas board folder <board-id> <folder> | --clear');
|
|
158
|
+
output(await invokeOperation('board.update', { id, folder }));
|
|
83
159
|
},
|
|
84
160
|
);
|