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.
- package/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/.github/extensions/pmx-canvas/tools.json +601 -22
- package/CHANGELOG.md +59 -0
- package/Readme.md +131 -532
- package/dist/canvas/global.css +2724 -476
- package/dist/canvas/index.js +168 -107
- package/dist/canvas/mcp-app.html +2899 -596
- 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/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/human-store.d.ts +2 -1
- 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 +52 -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 +449 -16
- package/docs/environment.md +0 -1
- package/docs/evals/curation-effect.md +128 -0
- package/docs/http-api.md +459 -37
- package/docs/mcp.md +146 -18
- 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 +216 -42
- package/skills/pmx-canvas/evals/evals.json +224 -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 +88 -11
- package/src/cli/commands/edges.ts +28 -0
- package/src/cli/commands/groups.ts +7 -0
- package/src/cli/commands/nodes.ts +1 -0
- package/src/cli/commands/query.ts +34 -2
- package/src/cli/commands/record.ts +199 -48
- package/src/cli/index.ts +6 -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 +543 -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 +6 -3
- package/src/client/nodes/FileNode.tsx +46 -42
- package/src/client/nodes/HtmlNode.tsx +32 -0
- 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/human-store.ts +13 -7
- 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 +235 -32
- package/src/client/state/workspace-settings.ts +11 -0
- package/src/client/theme/global.css +2724 -476
- 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.tsx +31 -0
- 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 +195 -83
- 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 +178 -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 +181 -11
- 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 +26 -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/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 +74 -25
- 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
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
## Canvas Types
|
|
2
|
+
|
|
3
|
+
**Node types (18):** `markdown`, `status`, `context`, `ledger`, `trace`, `file`, `diff`, `image`, `html`, `mermaid`, `mcp-app`, `webpage`, `json-render`, `graph`, `group`, `board`, plus internal thread node types `prompt` and `response`
|
|
4
|
+
|
|
5
|
+
**Edge types:** `flow`, `depends-on`, `relation`, `references` — all support labels, styles (solid/dashed/dotted), and animation.
|
|
6
|
+
|
|
7
|
+
## MCP Server
|
|
8
|
+
|
|
9
|
+
24 tools: 18 action-discriminated composites (`canvas_import`, `canvas_board`, `canvas_node`, `canvas_render`, `canvas_edge`, `canvas_group`, `canvas_history`, `canvas_view`, `canvas_query`, `canvas_webview`, `canvas_app`, `canvas_snapshot`, `canvas_ax_state`, `canvas_ax_work`, `canvas_ax_gate`, `canvas_ax_timeline`, `canvas_ax_delivery`, `canvas_intent`) plus 6 standalone tools (`canvas_batch`, `canvas_pin_nodes`, `canvas_invoke_command`, `canvas_ax_interaction`, `canvas_ingest_activity`, `canvas_screenshot`). `canvas_import` is the agent half of the human-consented attachment workflow: agents list/read requested imports, submit reviewable Markdown, or report unavailable; they cannot request, cancel, or commit. The 57 legacy single-purpose tools the composites replaced were removed in v0.3.0; v0.4.0 shipped the `canvas_snapshot` composite and removed the 6 deprecated snapshot standalones. Prefer composites for new MCP calls; see `docs/mcp.md` for the authoritative tool list and the legacy-to-composite migration reference.
|
|
10
|
+
|
|
11
|
+
### Agent-assisted document imports
|
|
12
|
+
|
|
13
|
+
PDF and Office drops retain the original (maximum 20 MiB) as a board-owned attachment. Nothing launches an agent automatically: a human explicitly consents and requests extraction, then reviews the returned sections, references, warnings, and `agentDescription` before committing source-linked Markdown. The agent reads controlled bytes through the returned HTTP download path, or inline base64 only at 2 MiB or below; a remote host may require manual byte transfer. Draft submission may happen while another board is active, but commit requires reopening the captured source board. PMX bundles no converter or OCR and makes no guarantee that a host can read every format, scan, chart, or diagram.
|
|
14
|
+
|
|
15
|
+
Originals remain in SQLite until their board is deleted; snapshots/restores do not discard them, and database backups include them. Static export v1 never includes original bytes. Source-linked Markdown is excluded by default and is controlled by `includeDerivedText`, independently of `includeFiles`; editing the Markdown does not remove its source classification.
|
|
16
|
+
|
|
17
|
+
The `diagram` action of `canvas_app` is a thin preset in `src/server/diagram-presets.ts` that proxies to the hosted [Excalidraw MCP app](https://github.com/excalidraw/excalidraw-mcp) (`https://mcp.excalidraw.com/mcp`). For any other MCP Apps server, use `canvas_app` action `open-mcp-app`.
|
|
18
|
+
|
|
19
|
+
15 static canvas resources: `canvas://boards`, `canvas://pinned-context`, `canvas://schema`, `canvas://layout`, `canvas://summary`, `canvas://spatial-context`, `canvas://history`, `canvas://code-graph`, `canvas://ax`, `canvas://ax-context`, `canvas://ax-timeline`, `canvas://ax-work`, `canvas://ax-pending-steering`, `canvas://ax-delivery`, `canvas://skills`; two canvas resource templates: `canvas://context{?budget,consumer,since}` and `canvas://graph{?focus,depth}`. Bundled skills additionally register per-skill `canvas://skills/<name>` resources and the `skill://{name}/{+path}` file template.
|
|
20
|
+
|
|
21
|
+
Resource change notifications: the MCP server emits `notifications/resources/updated` when canvas state changes. Pin changes notify `canvas://pinned-context`; all mutations notify `canvas://layout`, `canvas://summary`, `canvas://spatial-context`, `canvas://history`, `canvas://code-graph`, and `canvas://graph`. This enables real-time human→agent collaboration — humans pin nodes in the browser, agents are notified immediately.
|
|
22
|
+
|
|
23
|
+
### AX Primitives (host-agnostic)
|
|
24
|
+
|
|
25
|
+
Neutral, agent-agnostic agent-experience primitives. The core never imports a host SDK (e.g. `@github/copilot-sdk`); host adapters map onto these HTTP/MCP surfaces. State lives in three partitions:
|
|
26
|
+
|
|
27
|
+
- **Canvas-bound** (`focus`, `work-item`, `approval-gate`, `review-annotation`): live in `PmxAxState`, participate in snapshots + restore, cleared by `canvas_view { action: "clear" }`. Read via `canvas_ax_state { action: "get" }` / `canvas://ax-work`.
|
|
28
|
+
- **Timeline** (`agent-event`, `evidence-item`, `steering-message`): persist in dedicated DB tables for diagnostics/continuity, bounded by retention (500 rows/table), NOT restored by snapshots, NOT cleared by `canvas_view { action: "clear" }`. Read via `canvas_ax_timeline { action: "read" }` / `canvas://ax-timeline`.
|
|
29
|
+
- **Host/session** (`host-capability`): reported by adapters into its own table, exposed for diagnostics, survives `canvas_view { action: "clear" }`. Read via `canvas_ax_state { action: "get" }`.
|
|
30
|
+
|
|
31
|
+
Approval gates implement PMX approvals first (`pending → approved/rejected/held`); host permission hooks are mapped only where low-risk. **Unattended-approval policy** (`src/server/ax-gate-ttl.ts`): every gate carries `expiresAt` (`ttlMs`, default `PMX_CANVAS_GATE_TTL_MS` = 5 min); a 1s sweeper started with the server resolves unanswered gates to `held` (non-approval), records a `policy` agent-event, and re-emits presence; `POST /api/canvas/ax/approval/:id/reopen` (HTTP/SDK only — a human action) restarts the clock. **Scope fence** (`src/server/scope-fence.ts`): `policy.scope = { nodeIds, padding }` makes `executeOperation` refuse agent-originated mutations outside the fence with 403 (`meta.fromWorkbench` exempts the human; batch inner ops are always agent writes, so the fence cannot be keyed on `suppressAutoGhost`); unknown mutating ops are refused under a fence by default — add new layout ops to `checkScopeFence`.
|
|
32
|
+
|
|
33
|
+
- **Agent presence** (`src/server/agent-presence.ts`, shape in `src/shared/agent-presence.ts`): in-memory and TTL-swept like `IntentRegistry`, never persisted. Derived from feeds that already exist — every agent-originated mutation through `executeOperation` (no `x-pmx-workbench` marker) touches its caller as `tooling`; `ax.activity.ingest` kinds `session-start`/`session-end` attach/detach and `tool-start`/`tool-result` drive the phase; `POST /api/canvas/ax/presence` (`canvas_ax_state { action: "set-presence" }`) is the explicit path for `thinking`, cursor, focus. Transport-labelled writes (`api`/`mcp`/`sdk`/`cli`, no `agentId`) are **attributed to the single attached session** so one agent writing through MCP keeps one cursor; identified writers and multi-session boards stay separate; a human-started `browser` session absorbs agent-less writes under any label and takes the writer's name (`HUMAN_STARTED_SESSION_LABEL`); an attach whose label matches an already-attached session twin-merges (one agent, two channels — Copilot's extension + its MCP server) with the channel aliased onto the session. One `agent-presence` SSE frame carries the full snapshot on every change including expiry, and it also carries `activity` — the last 50 agent writes with a `describeWrite` summary (the External Steering feed and the session panel's Update rows). An explicit `attached: false` removes the presence outright (an ended session never lingers as an external writer). **`sessionActive` (any attached presence) gates all agent chrome except presence cursors** — `AgentPresenceLayer` paints every live writer (external ones `is-external`/dashed) so a human always sees where an agent is working; panels/chips/composer still mount on `sessionActive`, and a board with no writers at all stays byte-clean. Contract: `docs/ax-state-contract.md` (Agent presence); design and build plan: `docs/design.md`.
|
|
34
|
+
- **Human presence + user wins** (`src/server/human-presence.ts`, shape in `src/shared/human-presence.ts`): every open workbench tab heartbeats `POST /api/canvas/human-presence` (cursor, name, `grabbingNodeId`); one `human-presence` SSE frame per change. A held node is an **edit lock**: `executeOperation` refuses an agent write to it with 409 until release or the 8 s grab TTL (membership ops — dissolving its group, `group.add` — count as writes to the member), and the client vetoes a pending explicit intent on a grabbed node and records a `yield` timeline event. Human heartbeats are in `PRESENCE_EXEMPT_OPS` — they must never count as agent activity.
|
|
35
|
+
- **Shared undo stack with actors** (`mutation-history.ts`): `executeOperation` tags every recorded entry `human` (workbench marker) or `agent`; `GET /api/canvas/history` exposes `top`. The session panel offers undo only while an agent edit tops the stack and posts steering when the human takes it. SDK writes bypass the registry and default to `agent`.
|
|
36
|
+
|
|
37
|
+
Additional canvas-bound primitives: `elicitation` (request structured human input → respond), `mode-request` (request a plan/execute/autonomous transition → resolve), and a single `policy` singleton (tool/prompt policy: `tools.allowed|excluded|approvalRequired`, `prompt.systemAppend|mode`). All snapshot/restore with the rest of `PmxAxState` and are read via `canvas_ax_state { action: "get" }` / `canvas://ax-work` / `canvas://ax-context`.
|
|
38
|
+
|
|
39
|
+
#### Node interactions (capability-gated)
|
|
40
|
+
|
|
41
|
+
Eligible nodes emit one normalized, zod-validated `PmxAxInteraction` envelope (`{ type, sourceNodeId, payload, sourceSurface }`) that maps onto an AX operation. `applyAxInteraction` (`src/server/ax-interaction.ts`) is the single trust boundary and re-validates every interaction regardless of transport.
|
|
42
|
+
|
|
43
|
+
- **Capabilities:** `DEFAULT_NODE_AX_CAPABILITIES` is the per-node-type ceiling; a node may opt in / narrow via `data.axCapabilities` (`{ enabled, allowed }`), clamped to the ceiling (a node can never escalate). `html`/`html-primitive`, `mcp-app`, and internal `prompt`/`response` are disabled by default.
|
|
44
|
+
- **`sourceSurface` scoping:** sandboxed/opaque-origin iframe surfaces (`html-node`, `mcp-app`, `json-render`) are clamped to their OWN node — caller-supplied `nodeIds` are forced to `[sourceNodeId]`. Trusted surfaces (`native-node`, `adapter`) may target explicit nodeIds. **When adding a new sandboxed surface, add it to the `scoped` predicate** or it silently takes the permissive default.
|
|
45
|
+
- **Transports:** native node controls call `POST /api/canvas/ax/interaction` directly; sandboxed surfaces postMessage a nonce-tagged emit to the parent canvas, which validates source + per-surface nonce + node id before submitting. `html`/`mcp-app` use `window.PMX_AX.emit(type, payload)`; the json-render/graph viewer forwards a spec action named after an AX type (e.g. `on.press → { action: "ax.work.create", params }`).
|
|
46
|
+
- **Commands:** `ax.command.invoke` runs a registry command (`pmx.plan`, `pmx.execute`, `pmx.promote-context`, `pmx.summarize`, `pmx.review`) via `canvas_invoke_command`; unknown names are rejected (400) and a successful call records a `command` agent-event.
|
|
47
|
+
- **Delivery:** steering can be claimed by adapterless MCP clients (`canvas_ax_delivery { action: "claim" }` / `canvas://ax-pending-steering`) and acknowledged (`canvas_ax_delivery { action: "mark" }`); loop-safe (a consumer never receives steering it originated).
|
|
48
|
+
|
|
49
|
+
Interactions request PMX-AX primitives only — never arbitrary shell, tool, MCP, or host execution.
|
|
50
|
+
|
|
51
|
+
#### AX flows (panel and graph)
|
|
52
|
+
|
|
53
|
+
A task flow exists in two interchangeable forms. The `ax-flow` HTML primitive draws it as a panel;
|
|
54
|
+
`ax.flow.materialize` lays the same steps out as native nodes joined by `flow` edges with a
|
|
55
|
+
loop-back rail, each step linked to a work item. It is the only interaction that creates canvas
|
|
56
|
+
nodes, so it is granted to the `html` ceiling alone.
|
|
57
|
+
|
|
58
|
+
- Materialized steps carry `data.axStep` and render native Start/Done/Blocked controls
|
|
59
|
+
(`src/client/nodes/AxStepControls.tsx`) in both the node body and the expanded overlay — the
|
|
60
|
+
flow is drivable without the panel.
|
|
61
|
+
- Work-item status mirrors onto node status chips (`mirrorAxWorkStatusToNodes`), which is what
|
|
62
|
+
makes the in-progress node visible on the board while an agent works.
|
|
63
|
+
- `src/server/ax-flow-loop.ts` advances the loop server-side via `setWorkItemsChangedListener`
|
|
64
|
+
(see architecture rule 8), so it survives a browser reload and keeps running with the tab closed.
|
|
65
|
+
A module-level `advancing` guard prevents re-entrancy.
|
|
66
|
+
- Step geometry and the shared flow shape live in `src/shared/ax-flow.ts` so server and client
|
|
67
|
+
cannot drift.
|
|
68
|
+
|
|
69
|
+
### Spatial Semantics Layer
|
|
70
|
+
|
|
71
|
+
The canvas exposes spatial intelligence to agents via `canvas://spatial-context`:
|
|
72
|
+
- **Proximity clusters**: Automatically detects nodes grouped together on the canvas
|
|
73
|
+
- **Reading order**: Nodes sorted top-left to bottom-right (how humans read)
|
|
74
|
+
- **Pinned neighborhoods**: For each pinned node, lists nearby unpinned nodes (the human's implicit context)
|
|
75
|
+
- **`canvas://pinned-context`** now includes neighborhood data — nearby unpinned nodes for each pin
|
|
76
|
+
|
|
77
|
+
Use `canvas_query { action: "search" }` to find nodes by title/content keywords instead of parsing the full layout.
|
|
78
|
+
|
|
79
|
+
### Time Travel (Undo/Redo + History)
|
|
80
|
+
|
|
81
|
+
Every canvas mutation is recorded in an in-memory ring buffer (last 200 operations). Each entry captures forward/inverse closures for clean undo/redo.
|
|
82
|
+
|
|
83
|
+
- **`canvas_history`** (`action: "undo" | "redo"`) — step through history, reversing operations cleanly
|
|
84
|
+
- **`canvas://history`** — human-readable mutation timeline with cursor position
|
|
85
|
+
- **`canvas_snapshot`** (`action: "diff", snapshot`) — compare current canvas vs any saved snapshot (shows added/removed/modified nodes and edges)
|
|
86
|
+
- HTTP: `POST /api/canvas/undo`, `POST /api/canvas/redo`, `GET /api/canvas/history`
|
|
87
|
+
|
|
88
|
+
Design notes:
|
|
89
|
+
- History is session-scoped (in-memory, not persisted to disk)
|
|
90
|
+
- `arrange()` records as a single compound mutation (not N individual moves)
|
|
91
|
+
- Undo/redo emit SSE events so the browser updates immediately
|
|
92
|
+
- The `_suppressRecording` flag prevents undo/redo from creating new history entries
|
|
93
|
+
|
|
94
|
+
### Code Graph (Auto-Dependency Detection)
|
|
95
|
+
|
|
96
|
+
When file nodes are on the canvas, the system auto-detects import dependencies and creates `depends-on` edges between related files. The code graph updates live when files change.
|
|
97
|
+
|
|
98
|
+
- **`canvas://code-graph`** MCP resource — dependency structure: central files, isolated files, import/imported-by lists
|
|
99
|
+
- HTTP: `GET /api/canvas/code-graph`
|
|
100
|
+
- Supported languages: JS/TS (`import`/`require`), Python (`import`/`from`), Go (`import`), Rust (`mod`/`use crate`)
|
|
101
|
+
- Auto-edges use the `codegraph-` ID prefix and are suppressed from mutation history
|
|
102
|
+
- Recomputation is debounced (300ms) and triggered on file node add/remove and file content change
|
|
103
|
+
|
|
104
|
+
## Integration Paths
|
|
105
|
+
|
|
106
|
+
1. **MCP Server** (recommended) — `pmx-canvas --mcp`, auto-starts on first tool call
|
|
107
|
+
2. **HTTP API** — REST + SSE at `localhost:4313`
|
|
108
|
+
3. **JavaScript/TypeScript SDK (Bun runtime)** — `import { createCanvas } from 'pmx-canvas'`
|
|
109
|
+
4. **Agent Skills** — `skills/pmx-canvas/SKILL.md`, `skills/web-artifacts-builder/SKILL.md`, `skills/playwright-cli/SKILL.md`, `skills/pmx-canvas-testing/SKILL.md`, `skills/pmx-canvas-orchestration/SKILL.md` (multi-agent choreography ON the canvas: host executes, canvas is the graph/state/steering surface), plus repo-local agnostic PMX skills such as `doc-coauthoring`, `data-analysis`, `frontend-design`, `web-design-guidelines`, and `json-render-*`
|
|
@@ -35,7 +35,7 @@ surface each one binds to.
|
|
|
35
35
|
| `ingestActivity(event)` | `POST /api/canvas/ax/activity` · `canvas_ingest_activity` — board auto-reacts | Forwarding the host's tool/session hooks |
|
|
36
36
|
| `awaitGate(id)` | `GET /api/canvas/ax/{approval\|elicitation\|mode}/<id>?waitMs=` · `canvas_ax_gate { kind: "approval"\|"elicitation"\|"mode", action: "await" }` | Optionally surfacing a native modal; the agent must await PMX |
|
|
37
37
|
| `mirrorLog(event)` *(optional)* | `GET /api/canvas/ax/timeline` · `canvas://ax-timeline` | Writing AX events into the host's own chat/session log |
|
|
38
|
-
| `presence()` | `POST /api/canvas/ax/presence` · `canvas_ax_state { action: "set-presence" }` — or simply `ingestActivity` with `session-start` / `session-end` / `tool-start` / `tool-result` | Calling it from the host's session and tool hooks. Attach saves a pre-session snapshot; detach emits the `agent-session-ended` receipt — detach on shutdown (bounded, best-effort) so the human gets it promptly. If the host knows the model's token usage, report it as `contextUsage: { used, total }` — the
|
|
38
|
+
| `presence()` | `POST /api/canvas/ax/presence` · `canvas_ax_state { action: "set-presence" }` — or simply `ingestActivity` with `session-start` / `session-end` / `tool-start` / `tool-result` | Calling it from the host's session and tool hooks. Attach saves a pre-session snapshot; detach emits the `agent-session-ended` receipt — detach on shutdown (bounded, best-effort) so the human gets it promptly. If the host knows the model's token usage, report it as `contextUsage: { used, total }` — the context panel then names how many tokens the agent's whole context holds |
|
|
39
39
|
|
|
40
40
|
### Presence: the cursor works for every adapter
|
|
41
41
|
|
|
@@ -105,9 +105,10 @@ constants, so they cannot drift); the registry is `src/server/agent-presence.ts`
|
|
|
105
105
|
so clients never run their own ticker.
|
|
106
106
|
- **Transport.** One SSE frame, `agent-presence`, carries the full snapshot on
|
|
107
107
|
every change, including the last `MAX_ACTIVITY_ENTRIES` agent writes with a
|
|
108
|
-
one-line summary.
|
|
108
|
+
one-line summary. An attached presence also carries `session`
|
|
109
|
+
(`{ startedAt, read, created, edited, pinned }`, card ids on the open board
|
|
110
|
+
since it attached, counting every agent there, like the receipt): the agent
|
|
111
|
+
chip's "2 read · 1 edited" and the live lens. A recorded read re-emits the
|
|
112
|
+
frame. `GET /api/canvas/ax/presence` for the connect-time read;
|
|
109
113
|
`POST /api/canvas/ax/presence` (`canvas_ax_state { action: "set-presence" }`)
|
|
110
114
|
for explicit updates.
|
|
111
|
-
- **Budget.** `used` = estimated tokens of the `pinned-context.get` payload;
|
|
112
|
-
`total` = `PMX_CANVAS_CONTEXT_BUDGET_TOKENS` (default
|
|
113
|
-
`CONTEXT_BUDGET_DEFAULT_TOKENS`).
|
package/docs/cli.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# CLI reference
|
|
2
2
|
|
|
3
|
+
## Knowledge lifecycle data
|
|
4
|
+
|
|
5
|
+
`pmx-canvas board knowledge list` reads workspace categories/folders and shared relation presets.
|
|
6
|
+
`pmx-canvas board knowledge category-set '<JSON>'` accepts `{category: {...}}`;
|
|
7
|
+
`pmx-canvas board knowledge category-remove '{"id":"unused-category"}'` deletes an unused category. Explicit folder assignments (even empty folders) refuse deletion and name the folders to reassign or clear first. Unknown IDs are 404; missing/blank IDs are invalid input. No folder settings or inherited policies are silently cleared.
|
|
8
|
+
`board knowledge folder-set '<JSON>'` accepts `{path, categoryId, lifecycleOverride}`.
|
|
9
|
+
`board knowledge relation-preset-set '<JSON>'` accepts `{preset: {id, name, vocabulary}}`;
|
|
10
|
+
`board knowledge relation-preset-remove '{"id":"preset-id"}'` deletes a shared template.
|
|
11
|
+
Vocabulary entries are `{kind, ink, directed}`. These templates are managed in Home;
|
|
12
|
+
editing/deleting one does not rewrite boards. Applying a saved template explicitly copies
|
|
13
|
+
its vocabulary to a selected board. The canvas dropdown only filters existing relation kinds.
|
|
14
|
+
No workspace write opens a board; scope fences refuse agent workspace writes.
|
|
15
|
+
Moving/unfiling a board also checks its stored global scope or writer territory alongside
|
|
16
|
+
the active scope, without opening it. Home or an unfenced board does not bypass that policy.
|
|
17
|
+
`pmx-canvas board lifecycle get|set|review|restore '<JSON>'` uses `id` and the
|
|
18
|
+
[HTTP contract fields](http-api.md#knowledge-lifecycle-data-plan-017-slice-1).
|
|
19
|
+
For example: `pmx-canvas board lifecycle review '{"id":"card-id","outcome":"retain",
|
|
20
|
+
"evidence":"Checked source revision v2","applied":true,"expectedBoardId":"board-id",
|
|
21
|
+
"expectedContentRevision":12}'` (replace 12 with the revision of the card content actually checked).
|
|
22
|
+
Read supports `board`; writes target the open board. For dependencies also send `expectedSources`
|
|
23
|
+
from the checked lifecycle result's `qualification.observations`; stale or unavailable sources refuse
|
|
24
|
+
validation. Qualification includes due reasons, unknown/retired status and separate clocks.
|
|
25
|
+
Retired cards leave active context but remain in direct reads and search, explicitly marked.
|
|
26
|
+
|
|
27
|
+
`edge add` and `edge update` accept `--kind` and `--reason`; update also accepts `--clear-kind`
|
|
28
|
+
and `--clear-reason`. `board vocabulary <board-id> '<JSON-array>'` sets an editable vocabulary
|
|
29
|
+
of `{kind, ink, directed}`. These are semantic relations, independent of edge line type/style.
|
|
30
|
+
Dependency directions and the bounded brief lifecycle snapshot are documented in the HTTP contract.
|
|
31
|
+
|
|
3
32
|
The CLI is the shell-native way to run and control PMX Canvas. It targets
|
|
4
33
|
`http://localhost:4313` by default — override with `PMX_CANVAS_URL` or
|
|
5
34
|
`PMX_CANVAS_PORT` when the server runs elsewhere, or per invocation with the
|
|
@@ -34,9 +63,11 @@ The same stops and camera interpolation drive interactive presentation and optio
|
|
|
34
63
|
A visual stop editor and carrying tours into static exports/share links are not implemented here.
|
|
35
64
|
|
|
36
65
|
Click **Present** in the top bar, or open `/workbench?present=1` for a chrome-free
|
|
37
|
-
embedded/capture view
|
|
38
|
-
|
|
66
|
+
embedded/capture view (no rail, top bar, minimap or composer). Right/Down/Space
|
|
67
|
+
advances, Left/Up goes back, Esc exits. The presentation camera is local to the
|
|
68
|
+
viewer and never written to the board; board content continues updating over SSE.
|
|
39
69
|
Stops do not auto-advance. Missing targets show an error and can be skipped.
|
|
70
|
+
With `prefers-reduced-motion: reduce`, every stop and camera move jumps instead of animating.
|
|
40
71
|
|
|
41
72
|
Save this as `tour.json` (replace the IDs with IDs from `pmx-canvas node list`):
|
|
42
73
|
|
|
@@ -45,6 +76,7 @@ Save this as `tour.json` (replace the IDs with IDs from `pmx-canvas node list`):
|
|
|
45
76
|
"stops": [
|
|
46
77
|
{ "target": { "nodeId": "overview-group" }, "duration": 1.5, "padding": 60 },
|
|
47
78
|
{ "target": { "nodeId": "detail-note" }, "duration": 2, "easing": "ease-in-out", "pullback": 0.7 },
|
|
79
|
+
{ "target": { "rect": { "x": -400, "y": 200, "width": 1600, "height": 900 } }, "duration": 2 },
|
|
48
80
|
{ "target": { "viewport": { "x": 80, "y": 100, "scale": 0.5 } }, "duration": 1 }
|
|
49
81
|
]
|
|
50
82
|
}
|
|
@@ -55,10 +87,11 @@ pmx-canvas tour set --file tour.json
|
|
|
55
87
|
pmx-canvas tour get
|
|
56
88
|
```
|
|
57
89
|
|
|
58
|
-
A stop targets
|
|
90
|
+
A stop targets exactly one of: a node ID (including a group ID), a world-space
|
|
91
|
+
`rect` (`x`/`y` is its top-left corner), or an explicit viewport.
|
|
59
92
|
Viewport translation is screen-space: `screen = world * scale + offset`.
|
|
60
93
|
`duration` is transition time in seconds (default 1, zero jumps); `padding` is
|
|
61
|
-
screen pixels around a target (default 40). Easing is `linear`, `ease-in-out`
|
|
94
|
+
screen pixels around a node or rect target (default 40). Easing is `linear`, `ease-in-out`
|
|
62
95
|
(default), or `ease-out`. Zoom interpolates logarithmically about the moving
|
|
63
96
|
world-space centre. `pullback` (0–4, default 0) subtracts a sinusoidal log-zoom
|
|
64
97
|
offset mid-move without changing endpoints. Tours allow at most 1000 stops.
|
|
@@ -68,6 +101,33 @@ the board. A file containing `null` resets the tour: when none is saved, groups
|
|
|
68
101
|
are sorted by y, then x, then ID. A saved empty `stops` array deliberately has no
|
|
69
102
|
stops. SDK: `canvas.setTour(tourOrNull)` / `canvas.getTour()`.
|
|
70
103
|
|
|
104
|
+
### Driving a tour (agents)
|
|
105
|
+
|
|
106
|
+
The server keeps one tour cursor (in memory, not saved), tied to the board it was
|
|
107
|
+
started on; starting a tour on another board replaces it. An agent steps it and
|
|
108
|
+
every presenting viewer follows; a human's arrow keys move the same cursor,
|
|
109
|
+
so `next` always continues from where the audience actually is.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pmx-canvas tour go 0 # start presenting at the first stop
|
|
113
|
+
pmx-canvas tour go next # or: previous (clamped at the ends)
|
|
114
|
+
pmx-canvas tour go 2 --no-present # only move viewers already presenting
|
|
115
|
+
pmx-canvas tour exit # leave presentation everywhere
|
|
116
|
+
|
|
117
|
+
# Eased camera move, no tour needed (same fields as a stop)
|
|
118
|
+
pmx-canvas camera move --node <id> --duration 2 --pullback 0.6
|
|
119
|
+
pmx-canvas camera move --rect -400,200,1600,900 --easing ease-out
|
|
120
|
+
pmx-canvas camera move --viewport 80,100,0.5 --duration 0
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`tour go` starts presenting in idle workbenches unless `--no-present` is given.
|
|
124
|
+
`camera move` animates every open workbench; outside a presentation its end camera
|
|
125
|
+
becomes the board viewport. Camera moves and tour steps are navigation: they never
|
|
126
|
+
enter undo history, never count as agent writes, and are allowed under a scope fence.
|
|
127
|
+
A deterministic capture (`record --mode deterministic`) ignores both.
|
|
128
|
+
SDK: `canvas.goToTourStop(indexOrStep, { present })`, `canvas.exitTour()`,
|
|
129
|
+
`canvas.moveCamera(stop)`.
|
|
130
|
+
|
|
71
131
|
### Optional capture of the same tour
|
|
72
132
|
|
|
73
133
|
`record` is an optional local utility, not a second presentation model. It reads
|
|
@@ -83,31 +143,47 @@ pmx-canvas record --mode deterministic --present --fps 30 --resolution 1920x1080
|
|
|
83
143
|
pmx-canvas record --mode deterministic --tour-file tour.json --present --output frames
|
|
84
144
|
|
|
85
145
|
# Alternatively, sample the live presentation while agents update the board
|
|
86
|
-
pmx-canvas record --duration 10 --present --theme
|
|
146
|
+
pmx-canvas record --duration 10 --present --theme daylight --output activity.mp4
|
|
87
147
|
|
|
88
148
|
# Keep recording until SIGINT (Ctrl+C) or SIGTERM, then encode
|
|
89
149
|
pmx-canvas record --stop-on-signal --output live.mp4
|
|
90
150
|
```
|
|
91
151
|
|
|
152
|
+
A board walkthrough end to end: save the `tour.json` above, preview it with
|
|
153
|
+
**Present**, then render it at video quality and record a live pass while an
|
|
154
|
+
agent works:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
pmx-canvas tour set --file tour.json
|
|
158
|
+
pmx-canvas record --mode deterministic --present --theme midnight --resolution 1920x1080 --fps 30 --output walkthrough.mp4
|
|
159
|
+
pmx-canvas record --duration 20 --present --resolution 1920x1080 --output agent-pass.mp4 &
|
|
160
|
+
pmx-canvas node add --type markdown --title "Findings" --content "Added while recording"
|
|
161
|
+
wait
|
|
162
|
+
```
|
|
163
|
+
|
|
92
164
|
Options: `--mode realtime|deterministic` (default realtime), `--resolution WIDTHxHEIGHT`
|
|
93
165
|
(default 1280x720), `--fps` (1–120, default 30), `--theme`, `--present`,
|
|
94
166
|
`--duration SECONDS` or `--stop-on-signal` for realtime, `--tour-file FILE`
|
|
95
167
|
for deterministic mode, `--chrome-path PATH`, and required `--output PATH`.
|
|
96
168
|
Global `--port` / `--server-url` work here too. Existing output paths are refused.
|
|
97
169
|
|
|
98
|
-
An `.mp4` output uses ffmpeg/H.264; any other path is a
|
|
170
|
+
An `.mp4` output uses ffmpeg/H.264; any other path is a frame sequence directory
|
|
171
|
+
of `frame-000000.png` files.
|
|
99
172
|
Frames and `recording.json` are retained at `<output>.frames` even after video
|
|
100
|
-
encoding. If ffmpeg is missing, the command clearly reports the
|
|
101
|
-
and returns that directory. Encoding failures retain frames and exit nonzero.
|
|
173
|
+
encoding. If ffmpeg is missing, the command clearly reports the frame-sequence
|
|
174
|
+
fallback and returns that directory. Encoding failures retain frames and exit nonzero.
|
|
102
175
|
|
|
103
176
|
Deterministic mode resolves target geometry once and writes
|
|
104
177
|
`max(1, ceil(duration × fps))` frames per stop, including each endpoint. It sets
|
|
105
178
|
the camera, waits for two animation frames, checks the applied camera, then
|
|
106
179
|
captures. Duplicate a target to hold it. This makes **camera timing** deterministic,
|
|
107
180
|
not animated iframe content, fonts loaded later, network assets, or concurrent
|
|
108
|
-
board edits. Realtime mode
|
|
109
|
-
|
|
110
|
-
|
|
181
|
+
board edits. Realtime mode records Chrome's screencast (a frame per paint) and
|
|
182
|
+
writes the newest painted frame on every `--fps` tick while it records, so footage
|
|
183
|
+
keeps wall-clock speed and a stop signal keeps every frame written so far; ticks
|
|
184
|
+
with no new paint repeat the previous frame, counted as `duplicated` in
|
|
185
|
+
`recording.json`. Capture has no audio. Chrome and a Bun runtime with WebView
|
|
186
|
+
support are required; Chrome gets 60 seconds to cold-start.
|
|
111
187
|
Recording is a local CLI/file operation, not a remote HTTP/MCP file-writing API;
|
|
112
188
|
HTTP/MCP manage tours and retain their existing screenshot/automation surfaces.
|
|
113
189
|
|
|
@@ -209,6 +285,17 @@ none keeps 100% with scrolling. [Sizing and readability](node-types.md#mermaid-n
|
|
|
209
285
|
`--from-search` / `--to-search` must each resolve to exactly one node — broad
|
|
210
286
|
queries fail rather than guess. Use the full visible title.
|
|
211
287
|
|
|
288
|
+
Background `group create` and `edge add` accept `--destination-board <id>`,
|
|
289
|
+
`--request-id <logical-id>` and `--expected-board <active-id>`. The destination
|
|
290
|
+
does not open in the workbench; `--to-board` on an edge independently selects its
|
|
291
|
+
foreign endpoint. Reuse request IDs only for identical retries. See the
|
|
292
|
+
[creation/retry contract](http-api.md#nodes).
|
|
293
|
+
|
|
294
|
+
`search <query>` accepts `--board-id <id>`, `--folder <path>`, `--scope active|library`
|
|
295
|
+
and `--limit <n>` (`--library` also selects library scope). Board/folder filters
|
|
296
|
+
intersect; folders include descendants, and `--folder ""` selects unfiled boards.
|
|
297
|
+
Filters default omitted scope to library; explicit active scope stays active.
|
|
298
|
+
|
|
212
299
|
CLI create commands return the created node shape with normalized title,
|
|
213
300
|
content, and geometry, which makes scripting stacked layouts and batch
|
|
214
301
|
follow-ups easier.
|
|
@@ -282,14 +369,39 @@ node or fit the new ids — auto-placement is board-relative, not camera-relativ
|
|
|
282
369
|
|
|
283
370
|
## Boards
|
|
284
371
|
|
|
372
|
+
Home has Folders, Map, and Graph views. Folder paths organize boards independently
|
|
373
|
+
of links; dragging a board in Map persists its position in SQLite.
|
|
374
|
+
|
|
375
|
+
Graph is one zoomable Library > Board > Card
|
|
376
|
+
explorer. Library shows neutral, undirected, counted board-pair evidence bundles;
|
|
377
|
+
Board shows internal card relations and external neighbor boards; Card shows exact
|
|
378
|
+
one-hop qualified neighbors, incoming left and outgoing right. Click, Enter or Space
|
|
379
|
+
on a node drills; an edge selects its exact evidence in the existing bottom inspector.
|
|
380
|
+
Back restores the prior scene, camera, query, filters and selection; breadcrumbs go
|
|
381
|
+
up the ownership hierarchy instead. Open board/card is a separate content action.
|
|
382
|
+
Unconnected boards/cards have labelled clickable trays. Search and reveal actions
|
|
383
|
+
expose large sets with explicit displayed/total/filtered/hidden counts. A deterministic
|
|
384
|
+
bounded force solve supplies initial positions. Dragging a node pushes nearby nodes
|
|
385
|
+
and lets connected neighbors respond, then the graph settles around its drop position.
|
|
386
|
+
Link pull stays gentle even for highly connected nodes, with wider spacing between cards.
|
|
387
|
+
Canceled drags restore all displaced nodes. Positions remain local to Graph; live
|
|
388
|
+
updates alone preserve existing anchors. Graph's dock starts collapsed and compact.
|
|
389
|
+
Hover highlights a node's connections without fading the other links.
|
|
390
|
+
Entry and search preserve readable size; the header distinguishes off-screen nodes
|
|
391
|
+
from filtered or not-yet-drawn nodes. Fit view shows the whole drawn extent. Home Map
|
|
392
|
+
(including its 280 px default dock), Folders and server graph focus/depth contracts
|
|
393
|
+
are unchanged.
|
|
394
|
+
|
|
285
395
|
```bash
|
|
286
396
|
pmx-canvas board list # most recently opened first; activeBoardId null = Home
|
|
287
397
|
pmx-canvas board create "Q4 planning" # created, not opened
|
|
288
398
|
pmx-canvas board open <board-id> # open the returned ID before writing
|
|
289
399
|
pmx-canvas board open --home # return the shared workbench to Home
|
|
290
400
|
pmx-canvas board rename <board-id> "New name"
|
|
291
|
-
pmx-canvas board create "Q4 planning" --
|
|
292
|
-
pmx-canvas board
|
|
401
|
+
pmx-canvas board create "Q4 planning" --folder Planning
|
|
402
|
+
pmx-canvas board folder <board-id> "Planning/Quarterly" # nested folders; --clear unfiles it
|
|
403
|
+
pmx-canvas board pin <board-id> --reason "Q4 rests on it" # join the agent's working set
|
|
404
|
+
pmx-canvas board unpin <board-id>
|
|
293
405
|
pmx-canvas board from <source-id> "Follow-up" --preview
|
|
294
406
|
pmx-canvas board from <source-id> "Follow-up" --nodes id1,id2 --readme --structure
|
|
295
407
|
```
|
|
@@ -297,11 +409,36 @@ pmx-canvas board from <source-id> "Follow-up" --nodes id1,id2 --readme --structu
|
|
|
297
409
|
Commands write to the board open in the workbench. `board open` switches the
|
|
298
410
|
shared visible board, not a private CLI target. Verify its returned
|
|
299
411
|
`activeBoardId` before writing; another participant can switch it later.
|
|
300
|
-
|
|
412
|
+
A pinned board's README and pinned cards reach the agent's brief whichever board is open; it
|
|
413
|
+
is read-only context, never a write target. Deletion remains human-only. `board from`
|
|
301
414
|
excludes `prompt`, `response`, `trace`, and `mcp-app` cards; selected reusable
|
|
302
415
|
cards get fresh IDs. `--structure` includes group frames; edges between copied
|
|
303
416
|
cards are retained automatically. `--readme` carries the designated README. The new board remains inactive and
|
|
304
|
-
does not inherit pins, AX state, or mutation history.
|
|
417
|
+
does not inherit pins, AX state, or mutation history. Its `previousBoardId`
|
|
418
|
+
records the source board.
|
|
419
|
+
|
|
420
|
+
## Connected memory
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
pmx-canvas memory-graph
|
|
424
|
+
pmx-canvas memory-graph --projection boards
|
|
425
|
+
pmx-canvas memory-graph --focus pins --depth 2
|
|
426
|
+
pmx-canvas memory-graph --focus '["board-id","card-id"]' --depth 1
|
|
427
|
+
pmx-canvas edge add --from <source-card-id> --to <target-card-id> --to-board <target-board-id> --type references
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Graph focus is a board ID, a JSON qualified key `[boardId,cardId|null]`, or
|
|
431
|
+
`pins`; omit it for the library. Depth is an integer 0–4, default 2, counting
|
|
432
|
+
undirected membership hops. Explicit `--depth 0` is valid; bare `--depth` and
|
|
433
|
+
empty values are rejected. `--projection full|boards` defaults to `full`;
|
|
434
|
+
`boards` returns compact board-only summaries. The projection returns `nodes`, `edges`,
|
|
435
|
+
`unresolvedLinks: [{ source, ref }]`, `focus`, and `depth`; nodes are
|
|
436
|
+
`summaryOnly: true` with summaries capped at 280 characters. It is the same
|
|
437
|
+
projection used by Home, links/backlinks, and brief discovery. Reads mark links
|
|
438
|
+
seen on their owning boards without switching or marking full content read.
|
|
439
|
+
`--to-board` keeps the source on the open board and targets a remote card;
|
|
440
|
+
auto-arrange stays local and static export shows external connection evidence,
|
|
441
|
+
not remote lines.
|
|
305
442
|
|
|
306
443
|
## Backup and restore
|
|
307
444
|
|
|
@@ -383,6 +520,7 @@ pmx-canvas ax steer "focus on the failing test first"
|
|
|
383
520
|
pmx-canvas ax evidence add --kind test-output --title "unit pass"
|
|
384
521
|
pmx-canvas ax timeline --limit 50
|
|
385
522
|
pmx-canvas ax reads --limit 50 # context read log: which context each agent read, pinned delivery
|
|
523
|
+
pmx-canvas ax reads status --board <id> # a board's last agent read, per-node reads, pin metadata
|
|
386
524
|
|
|
387
525
|
# Work items (canvas-bound)
|
|
388
526
|
pmx-canvas ax work add --title "Wire up auth" --status in-progress node-1
|
|
Binary file
|
|
@@ -18,7 +18,7 @@ body{margin:0}
|
|
|
18
18
|
<div style="display: flex; gap: 40px; align-items: flex-end">
|
|
19
19
|
<div style="flex: 1">
|
|
20
20
|
<h1 style="margin: 0; font-size: 28px; font-weight: 600; letter-spacing: -0.015em">What the agent did with context</h1>
|
|
21
|
-
<p style="margin: 4px 0 0; font-size: 13px; color: #8ea3bd">Two questions, two colours. Every mark has a glyph and a word, so it reads without the colour, and every mark explains itself on hover.</p>
|
|
21
|
+
<p style="margin: 4px 0 0; font-size: 13px; color: #8ea3bd">Two questions, two colours. Every mark has a glyph and a word, so it reads without the colour, and every mark explains itself on hover. <span style="color: #b9c6d6">Updated 2026-10-08: read, not read and changed show on pinned cards only — unpinned cards carry no read state; the session receipt and the dim-untouched lens say what the agent read. In headers, “by the agent” is the ✦ on the type icon (HeaderMarks).</span></p>
|
|
22
22
|
</div>
|
|
23
23
|
<div style="display: flex; gap: 10px">
|
|
24
24
|
<div style="{{s.rule}} border-color: rgba(75,188,255,0.4)"><span style="{{s.ruleDot}} background: #4BBCFF"></span><span><b style="font-weight: 600; color: #4BBCFF">Blue</b> — what's in context<br><span style="color: #8ea3bd">You or the agent pinned it</span></span></div>
|
|
@@ -70,7 +70,7 @@ body{margin:0}
|
|
|
70
70
|
|
|
71
71
|
<div style="{{sc.node}} left: 360px; top: 172px; border: 1.5px solid #4BBCFF"><div style="position: absolute; left: 0; right: 0; top: 0; height: 2.5px; background: #B388FF"></div><div style="{{sc.head}} background: rgba(75,188,255,0.10)"><span style="{{sc.title}}">SMB is price-sensitive</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.pen}}"></path></svg>edited</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><span style="{{sc.pin}}"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round"><path d="{{i.pin}}"></path></svg></span></div><div style="{{sc.body}}">finding · edited 14:12 · <span style="color: #B388FF">see change</span></div></div>
|
|
72
72
|
|
|
73
|
-
<div style="{{sc.node}} left: 640px; top: 172px"><div style="{{sc.head}}"><span style="{{sc.title}}">Competitor pricing</span><
|
|
73
|
+
<div style="{{sc.node}} left: 640px; top: 172px"><div style="{{sc.head}}"><span style="{{sc.title}}">Competitor pricing</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><button aria-label="Add to context (P)" style="width: 18px; height: 18px; box-sizing: border-box; border: 1.5px solid #6b7d94; border-radius: 999px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round"><path d="M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20"></path></svg></button></div><div style="{{sc.body}}">webpage · not pinned · read shows in the receipt</div></div>
|
|
74
74
|
|
|
75
75
|
<div style="{{sc.node}} left: 60px; top: 330px; border: 1.5px solid #4BBCFF"><div style="{{sc.head}} background: rgba(75,188,255,0.10)"><span style="{{sc.title}}">Churn by plan</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.eye}}"></path></svg>read</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><span style="{{sc.pin}} position: relative"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round"><path d="{{i.pin}}"></path></svg><span style="position: absolute; right: -3px; bottom: -3px; width: 9px; height: 9px; border-radius: 999px; background: #B388FF; border: 2px solid #0f1d31"></span></span></div><div style="{{sc.body}}">chart · pinned by Claude</div></div>
|
|
76
76
|
|
|
@@ -146,7 +146,7 @@ class Component extends DCLogic {
|
|
|
146
146
|
var key = [
|
|
147
147
|
k({ name: 'In context — pinned by you', desc: 'Blue border, tinted header, pin badge.', title: 'Raise Pro to $24?', meta: 'question', pin: true }),
|
|
148
148
|
k({ name: 'In context — pinned by the agent', desc: 'Same blue, with a violet dot on the pin; hover says why.', title: 'Churn by plan', meta: 'pinned by Claude · 14:04', pin: true, byAgent: true }),
|
|
149
|
-
k({ name: 'Read by the agent', desc: '
|
|
149
|
+
k({ name: 'Read by the agent', desc: 'Pinned, and loaded by the agent. Unpinned cards show no read state.', title: 'Competitor pricing', meta: 'read 14:11', pin: true, icon: i.eye, markText: 'read' }),
|
|
150
150
|
k({ name: 'Pinned, not read yet', desc: 'In context, but the agent hasn’t loaded it since you pinned it.', title: 'Pricing notes', meta: 'pinned 14:18', pin: true, icon: i.eyeOff, markText: 'not read', muted: true }),
|
|
151
151
|
k({ name: 'Created by the agent', desc: 'Its byline stays until you edit the node.', title: 'Churn flat after last raise', meta: 'created 14:06', icon: i.spark, markText: 'by Claude' }),
|
|
152
152
|
k({ name: 'Edited by the agent', desc: 'Violet bar for the session; “see change” opens the diff and undo.', title: 'SMB is price-sensitive', meta: 'edited 14:12 · see change', bar: true, icon: i.pen, markText: 'edited' }),
|