pmx-canvas 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/extensions/pmx-canvas/extension.mjs +9 -3
- package/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/.github/extensions/pmx-canvas/tools.json +9278 -2014
- package/CHANGELOG.md +34 -1
- package/dist/canvas/global.css +12 -17
- package/dist/canvas/index.js +58 -58
- package/dist/canvas/mcp-app.html +75 -80
- package/dist/types/client/canvas/submit-without-navigation.d.ts +3 -0
- package/dist/types/client/state/intent-bridge.d.ts +0 -3
- package/dist/types/client/state/presence-store.d.ts +3 -3
- package/dist/types/client/types.d.ts +1 -1
- package/dist/types/mcp/canvas-access.d.ts +1 -12
- package/dist/types/mcp/resource-subscriptions.d.ts +7 -0
- package/dist/types/mcp/server.d.ts +2 -0
- package/dist/types/server/ax-wait.d.ts +1 -0
- package/dist/types/server/canvas-operations.d.ts +1 -0
- package/dist/types/server/canvas-state.d.ts +2 -0
- package/dist/types/server/index.d.ts +5 -5
- package/dist/types/server/knowledge-lifecycle.d.ts +11 -2
- package/dist/types/server/lifecycle-status.d.ts +3 -1
- package/dist/types/server/operations/http.d.ts +10 -0
- package/dist/types/server/operations/index.d.ts +2 -2
- package/dist/types/server/operations/invoker.d.ts +4 -3
- package/dist/types/server/operations/mcp-contracts.d.ts +20 -0
- package/dist/types/server/operations/mcp.d.ts +2 -0
- package/dist/types/server/operations/ops/batch.d.ts +1 -0
- package/dist/types/server/operations/registry.d.ts +2 -2
- package/dist/types/server/operations/types.d.ts +12 -2
- package/dist/types/server/server.d.ts +2 -0
- package/dist/types/server/tour-control.d.ts +6 -3
- package/dist/types/server/webpage-node.d.ts +1 -0
- package/docs/api-reference.md +2 -2
- package/docs/cli.md +10 -1
- package/docs/design/Chrome.dc.html +1 -0
- package/docs/design.md +3 -1
- package/docs/http-api.md +31 -0
- package/docs/mcp.md +98 -22
- package/docs/node-types.md +3 -0
- package/docs/plans/plan-019-post-0.9-roadmap.md +187 -11
- package/docs/sdk.md +10 -0
- package/package.json +1 -1
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +9 -3
- 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 +9278 -2014
- package/skills/pmx-canvas/SKILL.md +12 -7
- package/skills/pmx-canvas/references/full-reference.md +35 -2
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +7 -7
- package/src/client/canvas/BoardCopyDialog.tsx +2 -1
- package/src/client/canvas/KnowledgeDialog.tsx +3 -0
- package/src/client/canvas/LifecyclePanel.tsx +4 -0
- package/src/client/canvas/RelationPresetsDialog.tsx +2 -0
- package/src/client/canvas/ToolRail.tsx +2 -0
- package/src/client/canvas/submit-without-navigation.ts +14 -0
- package/src/client/state/canvas-store.ts +12 -24
- package/src/client/state/intent-bridge.ts +0 -6
- package/src/client/state/presence-store.ts +3 -3
- package/src/client/state/sse-bridge.ts +11 -6
- package/src/client/theme/global.css +12 -17
- package/src/mcp/canvas-access.ts +6 -47
- package/src/mcp/resource-subscriptions.ts +181 -0
- package/src/mcp/server.ts +185 -219
- package/src/server/ax-wait.ts +21 -6
- package/src/server/canvas-operations.ts +6 -2
- package/src/server/canvas-state.ts +10 -0
- package/src/server/index.ts +20 -32
- package/src/server/knowledge-lifecycle.ts +66 -0
- package/src/server/lifecycle-status.ts +79 -7
- package/src/server/operations/http.ts +69 -21
- package/src/server/operations/index.ts +8 -1
- package/src/server/operations/invoker.ts +53 -5
- package/src/server/operations/mcp-contracts.ts +339 -0
- package/src/server/operations/mcp.ts +153 -18
- package/src/server/operations/ops/ax-await.ts +18 -10
- package/src/server/operations/ops/ax-read.ts +2 -0
- package/src/server/operations/ops/ax-timeline.ts +2 -2
- package/src/server/operations/ops/batch.ts +27 -8
- package/src/server/operations/ops/lifecycle.ts +3 -7
- package/src/server/operations/ops/nodes.ts +20 -8
- package/src/server/operations/ops/viewport.ts +3 -7
- package/src/server/operations/registry.ts +24 -4
- package/src/server/operations/types.ts +16 -2
- package/src/server/server.ts +23 -10
- package/src/server/tour-control.ts +17 -8
- package/src/server/webpage-node.ts +9 -4
package/docs/mcp.md
CHANGED
|
@@ -1,10 +1,92 @@
|
|
|
1
1
|
# MCP reference
|
|
2
2
|
|
|
3
|
-
PMX Canvas ships an MCP stdio server with **
|
|
3
|
+
PMX Canvas ships an MCP stdio server with **25 tools**, **15 static canvas
|
|
4
4
|
resources**, and two canvas resource templates, plus per-skill resources at
|
|
5
5
|
`canvas://skills/<name>` and the `skill://{name}/{+path}` template. The server emits
|
|
6
|
-
`notifications/resources/updated` when canvas state changes
|
|
7
|
-
|
|
6
|
+
`notifications/resources/updated` to subscribed connections when canvas state changes.
|
|
7
|
+
This uses MCP SDK v1, not SDK v2.
|
|
8
|
+
|
|
9
|
+
## Operation help (0.10)
|
|
10
|
+
|
|
11
|
+
Call `canvas_help {}` for the sorted registry names exposed through MCP, then
|
|
12
|
+
`canvas_help { op: "node.add" }` for one operation's public `tool`, `description`
|
|
13
|
+
and JSON `inputSchema`. The schema includes required fields, public field names
|
|
14
|
+
and constant routing selectors (`action`, and `kind` for gates). For example,
|
|
15
|
+
`ax.approval.request` maps to `canvas_ax_gate` with `kind: "approval"`,
|
|
16
|
+
`action: "request"` and the optional `approvalAction` field.
|
|
17
|
+
|
|
18
|
+
Text contains the JSON result; structured content wraps it in `{ result }`.
|
|
19
|
+
Unknown names, internal/human-only operations and non-registry tools such as
|
|
20
|
+
`canvas_screenshot` return text-only `isError`; use `tools/list` for those tools.
|
|
21
|
+
Help reads registry metadata only: it never starts a canvas, writes state, records
|
|
22
|
+
a content read or advances a cursor. It is read-only and idempotent.
|
|
23
|
+
|
|
24
|
+
Help derives its schema and guidance from the operation registry, not from live
|
|
25
|
+
board state. Handlers still enforce conditional requirements and authorization.
|
|
26
|
+
Existing input schemas stay in `tools/list`; help does not enable lazy discovery
|
|
27
|
+
in hosts. Repeated equivalent output branches are grouped within each tool,
|
|
28
|
+
preserving operation/payload validation and partial-error receipts.
|
|
29
|
+
|
|
30
|
+
## Tool results and effect hints (0.10)
|
|
31
|
+
|
|
32
|
+
All 25 tools advertise an object `outputSchema`. Registry-dispatched tools return
|
|
33
|
+
`structuredContent.result = { operation, outcome, data }`. `operation` names the
|
|
34
|
+
dispatched action (for example `node.add`), `outcome` is `success`, `error` or
|
|
35
|
+
`partial`, and `data` is the existing compact tool result. Prose results use
|
|
36
|
+
`data.message`. Exceptions use `operation: null`, `outcome: "error"` and
|
|
37
|
+
`data.message`; this does not guarantee that nothing changed before the exception.
|
|
38
|
+
Batch failures retain completed `results` and `refs`, with `partial` when at least
|
|
39
|
+
one entry completed. Check both `isError` and the outcome before using a result.
|
|
40
|
+
|
|
41
|
+
The three handwritten tools keep direct structured objects: `canvas_ax_interaction`
|
|
42
|
+
returns its accepted interaction, `canvas_ingest_activity` its event and reaction
|
|
43
|
+
records, and `canvas_screenshot` capture metadata alongside model-visible image
|
|
44
|
+
content. Their errors are text-only `isError` replies. Existing model-facing text
|
|
45
|
+
and compact/full projections remain unchanged; structured results do not introduce
|
|
46
|
+
additional full-card or UI payloads. Inspect the advertised schema for each tool.
|
|
47
|
+
|
|
48
|
+
All tools declare `readOnlyHint`, `destructiveHint`, `idempotentHint` and
|
|
49
|
+
`openWorldHint`. Composite hints cover every action, not only their read actions.
|
|
50
|
+
`canvas_query` is not read-only because context reads can advance a durable
|
|
51
|
+
consumer cursor. Hints describe effects; they grant no permission or retry guarantee.
|
|
52
|
+
|
|
53
|
+
## Cancellation and progress (0.10)
|
|
54
|
+
|
|
55
|
+
MCP cancellation reaches the operation layer in both local and daemon-attached
|
|
56
|
+
connections. Supported AX waits release their listeners and timers immediately;
|
|
57
|
+
batches stop before the next operation and keep completed writes. Webpage fetches
|
|
58
|
+
receive the signal and stop before writing fetched content after cancellation.
|
|
59
|
+
Cancellation does not roll back a created node or other completed mutations.
|
|
60
|
+
If webpage creation already committed, its receipt retains `fetch.cancelled: true`.
|
|
61
|
+
External app builds/runtime calls and local WebView captures are not interruptible
|
|
62
|
+
mid-call; do not treat cancellation as proof that those side effects stopped.
|
|
63
|
+
|
|
64
|
+
Calls supplying `_meta.progressToken` receive `notifications/progress` at batch
|
|
65
|
+
entry boundaries and supported AX wait start/completion, with `progress`, optional
|
|
66
|
+
`total`, optional `message` and the same token. This works over the daemon bridge
|
|
67
|
+
as well as local stdio. No token means
|
|
68
|
+
no progress notifications. A host that aborts its connection may not receive a
|
|
69
|
+
partial result; inspect canvas state before retrying. See the
|
|
70
|
+
[HTTP streaming contract](http-api.md#operation-cancellation-and-progress-010).
|
|
71
|
+
|
|
72
|
+
## Resource subscriptions (0.10)
|
|
73
|
+
|
|
74
|
+
The server advertises `resources.subscribe`. Send `resources/subscribe` with an
|
|
75
|
+
exact live URI, then `resources/unsubscribe` to stop. Subscriptions belong to the
|
|
76
|
+
connection and disappear on close; reconnecting clients must subscribe again.
|
|
77
|
+
|
|
78
|
+
Live resources are `canvas://layout`, `boards`, `summary`, `context`, `graph`,
|
|
79
|
+
`spatial-context`, `history`, `code-graph`, `pinned-context`, `ax`, `ax-context`,
|
|
80
|
+
`ax-timeline`, `ax-work`, `ax-pending-steering` and `ax-delivery` (each with the
|
|
81
|
+
`canvas://` prefix). Parameterized context and graph URIs are supported, for example
|
|
82
|
+
`canvas://context?consumer=my-agent&budget=3000`; notifications echo the exact
|
|
83
|
+
subscribed URI. Static schema and bundled skill resources do not support subscriptions.
|
|
84
|
+
|
|
85
|
+
Notifications invalidate cached data, not deliver it. Read the resource when needed.
|
|
86
|
+
They can be broader than the underlying change, and daemon reconnection invalidates
|
|
87
|
+
subscribed resources to cover missed events. Notification delivery does not record
|
|
88
|
+
a context read or advance a consumer cursor. Explicit `resources/read` works without
|
|
89
|
+
subscriptions, including on hosts that do not use this capability.
|
|
8
90
|
|
|
9
91
|
> **Consolidation complete (plan-006/008).** The MCP surface shrank from 84
|
|
10
92
|
> tools to 22: 16 action-discriminated **composites** (recommended — see
|
|
@@ -57,7 +139,7 @@ on its source board. It appears as a `portal` edge in `canvas://graph`, independ
|
|
|
57
139
|
|
|
58
140
|
## Board tours
|
|
59
141
|
|
|
60
|
-
`canvas_view { action: "get-tour" }` returns `{ tour, derived }`, using group
|
|
142
|
+
`canvas_view { action: "get-tour" }` returns `{ tour, derived, position }`, using group
|
|
61
143
|
reading order when there is no saved tour. `canvas_view { action: "set-tour",
|
|
62
144
|
tour: { stops: [...] } }` persists an ordered tour; `tour: null` resets it.
|
|
63
145
|
`canvas_view { action: "tour-go", stop: 0 }` (or `step: "next" | "previous"`)
|
|
@@ -83,12 +165,12 @@ Add to your agent's MCP config:
|
|
|
83
165
|
}
|
|
84
166
|
```
|
|
85
167
|
|
|
86
|
-
The canvas auto-starts on first
|
|
168
|
+
The canvas auto-starts on first canvas operation, not on `canvas_help`.
|
|
87
169
|
|
|
88
170
|
## Private MCP App preview
|
|
89
171
|
|
|
90
172
|
`pmx-canvas --mcp-app` runs a **separate, experimental stdio profile**; the
|
|
91
|
-
|
|
173
|
+
25-tool `--mcp` profile above is separate. Build from this checkout first:
|
|
92
174
|
|
|
93
175
|
```bash
|
|
94
176
|
bun run build
|
|
@@ -170,6 +252,10 @@ in the user's browser. Standalone Markdown edits carry captured board/content
|
|
|
170
252
|
revisions; a refused save keeps the current editor draft. Copy that draft before
|
|
171
253
|
closing the editor or switching boards; unsaved drafts do not survive remounts.
|
|
172
254
|
|
|
255
|
+
Knowledge review, categories, relation presets and board-copy forms handle saves
|
|
256
|
+
in JavaScript, including Enter and input validation. They do not require the
|
|
257
|
+
outer host to grant `allow-forms`; the SDK test host keeps `sandbox="allow-scripts"`.
|
|
258
|
+
|
|
173
259
|
**Host constraints still apply.** Native PMX controls work without child frames.
|
|
174
260
|
HTML, Mermaid, JSON/graph and nested app renderers need the host to permit local
|
|
175
261
|
`srcdoc` frames. The portable MCP Apps default with empty `frameDomains` is
|
|
@@ -354,7 +440,7 @@ Single-card and layout reads record delivered content, not incident relations.
|
|
|
354
440
|
Use a complete graph or brief relation entry to acknowledge those relations.
|
|
355
441
|
Reads never mark full card content read or
|
|
356
442
|
switch the workbench. Pull needed cards in full separately.
|
|
357
|
-
|
|
443
|
+
These reads add no tools beyond the catalog listed above.
|
|
358
444
|
|
|
359
445
|
Library search is `canvas_query { action: "search", query: "auth", scope:
|
|
360
446
|
"library" }`. It returns board/card IDs and never switches the active board.
|
|
@@ -487,13 +573,14 @@ agent intends to publish its own cursor or attention target.
|
|
|
487
573
|
|
|
488
574
|
## Standalone tools
|
|
489
575
|
|
|
490
|
-
|
|
576
|
+
7 tools that intentionally stay outside the composites — folding them would
|
|
491
577
|
hurt (distinct callers, binary payloads, trust-boundary or execution-intent
|
|
492
578
|
semantics). See [Migration reference](#migration-reference) below for the
|
|
493
579
|
legacy tools the composites replaced.
|
|
494
580
|
|
|
495
581
|
| Tool | Description |
|
|
496
582
|
|------|-------------|
|
|
583
|
+
| `canvas_help` | List MCP registry operations or fetch one operation's public arguments and guidance (`op` optional); no canvas access |
|
|
497
584
|
| `canvas_batch` | Run a batch of canvas operations with `$ref` support |
|
|
498
585
|
| `canvas_pin_nodes` | Pin nodes to include in agent context (`nodeIds`, `mode` set/add/remove, optional `reason` shown to the human) |
|
|
499
586
|
| `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 |
|
|
@@ -699,20 +786,9 @@ interaction against the node's effective capabilities.
|
|
|
699
786
|
|
|
700
787
|
## Change notifications
|
|
701
788
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
- Pin changes notify `canvas://pinned-context`, `canvas://ax`, and `canvas://ax-context`
|
|
706
|
-
- AX focus changes notify `canvas://ax` and `canvas://ax-context`
|
|
707
|
-
- Canvas-bound AX mutations (work items, approval gates, review annotations,
|
|
708
|
-
host capability) notify `canvas://ax`, `canvas://ax-work`, and `canvas://ax-context`
|
|
709
|
-
- AX timeline mutations (agent-events, evidence, steering) notify
|
|
710
|
-
`canvas://ax-timeline` and `canvas://ax-context`
|
|
711
|
-
- All mutations notify `canvas://layout`, `canvas://summary`,
|
|
712
|
-
`canvas://spatial-context`, `canvas://history`, `canvas://code-graph`, and `canvas://graph`
|
|
713
|
-
|
|
714
|
-
This closes the human-to-agent loop: spatial curation in the browser becomes
|
|
715
|
-
an immediate signal in the agent's context.
|
|
789
|
+
Notifications require an explicit subscription to each live resource URI. See
|
|
790
|
+
[Resource subscriptions](#resource-subscriptions-010) for connection lifetime,
|
|
791
|
+
reconnection and broad cache invalidation. Receiving a notification is not a content read.
|
|
716
792
|
|
|
717
793
|
## Codex App Adapter
|
|
718
794
|
|
package/docs/node-types.md
CHANGED
|
@@ -77,6 +77,9 @@ Tick a task directly on its card, including quoted and nested tasks. A card clic
|
|
|
77
77
|
only that task's `[ ]` or `[x]` marker, preserving the rest of the source exactly.
|
|
78
78
|
Task-shaped text in code examples and raw HTML checkboxes are not Markdown task controls.
|
|
79
79
|
|
|
80
|
+
Expand a Markdown card to read and edit the full document. Source stays outside the
|
|
81
|
+
scrolling text, below ordinary documents and above documents with flow actions.
|
|
82
|
+
|
|
80
83
|
## File nodes
|
|
81
84
|
|
|
82
85
|
File nodes display project files with line numbers and language detection.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Plan 019: After 0.9.0
|
|
2
2
|
|
|
3
|
-
**Status (2026-10-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
**Status (2026-10-24):** 0.9.3 is released to npm and GitHub, with fresh registry smoke
|
|
4
|
+
passing. Step 2, MCP hardening and SDK tour result parity on SDK v1, is implemented
|
|
5
|
+
and pushed with the Settings tooltip fix, operation help and schema-size reduction.
|
|
6
|
+
The maintainer authorized review, testing and release of 0.10.0; release gates are in progress.
|
|
7
|
+
Later version numbers are proposals, not publication approval; every release must pass
|
|
8
|
+
the [release gates](../RELEASE.md).
|
|
8
9
|
**Sources:** [product vision](../product-vision-2026-09.md) (moves and the 2026-10-19 sequence),
|
|
9
10
|
[design.md build plan](../design.md#build-plan) (Waves 4, 5, Later),
|
|
10
11
|
[plan 009](plan-009-tech-debt-backlog.md) (open debt),
|
|
@@ -21,8 +22,8 @@ measured; the maintainer carries that risk rather than reinstating an earlier ga
|
|
|
21
22
|
|
|
22
23
|
| Step | Proposed version | Scope | Vision | Size |
|
|
23
24
|
|---|---|---|---|---|
|
|
24
|
-
| 1 | 0.9.
|
|
25
|
-
| 2 | 0.10 | MCP hardening
|
|
25
|
+
| 1 | 0.9.3 | Cleanup: tour debt, large-board costs, bounded due evaluator, MCP reconnect, lint | 12, 1 | S–M |
|
|
26
|
+
| 2 | 0.10 | MCP hardening, operation help and bounded discovery-schema reduction | 6a, 1 | M |
|
|
26
27
|
| 3 | 0.11 | One frame host, portal-layer mount, Wave-0 design pass | 5, 9 | M–L |
|
|
27
28
|
| 4 | 0.12 | Wave 5: agent output as nodes, make/inline board, group drill-in, relations sketch parity | 3, 0 | L |
|
|
28
29
|
| 5 | later | Trust (M half), journal, concurrent boards, binary | 7, 4, 8 | L–XL |
|
|
@@ -31,10 +32,66 @@ measured; the maintainer carries that risk rather than reinstating an earlier ga
|
|
|
31
32
|
Each step starts after the previous release ships, except that a concrete defect found in
|
|
32
33
|
use can be fixed narrowly in a patch release without pulling later scope forward.
|
|
33
34
|
|
|
34
|
-
## Step 1: 0.9.
|
|
35
|
+
## Step 1: 0.9.3 cleanup
|
|
35
36
|
|
|
36
37
|
Debt deliberately kept out of 0.9.0, plus measured performance leads.
|
|
37
38
|
|
|
39
|
+
**Local checkpoint, 2026-10-24 (not release approval):**
|
|
40
|
+
- Camera moves now persist only the viewport. A headed browser regression failed on the
|
|
41
|
+
baseline's two full-card geometry writes, then passed without them; the complete seven-case
|
|
42
|
+
presentation/recording file passes. Both camera paths use one animation driver while retaining
|
|
43
|
+
their existing interpolation. Tour resolution reads geometry without hydrating card contents.
|
|
44
|
+
- Tour reads share one result builder. HTTP and MCP return `{ tour, derived, position }`;
|
|
45
|
+
the SDK preserves its existing direct tour result (`.stops`). Result-shape parity is
|
|
46
|
+
deferred to 0.10 because changing the SDK to `.tour.stops` breaks callers.
|
|
47
|
+
- `bun run scripts/probe-mcp-reconnect.ts` opened 12 local stdio fixture apps concurrently,
|
|
48
|
+
then restored them through five server restarts and queried every replacement session's live
|
|
49
|
+
tool catalog. All 60 restored sessions passed, with no `-32001` timeout. The native-host/remote
|
|
50
|
+
backend failure remains open; this probe is not evidence that it is fixed.
|
|
51
|
+
- Saved Markdown skips unused reference parsing; saved targets, unresolved links, drafts and
|
|
52
|
+
inline images retain their behavior. The measurements below leave serialization, offscreen
|
|
53
|
+
rendering and SSE unchanged because each needs a separate contract or lifecycle decision.
|
|
54
|
+
- Lifecycle-get, node-get and review qualification use the dependency/portal closure, including
|
|
55
|
+
incoming cross-board sources and unsaved active-board edges. Latest evidence and retirement
|
|
56
|
+
summaries use indexed queries; requested audit history remains complete. Home counts are
|
|
57
|
+
unchanged. **Deferred:** aggregate-only Home reads, per-card storage reads within closure boards,
|
|
58
|
+
and whole-library mutation broadcasts. The current Home client consumes `knowledge.list.cards`.
|
|
59
|
+
- Lint passes with 55 warnings and 12 infos, down from 63 warnings and 12 infos. Eight unused
|
|
60
|
+
import diagnostics were removed in the touched SDK module. Remaining diagnostics are listed below.
|
|
61
|
+
- Combined checkout verification passed: `bun run build`, `bun run typecheck`, `bun run test`
|
|
62
|
+
(1,503 tests), `bun run test:client` (332 tests), and
|
|
63
|
+
`xvfb-run -a bash scripts/run-playwright.sh --headed` (333 tests). The final node-get
|
|
64
|
+
integration assertion also passed its 32-case relation suite, typecheck and lint. The inspected
|
|
65
|
+
tour recording shows both stops and the restored editor after exit. These are local source
|
|
66
|
+
checks, not release smoke, CI, installed-adapter or native-host verification. The patch-only
|
|
67
|
+
decision is settled; release gates are being run against the final 0.9.3 candidate.
|
|
68
|
+
|
|
69
|
+
**Reproducible measurements (local Bun 1.4.4, synthetic data):**
|
|
70
|
+
|
|
71
|
+
| Workload and command | Before | After | Limits |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| 12 Markdown cards, five decodable 400×300 PNGs, 2,459,314 source bytes; `bun run scripts/benchmark-markdown-load.ts --browser --expect-no-reference-lex` | 24 extra reference parses scanning 4,918,628 bytes | Zero extra reference parses; all 12 normalized HTML hashes match | Three warmups and nine HTTP samples; headed Chromium at 1440×900, 2×, one warmup and three reloads. Timing varied on the shared orb, so no board-load speedup claim |
|
|
74
|
+
| Same Markdown board, public state serialization | 4,927,936 bytes | Unchanged | 2,460,294 bytes are duplicated top-level content; removing that alias is only a counterfactual measurement |
|
|
75
|
+
| Same Markdown board, offscreen rendering | Six offscreen POSTs, 508,608 source bytes | Unchanged | All 12 cards render; all five images decode |
|
|
76
|
+
| Same Markdown board, one-character edit | First layout SSE frame: 2,466,713 bytes, 12 nodes | Unchanged | First frame only, not total event traffic |
|
|
77
|
+
| 12 boards × 24 cards × 32 reviews; `bun run scripts/benchmark-lifecycle.ts` | 13 board reads and 9,248 full-history records per request | Two board reads and 32 records per request | One independent inactive-card request; all 32 requested audit records returned. Closure boards still load whole board bodies |
|
|
78
|
+
| Same lifecycle workload, warm medians from three independent runs | 16.016 / 14.938 / 16.648 ms | 0.832 / 1.101 / 0.609 ms | Five warmups and 20 samples per run. First request initializes indexes and was not consistently faster; no cold-start claim |
|
|
79
|
+
|
|
80
|
+
Remove `--expect-no-reference-lex` when running the Markdown script against the baseline.
|
|
81
|
+
Both benchmarks isolate their databases in disposable workspaces. Dependency-heavy lifecycle
|
|
82
|
+
behavior is covered by cycle, provenance, missing-source and cross-board tests, not this timing workload.
|
|
83
|
+
|
|
84
|
+
**Remaining lint diagnostics:** `bunx --no-install biome check . --max-diagnostics=200`
|
|
85
|
+
lists the exact locations. These remain outside the narrow behavioral fixes:
|
|
86
|
+
|
|
87
|
+
| Diagnostics | Count | Reason retained |
|
|
88
|
+
|---|---:|---|
|
|
89
|
+
| Unused imports / variables / parameters / private members | 11 / 8 / 6 / 1 | Spread across unrelated client, server and test modules; remove with their owning cleanup |
|
|
90
|
+
| Optional-chain suggestions | 23 | Existing style suggestions, including untouched regions of changed files |
|
|
91
|
+
| Literal template placeholders | 3 | Tests intentionally exercise literal `${…}` text |
|
|
92
|
+
| Global `isNaN`, confusing `void`, comma operator | 1 each | Existing chart coercion, frame callback and presence expressions need individual semantic review |
|
|
93
|
+
| Infos: template strings / switch cases / index lookup / config deprecation | 6 / 3 / 2 / 1 | Non-gating style/config follow-up, no rule disabled |
|
|
94
|
+
|
|
38
95
|
- **Tour debt** ([vision move 12](../product-vision-2026-09.md#12-tours-the-board-is-the-presentation-m)):
|
|
39
96
|
a tour camera move saves every node's layout (`commitViewport` → `persistLayout` from the SSE
|
|
40
97
|
camera handler) and re-reads the whole layout (`tour-control.ts`); `animateCameraPath`
|
|
@@ -55,8 +112,8 @@ Debt deliberately kept out of 0.9.0, plus measured performance leads.
|
|
|
55
112
|
**Done when**
|
|
56
113
|
- A tour step changes the viewport and writes no node layout: a test asserts the intended
|
|
57
114
|
viewport change and that no layout-persistence write occurs during `tour go`/`next`
|
|
58
|
-
(unchanged positions alone would also pass a needless identical rewrite). SDK
|
|
59
|
-
|
|
115
|
+
(unchanged positions alone would also pass a needless identical rewrite). The SDK keeps its
|
|
116
|
+
existing tour shape; result-shape parity moves to step 2. One camera-animation path remains.
|
|
60
117
|
- Each WI-01 amplifier has a reproducible measurement script and a before/after number on the
|
|
61
118
|
same workload, per the measurement rules in `CLAUDE.md`; unimplicated ones are recorded, not changed.
|
|
62
119
|
- A one-card lifecycle request on a board with populated review histories reads only its
|
|
@@ -68,6 +125,121 @@ Debt deliberately kept out of 0.9.0, plus measured performance leads.
|
|
|
68
125
|
[Vision move 6a](../product-vision-2026-09.md#6a-make-the-tool-surface-cheap-s--staged-follow-up)
|
|
69
126
|
and move 1's context delivery, on the current SDK v1.
|
|
70
127
|
|
|
128
|
+
**Local implementation checkpoint (2026-10-24):**
|
|
129
|
+
- All 24 tools advertise output schemas and explicit effect hints. Registry results use
|
|
130
|
+
`{ result: { operation, outcome, data } }`; handwritten interaction, activity and screenshot
|
|
131
|
+
tools retain their direct objects. Existing model-facing text/projections stay unchanged.
|
|
132
|
+
Schemas distinguish batch success, empty failure and retained partial outcomes.
|
|
133
|
+
- Cancellation reaches AX waits and webpage I/O through local and HTTP invokers. Batches
|
|
134
|
+
retain completed receipts and stop before subsequent operations. Progress is opt-in through
|
|
135
|
+
MCP tokens and HTTP NDJSON. External runtime/build calls and local WebView captures remain
|
|
136
|
+
noninterruptible mid-call. Disconnects may lose the response, never undo completed writes.
|
|
137
|
+
- Subscriptions belong to each connection, include exact parameterized URIs, and dispose
|
|
138
|
+
on unsubscribe/close. Local state and workbench events cover library-only changes as well
|
|
139
|
+
as active nodes; remote SSE reconnects invalidate subscribed resources. Notifications never
|
|
140
|
+
record reads or advance cursors. A library-only-change regression failed before integration
|
|
141
|
+
and passes with the shared event source.
|
|
142
|
+
- SDK `getTour()` now returns `{ tour, derived, position }`; `.tour.stops` is documented as
|
|
143
|
+
the minor-version breaking change. No SDK/dependency upgrade or frame-host work.
|
|
144
|
+
|
|
145
|
+
**Approved follow-up, 2026-10-24:** `canvas_help { op }` derives one operation's
|
|
146
|
+
public arguments, required fields, routing selectors and guidance from the registry.
|
|
147
|
+
Omitting `op` lists MCP registry names; internal/human-only and non-registry tools are
|
|
148
|
+
excluded. Metadata reads neither boot a canvas nor record content delivery. The catalog
|
|
149
|
+
now has 25 tools. Conditional handler validation still applies; no lazy host discovery
|
|
150
|
+
or smaller input schemas are claimed.
|
|
151
|
+
|
|
152
|
+
Equivalent success schemas shared by identity are grouped within each tool. Distinct
|
|
153
|
+
payload contracts, error branches and batch partial receipts remain unchanged. Two
|
|
154
|
+
real stdio measurements with `bun run scripts/measure-mcp-catalog.ts` were byte-identical:
|
|
155
|
+
the previous 24-tool candidate's 144,680 UTF-8 JSON bytes become 137,381 for the same
|
|
156
|
+
tools (7,299 fewer, 5.05%). Existing output schemas drop from 77,105 to 69,806 bytes.
|
|
157
|
+
Adding help costs 1,156 catalog bytes including its separator: 138,537 bytes total,
|
|
158
|
+
6,143 fewer than the previous candidate (4.25%). Input-schema byte counts are unchanged.
|
|
159
|
+
This remains larger than published 0.9.3's 65,219 bytes. Bytes are not tokens, latency
|
|
160
|
+
or measured agent effectiveness. `session.start` and composite-input redesign remain deferred.
|
|
161
|
+
|
|
162
|
+
**Follow-up verification:** build, typecheck and `bun run test` pass (1,546 tests).
|
|
163
|
+
Real SDK stdio checks enumerate help for every exposed registry operation, validate
|
|
164
|
+
required fields, aliases and gate selectors, and create/remove a card using returned
|
|
165
|
+
arguments. Schema controls reject mismatched operations, malformed receipts and extra
|
|
166
|
+
envelope fields while accepting extensible payloads. Lint passes with 55 warnings and
|
|
167
|
+
12 infos. The first combined run caught a second frozen tool list still expecting 24;
|
|
168
|
+
that assertion now includes help. Test-fixture/typecheck failures were corrected, with
|
|
169
|
+
first-failure logs retained.
|
|
170
|
+
|
|
171
|
+
**Full candidate rerun requested by the maintainer:** `bun run test:coverage` passes
|
|
172
|
+
1,546 tests (67.27% lines, 73.62% functions, above the 60%/64% floors);
|
|
173
|
+
`bun run test:client` passes 332; `xvfb-run -a bash scripts/run-playwright.sh --headed`
|
|
174
|
+
passes all 333 desktop and 600/1024/1920 reference cases. Headed `test:e2e-cli`,
|
|
175
|
+
`release:smoke`, `pack:dry-run`, build, typecheck, lint and generated-catalog mirror
|
|
176
|
+
checks pass. A fresh packed MCP consumer discovers 25 tools, reads help without
|
|
177
|
+
creating state, and validates add/get results. Its allowed dependency versions
|
|
178
|
+
(SDK 1.32.2, Zod 4.6.7 versus checkout 1.28.0/4.3.6) encode nullable primitive schemas
|
|
179
|
+
as type arrays instead of `anyOf`. The initial byte-identity assertion failed;
|
|
180
|
+
comparison passes when only that equivalent encoding is normalized. No dependency changed.
|
|
181
|
+
|
|
182
|
+
The live portal serves the exact rebuilt bundle. Real stdio help-guided calls and
|
|
183
|
+
headed browser checks pass human pin → notification → explicit read → rendered edit,
|
|
184
|
+
unsubscribe, numeric progress tokens, cancelled approval waits, partial batch receipts
|
|
185
|
+
and refresh persistence. Both minimap toggles leave no tooltip and preserve Settings
|
|
186
|
+
focus. The first recording encoder fell behind; a later recording with the large suite
|
|
187
|
+
finished and a smaller viewport succeeded and was inspected frame by frame.
|
|
188
|
+
Native Amp/Copilot acceptance, Windows/macOS and remote/native reconnect remain unverified.
|
|
189
|
+
|
|
190
|
+
**Initial hardening verification:** build and typecheck pass; `bun run test` passes 1,544 tests and
|
|
191
|
+
`bun run test:client` passes 332. `xvfb-run -a bash scripts/run-playwright.sh --headed`
|
|
192
|
+
passes 333 cases; three pin/viewport/polling controls also pass after the final local
|
|
193
|
+
subscription event hook. `bun run release:smoke` passes on a disposable packed install,
|
|
194
|
+
not a registry publication. Lint passes with the same 55 warnings and 12 infos; generated
|
|
195
|
+
tool catalogs match. Real stdio tests cover local and daemon-attached progress/cancellation
|
|
196
|
+
and resource isolation. Initial test typing/SDK error-envelope failures and the red
|
|
197
|
+
library-notification regression were corrected; this is not a first-run-green claim.
|
|
198
|
+
Native 0.10 host acceptance, Windows/macOS and remote/native reconnect remain unverified.
|
|
199
|
+
Bounded simplify/harden review found no further blockers and made no additional changes.
|
|
200
|
+
|
|
201
|
+
**Independent baseline evidence:** the
|
|
202
|
+
[0.9.3 test thread](https://ampcode.com/threads/T-01a048cf-adb3-71bd-a7c6-472053b691d1)
|
|
203
|
+
reports no new confirmed functional defect after reruns, including installed SDK direct-tour
|
|
204
|
+
compatibility and native Amp pin/read/edit/ack acceptance. It does not establish 0.10 MCP
|
|
205
|
+
structured-output, cancellation or subscription conformance. Its low-severity KaTeX advisory,
|
|
206
|
+
unresolved first-run coverage timeout and remote/native reconnect gap remain separate from
|
|
207
|
+
this candidate; no dependency or reconnect fix is claimed here.
|
|
208
|
+
|
|
209
|
+
**Discovery cost:** `bun run scripts/measure-mcp-catalog.ts` measures UTF-8 bytes of the
|
|
210
|
+
real SDK client's `tools/list` JSON in a disposable stdio workspace, without canvas reads.
|
|
211
|
+
The 0.9.3 baseline is 65,219 bytes; the initial hardening candidate was 144,680 bytes, both 24 tools.
|
|
212
|
+
Output schemas contributed 77,105 bytes before the follow-up above. This is an increase in discovery overhead, not a
|
|
213
|
+
claim of cheaper prompts or a token estimate. Existing result text is unchanged; structured
|
|
214
|
+
results duplicate that projection for machine consumers. Host-specific prompt costs are unmeasured.
|
|
215
|
+
|
|
216
|
+
| Tool | 0.9.3 bytes | Initial hardening bytes |
|
|
217
|
+
|---|---:|---:|
|
|
218
|
+
| `canvas_pin_nodes` | 782 | 2227 |
|
|
219
|
+
| `canvas_invoke_command` | 804 | 2312 |
|
|
220
|
+
| `canvas_batch` | 1367 | 5184 |
|
|
221
|
+
| `canvas_import` | 1152 | 4251 |
|
|
222
|
+
| `canvas_snapshot` | 2238 | 6365 |
|
|
223
|
+
| `canvas_board` | 5859 | 14803 |
|
|
224
|
+
| `canvas_node` | 8184 | 13485 |
|
|
225
|
+
| `canvas_render` | 6321 | 11165 |
|
|
226
|
+
| `canvas_edge` | 2186 | 4423 |
|
|
227
|
+
| `canvas_group` | 1953 | 4532 |
|
|
228
|
+
| `canvas_history` | 494 | 2430 |
|
|
229
|
+
| `canvas_view` | 4341 | 12821 |
|
|
230
|
+
| `canvas_query` | 2476 | 7000 |
|
|
231
|
+
| `canvas_app` | 4729 | 7496 |
|
|
232
|
+
| `canvas_webview` | 1810 | 4834 |
|
|
233
|
+
| `canvas_ax_state` | 4462 | 7652 |
|
|
234
|
+
| `canvas_ax_work` | 2074 | 4527 |
|
|
235
|
+
| `canvas_ax_gate` | 2417 | 8285 |
|
|
236
|
+
| `canvas_ax_timeline` | 2637 | 6135 |
|
|
237
|
+
| `canvas_ax_delivery` | 1366 | 3284 |
|
|
238
|
+
| `canvas_intent` | 3127 | 5453 |
|
|
239
|
+
| `canvas_ax_interaction` | 1460 | 1969 |
|
|
240
|
+
| `canvas_ingest_activity` | 2341 | 2872 |
|
|
241
|
+
| `canvas_screenshot` | 604 | 1140 |
|
|
242
|
+
|
|
71
243
|
1. Remeasure `tools/list` size per tool before any schema change.
|
|
72
244
|
2. `outputSchema` + `structuredContent` for stable results (IDs, revisions, mutation
|
|
73
245
|
outcomes); compact model-facing content; UI-only payloads in `_meta` where supported.
|
|
@@ -77,8 +249,12 @@ and move 1's context delivery, on the current SDK v1.
|
|
|
77
249
|
for long operations where the host supports it; partial outcomes reported honestly.
|
|
78
250
|
5. Resource subscriptions: advertise the capability, track subscribed URIs per connection,
|
|
79
251
|
notify only subscribers. Explicit context reads keep working for hosts without them.
|
|
252
|
+
6. Align SDK tour reads with HTTP/MCP `{ tour, derived, position }`; document the breaking
|
|
253
|
+
change from `.stops` to `.tour.stops` at this minor-version boundary.
|
|
254
|
+
|
|
255
|
+
7. Approved follow-up: `canvas_help { op }` and bounded output-schema deduplication, as above.
|
|
80
256
|
|
|
81
|
-
Candidates, not automatic scope: `
|
|
257
|
+
Candidates, not automatic scope: `session.start`, composite-input redesign.
|
|
82
258
|
|
|
83
259
|
**Done when**
|
|
84
260
|
- Representative read and mutation results validate against their advertised schemas.
|
package/docs/sdk.md
CHANGED
|
@@ -36,6 +36,16 @@ Missing/stale validating preconditions fail. Reviewed content must persist befor
|
|
|
36
36
|
record. Read, edit, refresh and explicit retirement restore never renew validation; historical
|
|
37
37
|
records retain their reviewed revision, and legacy unversioned evidence remains unknown.
|
|
38
38
|
|
|
39
|
+
## Board tours
|
|
40
|
+
|
|
41
|
+
`canvas.getTour()` returns `{ tour, derived, position }`, matching HTTP and MCP.
|
|
42
|
+
Read stops from `canvas.getTour().tour.stops`. `derived` is true when stops come
|
|
43
|
+
from group reading order rather than a saved tour. `position` is the current
|
|
44
|
+
stop index, or null outside a tour.
|
|
45
|
+
This is a breaking change in 0.10: replace `.getTour().stops` with `.getTour().tour.stops`.
|
|
46
|
+
`canvas.setTour(tourOrNull)` saves the tour or resets it to derived group order.
|
|
47
|
+
See the [tour contract](http-api.md#board-tours) for navigation and camera moves.
|
|
48
|
+
|
|
39
49
|
## Quick example
|
|
40
50
|
|
|
41
51
|
`canvas.addNode` also accepts `destinationBoardId`, `requestId`, and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmx-canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Spatial canvas workbench for coding agents — infinite 2D canvas with agent-native CLI, MCP integration, nodes, edges, file watching, and snapshots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/server/index.ts",
|
|
@@ -312,7 +312,11 @@ async function startPanelServer(instanceId, ctx, pmx) {
|
|
|
312
312
|
jsonResponse(res, 400, { ok: false, error: "prompt is required" });
|
|
313
313
|
return;
|
|
314
314
|
}
|
|
315
|
-
|
|
315
|
+
if (!copilotSession) {
|
|
316
|
+
jsonResponse(res, 503, { ok: false, error: "Copilot session is unavailable." });
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
await copilotSession.send({ prompt: body.prompt, mode: "immediate" });
|
|
316
320
|
// Explicit user instruction from the panel → mirror onto the AX
|
|
317
321
|
// timeline as a steering message (fire-and-forget).
|
|
318
322
|
const target = await verifiedEntryTarget(entry);
|
|
@@ -635,7 +639,8 @@ const pmxCanvas = createCanvas({
|
|
|
635
639
|
handler: async (ctx) => {
|
|
636
640
|
const prompt = typeof ctx.input?.prompt === "string" ? ctx.input.prompt.trim() : "";
|
|
637
641
|
if (!prompt) throw new CanvasError("prompt_required", "prompt is required");
|
|
638
|
-
|
|
642
|
+
if (!copilotSession) throw new CanvasError("copilot_unavailable", "Copilot session is unavailable.");
|
|
643
|
+
await copilotSession.send({ prompt, mode: "immediate" });
|
|
639
644
|
// Mirror the explicit user instruction onto the AX timeline as a
|
|
640
645
|
// steering message (fire-and-forget). This is an explicit action
|
|
641
646
|
// flow, never a sync from the prompt hook.
|
|
@@ -867,7 +872,8 @@ sessionWorkspaceRoot = resolve((await copilotSession.rpc.metadata.snapshot()).wo
|
|
|
867
872
|
steeringDeliveryPump = createSteeringDeliveryPump({
|
|
868
873
|
consumer: "copilot",
|
|
869
874
|
claim: claimCopilotSteering,
|
|
870
|
-
|
|
875
|
+
// The SDK defaults to enqueue; canvas steering must target the active turn.
|
|
876
|
+
send: async (message) => await copilotSession.send({ prompt: message, mode: "immediate" }),
|
|
871
877
|
mark: markCopilotSteering,
|
|
872
878
|
getPresence: getCopilotPresence,
|
|
873
879
|
setPresence: async (patch) => await postPresence(sessionWorkspaceRoot, patch),
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "pmx-canvas",
|
|
4
4
|
"description": "PMX Canvas spatial workbench and MCP tools, with a native canvas panel in the GitHub Copilot app.",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.10.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "pskoett",
|
|
8
8
|
"url": "https://github.com/pskoett"
|