pmx-canvas 0.2.6 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +156 -1
- package/Readme.md +13 -11
- package/dist/canvas/index.js +18 -18
- package/dist/json-render/index.css +1 -1
- package/dist/types/mcp/canvas-access.d.ts +23 -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-state.d.ts +2 -0
- package/dist/types/server/ext-app-lookup.d.ts +1 -3
- package/dist/types/server/operations/composites.d.ts +29 -23
- package/dist/types/server/operations/http.d.ts +2 -1
- 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 +7 -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 +1 -1
- 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 +20 -15
- 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 +65 -62
- 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/client/App.tsx +2 -1
- package/src/mcp/canvas-access.ts +115 -107
- package/src/mcp/server.ts +74 -201
- package/src/server/ax-state-manager.ts +3 -2
- package/src/server/bundled-skills.ts +3 -3
- package/src/server/canvas-schema.ts +46 -29
- package/src/server/canvas-state.ts +5 -0
- package/src/server/code-graph.ts +1 -1
- package/src/server/ext-app-lookup.ts +1 -8
- package/src/server/index.ts +1 -1
- package/src/server/intent-registry.ts +1 -1
- package/src/server/operations/composites.ts +39 -39
- package/src/server/operations/http.ts +3 -2
- package/src/server/operations/mcp.ts +7 -6
- package/src/server/operations/ops/app.ts +4 -4
- package/src/server/operations/ops/nodes.ts +5 -5
- package/src/server/operations/ops/query.ts +19 -8
- package/src/server/operations/ops/snapshots.ts +6 -6
- package/src/server/server.ts +40 -4
- package/src/shared/ax-intent.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,160 @@
|
|
|
3
3
|
All notable changes to `pmx-canvas` are documented here. This project follows
|
|
4
4
|
[Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
-
## [
|
|
6
|
+
## [0.3.0] - 2026-07-07
|
|
7
|
+
|
|
8
|
+
### Breaking
|
|
9
|
+
|
|
10
|
+
- **MCP tool surface shrinks from 84 to 27.** The 57 deprecated legacy
|
|
11
|
+
single-purpose MCP tools left over from the v0.2 composites migration are
|
|
12
|
+
removed. Each has a direct composite replacement — same operation, new
|
|
13
|
+
entry point:
|
|
14
|
+
- **`canvas_node`**: `canvas_add_node` → `action: "add"`; `canvas_get_node`
|
|
15
|
+
→ `action: "get"`; `canvas_update_node` → `action: "update"`;
|
|
16
|
+
`canvas_remove_node` → `action: "remove"`; `canvas_add_html_node` →
|
|
17
|
+
`action: "add"` with `type: "html"`; `canvas_add_html_primitive` →
|
|
18
|
+
`action: "add"` with `type: "html"` + `primitive: "<kind>"`;
|
|
19
|
+
`canvas_refresh_webpage_node` → `action: "update"` with `refresh: true`.
|
|
20
|
+
- **`canvas_render`**: `canvas_describe_schema` → `action:
|
|
21
|
+
"describe-schema"`; `canvas_validate_spec` → `action: "validate"`;
|
|
22
|
+
`canvas_add_json_render_node` → `action: "add-json-render"`;
|
|
23
|
+
`canvas_stream_json_render_node` → `action: "stream-json-render"`;
|
|
24
|
+
`canvas_add_graph_node` → `action: "add-graph"`.
|
|
25
|
+
- **`canvas_edge`**: `canvas_add_edge` → `action: "add"`;
|
|
26
|
+
`canvas_remove_edge` → `action: "remove"`.
|
|
27
|
+
- **`canvas_group`**: `canvas_create_group` → `action: "create"`;
|
|
28
|
+
`canvas_group_nodes` → `action: "add"`; `canvas_ungroup` → `action:
|
|
29
|
+
"ungroup"`.
|
|
30
|
+
- **`canvas_history`**: `canvas_undo` → `action: "undo"`; `canvas_redo` →
|
|
31
|
+
`action: "redo"`.
|
|
32
|
+
- **`canvas_view`**: `canvas_arrange` → `action: "arrange"`;
|
|
33
|
+
`canvas_focus_node` → `action: "focus"`; `canvas_fit_view` → `action:
|
|
34
|
+
"fit"`; `canvas_clear` → `action: "clear"`; `canvas_remove_annotation` →
|
|
35
|
+
`action: "remove-annotation"`.
|
|
36
|
+
- **`canvas_query`**: `canvas_search` → `action: "search"`;
|
|
37
|
+
`canvas_get_layout` → `action: "layout"`; `canvas_validate` → `action:
|
|
38
|
+
"validate"`.
|
|
39
|
+
- **`canvas_app`**: `canvas_open_mcp_app` → `action: "open-mcp-app"`;
|
|
40
|
+
`canvas_add_diagram` → `action: "diagram"`; `canvas_build_web_artifact` →
|
|
41
|
+
`action: "build-artifact"`.
|
|
42
|
+
- **`canvas_webview`**: `canvas_webview_status` → `action: "status"`;
|
|
43
|
+
`canvas_webview_start` → `action: "start"`; `canvas_webview_stop` →
|
|
44
|
+
`action: "stop"`; `canvas_resize` → `action: "resize"`; `canvas_evaluate`
|
|
45
|
+
→ `action: "evaluate"`.
|
|
46
|
+
- **`canvas_ax_state`**: `canvas_get_ax` → `action: "get"`;
|
|
47
|
+
`canvas_set_ax_focus` → `action: "set-focus"`; `canvas_set_ax_policy` →
|
|
48
|
+
`action: "set-policy"`; `canvas_report_host_capability` → `action:
|
|
49
|
+
"report-capability"`.
|
|
50
|
+
- **`canvas_ax_work`**: `canvas_add_work_item` → `action: "add"`;
|
|
51
|
+
`canvas_update_work_item` → `action: "update"`;
|
|
52
|
+
`canvas_add_review_annotation` → `action: "annotate"`.
|
|
53
|
+
- **`canvas_ax_gate`**: `canvas_request_approval` → `kind: "approval"`,
|
|
54
|
+
`action: "request"`; `canvas_resolve_approval` → `kind: "approval"`,
|
|
55
|
+
`action: "resolve"`; `canvas_await_approval` → `kind: "approval"`,
|
|
56
|
+
`action: "await"`; `canvas_request_elicitation` → `kind: "elicitation"`,
|
|
57
|
+
`action: "request"`; `canvas_respond_elicitation` → `kind:
|
|
58
|
+
"elicitation"`, `action: "resolve"`; `canvas_await_elicitation` → `kind:
|
|
59
|
+
"elicitation"`, `action: "await"`; `canvas_request_mode` → `kind:
|
|
60
|
+
"mode"`, `action: "request"`; `canvas_resolve_mode` → `kind: "mode"`,
|
|
61
|
+
`action: "resolve"`; `canvas_await_mode` → `kind: "mode"`, `action:
|
|
62
|
+
"await"`.
|
|
63
|
+
- **`canvas_ax_timeline`**: `canvas_get_ax_timeline` → `action: "read"`;
|
|
64
|
+
`canvas_record_ax_event` → `action: "record-event"`; `canvas_add_evidence`
|
|
65
|
+
→ `action: "add-evidence"`; `canvas_send_steering` → `action:
|
|
66
|
+
"send-steering"`.
|
|
67
|
+
- **`canvas_ax_delivery`**: `canvas_claim_ax_delivery` → `action: "claim"`;
|
|
68
|
+
`canvas_mark_ax_delivery` → `action: "mark"`.
|
|
69
|
+
|
|
70
|
+
The HTTP API, the SDK, and `canvas_batch` are unaffected — these are the
|
|
71
|
+
same underlying operations, only the standalone MCP tool entry points are
|
|
72
|
+
removed. `docs/mcp.md` retains the full migration table for reference.
|
|
73
|
+
|
|
74
|
+
- **Malformed JSON request bodies now return 400.** Every HTTP API route
|
|
75
|
+
responds `400 { ok: false, error: "Malformed JSON body." }` when a non-empty
|
|
76
|
+
body fails to parse, instead of silently treating it as an empty request.
|
|
77
|
+
Empty bodies are still accepted.
|
|
78
|
+
|
|
79
|
+
### Deprecated
|
|
80
|
+
|
|
81
|
+
- The 6 snapshot standalone tools (`canvas_snapshot`, `canvas_list_snapshots`,
|
|
82
|
+
`canvas_restore`, `canvas_delete_snapshot`, `canvas_gc_snapshots`,
|
|
83
|
+
`canvas_diff`) now carry deprecation notices in their tool descriptions and
|
|
84
|
+
fold into a `canvas_snapshot` composite (`action: save|list|restore|delete
|
|
85
|
+
|gc|diff`) in v0.4.
|
|
86
|
+
|
|
87
|
+
### Removed
|
|
88
|
+
|
|
89
|
+
- Legacy `ext-app-ext-app-…` double-prefix blob-lookup fallback in
|
|
90
|
+
`findCanvasExtAppNodeId` (`src/server/ext-app-lookup.ts`), scheduled for
|
|
91
|
+
removal since v0.1.4. All ext-app node IDs have carried the single-prefix
|
|
92
|
+
form since then; the primary lookup and the data-scan fallback are
|
|
93
|
+
unaffected.
|
|
94
|
+
- The orphaned `dist/client` bundle and the generated web-artifact build
|
|
95
|
+
projects under `.pmx-canvas/artifacts/.web-artifacts/` are no longer
|
|
96
|
+
committed to the repo.
|
|
97
|
+
|
|
98
|
+
### Fixed
|
|
99
|
+
|
|
100
|
+
- HTTP `GET /api/canvas/search` now honors the `limit` query parameter
|
|
101
|
+
(previously only the MCP tool applied it).
|
|
102
|
+
- The SDK's `setContextPins` emits the same `context-pins-changed` event as
|
|
103
|
+
the HTTP API and MCP tool, instead of a full layout update.
|
|
104
|
+
- `canvas_ax_interaction` and `canvas_ingest_activity` return a clean tool
|
|
105
|
+
error instead of an MCP protocol error when they fail.
|
|
106
|
+
- The code graph resolves workspace-relative imports against the configured
|
|
107
|
+
workspace root instead of the server process working directory.
|
|
108
|
+
- The MCP server now reports the real package version in its handshake
|
|
109
|
+
(read from `package.json`) instead of a stale hard-coded `0.1.0`.
|
|
110
|
+
|
|
111
|
+
### Docs
|
|
112
|
+
|
|
113
|
+
- Operation descriptions and field hints no longer route agents to MCP tools
|
|
114
|
+
removed in v0.3.0.
|
|
115
|
+
|
|
116
|
+
## [0.2.7] - 2026-06-25
|
|
117
|
+
|
|
118
|
+
### Fixed
|
|
119
|
+
|
|
120
|
+
- **Ghost Cursor of Intent is no longer hidden behind the welcome card on an empty board (report
|
|
121
|
+
Finding J).** The intent ghost lives inside the zoom/pan world transform (its own stacking
|
|
122
|
+
context), so its high z-index could not lift it above the `.welcome-card`, which is a sibling
|
|
123
|
+
outside the transform. The welcome card is now suppressed while a ghost intent is live
|
|
124
|
+
(`intents.value.size > 0`), so a `canvas_intent` signal on a fresh board is visible immediately;
|
|
125
|
+
the card returns when the intent clears/settles and the board is still empty. Verified by
|
|
126
|
+
screenshot in the WebKit backend.
|
|
127
|
+
- **MCP `--mcp` no longer silently splits to (or silently adopts) a wrong workspace — structural
|
|
128
|
+
fix (report Finding I).** The GitHub Copilot adapter spawns `pmx-canvas --mcp` from an incidental
|
|
129
|
+
cwd (e.g. `~/.copilot`); the old code then either split to a hidden fallback port (when the
|
|
130
|
+
preferred port was held) or adopted that incidental cwd as the workspace (when the port was free),
|
|
131
|
+
so writes landed on a canvas the project panel never renders. Now, in `createCanvasAccess`:
|
|
132
|
+
- **Port held by a different-workspace daemon →** the MCP server **attaches** to it (inherits its
|
|
133
|
+
workspace) so writes are visible where the panel renders, instead of splitting.
|
|
134
|
+
- **Free port + incidental launch cwd (`~/.copilot`-shaped) →** it still binds (the agent always
|
|
135
|
+
gets a working canvas) but emits a loud, actionable stderr warning instead of silently adopting
|
|
136
|
+
the cwd; a race-tolerant re-probe first attaches to any daemon that appeared on the port.
|
|
137
|
+
- **`PMX_CANVAS_WORKSPACE_ROOT=<abs project root>`** (new) pins the workspace for both the lookup
|
|
138
|
+
and the bound daemon (`startCanvasServer` honors it), overriding the launch cwd — the deterministic
|
|
139
|
+
host fix. `PMX_CANVAS_ALLOW_WORKSPACE_SPLIT=1` (or a distinct `PMX_CANVAS_PORT`) forces a separate
|
|
140
|
+
canvas. The incidental detector is **positive-signal only** (home dir / dot-child of home), so the
|
|
141
|
+
`mkdtemp` temp dirs the test suite runs from are never misflagged — startup behavior is
|
|
142
|
+
byte-identical for real projects and tests.
|
|
143
|
+
Verified on the real `--mcp` stdio path: port-held → attach (no fallback); incidental + free →
|
|
144
|
+
bind-but-warn (no split); `PMX_CANVAS_WORKSPACE_ROOT` → binds the project root (no warning); real
|
|
145
|
+
project → binds (no warning). Pure `shouldAttachToExistingDaemon` + `looksLikeIncidentalCwd`
|
|
146
|
+
helpers are unit-tested.
|
|
147
|
+
|
|
148
|
+
### Docs
|
|
149
|
+
|
|
150
|
+
- **Clarified the `color` contract: renderer color vs persisted metadata (report Finding H).** A
|
|
151
|
+
top-level `color` is a renderer parameter only for `group` (frame accent) and `graph` nodes; on
|
|
152
|
+
`markdown` / `status` / `context` it is dropped, and while an arbitrary `data.color` posted under
|
|
153
|
+
`data` persists like any `data.*` metadata, it is not read as a render color for basic node types.
|
|
154
|
+
The reference now states this renderer-vs-storage distinction so docs/schema/runtime agree.
|
|
155
|
+
- **Made the WebView automation timeout error actionable (report Finding G).** The chrome backend is
|
|
156
|
+
known-flaky on some hosts (Bun.WebView), reproduced in both the Copilot and Codex hosts; the webkit
|
|
157
|
+
backend (the macOS default) works. The timeout error now points to `start --backend webkit` and the
|
|
158
|
+
already-configurable `PMX_CANVAS_WEBVIEW_TIMEOUT_MS` instead of a dead-end "may be unavailable".
|
|
159
|
+
Not a PMX regression — no canvas source touches the WebView/automation path.
|
|
7
160
|
|
|
8
161
|
## [0.2.6] - 2026-06-25
|
|
9
162
|
|
|
@@ -2488,6 +2641,8 @@ otherwise have to discover by trial and error.
|
|
|
2488
2641
|
- Regression coverage for snapshot flat-`id` aliases on both MCP and
|
|
2489
2642
|
HTTP surfaces, plus async / top-level-`await` WebView script bodies.
|
|
2490
2643
|
|
|
2644
|
+
[0.3.0]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.3.0
|
|
2645
|
+
[0.2.7]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.2.7
|
|
2491
2646
|
[0.2.6]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.2.6
|
|
2492
2647
|
[0.2.5]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.2.5
|
|
2493
2648
|
[0.2.4]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.2.4
|
package/Readme.md
CHANGED
|
@@ -98,14 +98,14 @@ vendor-specific.
|
|
|
98
98
|
|
|
99
99
|
Spatial state auto-saves to `.pmx-canvas/canvas.db` (debounced ~500 ms) —
|
|
100
100
|
git-committable, shareable across machines, and survives both browser
|
|
101
|
-
refresh and server restart. Named [snapshots](docs/mcp.md#tools), full
|
|
101
|
+
refresh and server restart. Named [snapshots](docs/mcp.md#standalone-tools), full
|
|
102
102
|
undo/redo, and an auto-detected code graph (JS/TS, Python, Go, Rust) make
|
|
103
103
|
the canvas durable rather than throwaway. Stop the server before committing
|
|
104
104
|
the DB so SQLite WAL data is checkpointed into the file.
|
|
105
105
|
|
|
106
106
|
### 06 / Any agent
|
|
107
107
|
|
|
108
|
-
Harness-agnostic. Drive the canvas from [MCP](docs/mcp.md) (
|
|
108
|
+
Harness-agnostic. Drive the canvas from [MCP](docs/mcp.md) (27 tools,
|
|
109
109
|
14 resources, change notifications), the [CLI](docs/cli.md), the
|
|
110
110
|
[HTTP API](docs/http-api.md), or the [Bun SDK](docs/sdk.md). Works with
|
|
111
111
|
Claude Code, GitHub Copilot CLI, Codex, Cursor, Windsurf, or any agent
|
|
@@ -136,9 +136,9 @@ surfaces (the core never imports a host SDK).
|
|
|
136
136
|
preview).
|
|
137
137
|
- **Codex app** — native through the Codex in-app Browser (opened to
|
|
138
138
|
`/workbench`) plus the PMX MCP server: agents read `canvas://ax-context` /
|
|
139
|
-
`
|
|
140
|
-
extension API needed — Codex's two native surfaces
|
|
141
|
-
exactly what the canvas requires.
|
|
139
|
+
`canvas_ax_state { action: "get" }` and label Codex-originated focus with
|
|
140
|
+
`source: "codex"`. No extension API needed — Codex's two native surfaces
|
|
141
|
+
(MCP + in-app Browser) are exactly what the canvas requires.
|
|
142
142
|
|
|
143
143
|
The contract is host-agnostic, so a new host plugs in the same way: map its
|
|
144
144
|
hooks, canvas, and session APIs onto PMX's AX primitives — no core changes.
|
|
@@ -219,8 +219,9 @@ Codex needs no extension — its two native surfaces are exactly what the canvas
|
|
|
219
219
|
requires. Add the PMX MCP server to the Codex workspace config (same snippet as
|
|
220
220
|
[Connect your agent](#connect-your-agent-mcp)), then open the returned
|
|
221
221
|
`/workbench` URL in the **Codex in-app Browser** so you can see mutations live.
|
|
222
|
-
Agents read pinned/focused context from `canvas://ax-context` /
|
|
223
|
-
and label Codex-originated focus with
|
|
222
|
+
Agents read pinned/focused context from `canvas://ax-context` /
|
|
223
|
+
`canvas_ax_state { action: "get" }` and label Codex-originated focus with
|
|
224
|
+
`source: "codex"`. See
|
|
224
225
|
[`codex-app-adapter.md`](skills/pmx-canvas/references/codex-app-adapter.md) for
|
|
225
226
|
the full workflow and live-test checklist.
|
|
226
227
|
|
|
@@ -255,7 +256,7 @@ the agent can read `canvas://skills` and pull in companion skills
|
|
|
255
256
|
the three-tier visual matrix (json-render → html → web-artifact)
|
|
256
257
|
- **[CLI reference](docs/cli.md)** — full command surface, daemon mode,
|
|
257
258
|
watch streams, WebView automation
|
|
258
|
-
- **[MCP reference](docs/mcp.md)** —
|
|
259
|
+
- **[MCP reference](docs/mcp.md)** — 27 tools, 14 resources, change
|
|
259
260
|
notifications, node-type routing
|
|
260
261
|
- **[HTTP API](docs/http-api.md)** — REST endpoints, SSE, batch operations
|
|
261
262
|
- **[AX host-adapter contract](docs/ax-host-adapter-contract.md)** — how native
|
|
@@ -273,9 +274,10 @@ the agent can read `canvas://skills` and pull in companion skills
|
|
|
273
274
|
- **What leaves your machine.** The core canvas runs entirely on
|
|
274
275
|
`localhost`. Network egress only happens for explicit, opt-in flows:
|
|
275
276
|
`webpage` nodes fetch the URL you give them; `mcp-app` /
|
|
276
|
-
`
|
|
277
|
-
(the Excalidraw preset uses `https://mcp.excalidraw.com/mcp`);
|
|
278
|
-
itself reads the npm registry on first install. Nothing else phones
|
|
277
|
+
`canvas_app { action: "diagram" }` calls go to whatever MCP server URL you
|
|
278
|
+
configure (the Excalidraw preset uses `https://mcp.excalidraw.com/mcp`);
|
|
279
|
+
`bunx` itself reads the npm registry on first install. Nothing else phones
|
|
280
|
+
home.
|
|
279
281
|
|
|
280
282
|
## Tech stack
|
|
281
283
|
|