pmx-canvas 0.2.7 → 0.3.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/CHANGELOG.md +148 -1
- package/Readme.md +13 -11
- package/dist/canvas/index.js +2 -2
- package/dist/json-render/index.css +1 -1
- package/dist/types/cli/daemon.d.ts +74 -0
- package/dist/types/cli/watch.d.ts +2 -2
- package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
- package/dist/types/client/canvas/CommandPalette.d.ts +1 -1
- package/dist/types/client/canvas/Minimap.d.ts +1 -1
- package/dist/types/client/nodes/FileNode.d.ts +1 -1
- package/dist/types/client/nodes/ImageNode.d.ts +1 -1
- package/dist/types/client/nodes/InlineFormatBar.d.ts +1 -1
- package/dist/types/client/nodes/MarkdownNode.d.ts +1 -1
- package/dist/types/client/nodes/PromptNode.d.ts +1 -1
- package/dist/types/client/nodes/ResponseNode.d.ts +1 -1
- package/dist/types/mcp/canvas-access.d.ts +0 -7
- package/dist/types/server/ax-state-manager.d.ts +3 -2
- package/dist/types/server/bundled-skills.d.ts +3 -3
- package/dist/types/server/canvas-schema.d.ts +1 -1
- package/dist/types/server/canvas-state.d.ts +2 -0
- package/dist/types/server/ext-app-lookup.d.ts +1 -3
- package/dist/types/server/html-primitives.d.ts +1 -1
- package/dist/types/server/index.d.ts +4 -4
- package/dist/types/server/operations/composites.d.ts +29 -23
- package/dist/types/server/operations/http.d.ts +2 -1
- package/dist/types/server/operations/index.d.ts +1 -1
- package/dist/types/server/operations/ops/ax-read.d.ts +2 -0
- package/dist/types/server/operations/ops/canvas-wire.d.ts +2 -0
- package/dist/types/server/operations/ops/ext-app.d.ts +2 -0
- package/dist/types/shared/ax-intent.d.ts +1 -1
- package/docs/RELEASE.md +23 -8
- package/docs/ax-host-adapter-contract.md +7 -7
- package/docs/ax-state-contract.md +7 -6
- package/docs/bun-webview-integration.md +5 -5
- package/docs/cli.md +1 -1
- package/docs/http-api.md +35 -3
- package/docs/mcp.md +121 -100
- package/docs/node-types.md +45 -35
- package/docs/plans/plan-006-mcp-tool-consolidation.md +3 -1
- package/docs/plans/plan-008-registry-finish.md +2 -0
- package/docs/plans/plan-009-tech-debt-backlog.md +51 -0
- package/docs/screenshot.png +0 -0
- package/docs/tech-debt-assessment-2026-06.md +1 -1
- package/docs/tech-debt-assessment-2026-07.md +135 -0
- package/package.json +5 -2
- package/skills/data-analysis/SKILL.md +3 -3
- package/skills/frontend-design/SKILL.md +3 -2
- package/skills/json-render-mcp/SKILL.md +4 -3
- package/skills/playwright-cli/SKILL.md +1 -1
- package/skills/pmx-canvas/SKILL.md +12 -7
- package/skills/pmx-canvas/evals/evals.json +2 -2
- package/skills/pmx-canvas/references/ax-html-control-surface.md +3 -1
- package/skills/pmx-canvas/references/excalidraw-diagram-authoring.md +2 -2
- package/skills/pmx-canvas/references/full-reference.md +58 -56
- package/skills/pmx-canvas/references/html-primitives.md +3 -3
- package/skills/tufte-viz/SKILL.md +5 -4
- package/skills/web-artifacts-builder/SKILL.md +4 -4
- package/src/cli/agent.ts +1861 -1548
- package/src/cli/daemon.ts +460 -0
- package/src/cli/index.ts +63 -326
- package/src/cli/watch.ts +2 -10
- package/src/client/App.tsx +48 -46
- package/src/client/canvas/AttentionHistory.tsx +11 -1
- package/src/client/canvas/CanvasNode.tsx +41 -29
- package/src/client/canvas/CanvasViewport.tsx +101 -66
- package/src/client/canvas/CommandPalette.tsx +61 -27
- package/src/client/canvas/ContextMenu.tsx +13 -20
- package/src/client/canvas/ContextPinBar.tsx +1 -5
- package/src/client/canvas/ContextPinHud.tsx +1 -6
- package/src/client/canvas/DockedNode.tsx +4 -4
- package/src/client/canvas/EdgeLayer.tsx +37 -36
- package/src/client/canvas/ExpandedNodeOverlay.tsx +69 -45
- package/src/client/canvas/FocusFieldLayer.tsx +20 -22
- package/src/client/canvas/IntentLayer.tsx +31 -14
- package/src/client/canvas/Minimap.tsx +11 -16
- package/src/client/canvas/SelectionBar.tsx +4 -11
- package/src/client/canvas/ShortcutOverlay.tsx +3 -1
- package/src/client/canvas/SnapshotPanel.tsx +77 -95
- package/src/client/canvas/auto-fit.ts +15 -14
- package/src/client/canvas/snap-guides.ts +12 -12
- package/src/client/canvas/use-node-resize.ts +1 -5
- package/src/client/canvas/use-pan-zoom.ts +25 -26
- package/src/client/ext-app/bridge.ts +3 -12
- package/src/client/icons.tsx +63 -20
- package/src/client/nodes/ContextNode.tsx +14 -25
- package/src/client/nodes/ExtAppFrame.tsx +60 -39
- package/src/client/nodes/FileNode.tsx +74 -62
- package/src/client/nodes/GroupNode.tsx +4 -6
- package/src/client/nodes/HtmlNode.tsx +76 -46
- package/src/client/nodes/ImageNode.tsx +18 -27
- package/src/client/nodes/InlineFormatBar.tsx +4 -21
- package/src/client/nodes/InlineMarkdownEditor.tsx +0 -1
- package/src/client/nodes/LedgerNode.tsx +10 -4
- package/src/client/nodes/MarkdownNode.tsx +3 -10
- package/src/client/nodes/McpAppNode.tsx +26 -22
- package/src/client/nodes/MdFormatBar.tsx +10 -7
- package/src/client/nodes/PromptNode.tsx +23 -51
- package/src/client/nodes/ResponseNode.tsx +3 -13
- package/src/client/nodes/StatusNode.tsx +5 -9
- package/src/client/nodes/StatusSummary.tsx +2 -8
- package/src/client/nodes/WebpageNode.tsx +20 -14
- package/src/client/nodes/iframe-document-url.ts +25 -16
- package/src/client/nodes/image-warnings.ts +1 -7
- package/src/client/nodes/md-format.ts +20 -5
- package/src/client/state/attention-bridge.ts +4 -9
- package/src/client/state/attention-store.ts +1 -7
- package/src/client/state/canvas-store.ts +52 -36
- package/src/client/state/intent-bridge.ts +176 -112
- package/src/client/state/intent-store.ts +4 -1
- package/src/client/state/sse-bridge.ts +53 -70
- package/src/json-render/catalog.ts +12 -16
- package/src/json-render/charts/components.tsx +16 -20
- package/src/json-render/charts/extra-components.tsx +8 -16
- package/src/json-render/charts/extra-definitions.ts +1 -2
- package/src/json-render/charts/tufte-components.tsx +37 -20
- package/src/json-render/charts/tufte-definitions.ts +8 -2
- package/src/json-render/renderer/index.tsx +42 -22
- package/src/json-render/schema.ts +6 -3
- package/src/json-render/server.ts +33 -39
- package/src/mcp/canvas-access.ts +40 -121
- package/src/mcp/server.ts +206 -271
- package/src/server/agent-context.ts +63 -36
- package/src/server/ax-context.ts +7 -5
- package/src/server/ax-interaction.ts +176 -43
- package/src/server/ax-state-manager.ts +185 -41
- package/src/server/ax-state.ts +142 -47
- package/src/server/bundled-skills.ts +3 -3
- package/src/server/canvas-db.ts +213 -95
- package/src/server/canvas-operations.ts +177 -120
- package/src/server/canvas-provenance.ts +1 -4
- package/src/server/canvas-schema.ts +500 -102
- package/src/server/canvas-serialization.ts +27 -35
- package/src/server/canvas-state.ts +155 -58
- package/src/server/chart-template.ts +4 -5
- package/src/server/code-graph.ts +20 -7
- package/src/server/diagram-presets.ts +28 -29
- package/src/server/ext-app-lookup.ts +4 -20
- package/src/server/html-node-summary.ts +19 -10
- package/src/server/html-primitives.ts +326 -97
- package/src/server/html-surface.ts +6 -9
- package/src/server/image-source.ts +6 -4
- package/src/server/index.ts +321 -218
- package/src/server/intent-registry.ts +3 -6
- package/src/server/mcp-app-candidate.ts +5 -10
- package/src/server/mcp-app-host.ts +14 -38
- package/src/server/mcp-app-runtime.ts +12 -20
- package/src/server/mutation-history.ts +15 -5
- package/src/server/operations/composites.ts +38 -40
- package/src/server/operations/http.ts +5 -5
- package/src/server/operations/index.ts +7 -1
- package/src/server/operations/invoker.ts +4 -3
- package/src/server/operations/mcp.ts +29 -36
- package/src/server/operations/ops/annotation.ts +122 -10
- package/src/server/operations/ops/app.ts +102 -77
- package/src/server/operations/ops/ax-await.ts +17 -10
- package/src/server/operations/ops/ax-read.ts +347 -0
- package/src/server/operations/ops/ax-shared.ts +2 -7
- package/src/server/operations/ops/ax-state.ts +32 -14
- package/src/server/operations/ops/ax-timeline.ts +32 -19
- package/src/server/operations/ops/ax-work.ts +54 -37
- package/src/server/operations/ops/batch.ts +39 -14
- package/src/server/operations/ops/canvas-wire.ts +91 -0
- package/src/server/operations/ops/edges.ts +37 -25
- package/src/server/operations/ops/ext-app.ts +346 -0
- package/src/server/operations/ops/groups.ts +49 -20
- package/src/server/operations/ops/intent.ts +18 -12
- package/src/server/operations/ops/json-render.ts +239 -98
- package/src/server/operations/ops/nodes.ts +300 -111
- package/src/server/operations/ops/query.ts +62 -33
- package/src/server/operations/ops/snapshots.ts +35 -26
- package/src/server/operations/ops/validate.ts +2 -1
- package/src/server/operations/ops/viewport.ts +60 -16
- package/src/server/operations/ops/webview.ts +44 -18
- package/src/server/operations/registry.ts +2 -3
- package/src/server/operations/types.ts +7 -5
- package/src/server/operations/webview-runner.ts +1 -3
- package/src/server/placement.ts +8 -18
- package/src/server/server.ts +121 -1012
- package/src/server/spatial-analysis.ts +39 -25
- package/src/server/trace-manager.ts +3 -8
- package/src/server/web-artifacts.ts +23 -27
- package/src/server/webpage-node.ts +5 -13
- package/src/shared/auto-arrange.ts +12 -5
- package/src/shared/ax-intent.ts +1 -1
- package/src/shared/content-height-reporter.ts +8 -6
- package/src/shared/ext-app-tool-result.ts +2 -6
- package/src/shared/placement.ts +1 -4
- package/src/shared/semantic-attention.ts +39 -37
- package/src/shared/surface.ts +8 -4
package/docs/mcp.md
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
# MCP reference
|
|
2
2
|
|
|
3
|
-
PMX Canvas ships an MCP stdio server with **
|
|
3
|
+
PMX Canvas ships an MCP stdio server with **27 tools** + **14 core resources**,
|
|
4
4
|
plus per-skill resources at `canvas://skills/<name>`. The server emits
|
|
5
5
|
`notifications/resources/updated` when canvas state changes — humans pin
|
|
6
6
|
nodes in the browser, agents are notified immediately.
|
|
7
7
|
|
|
8
|
-
> **Consolidation in
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
>
|
|
13
|
-
>
|
|
14
|
-
>
|
|
8
|
+
> **Consolidation completed in v0.3.0 (plan-006/008).** The MCP surface shrank
|
|
9
|
+
> from 84 tools to 27: 15 action-discriminated **composites** (recommended —
|
|
10
|
+
> see below) plus 12 standalone tools. The 57 legacy single-purpose tools that
|
|
11
|
+
> the composites replaced were removed in v0.3.0 per
|
|
12
|
+
> [`api-stability.md`](api-stability.md); their descriptions carried
|
|
13
|
+
> `Deprecated:` prefixes for one minor before removal. The 6 snapshot tools
|
|
14
|
+
> remain registered as deprecated standalones — they fold into a
|
|
15
|
+
> `canvas_snapshot` composite in v0.4 (see [Standalone tools](#standalone-tools)
|
|
16
|
+
> below). **Prefer the composites.**
|
|
15
17
|
|
|
16
18
|
## Connect
|
|
17
19
|
|
|
@@ -35,15 +37,15 @@ The canvas auto-starts on first tool call.
|
|
|
35
37
|
Action-discriminated tools that consolidate the single-purpose tools. Each maps
|
|
36
38
|
its `action` to the same operation the legacy tool used, so results are identical.
|
|
37
39
|
|
|
38
|
-
| Composite | `action` values |
|
|
40
|
+
| Composite | `action` values | Replaced (removed in v0.3.0) |
|
|
39
41
|
|-----------|-----------------|----------|
|
|
40
42
|
| `canvas_node` | `add` · `get` · `update` · `remove` | `canvas_add_node`, `canvas_get_node`, `canvas_update_node`, `canvas_remove_node`, `canvas_add_html_node` (`add` + `type:"html"`), `canvas_add_html_primitive` (`add` + `type:"html"`, `primitive:"<kind>"`), `canvas_refresh_webpage_node` (`update` + `refresh:true`) |
|
|
41
43
|
| `canvas_render` | `describe-schema` · `validate` · `add-json-render` · `stream-json-render` · `add-graph` | `canvas_describe_schema`, `canvas_validate_spec`, `canvas_add_json_render_node`, `canvas_stream_json_render_node`, `canvas_add_graph_node` |
|
|
42
44
|
| `canvas_edge` | `add` · `remove` | `canvas_add_edge`, `canvas_remove_edge` |
|
|
43
45
|
| `canvas_group` | `create` · `add` · `ungroup` | `canvas_create_group`, `canvas_group_nodes`, `canvas_ungroup` |
|
|
44
46
|
| `canvas_history` | `undo` · `redo` | `canvas_undo`, `canvas_redo` |
|
|
45
|
-
| `canvas_view` | `arrange` · `focus` · `fit` · `clear` | `canvas_arrange`, `canvas_focus_node`, `canvas_fit_view`, `canvas_clear` |
|
|
46
|
-
| `canvas_query` | `search` · `layout` | `canvas_search`, `canvas_get_layout` |
|
|
47
|
+
| `canvas_view` | `arrange` · `focus` · `fit` · `clear` · `remove-annotation` | `canvas_arrange`, `canvas_focus_node`, `canvas_fit_view`, `canvas_clear`, `canvas_remove_annotation` |
|
|
48
|
+
| `canvas_query` | `search` · `layout` · `validate` | `canvas_search`, `canvas_get_layout`, `canvas_validate` |
|
|
47
49
|
| `canvas_webview` | `status` · `start` · `stop` · `resize` · `evaluate` | `canvas_webview_status`, `canvas_webview_start`, `canvas_webview_stop`, `canvas_resize`, `canvas_evaluate` |
|
|
48
50
|
| `canvas_app` | `open-mcp-app` · `diagram` · `build-artifact` | `canvas_open_mcp_app`, `canvas_add_diagram`, `canvas_build_web_artifact` |
|
|
49
51
|
| `canvas_ax_state` | `get` · `set-focus` · `set-policy` · `report-capability` | `canvas_get_ax`, `canvas_set_ax_focus`, `canvas_set_ax_policy`, `canvas_report_host_capability` |
|
|
@@ -64,7 +66,7 @@ veto it — before the mutation lands.
|
|
|
64
66
|
- `clear` — abandon/dissolve it explicitly. Normal linked mutations settle automatically.
|
|
65
67
|
|
|
66
68
|
Intents are **ephemeral presence**: never persisted, never snapshotted, never in
|
|
67
|
-
`
|
|
69
|
+
`canvas_query { action: "layout" }`, and auto-expiring. They ride their own SSE channel
|
|
68
70
|
(`ax-intent` / `ax-intent-clear`) and replay to reconnecting browsers while still
|
|
69
71
|
live. Best practice — narrate your next move: `signal` → mutate with the returned
|
|
70
72
|
`intent.id` as `intentId`. A vetoed or expired linked mutation is rejected, and a
|
|
@@ -87,86 +89,105 @@ tools). `canvas_screenshot` also stays standalone — it returns a binary image
|
|
|
87
89
|
the composite/registry JSON wire shape does not model. (Wave 5 folded
|
|
88
90
|
`canvas_refresh_webpage_node` → `canvas_node { action: "update", refresh: true }` after
|
|
89
91
|
fixing `node.update`'s `formatResult` to surface a FAILED refresh as `isError` +
|
|
90
|
-
`{ ok:false, error }` instead of masking it as a false `{ ok:true }`.)
|
|
91
|
-
fold
|
|
92
|
+
`{ ok:false, error }` instead of masking it as a false `{ ok:true }`.) The 6
|
|
93
|
+
snapshot tools are the one deferred fold: a `canvas_snapshot` composite is
|
|
94
|
+
planned for v0.4 (the name collides with the legacy `canvas_snapshot` save
|
|
95
|
+
tool, and [`api-stability.md`](api-stability.md) requires deprecating a tool
|
|
96
|
+
for one minor before removing it) — they stay registered as deprecated
|
|
97
|
+
standalones until then.
|
|
92
98
|
|
|
93
|
-
##
|
|
99
|
+
## Standalone tools
|
|
100
|
+
|
|
101
|
+
12 tools that intentionally stay outside the composites — either because
|
|
102
|
+
folding them would hurt (distinct callers, binary payloads, trust-boundary or
|
|
103
|
+
execution-intent semantics), or because they're mid-deprecation pending a
|
|
104
|
+
v0.4 composite. See [Migration reference](#migration-reference) below for the
|
|
105
|
+
57 tools these composites replaced.
|
|
94
106
|
|
|
95
107
|
| Tool | Description |
|
|
96
108
|
|------|-------------|
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `canvas_add_diagram` | Hand-drawn diagram via the hosted Excalidraw MCP App (preset alias for `canvas_open_mcp_app`) |
|
|
101
|
-
| `canvas_open_mcp_app` | Open any [MCP Apps](https://modelcontextprotocol.io/docs/extensions/apps) server's `ui://` resource as an iframe node |
|
|
102
|
-
| `canvas_describe_schema` | Describe the running server's create schemas, examples, json-render catalog, and HTML primitive catalog |
|
|
103
|
-
| `canvas_validate_spec` | Validate a json-render spec, graph payload, or HTML primitive payload without creating a node |
|
|
104
|
-
| `canvas_refresh_webpage_node` | **Deprecated** → `canvas_node { action: "update", refresh: true }`. Re-fetch and update a webpage node from its stored URL |
|
|
105
|
-
| `canvas_add_json_render_node` | Create a native json-render node from a validated spec |
|
|
106
|
-
| `canvas_stream_json_render_node` | Progressively build a json-render node from SpecStream JSON-Patch ops (live/streaming panels) |
|
|
107
|
-
| `canvas_add_graph_node` | Create a native graph node (line, bar, pie, area, scatter, radar, stacked-bar, composed, sparkline, dot-plot, bullet, slopegraph) |
|
|
108
|
-
| `canvas_build_web_artifact` | Build a bundled HTML artifact and open it on the canvas |
|
|
109
|
-
|
|
110
|
-
`canvas_add_html_node` accepts optional `summary`, `agentSummary`, `embeddedNodeIds`, and
|
|
111
|
-
`embeddedUrls`. PMX also derives a bounded text summary from visible HTML, so rich HTML nodes stay
|
|
112
|
-
searchable and readable in pinned/spatial context.
|
|
113
|
-
| `canvas_update_node` | Update content, position, size, collapsed state |
|
|
114
|
-
| `canvas_remove_node` | Remove a node and its edges |
|
|
115
|
-
| `canvas_get_layout` | Get full canvas state |
|
|
116
|
-
| `canvas_get_node` | Get a single node by ID |
|
|
117
|
-
| `canvas_remove_annotation` | Remove a human-drawn annotation by ID |
|
|
118
|
-
| `canvas_add_edge` | Connect two nodes |
|
|
119
|
-
| `canvas_remove_edge` | Remove a connection |
|
|
120
|
-
| `canvas_arrange` | Auto-arrange (grid/column/flow) |
|
|
121
|
-
| `canvas_validate` | Validate collisions, containment, and missing edge endpoints |
|
|
122
|
-
| `canvas_focus_node` | Pan viewport to a node; use CLI `focus --no-pan` when you only need to select/raise |
|
|
123
|
-
| `canvas_fit_view` | Fit the canvas viewport to all nodes or a selected subset |
|
|
124
|
-
| `canvas_get_ax` | Read the PMX AX state (focus, work items, approvals, review annotations, host capability) plus pinned/focused context |
|
|
125
|
-
| `canvas_set_ax_focus` | Set the host-agnostic AX focus node set; adapters can pass a source such as `codex` |
|
|
126
|
-
| `canvas_record_ax_event` | Record a normalized timeline `agent-event` (prompt/assistant-message/tool-start/tool-result/failure/approval/steering) |
|
|
127
|
-
| `canvas_send_steering` | Record a `steering-message`: a user instruction from the surface to the active agent session |
|
|
128
|
-
| `canvas_get_ax_timeline` | Read the bounded AX timeline (events, evidence, steering) plus counts |
|
|
129
|
-
| `canvas_add_work_item` | Add a canvas-bound `work-item` (visible task/plan/status tied to nodes) |
|
|
130
|
-
| `canvas_update_work_item` | Update a work item's title/status/detail/nodeIds by ID |
|
|
131
|
-
| `canvas_request_approval` | Request human approval via an `approval-gate` (pending) before a high-impact action |
|
|
132
|
-
| `canvas_resolve_approval` | Resolve a pending approval gate (`approved`/`rejected`) |
|
|
133
|
-
| `canvas_add_evidence` | Record an `evidence-item` on the timeline (logs/tool-result/screenshot/file/diff/test-output) |
|
|
134
|
-
| `canvas_add_review_annotation` | Add a canvas-bound `review-annotation` (comment/finding) anchored to a node, file, or region |
|
|
135
|
-
| `canvas_report_host_capability` | Report a host/session `host-capability` for diagnostics |
|
|
109
|
+
| `canvas_batch` | Run a batch of canvas operations with `$ref` support |
|
|
110
|
+
| `canvas_pin_nodes` | Pin nodes to include in agent context |
|
|
111
|
+
| `canvas_invoke_command` | Invoke a registry command (`pmx.plan`, `pmx.execute`, `pmx.promote-context`, `pmx.summarize`, `pmx.review`); records a `command` agent-event, unknown names rejected |
|
|
136
112
|
| `canvas_ax_interaction` | Submit one capability-gated AX interaction envelope (`{ type, sourceNodeId, payload }`) that maps onto an AX operation; the server re-validates and clamps sandboxed surfaces to their own node |
|
|
137
|
-
| `canvas_claim_ax_delivery` | Claim undelivered steering messages for an adapterless consumer (loop-safe — never returns steering the consumer originated) |
|
|
138
|
-
| `canvas_mark_ax_delivery` | Mark a steering message delivered for a consumer |
|
|
139
|
-
| `canvas_request_elicitation` | Request structured human input via a canvas-bound `elicitation` (pending) |
|
|
140
|
-
| `canvas_respond_elicitation` | Respond to / resolve a pending elicitation |
|
|
141
|
-
| `canvas_request_mode` | Request a workflow `mode-request` transition (plan/execute/autonomous) |
|
|
142
|
-
| `canvas_resolve_mode` | Resolve a pending mode request |
|
|
143
113
|
| `canvas_ingest_activity` | Ingest a harness-forwarded agent activity (tool/session event); the board auto-reacts with kind-driven, overridable defaults (failure → work item + review + evidence; `tool-result`+success → evidence). Makes AX bidirectional |
|
|
144
|
-
| `canvas_await_approval` | Block until an approval gate resolves (human approves/rejects in the browser) or the timeout elapses (`timeoutMs` 0 = immediate read). Gates that actually gate |
|
|
145
|
-
| `canvas_await_elicitation` | Block until an elicitation is answered or the timeout elapses |
|
|
146
|
-
| `canvas_await_mode` | Block until a mode request resolves or the timeout elapses |
|
|
147
|
-
| `canvas_invoke_command` | Invoke a registry command (`pmx.plan`, `pmx.execute`, `pmx.promote-context`, `pmx.summarize`, `pmx.review`); records a `command` agent-event, unknown names rejected |
|
|
148
|
-
| `canvas_set_ax_policy` | Patch the canvas-bound tool/prompt policy (`tools.allowed\|excluded\|approvalRequired`, `prompt.systemAppend\|mode`); patches merge and are normalized |
|
|
149
|
-
| `canvas_pin_nodes` | Pin nodes to include in agent context |
|
|
150
|
-
| `canvas_clear` | Clear all nodes and edges |
|
|
151
|
-
| `canvas_snapshot` | Save current canvas as a named snapshot |
|
|
152
|
-
| `canvas_list_snapshots` | List saved snapshots, bounded to the newest 20 by default |
|
|
153
|
-
| `canvas_gc_snapshots` | Delete old snapshots while keeping the newest N |
|
|
154
|
-
| `canvas_restore` | Restore canvas from a saved snapshot |
|
|
155
|
-
| `canvas_delete_snapshot` | Delete a saved snapshot |
|
|
156
|
-
| `canvas_search` | Find nodes by title/content keywords |
|
|
157
|
-
| `canvas_undo` | Undo the last canvas mutation |
|
|
158
|
-
| `canvas_redo` | Redo the last undone mutation |
|
|
159
|
-
| `canvas_diff` | Compare current canvas vs a saved snapshot |
|
|
160
|
-
| `canvas_create_group` | Create a group containing specified nodes |
|
|
161
|
-
| `canvas_group_nodes` | Add nodes to an existing group |
|
|
162
|
-
| `canvas_ungroup` | Release all children from a group |
|
|
163
|
-
| `canvas_batch` | Run a batch of canvas operations with `$ref` support |
|
|
164
|
-
| `canvas_webview_status` | Get Bun.WebView automation status for the workbench |
|
|
165
|
-
| `canvas_webview_start` | Start or replace the Bun.WebView automation session |
|
|
166
|
-
| `canvas_webview_stop` | Stop the active Bun.WebView automation session |
|
|
167
|
-
| `canvas_evaluate` | Evaluate JavaScript in the active workbench automation session |
|
|
168
|
-
| `canvas_resize` | Resize the active workbench automation viewport |
|
|
169
114
|
| `canvas_screenshot` | Capture a screenshot from the active workbench automation session |
|
|
115
|
+
| `canvas_snapshot` | **Deprecated** → folds into the `canvas_snapshot` composite in v0.4 (actions `save\|list\|restore\|delete\|gc\|diff`). Save current canvas as a named snapshot |
|
|
116
|
+
| `canvas_list_snapshots` | **Deprecated** → folds into the `canvas_snapshot` composite in v0.4 (actions `save\|list\|restore\|delete\|gc\|diff`). List saved snapshots, bounded to the newest 20 by default |
|
|
117
|
+
| `canvas_restore` | **Deprecated** → folds into the `canvas_snapshot` composite in v0.4 (actions `save\|list\|restore\|delete\|gc\|diff`). Restore canvas from a saved snapshot |
|
|
118
|
+
| `canvas_delete_snapshot` | **Deprecated** → folds into the `canvas_snapshot` composite in v0.4 (actions `save\|list\|restore\|delete\|gc\|diff`). Delete a saved snapshot |
|
|
119
|
+
| `canvas_gc_snapshots` | **Deprecated** → folds into the `canvas_snapshot` composite in v0.4 (actions `save\|list\|restore\|delete\|gc\|diff`). Delete old snapshots while keeping the newest N |
|
|
120
|
+
| `canvas_diff` | **Deprecated** → folds into the `canvas_snapshot` composite in v0.4 (actions `save\|list\|restore\|delete\|gc\|diff`). Compare current canvas vs a saved snapshot |
|
|
121
|
+
|
|
122
|
+
`canvas_node { action: "add", type: "html" }` accepts optional `summary`, `agentSummary`,
|
|
123
|
+
`embeddedNodeIds`, and `embeddedUrls`. PMX also derives a bounded text summary from visible
|
|
124
|
+
HTML, so rich HTML nodes stay searchable and readable in pinned/spatial context.
|
|
125
|
+
|
|
126
|
+
## Migration reference
|
|
127
|
+
|
|
128
|
+
The 57 legacy single-purpose tools below were removed in v0.3.0. Each row is
|
|
129
|
+
the composite call that replaces it — kept as a lookup table for anyone
|
|
130
|
+
migrating an older integration.
|
|
131
|
+
|
|
132
|
+
| Removed tool | Composite replacement |
|
|
133
|
+
|------|-------------|
|
|
134
|
+
| `canvas_add_node` | `canvas_node { action: "add" }` |
|
|
135
|
+
| `canvas_get_node` | `canvas_node { action: "get" }` |
|
|
136
|
+
| `canvas_update_node` | `canvas_node { action: "update" }` |
|
|
137
|
+
| `canvas_remove_node` | `canvas_node { action: "remove" }` |
|
|
138
|
+
| `canvas_add_html_node` | `canvas_node { action: "add", type: "html" }` |
|
|
139
|
+
| `canvas_add_html_primitive` | `canvas_node { action: "add", type: "html", primitive: "<kind>" }` |
|
|
140
|
+
| `canvas_refresh_webpage_node` | `canvas_node { action: "update", refresh: true }` |
|
|
141
|
+
| `canvas_describe_schema` | `canvas_render { action: "describe-schema" }` |
|
|
142
|
+
| `canvas_validate_spec` | `canvas_render { action: "validate" }` |
|
|
143
|
+
| `canvas_add_json_render_node` | `canvas_render { action: "add-json-render" }` |
|
|
144
|
+
| `canvas_stream_json_render_node` | `canvas_render { action: "stream-json-render" }` |
|
|
145
|
+
| `canvas_add_graph_node` | `canvas_render { action: "add-graph" }` |
|
|
146
|
+
| `canvas_add_edge` | `canvas_edge { action: "add" }` |
|
|
147
|
+
| `canvas_remove_edge` | `canvas_edge { action: "remove" }` |
|
|
148
|
+
| `canvas_create_group` | `canvas_group { action: "create" }` |
|
|
149
|
+
| `canvas_group_nodes` | `canvas_group { action: "add" }` |
|
|
150
|
+
| `canvas_ungroup` | `canvas_group { action: "ungroup" }` |
|
|
151
|
+
| `canvas_undo` | `canvas_history { action: "undo" }` |
|
|
152
|
+
| `canvas_redo` | `canvas_history { action: "redo" }` |
|
|
153
|
+
| `canvas_arrange` | `canvas_view { action: "arrange" }` |
|
|
154
|
+
| `canvas_focus_node` | `canvas_view { action: "focus" }` |
|
|
155
|
+
| `canvas_fit_view` | `canvas_view { action: "fit" }` |
|
|
156
|
+
| `canvas_clear` | `canvas_view { action: "clear" }` |
|
|
157
|
+
| `canvas_remove_annotation` | `canvas_view { action: "remove-annotation" }` |
|
|
158
|
+
| `canvas_search` | `canvas_query { action: "search" }` |
|
|
159
|
+
| `canvas_get_layout` | `canvas_query { action: "layout" }` |
|
|
160
|
+
| `canvas_validate` | `canvas_query { action: "validate" }` |
|
|
161
|
+
| `canvas_open_mcp_app` | `canvas_app { action: "open-mcp-app" }` |
|
|
162
|
+
| `canvas_add_diagram` | `canvas_app { action: "diagram" }` |
|
|
163
|
+
| `canvas_build_web_artifact` | `canvas_app { action: "build-artifact" }` |
|
|
164
|
+
| `canvas_webview_status` | `canvas_webview { action: "status" }` |
|
|
165
|
+
| `canvas_webview_start` | `canvas_webview { action: "start" }` |
|
|
166
|
+
| `canvas_webview_stop` | `canvas_webview { action: "stop" }` |
|
|
167
|
+
| `canvas_resize` | `canvas_webview { action: "resize" }` |
|
|
168
|
+
| `canvas_evaluate` | `canvas_webview { action: "evaluate" }` |
|
|
169
|
+
| `canvas_get_ax` | `canvas_ax_state { action: "get" }` |
|
|
170
|
+
| `canvas_set_ax_focus` | `canvas_ax_state { action: "set-focus" }` |
|
|
171
|
+
| `canvas_set_ax_policy` | `canvas_ax_state { action: "set-policy" }` |
|
|
172
|
+
| `canvas_report_host_capability` | `canvas_ax_state { action: "report-capability" }` |
|
|
173
|
+
| `canvas_add_work_item` | `canvas_ax_work { action: "add" }` |
|
|
174
|
+
| `canvas_update_work_item` | `canvas_ax_work { action: "update" }` |
|
|
175
|
+
| `canvas_add_review_annotation` | `canvas_ax_work { action: "annotate" }` |
|
|
176
|
+
| `canvas_request_approval` | `canvas_ax_gate { kind: "approval", action: "request" }` |
|
|
177
|
+
| `canvas_resolve_approval` | `canvas_ax_gate { kind: "approval", action: "resolve" }` |
|
|
178
|
+
| `canvas_await_approval` | `canvas_ax_gate { kind: "approval", action: "await" }` |
|
|
179
|
+
| `canvas_request_elicitation` | `canvas_ax_gate { kind: "elicitation", action: "request" }` |
|
|
180
|
+
| `canvas_respond_elicitation` | `canvas_ax_gate { kind: "elicitation", action: "resolve" }` |
|
|
181
|
+
| `canvas_await_elicitation` | `canvas_ax_gate { kind: "elicitation", action: "await" }` |
|
|
182
|
+
| `canvas_request_mode` | `canvas_ax_gate { kind: "mode", action: "request" }` |
|
|
183
|
+
| `canvas_resolve_mode` | `canvas_ax_gate { kind: "mode", action: "resolve" }` |
|
|
184
|
+
| `canvas_await_mode` | `canvas_ax_gate { kind: "mode", action: "await" }` |
|
|
185
|
+
| `canvas_get_ax_timeline` | `canvas_ax_timeline { action: "read" }` |
|
|
186
|
+
| `canvas_record_ax_event` | `canvas_ax_timeline { action: "record-event" }` |
|
|
187
|
+
| `canvas_add_evidence` | `canvas_ax_timeline { action: "add-evidence" }` |
|
|
188
|
+
| `canvas_send_steering` | `canvas_ax_timeline { action: "send-steering" }` |
|
|
189
|
+
| `canvas_claim_ax_delivery` | `canvas_ax_delivery { action: "claim" }` |
|
|
190
|
+
| `canvas_mark_ax_delivery` | `canvas_ax_delivery { action: "mark" }` |
|
|
170
191
|
|
|
171
192
|
## Resources
|
|
172
193
|
|
|
@@ -255,27 +276,27 @@ raw stroke geometry or visual shape.
|
|
|
255
276
|
|
|
256
277
|
Annotations are a browser-visible markup layer. Use the pen toolbar button to
|
|
257
278
|
draw and the eraser toolbar button to remove an annotation again; agents can also
|
|
258
|
-
remove a known annotation ID with `
|
|
279
|
+
remove a known annotation ID with `canvas_view { action: "remove-annotation", id }`.
|
|
259
280
|
|
|
260
281
|
Use WebView automation when an agent needs to actually see annotations as drawn.
|
|
261
|
-
For example, inspect `.annotation-layer path` with `
|
|
262
|
-
`canvas_screenshot` to distinguish an arrow from a line, circle, or highlight.
|
|
282
|
+
For example, inspect `.annotation-layer path` with `canvas_webview { action: "evaluate" }`
|
|
283
|
+
or capture a `canvas_screenshot` to distinguish an arrow from a line, circle, or highlight.
|
|
263
284
|
|
|
264
285
|
## Node-type routing
|
|
265
286
|
|
|
266
|
-
MCP node creation uses dedicated
|
|
267
|
-
`mcp.nodeTypeRouting` from `
|
|
268
|
-
in doubt:
|
|
269
|
-
|
|
270
|
-
- `json-render` → `
|
|
271
|
-
- `graph` → `
|
|
272
|
-
- `html-primitive` → `canvas_node { action: "add", type: "html", primitive: "<kind>" }`
|
|
273
|
-
- `html` → `canvas_node { action: "add", type: "html" }`
|
|
274
|
-
- `web-artifact` → `
|
|
275
|
-
- `mcp-app` → `
|
|
276
|
-
- `group` → `
|
|
287
|
+
MCP node creation uses dedicated composite actions for structured node
|
|
288
|
+
families. Read `mcp.nodeTypeRouting` from `canvas_render { action:
|
|
289
|
+
"describe-schema" }` / `canvas://schema` when in doubt:
|
|
290
|
+
|
|
291
|
+
- `json-render` → `canvas_render { action: "add-json-render" }`
|
|
292
|
+
- `graph` → `canvas_render { action: "add-graph" }`
|
|
293
|
+
- `html-primitive` → `canvas_node { action: "add", type: "html", primitive: "<kind>" }`
|
|
294
|
+
- `html` → `canvas_node { action: "add", type: "html" }`
|
|
295
|
+
- `web-artifact` → `canvas_app { action: "build-artifact" }`
|
|
296
|
+
- `mcp-app` → `canvas_app { action: "open-mcp-app" }`
|
|
297
|
+
- `group` → `canvas_group { action: "create" }`
|
|
277
298
|
- Basic nodes (`markdown`, `status`, `file`, `image`, `webpage`) →
|
|
278
|
-
`
|
|
299
|
+
`canvas_node { action: "add" }`
|
|
279
300
|
|
|
280
301
|
## CLI/MCP alignment
|
|
281
302
|
|
package/docs/node-types.md
CHANGED
|
@@ -45,7 +45,7 @@ When an agent edits a file through its normal tools, the canvas node updates
|
|
|
45
45
|
automatically via `fs.watch()`.
|
|
46
46
|
|
|
47
47
|
```ts
|
|
48
|
-
|
|
48
|
+
canvas_node({ action: 'add', type: 'file', content: 'src/server/index.ts' })
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
## Image nodes
|
|
@@ -55,7 +55,8 @@ HTTP(S)-backed images preserve provenance so agents can tell where evidence
|
|
|
55
55
|
came from. Nodes can carry validation status or warnings.
|
|
56
56
|
|
|
57
57
|
```ts
|
|
58
|
-
|
|
58
|
+
canvas_node({
|
|
59
|
+
action: 'add',
|
|
59
60
|
type: 'image',
|
|
60
61
|
content: 'artifacts/dashboard.png',
|
|
61
62
|
data: {
|
|
@@ -73,8 +74,8 @@ keep enough information for an agent to refresh the node from the original
|
|
|
73
74
|
URL later.
|
|
74
75
|
|
|
75
76
|
```ts
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
canvas_node({ action: 'add', type: 'webpage', url: 'https://example.com/docs' })
|
|
78
|
+
canvas_node({ action: 'update', id: 'node-abc123', refresh: true })
|
|
78
79
|
```
|
|
79
80
|
|
|
80
81
|
## MCP App nodes
|
|
@@ -82,11 +83,12 @@ canvas_refresh_webpage_node({ id: 'node-abc123' })
|
|
|
82
83
|
`mcp-app` nodes embed other MCP servers' UI resources (`ui://...`) directly
|
|
83
84
|
on the canvas as sandboxed iframes. Any server implementing the
|
|
84
85
|
[MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps)
|
|
85
|
-
can be opened with `
|
|
86
|
+
can be opened with `canvas_app { action: "open-mcp-app" }`.
|
|
86
87
|
|
|
87
88
|
Generic `pmx-canvas node add --type mcp-app` is intentionally rejected —
|
|
88
|
-
these nodes need tool/session metadata. Use `
|
|
89
|
-
`
|
|
89
|
+
these nodes need tool/session metadata. Use `canvas_app { action:
|
|
90
|
+
"open-mcp-app" }` (or the `canvas_app { action: "diagram" }` Excalidraw
|
|
91
|
+
preset) instead.
|
|
90
92
|
|
|
91
93
|
### Excalidraw preset (hand-drawn diagrams)
|
|
92
94
|
|
|
@@ -95,7 +97,8 @@ server at `https://mcp.excalidraw.com/mcp`. PMX Canvas exposes a one-call
|
|
|
95
97
|
preset:
|
|
96
98
|
|
|
97
99
|
```ts
|
|
98
|
-
|
|
100
|
+
canvas_app({
|
|
101
|
+
action: 'diagram',
|
|
99
102
|
elements: [
|
|
100
103
|
{ type: 'rectangle', id: 'a', x: 80, y: 120, width: 180, height: 80,
|
|
101
104
|
roundness: { type: 3 }, backgroundColor: '#a5d8ff', fillStyle: 'solid',
|
|
@@ -111,8 +114,8 @@ canvas_add_diagram({
|
|
|
111
114
|
});
|
|
112
115
|
```
|
|
113
116
|
|
|
114
|
-
For any other MCP App, call `
|
|
115
|
-
transport, tool name, and arguments.
|
|
117
|
+
For any other MCP App, call `canvas_app { action: "open-mcp-app" }` directly
|
|
118
|
+
with the server's transport, tool name, and arguments.
|
|
116
119
|
|
|
117
120
|
## json-render nodes
|
|
118
121
|
|
|
@@ -122,7 +125,8 @@ transport, tool name, and arguments.
|
|
|
122
125
|
and component catalog (core + react + shadcn).
|
|
123
126
|
|
|
124
127
|
```ts
|
|
125
|
-
|
|
128
|
+
canvas_render({
|
|
129
|
+
action: 'add-json-render',
|
|
126
130
|
title: 'Deploy status',
|
|
127
131
|
spec: {
|
|
128
132
|
root: 'card',
|
|
@@ -144,7 +148,8 @@ host-provided handlers. PMX wires AX handlers named after interaction types, so
|
|
|
144
148
|
spec action named `ax.*` becomes a capability-gated AX interaction:
|
|
145
149
|
|
|
146
150
|
```ts
|
|
147
|
-
|
|
151
|
+
canvas_render({
|
|
152
|
+
action: 'add-json-render',
|
|
148
153
|
title: 'Approve plan',
|
|
149
154
|
spec: {
|
|
150
155
|
root: 'btn',
|
|
@@ -164,8 +169,8 @@ source + per-viewer nonce + node id) and submits it server-side; `json-render` /
|
|
|
164
169
|
`graph` viewers are sandboxed surfaces, so caller-supplied `nodeIds` are clamped
|
|
165
170
|
to the node's own id. See the [MCP reference](mcp.md#node-interactions-capability-gated).
|
|
166
171
|
|
|
167
|
-
Use `
|
|
168
|
-
component catalog before building a spec.
|
|
172
|
+
Use `canvas_render { action: "describe-schema" }` / `canvas_render { action:
|
|
173
|
+
"validate" }` to introspect the component catalog before building a spec.
|
|
169
174
|
|
|
170
175
|
## HTML nodes
|
|
171
176
|
|
|
@@ -182,7 +187,9 @@ match the active theme. Theme updates are posted into sandboxed HTML iframes,
|
|
|
182
187
|
so theme-aware HTML can follow dark/light switches without reopening the node.
|
|
183
188
|
|
|
184
189
|
```ts
|
|
185
|
-
|
|
190
|
+
canvas_node({
|
|
191
|
+
action: 'add',
|
|
192
|
+
type: 'html',
|
|
186
193
|
title: 'Cost projection',
|
|
187
194
|
html: '<canvas id="c"></canvas><script src="https://cdn.jsdelivr.net/npm/chart.js"></script><script>...</script>',
|
|
188
195
|
})
|
|
@@ -213,8 +220,10 @@ presentation, explainer, status report, incident report, triage board, config
|
|
|
213
220
|
editor, or prompt tuner.
|
|
214
221
|
|
|
215
222
|
```ts
|
|
216
|
-
|
|
217
|
-
|
|
223
|
+
canvas_node({
|
|
224
|
+
action: 'add',
|
|
225
|
+
type: 'html',
|
|
226
|
+
primitive: 'choice-grid',
|
|
218
227
|
title: 'Implementation options',
|
|
219
228
|
data: {
|
|
220
229
|
items: [
|
|
@@ -246,9 +255,9 @@ A **web artifact** is a single-file, fully bundled HTML app (React + Tailwind
|
|
|
246
255
|
real interactive app — charts, forms, mini-dashboards — beyond what a static
|
|
247
256
|
node or `html` snippet can express.
|
|
248
257
|
|
|
249
|
-
`
|
|
250
|
-
`index.css`, `main.tsx`, `index.html`, plus extra files), runs the
|
|
251
|
-
web-artifacts-builder scripts, writes the self-contained HTML to
|
|
258
|
+
`canvas_app { action: "build-artifact" }` takes source strings (`App.tsx`,
|
|
259
|
+
optional `index.css`, `main.tsx`, `index.html`, plus extra files), runs the
|
|
260
|
+
bundled web-artifacts-builder scripts, writes the self-contained HTML to
|
|
252
261
|
`.pmx-canvas/artifacts/<slug>.html`, and (by default) opens it in the canvas.
|
|
253
262
|
|
|
254
263
|
```bash
|
|
@@ -277,7 +286,7 @@ as dashed-border frames with a title bar and optional accent color.
|
|
|
277
286
|
lay children out inside it
|
|
278
287
|
|
|
279
288
|
```ts
|
|
280
|
-
|
|
289
|
+
canvas_group({ action: 'create', title: 'Auth Module', childIds: ['node-1', 'node-2'], color: '#4a9eff' })
|
|
281
290
|
```
|
|
282
291
|
|
|
283
292
|
## Edge types
|
|
@@ -296,25 +305,26 @@ All edges support labels, styles (solid/dashed/dotted), and animation.
|
|
|
296
305
|
Agents don't have to guess node shapes. The running server exposes its create
|
|
297
306
|
schemas, json-render component catalog, and node-type examples:
|
|
298
307
|
|
|
299
|
-
- `
|
|
300
|
-
schemas, required fields, json-render components, HTML primitives, and sample payloads
|
|
301
|
-
- `
|
|
308
|
+
- `canvas_render { action: "describe-schema" }` / `GET /api/canvas/schema` — list all
|
|
309
|
+
node-create schemas, required fields, json-render components, HTML primitives, and sample payloads
|
|
310
|
+
- `canvas_render { action: "validate" }` / `POST /api/canvas/schema/validate` — validate a
|
|
302
311
|
json-render spec, graph payload, or HTML primitive payload **without** creating a node
|
|
303
|
-
- `
|
|
312
|
+
- `canvas_query { action: "validate" }` / `GET /api/canvas/validate` — validate the current
|
|
304
313
|
layout for collisions, containment, and missing edge endpoints
|
|
305
314
|
- `canvas://schema` — the same data as an MCP resource
|
|
306
315
|
|
|
307
316
|
The CLI's `node schema` / `validate spec` subcommands surface the same data
|
|
308
317
|
from the terminal.
|
|
309
318
|
|
|
310
|
-
MCP node creation uses dedicated
|
|
311
|
-
`mcp.nodeTypeRouting` from `
|
|
312
|
-
|
|
313
|
-
`
|
|
314
|
-
`
|
|
315
|
-
`html` → `
|
|
316
|
-
`
|
|
317
|
-
`
|
|
318
|
-
`
|
|
319
|
+
MCP node creation uses dedicated composite actions for structured node
|
|
320
|
+
families. Read `mcp.nodeTypeRouting` from `canvas_render { action:
|
|
321
|
+
"describe-schema" }` when in doubt:
|
|
322
|
+
`json-render` → `canvas_render { action: "add-json-render" }`,
|
|
323
|
+
`graph` → `canvas_render { action: "add-graph" }`,
|
|
324
|
+
`html-primitive` → `canvas_node { action: "add", type: "html", primitive: "<kind>" }`,
|
|
325
|
+
`html` → `canvas_node { action: "add", type: "html" }`,
|
|
326
|
+
`web-artifact` → `canvas_app { action: "build-artifact" }`,
|
|
327
|
+
`mcp-app` → `canvas_app { action: "open-mcp-app" }`,
|
|
328
|
+
`group` → `canvas_group { action: "create" }`.
|
|
319
329
|
Basic nodes (`markdown`, `status`, `file`, `image`, `webpage`) use
|
|
320
|
-
`
|
|
330
|
+
`canvas_node { action: "add" }`.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Plan 006: MCP tool consolidation (69 tools to 21)
|
|
2
2
|
|
|
3
|
-
**Status
|
|
3
|
+
**Status: completed in v0.3.0 (canvas_snapshot composite moved to v0.4).**
|
|
4
|
+
|
|
5
|
+
**Status (historical):** In progress — wave 1 landed (7 canvas composites) and the AX wave landed (5 composites: `canvas_ax_state`, `canvas_ax_work`, `canvas_ax_gate`, `canvas_ax_timeline`, `canvas_ax_delivery`). Remaining (closed by plan-008 + the v0.3.0 removal): `canvas_snapshot` (name held by the legacy save tool until v0.4), `canvas_app`/`canvas_webview` (landed via plan-005 item 8), and the deferred actions `refresh` / `add-primitive` / `remove-annotation` / board validation (landed via plan-008 waves 1 and 5).
|
|
4
6
|
**Date:** 2026-06-12
|
|
5
7
|
**Depends on:** plan-005 (operation registry). Slices 1-4 are migrated; consolidation lands per-domain as the corresponding registry slices complete.
|
|
6
8
|
**Motivation:** docs/tech-debt-assessment-2026-06.md item 2. Governed by docs/api-stability.md (deprecation: marked in one minor, removed in the next).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Plan 008 — Finish the operation-registry refactor (plan-005 items 8–9 + plan-006 completion)
|
|
2
2
|
|
|
3
|
+
**Status: completed in v0.3.0 (canvas_snapshot composite moved to v0.4).**
|
|
4
|
+
|
|
3
5
|
**Status:** Complete
|
|
4
6
|
**Date:** 2026-06-15
|
|
5
7
|
**Depends on:** plan-005 (registry — slices 1–7 merged), plan-006 (consolidation — waves 1–2 merged), plan-007 (AX domain — merged).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Plan 009 — Tech debt backlog (open findings from the July 2026 assessment)
|
|
2
|
+
|
|
3
|
+
**Status:** Open
|
|
4
|
+
**Date:** 2026-07-06
|
|
5
|
+
**Motivation:** [`docs/tech-debt-assessment-2026-07.md`](../tech-debt-assessment-2026-07.md) (revised 2026-07-06). The v0.3.0 tree plus the same-day fix pass closed H1, H2, M12, and the small residuals of C2/C3/M4/M7/M9/L7. This plan records everything still open so it survives the release. Finding IDs below refer to the assessment, which carries the full `file:line` evidence.
|
|
6
|
+
|
|
7
|
+
Each item is tagged by shape: **project** (multi-day, own plan/PR), **decision** (needs a maintainer call before code), or **small** (safe standalone change).
|
|
8
|
+
|
|
9
|
+
## Phase 1 — finish what was started
|
|
10
|
+
|
|
11
|
+
| Item | Source | What's open | Shape |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| Complete the registry migration | C1 | Fold the remaining hand-written routes in `server.ts` into operations; collapse the 76-method `PmxCanvas` onto `executeOperation`; migrate the CLI's 60 raw `fetch` calls onto the operation invoker. **Slice 1 done post-0.3.0:** the 7 `/api/ext-app/*` routes moved to `ops/ext-app.ts` (~290 lines out of `server.ts`, the 5 clone handlers — old M5 — collapsed to one parametrized definition; wire envelopes byte-identical, no new MCP tools). **Slice 2 done:** the 15 ax wire routes (8 GET lists + `ax/context` + `ax/surface-snapshot` + `pinned-context` + `code-graph` + `ax/activity` + `ax/interaction` + legacy `PATCH /api/canvas/ax`) moved to `ops/ax-read.ts` (~370 more lines out of `server.ts`); `open-external` stays hand-written (coupled to the live server port + system browser opener). **Slice 3 done:** theme GET/POST, canvas update, viewport, annotation POST, and node `:id/refresh` moved to the registry (`ops/canvas-wire.ts`, plus additions to `ops/viewport.ts`, `ops/annotation.ts`, `ops/nodes.ts`); the two dispatch gates unified into one `/api/` gate; `server.ts` is at ~2,980 lines (from 3,873 at the audit). **Remaining routes (~20)** are the deliberate poor fits (SSE, binary, HTML/static, file bodies) plus four server-coupled handlers: `prompt` + workbench `state`/`open`/`intent` (module-local `primaryWorkbench*` session state), `render` (Excalidraw URL-normalizer chain), `open-external` (live port + system browser). Those need state injection like the webview runner — a deliberate follow-up, not mechanical. After routes, the bigger halves remain: `PmxCanvas` (76 methods) onto `executeOperation`, and the CLI's raw fetches onto the invoker. | project (in progress) |
|
|
14
|
+
| One HTTP envelope | M4 residual | Registry ops return bare bodies, legacy ext-app handlers `{ok:true,result}`, 404s plaintext. Unify (naturally falls out of C1). Also: surface persistence save failures via a `/health` degraded flag — `canvas-state.ts` has 63 catch→warn→continue sites. | project (with C1) |
|
|
15
|
+
| `dist/` commit policy | C3 residual | **Decided + done post-0.3.0:** `dist/` stays committed; `test.yml` now has a `dist/types` staleness gate (rebuild + fail on drift). The `dist/canvas`/`dist/json-render` bundles are deliberately not byte-checked — bundler output varies across bun versions; their staleness story folds into M1. | done |
|
|
16
|
+
| Skill-mirror validator | C2 residual | `validate:agent-skills` exits 0 when the (local-only, gitignored) trees are absent. Docs are honest about this now; decide whether to repoint, gate, or delete the check. | decision |
|
|
17
|
+
| Generate CLAUDE.md/AGENTS.md from one source | M9 residual | The twins are byte-identical again but still hand-maintained; generate or symlink to prevent the next drift. | small |
|
|
18
|
+
|
|
19
|
+
## Phase 2 — make the safety net real
|
|
20
|
+
|
|
21
|
+
| Item | Source | What's open | Shape |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| Lint/format tooling | H6 | **Done post-0.3.0:** Biome 2.5 adopted — `bun run lint` / `lint:fix`, wired into `release:check` (making RELEASE.md's "lints" claim true) and CI. First-run format sweep landed as its own mechanical commit; 7 lint errors hand-fixed (incl. a real conditional-hooks bug in `SelectionBar.tsx`). Deliberately disabled rules to revisit: a11y group, `useExhaustiveDependencies` (misfires on Preact signals), `noNonNullAssertion` (143 deliberate uses), `noArrayIndexKey` (13 sites). ~77 warnings (unused imports/vars, optional-chain) left as a burn-down list — warnings don't fail the gate. | done |
|
|
24
|
+
| Client + server unit coverage | H7 | Zero component render tests (no DOM test lib in repo); untested big modules: `ax-state-manager.ts` (826 lines), `mcp-app-host.ts` (814), `canvas-schema.ts` (644), `shared/semantic-attention.ts` (600, in zero test files). Coverage is collected but gates nothing; tests aren't typechecked. Add `happy-dom` + `@testing-library/preact`, a tests tsconfig, and a coverage threshold. | project |
|
|
25
|
+
| Daemon port/lock lifecycle | H4 | **Fixed post-0.3.0** (`src/cli/daemon.ts` + `tests/unit/cli-daemon.test.ts`). Note the original finding was partly wrong: the daemon child was already strict-port (`PmxCanvas.start` pins `allowPortFallback: false`), so fallback-blind polling could not occur. The real defects — fixed — were: the pre-check accepted any responsive `/health` as "already running" (even a foreign workspace's daemon), a TOCTOU double-spawn window, the pid recorded only after health passed (slow start → unkillable orphan), and no PID-recycling guard. The flaky `pmx-canvas-sdk.test.ts` port collision is NOT this — it's M8's copy-pasted `getAvailablePort()` racing. | done |
|
|
26
|
+
| Test-suite structure | M8 | Integration monoliths under `tests/unit/` (`server-api` 5,213 lines, `cli-node` 2,903); `getAvailablePort()` copy-pasted in 5 files; `waitForPersistence(650ms)` fixed sleeps in 9 files + ~19 magic `Bun.sleep`s; Playwright lacks `retries`/`forbidOnly`; `test:e2e-cli` (517-line script) runs in no CI workflow. *Post-0.3.0:* `operation-parity` now binds port 0 and derives the port from the base URL (removes one reserve-then-rebind race); the shared-helper dedup and the rest remain. Also noted: `ax-parity.test.ts` is a string-matching source-analysis test whose needles broke when Biome re-wrapped `cmd(` calls — its CLI needles are now layout-independent, but any future needle should avoid depending on line layout. **Also noted (2026-07-07):** the `server-api` Excalidraw diagram tests do real network round-trips to the hosted `mcp.excalidraw.com` MCP server and intermittently time out (30s) under full parallel runs — they should be mocked or moved to a network-tagged tier. | project |
|
|
27
|
+
| `noUncheckedIndexedAccess` | L7 residual | Enable in tsconfig; will surface many index-access errors — treat as its own sweep. | small (noisy) |
|
|
28
|
+
|
|
29
|
+
## Phase 3 — client consolidation
|
|
30
|
+
|
|
31
|
+
| Item | Source | What's open | Shape |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| One node factory | H5 | `sse-bridge.ts` (1,066 lines) keeps its own `DEFAULT_POSITIONS`/`makeNode` divergent from `canvas-store`; `responseToThreadMap` is not cleaned on SSE reconnect; server-side `syncEventToCanvasState` (~330 lines) mirrors it as an if/else chain with geometry defaults duplicated against `ensureDefaultDockedNodes`. Share one factory; treat `canvas-layout-update` as the single source of truth; table-drive the event sync. | project |
|
|
34
|
+
| Shared AX iframe bridge | M2 | The ~33-line `onAxMessage` listener is copy-pasted in `HtmlNode.tsx`, `McpAppNode.tsx`, `ExtAppFrame.tsx`; `pmx-canvas-ax` protocol string spread across 9 sites. This is the sandboxed-surface trust boundary (prior near-miss: LRN-20260607-005). Extract `useAxSurfaceBridge` + a protocol-constants module. | project (security-adjacent) |
|
|
35
|
+
| `ExtAppFrame.tsx` timing hacks | M3 | 915 lines, 12 refs, 7 `setTimeout`s, 5 rAFs, WebKit remount slot counter, 1200 ms fallback bootstrap, two near-duplicate `buildHostContext` blocks. Extract `useExtAppBridge`; single `buildHostContext`. | project |
|
|
36
|
+
| json-render stack decision | M1 | Preact + React 19 + recharts all runtime deps; 7 exact-pinned `@json-render/*` incl. 3 devtools packages shipped; `dist/json-render/index.js` 1.37 MB and `dist/canvas/index.js` 599 KB both unminified; build script shells to python3 with a stale-bundle fallback. Minimum: minify, move devtools to devDependencies, lazy-load the viewer, replace the python mtime gate. Bigger call: separate optional package if the React stack stays. | decision + project |
|
|
37
|
+
| Client dead code / duplication | L1, L2, L3 | `ContextPinHud.tsx` unreferenced; three pure re-export shims; two parallel markdown-format stacks; `global.css` 3,746 lines with 11 `!important` vs 227 inline styles and unscaled z-indexes. | small (batchable) |
|
|
38
|
+
|
|
39
|
+
## Smaller items (no phase, pick up opportunistically)
|
|
40
|
+
|
|
41
|
+
| Item | Source | What's open |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| Per-action composite schemas | M6 | Composite tools advertise every field optional; per-action required fields fail only at runtime. Decide: `oneOf` schemas vs per-action requirement docs. (Now the only schema surface agents see.) |
|
|
44
|
+
| Packaging | M10 | `files` ships both `src/` and `dist/` (~double tarball, two import paths); `bin` points at raw `.ts` (undocumented Bun-only constraint); `@types/turndown` in runtime deps. |
|
|
45
|
+
| Env var hygiene | M11 residual | `PMX_CANVAS_PORT` vs `PMX_WEB_CANVAS_PORT` applied inconsistently across entry points; `PMX_DATA` (15 uses) and the `PMX_CANVAS_JSON_RENDER_*` / `PMX_MCP_APP_HOST_*` families undocumented. |
|
|
46
|
+
| `publish.yml` e2e gap | M11 residual | Publishing skips e2e with no verification that the tagged SHA passed `test.yml`. |
|
|
47
|
+
| MCP notification fan-out | M7 residual | Five `canvas://` resource URIs notify on every mutation regardless of type (`mcp/server.ts:95-99`). |
|
|
48
|
+
| Legacy migration code on every boot | L4 | JSON→SQLite migration runs unconditionally (`canvas-state.ts:758,785`); gate behind a one-shot marker and retire. |
|
|
49
|
+
| Suppression/mutation plumbing | L5 | Two parallel suppression depth-counters; `onMutation` is a single-slot setter wired twice (last-write-wins). |
|
|
50
|
+
| Module-global lifecycle leaks | L6 | ~20 module-level `let`s in `server.ts`; code-graph debounce timer survives `stopCanvasServer`; remote SSE watcher loop has no cancellation. |
|
|
51
|
+
| June doc citations | L7 residual | `tech-debt-assessment-2026-06.md` cites gitignored `.learnings/` entries future maintainers can't read. |
|
package/docs/screenshot.png
CHANGED
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tech Debt Assessment & Direction Proposal — June 2026
|
|
2
2
|
|
|
3
|
-
**Status:**
|
|
3
|
+
**Status:** Superseded by [tech-debt-assessment-2026-07.md](tech-debt-assessment-2026-07.md)
|
|
4
4
|
**Date:** 2026-06-10
|
|
5
5
|
**Scope:** Full-repo audit at v0.1.36 (~70k lines TS; src/server 23.2k, src/client 13.9k, src/mcp 4.2k, src/cli 4.0k)
|
|
6
6
|
|