pmx-canvas 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/extensions/pmx-canvas/extension.mjs +1 -0
- package/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/amp-plugin/pmx-canvas/runtime.json +1 -1
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/SKILL.md +27 -11
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/evals/evals.json +88 -6
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/full-reference.md +62 -8
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/installing-pmx-canvas.md +61 -11
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/tours-and-recording.md +14 -8
- package/dist/amp-plugin/pmx-canvas/skills/pmx-canvas/references/workbench-workflows.md +11 -3
- package/docs/agent-plugin.md +6 -0
- package/docs/amp-plugin.md +3 -4
- package/package.json +1 -1
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +1 -0
- 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/skills/pmx-canvas/SKILL.md +27 -11
- package/skills/pmx-canvas/evals/evals.json +88 -6
- package/skills/pmx-canvas/references/full-reference.md +62 -8
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +61 -11
- package/skills/pmx-canvas/references/tours-and-recording.md +14 -8
- package/skills/pmx-canvas/references/workbench-workflows.md +11 -3
- package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +2 -2
- package/skills/web-artifacts-builder/scripts/init-artifact.sh +6 -6
- package/src/server/canvas-db.ts +13 -2
- package/src/server/web-artifacts/scripts/bundle-artifact.sh +2 -2
- package/src/server/web-artifacts/scripts/init-artifact.sh +6 -6
|
@@ -50,6 +50,7 @@ function delay(ms) {
|
|
|
50
50
|
async function fetchJson(baseUrl, path, options = {}) {
|
|
51
51
|
const response = await fetch(`${baseUrl}${path}`, {
|
|
52
52
|
...options,
|
|
53
|
+
headers: { "x-pmx-source": "copilot", ...options.headers },
|
|
53
54
|
signal: AbortSignal.timeout(options.timeoutMs ?? HEALTH_TIMEOUT_MS),
|
|
54
55
|
});
|
|
55
56
|
if (!response.ok) {
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
All notable changes to `pmx-canvas` are documented here. This project follows
|
|
4
4
|
[Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.12.1] - 2026-11-05
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- Copilot adapter actions are attributed to Copilot instead of appearing as a separate API writer.
|
|
11
|
+
- Bundled agent guidance now describes current delivery, consent, live-card, batch and tour behavior accurately.
|
|
12
|
+
- Web artifact setup stops on dependency-install failures and shows the package-manager error.
|
|
13
|
+
- Reduced disk writes when creating a workspace database without weakening save durability.
|
|
14
|
+
|
|
15
|
+
### Internal
|
|
16
|
+
|
|
17
|
+
- Browser CI uses Ubuntu 24.04, which the installed Playwright version supports.
|
|
18
|
+
- Editor-history checks now verify that the history panel opens before continuing.
|
|
19
|
+
|
|
6
20
|
## [0.12.0] - 2026-10-31
|
|
7
21
|
|
|
8
22
|
### Added
|
|
@@ -15,11 +15,13 @@ Use this entry guide for every task, then load only the task-specific reference
|
|
|
15
15
|
|
|
16
16
|
## Runtime and skill identity
|
|
17
17
|
|
|
18
|
-
PMX Canvas 0.12.
|
|
18
|
+
PMX Canvas 0.12.1 requires **Bun >=1.4.4**, including npm installations. Check `bun --version`
|
|
19
19
|
and the MCP host's PATH. Install or configure only when requested. Read
|
|
20
20
|
[Installing PMX Canvas](references/installing-pmx-canvas.md) for pinned setup and managed services.
|
|
21
21
|
In Amp, portal access and native MCP discovery are separate; workspace commands need human trust
|
|
22
|
-
approval.
|
|
22
|
+
approval. Raw MCP does not install an idle-thread wake-up adapter. The opt-in
|
|
23
|
+
[Amp plugin](references/installing-pmx-canvas.md#amp-plugin-bound-threads) adds board binding,
|
|
24
|
+
receipt-based delivery and steering while its executor is awake.
|
|
23
25
|
|
|
24
26
|
After upgrading, run `pmx-canvas skills sync --check` first (exit 1 means drift). Review whole-tree
|
|
25
27
|
differences and preserve local edits. `skills sync --yes` replaces all drifted installed copies
|
|
@@ -60,12 +62,15 @@ See [workspace targeting](references/workbench-workflows.md#workspace-safety) fo
|
|
|
60
62
|
|
|
61
63
|
## Read, then act on the intended board
|
|
62
64
|
|
|
63
|
-
1.
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
1. With the Amp plugin, inspect `pmx_canvas_session { action: "status" }` and use its bound
|
|
66
|
+
board without opening it. Use routed MCP query tools, not resource reads or CLI calls;
|
|
67
|
+
those bypass binding. Without a binding, reuse one visible workbench and call
|
|
68
|
+
`canvas_board { action: "list" }` before board work.
|
|
69
|
+
Home (`activeBoardId: null`) is not an empty library. For unbound active-board work, open
|
|
70
|
+
the intended board and verify `activeBoardId`. Opening changes the shared workbench.
|
|
66
71
|
Library discovery and supported background creation need no switch.
|
|
67
|
-
2. Read `
|
|
68
|
-
|
|
72
|
+
2. Read `canvas_query { action: "context", consumer: "<stable-unique-id>" }`, or, without
|
|
73
|
+
a binding, `canvas://context?consumer=<stable-unique-id>`. Use a stable consumer
|
|
69
74
|
only when durable deltas are wanted; omit it for a fresh read. Follow `cursor.next` as `since`
|
|
70
75
|
to finish a budgeted brief. Budgets are UTF-16 code units, not tokens.
|
|
71
76
|
3. The brief is a map of summaries, pins and relations, not a full-content read. Pull needed cards
|
|
@@ -77,7 +82,9 @@ See [workspace targeting](references/workbench-workflows.md#workspace-safety) fo
|
|
|
77
82
|
marks prove delivery, not understanding or approval. Refresh stale context after interruptions.
|
|
78
83
|
5. Snapshot before clear, restore or major rearrangement. Confirm destructive changes first.
|
|
79
84
|
6. Signal meaningful mutations with `canvas_intent { action: "signal", ttlMs: 30000, ... }`,
|
|
80
|
-
then pass the returned `intent.id`
|
|
85
|
+
then pass the returned `intent.id` on a supported node/edge/group mutation. For batches,
|
|
86
|
+
link the supported leaf's `args.intentId`, never the batch envelope. Quiet expiry proceeds
|
|
87
|
+
unlinked; a human veto refuses the linked write. Only an explicit intent gives a pre-write
|
|
81
88
|
veto window; automatic ghosts are not a substitute. Skip signals for trivial/high-frequency churn.
|
|
82
89
|
7. Reuse an adapter-owned session. Inspect `canvas_ax_state { action: "presence" }` first.
|
|
83
90
|
Copilot's `copilot` identity is not a new task-named agent. Put task descriptions in `detail`.
|
|
@@ -86,7 +93,9 @@ See [workspace targeting](references/workbench-workflows.md#workspace-safety) fo
|
|
|
86
93
|
Inspect rendered content, sizes and relations before reporting success. A stored payload or
|
|
87
94
|
`panned: true` is not evidence of what the human sees.
|
|
88
95
|
9. Read steering as your own consumer, act, verify the visible result, then mark that message
|
|
89
|
-
delivered.
|
|
96
|
+
delivered. With the Amp plugin, first `receive` the supplied token, then `acknowledge` only
|
|
97
|
+
after verified action; receiving a context map is not a full card read or completion.
|
|
98
|
+
Remove owned temporary nodes when the task calls for leaving the board unchanged.
|
|
90
99
|
|
|
91
100
|
When authoring a board, inspect its `readmeNodeId`. If absent, choose/create a concise Markdown
|
|
92
101
|
introduction and designate it through `canvas_board update`. Preserve an existing human choice.
|
|
@@ -121,6 +130,9 @@ Standalone tools: `canvas_batch`, `canvas_pin_nodes`, `canvas_screenshot`, `canv
|
|
|
121
130
|
`canvas_ingest_activity`, `canvas_invoke_command`, `canvas_help`. Do not invent removed legacy tools.
|
|
122
131
|
See [full API reference](references/full-reference.md) for payloads and
|
|
123
132
|
[composite action lists](references/workbench-workflows.md#current-mcp-composites).
|
|
133
|
+
Before interpreting a reply, read [MCP result shapes](references/full-reference.md#mcp-results-and-cancellation-010):
|
|
134
|
+
registry results use `result.data`, help uses `result`, and direct tools use their own schema.
|
|
135
|
+
Do not apply one unwrap rule to every tool; retain partial-write and error information.
|
|
124
136
|
|
|
125
137
|
## Choose the lightest useful surface
|
|
126
138
|
|
|
@@ -138,6 +150,9 @@ For ordinary work planning, deliberately create `status` cards with `data.workSt
|
|
|
138
150
|
session, task or approval; do not generate a card for every work event. Connect useful steps,
|
|
139
151
|
alternatives and loops with existing relations. Humans can Edit/Save/Cancel inside each card.
|
|
140
152
|
See [work planning](references/full-reference.md#task-plan-with-dependencies) for examples.
|
|
153
|
+
To display an existing task instead, create a [live task card](references/full-reference.md#live-task-cards)
|
|
154
|
+
with `data.workItemId`. Its task-derived fields are read-only and its task owner is immutable;
|
|
155
|
+
update the underlying task, not the presentation. Deleting the card does not cancel the task.
|
|
141
156
|
|
|
142
157
|
Read [HTML primitives](references/html-primitives.md) before choosing their payloads or copy/export
|
|
143
158
|
flows, [AX control surfaces](references/ax-html-control-surface.md) before authoring interactive
|
|
@@ -213,8 +228,9 @@ otherwise recheck before reuse.
|
|
|
213
228
|
Read [Tours and recording](references/tours-and-recording.md) before authoring, navigating or
|
|
214
229
|
capturing a tour. `set-tour` persists stops; deterministic capture uses the same model in its own
|
|
215
230
|
viewer. Rendering and free pan are local, but human Next/Back and agent `tour-go` share a cursor
|
|
216
|
-
and affect presenting viewers; `tour-exit` exits
|
|
217
|
-
|
|
231
|
+
for the target board and affect its presenting viewers; `tour-exit` exits those viewers.
|
|
232
|
+
Optional presenter fences reject stale commands and presenter-bearing background calls,
|
|
233
|
+
not other viewers. A superseded result is not applied navigation.
|
|
218
234
|
|
|
219
235
|
Use the [browser workflow reference](references/workbench-workflows.md#browser-workflows) for
|
|
220
236
|
keyboard, groups, menus, reconnect/draft behavior and host-local theme overrides. Use the picker
|
|
@@ -564,17 +564,17 @@
|
|
|
564
564
|
{
|
|
565
565
|
"id": 44,
|
|
566
566
|
"name": "presenter-superseded-is-not-applied-navigation",
|
|
567
|
-
"prompt": "In
|
|
568
|
-
"expected_output": "Reads the actual activation stamps and uses positive safe-integer intents with independent document IDs. Checks applied delivery stamps and cursor/event behavior. Older intent
|
|
567
|
+
"prompt": "In disposable boards A and B, verify optional presenter ordering. On visible A send a valid go with intent 2, then an exit with intent 1 for the same document and activation. Repeat with a stale activation. Include an independent-document control and an ordinary unfenced call. Then target background B with a presenter-bearing call and an unfenced control. Can ok:true or the SDK exit return prove the stale command ran?",
|
|
568
|
+
"expected_output": "Reads the actual activation stamps and uses positive safe-integer intents with independent document IDs. Checks applied delivery stamps and cursor/event behavior. Older intent, stale activation and presenter-bearing background calls return ok:true,superseded:true without navigation or cursor change. Independent and unfenced controls still apply on their target board; B's tour does not replace A's cursor or navigate its viewers. Explains that the fence orders requests, does not grant authority or isolate same-board viewers, and that SDK exit returns void while fenced go may return superseded:true. Does not count eval definitions as executed evidence.",
|
|
569
569
|
"assertions": [
|
|
570
570
|
{
|
|
571
571
|
"name": "checks-superseded-side-effects",
|
|
572
|
-
"description": "Observes no navigation event or cursor change for stale intent and
|
|
572
|
+
"description": "Observes no navigation event or cursor change for stale intent, stale activation and presenter-bearing background calls, rather than treating ok:true as applied navigation",
|
|
573
573
|
"type": "output_check"
|
|
574
574
|
},
|
|
575
575
|
{
|
|
576
576
|
"name": "positive-controls-and-stamps",
|
|
577
|
-
"description": "Verifies applied epoch/generation/sequence for the newer request and
|
|
577
|
+
"description": "Verifies applied epoch/generation/sequence for the newer request and independent-document/unfenced controls; B's unfenced call changes only B's cursor while A remains visible with its own cursor",
|
|
578
578
|
"type": "output_check"
|
|
579
579
|
},
|
|
580
580
|
{
|
|
@@ -587,7 +587,7 @@
|
|
|
587
587
|
{
|
|
588
588
|
"id": 23,
|
|
589
589
|
"name": "multi-board-targeting",
|
|
590
|
-
"prompt": "I have Roadmap and Incident Review boards. Add a decision note only to Incident Review and set its tour to the Summary group.
|
|
590
|
+
"prompt": "Using raw MCP without an Amp plugin binding, I have Roadmap and Incident Review boards. Add a decision note only to Incident Review and set its tour to the Summary group. Preserve Roadmap content; switching the shared view is allowed.",
|
|
591
591
|
"expected_output": "Lists/gets boards, resolves the exact Incident Review board and calls canvas_board action open or CLI board open with its ID, verifies the returned activeBoardId, searches for the Summary group there, then adds the note and sets that board's tour. It explains that opening switches the shared view but preserves Roadmap content. It does not infer IDs from titles, mutate Roadmap, invent inactive-board write targeting, or assume that a board switch succeeded. It validates Incident Review and reports board/node IDs.",
|
|
592
592
|
"assertions": [
|
|
593
593
|
{
|
|
@@ -753,7 +753,7 @@
|
|
|
753
753
|
{
|
|
754
754
|
"id": 30,
|
|
755
755
|
"name": "amp-native-steering-evidence-boundary",
|
|
756
|
-
"prompt": "On this disposable board, native Amp MCP is connected and your source/consumer is amp-review. The browser pinned the Review card and sent amp-review a fresh instruction to append receipt CHECK-30. Prove the round trip, then confirm that an idle Amp thread will now wake automatically and that native Skills discovery works.",
|
|
756
|
+
"prompt": "On this disposable board, raw native Amp MCP is connected without the directory plugin and your source/consumer is amp-review. The browser pinned the Review card and sent amp-review a fresh instruction to append receipt CHECK-30. Prove the round trip, then confirm that an idle Amp thread will now wake automatically and that native Skills discovery works.",
|
|
757
757
|
"expected_output": "Uses actual Amp Canvas tools to read the pinned card, claims only as amp-review, signals intent and appends the requested receipt without losing existing content. Verifies the rendered receipt before marking that delivery for amp-review and confirms it is no longer pending. Uses a different recipient as a negative control and detaches only self-owned test sessions. Reports active-agent polling as verified but declines to infer idle-thread wake-up, persistent pumping or native MCP Skills discovery from this evidence.",
|
|
758
758
|
"assertions": [
|
|
759
759
|
{
|
|
@@ -1081,6 +1081,88 @@
|
|
|
1081
1081
|
"type": "output_check"
|
|
1082
1082
|
}
|
|
1083
1083
|
]
|
|
1084
|
+
},
|
|
1085
|
+
{
|
|
1086
|
+
"id": 45,
|
|
1087
|
+
"name": "quiet-expiry-versus-veto-and-leaf-linkage",
|
|
1088
|
+
"prompt": "In a disposable canvas, signal separate create intents for three Markdown cards. Let the harness quietly expire one, human-veto another, and leave the third live. Create each through a separate batch leaf using the returned intent ID. Explain whether putting one intentId on the batch envelope would protect every sibling. Do not bypass the veto or treat expiry as approval.",
|
|
1089
|
+
"expected_output": "Uses operations[].args.intentId on supported node.add leaves, never the batch envelope. Verifies the expired case proceeds unlinked, the vetoed case creates no card, and the live case settles once. Explains the standalone-MCP versus attached-HTTP top-level mismatch without relying on either behavior. Ordinary scope/revision rules still apply; no new ID is minted to evade the veto.",
|
|
1090
|
+
"assertions": [
|
|
1091
|
+
{
|
|
1092
|
+
"name": "distinguishes-expiry-from-human-refusal",
|
|
1093
|
+
"description": "Readback finds the expired control's card but no vetoed card; the agent neither labels quiet expiry a veto nor retries the vetoed plan under another ID",
|
|
1094
|
+
"type": "output_check"
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
"name": "links-only-the-supported-leaf",
|
|
1098
|
+
"description": "Trace puts intentId in node.add args, verifies live settlement, and does not claim one settled intent protects later siblings or a top-level batch intent is portable",
|
|
1099
|
+
"type": "output_check"
|
|
1100
|
+
}
|
|
1101
|
+
]
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
"id": 46,
|
|
1105
|
+
"name": "amp-bound-delivery-and-separate-jev-consents",
|
|
1106
|
+
"prompt": "The actual Amp plugin binds this thread to A while the human views B. Its context packet contains a receive token and a summary of A/Review. Addressed steering asks you to append CHECK-46 there. Context ranking is enabled but Jev advice is off. Show the edit, acknowledge it, and ask Jev to rank your proposed changes. Can you read canvas://context instead, open A, or wake a sleeping orb? Do not change consent yourself.",
|
|
1107
|
+
"expected_output": "Checks session status, receives each supplied packet token, reads full A/Review through routed MCP, edits without switching B, and verifies the result before acknowledging steering. Does not mistake a context receipt for a full read or completed action. Declines Jev inference without the separate advice consent, using deterministic fallback or requesting human opt-in. Reports awake-executor idle wake separately from sleeping-orb resume.",
|
|
1108
|
+
"assertions": [
|
|
1109
|
+
{
|
|
1110
|
+
"name": "uses-bound-tools-without-navigation",
|
|
1111
|
+
"description": "Trace uses routed MCP rather than CLI or resources/read, preserves B's active view, and never overrides the bound destination",
|
|
1112
|
+
"type": "output_check"
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
"name": "receive-is-not-acknowledge",
|
|
1116
|
+
"description": "Packet reception precedes full content reading and action; visible CHECK-46 verification precedes steering acknowledgment, and failed/unverified work is not acknowledged",
|
|
1117
|
+
"type": "output_check"
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
"name": "consent-and-wake-boundaries",
|
|
1121
|
+
"description": "Ranking consent is not reused for advice, no consent is enabled by the agent, and native awake-executor wake is not claimed to wake a sleeping orb",
|
|
1122
|
+
"type": "output_check"
|
|
1123
|
+
}
|
|
1124
|
+
]
|
|
1125
|
+
},
|
|
1126
|
+
{
|
|
1127
|
+
"id": 47,
|
|
1128
|
+
"name": "authored-versus-live-task-card-ownership",
|
|
1129
|
+
"prompt": "In a disposable library, A and B each have a task named Review. Show A's existing task as a live status card and also create an independent authored plan card. Mark A's task in-progress, move its presentation to B, then delete that presentation. Do not transfer or cancel either task. Can you edit the live card's title/progress or rebind it to B's same-named task?",
|
|
1130
|
+
"expected_output": "Resolves task identity on A, creates the live card using workItemId without derived fields, and creates the authored card separately with workState. Updates the task through canvas_ax_work on A. After moving, confirms immutable workItemBoardId A and fresh task-derived display; rejects title/progress edits and rebinding. Deleting the presentation leaves both tasks intact and the authored card independent.",
|
|
1131
|
+
"assertions": [
|
|
1132
|
+
{
|
|
1133
|
+
"name": "separates-task-from-presentation",
|
|
1134
|
+
"description": "Live creation includes the resolved task ID but no derived title/content/workState/detail/progress; authored creation uses workState without a task binding",
|
|
1135
|
+
"type": "output_check"
|
|
1136
|
+
},
|
|
1137
|
+
{
|
|
1138
|
+
"name": "preserves-owner-across-move",
|
|
1139
|
+
"description": "Readback after relocation shows owner A, the original task ID and updated state, never B's same-title task; no rebinding or direct display-field edit is attempted as a solution",
|
|
1140
|
+
"type": "output_check"
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
"name": "deletion-is-not-cancellation",
|
|
1144
|
+
"description": "After deleting only the presentation, qualified task reads confirm A's task is still in-progress and B's task unchanged; authored plan data remains independent",
|
|
1145
|
+
"type": "output_check"
|
|
1146
|
+
}
|
|
1147
|
+
]
|
|
1148
|
+
},
|
|
1149
|
+
{
|
|
1150
|
+
"id": 48,
|
|
1151
|
+
"name": "batch-annotation-partial-result-and-tool-envelopes",
|
|
1152
|
+
"prompt": "In a disposable canvas, read canvas_help for supported batch operations. Add a text annotation with an explicit ID, then submit a deliberate unsupported edge.update as the second batch entry. Inspect the failure before retrying the annotation, then remove it. Compare the raw structured replies from canvas_help, canvas_batch and canvas_ingest_activity. Can you always unwrap result.data or retry the entire failed batch?",
|
|
1153
|
+
"expected_output": "Uses annotation.add/remove, identifies edge.update as unsupported, and checks the failedIndex plus committed results/refs before retrying. Equal normalized annotation content with the same ID reuses the mark; removal is not a durable replay receipt. Distinguishes registry result.operation/outcome/data, help metadata under result and direct activity fields. It preserves isError/partial state instead of discarding it or blindly replaying writes.",
|
|
1154
|
+
"assertions": [
|
|
1155
|
+
{
|
|
1156
|
+
"name": "partial-failure-keeps-earlier-annotation",
|
|
1157
|
+
"description": "Failure at index 1 retains one annotation; identical-ID/content retry does not duplicate it, and removal erases that mark only",
|
|
1158
|
+
"type": "output_check"
|
|
1159
|
+
},
|
|
1160
|
+
{
|
|
1161
|
+
"name": "decodes-per-tool-contract",
|
|
1162
|
+
"description": "Extracts batch results from structuredContent.result.data and checks outcome partial, reads help from result, and reads activity fields directly without blanket unwrapping",
|
|
1163
|
+
"type": "output_check"
|
|
1164
|
+
}
|
|
1165
|
+
]
|
|
1084
1166
|
}
|
|
1085
1167
|
]
|
|
1086
1168
|
}
|
|
@@ -624,8 +624,11 @@ persisted, auto-expiring (~8s), never in `canvas_query layout`.
|
|
|
624
624
|
Narrate → linked mutation → automatic settle:
|
|
625
625
|
1. `canvas_intent { action: "signal", kind: "create", nodeType: "markdown", label: "Add evidence", reason: "capturing the failing test", confidence: 0.8 }` → returns `intent.id` and the `position` the canvas chose.
|
|
626
626
|
2. Make the real move and pass that id: `canvas_node { action: "add", intentId: <intent.id>, ... }`.
|
|
627
|
-
3.
|
|
628
|
-
|
|
627
|
+
3. A human-vetoed intent rejects its linked mutation. A quietly expired ghost does not:
|
|
628
|
+
the write proceeds unlinked, subject to the ordinary permissions and revision checks.
|
|
629
|
+
A successful write linked to a still-live intent settles the ghost automatically.
|
|
630
|
+
Expiry is neither approval nor a human veto. Never retry a vetoed plan under a new ID
|
|
631
|
+
just to bypass the human's decision.
|
|
629
632
|
|
|
630
633
|
Use `canvas_intent { action: "clear", id }` only when abandoning a plan without
|
|
631
634
|
performing the linked mutation.
|
|
@@ -650,9 +653,18 @@ edits; destructive actions (clear/restore/remove); and creating
|
|
|
650
653
|
artifact/report/dashboard nodes. Skip for tiny metadata fixes, API-only pin/unpin
|
|
651
654
|
verification, deterministic report-node refreshes the human just asked for,
|
|
652
655
|
post-restore cleanup, and bulk fixture churn. **For batch work, signal one ghost
|
|
653
|
-
per human-meaningful move, not one per low-level op
|
|
654
|
-
|
|
655
|
-
|
|
656
|
+
per human-meaningful move, not one per low-level op.** Put its `intentId` inside the
|
|
657
|
+
supported leaf operation's `args`, never on the `canvas_batch` envelope. Each live
|
|
658
|
+
intent settles once; it is not a veto gate for every sibling in a batch. For example,
|
|
659
|
+
after signalling a create intent, use its actual returned ID in this leaf:
|
|
660
|
+
|
|
661
|
+
```json
|
|
662
|
+
{"operations":[{"op":"node.add","args":{"type":"markdown","title":"Evidence","content":"Observed failure","intentId":"<returned-intent-id>"}}]}
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
Do not rely on a top-level batch `intentId`: standalone MCP can refuse it, while the
|
|
666
|
+
attached HTTP batch reader does not forward it. Unsupported operations cannot be made
|
|
667
|
+
veto-linked by wrapping them in a batch. Use `seq` to order separate staged previews.
|
|
656
668
|
|
|
657
669
|
### Standalones (first-class — not deprecated)
|
|
658
670
|
|
|
@@ -663,10 +675,12 @@ composite in v0.4.0 (actions `save | list | restore | delete | gc | diff`); the
|
|
|
663
675
|
standalones were removed after their deprecated 0.3.x window.
|
|
664
676
|
|
|
665
677
|
`canvas_batch` supports exactly these ops: `node.add`, `node.update`, `node.remove`, `graph.add`,
|
|
666
|
-
`edge.add`, `edge.
|
|
667
|
-
`pin.remove`, `snapshot.save`, and `arrange`.
|
|
678
|
+
`edge.add`, `edge.remove`, `group.create`, `group.add`, `group.remove`, `annotation.add`,
|
|
679
|
+
`annotation.remove`, `pin.set`, `pin.add`, `pin.remove`, `snapshot.save`, and `arrange`.
|
|
680
|
+
`edge.update` is not supported. Anything else fails with "Unsupported canvas_batch
|
|
668
681
|
operation" — batch is non-atomic, so earlier ops stay applied and the response carries
|
|
669
|
-
`failedIndex
|
|
682
|
+
`failedIndex`, `results` and `refs`. Inspect that committed prefix before retrying; an
|
|
683
|
+
error does not roll it back. `canvas_screenshot` requires an active automation WebView: call
|
|
670
684
|
`canvas_webview { action: "start" }` first.
|
|
671
685
|
|
|
672
686
|
> **Removed in v0.3.0 → use the composite instead**: `canvas_open_mcp_app` / `canvas_add_diagram` /
|
|
@@ -1186,6 +1200,22 @@ writes occurred. Interaction, activity-ingestion and screenshot tools instead
|
|
|
1186
1200
|
use direct structured objects matching their schemas. Check `isError` and domain
|
|
1187
1201
|
outcomes. A composite's annotations cover all its actions, not just reads.
|
|
1188
1202
|
|
|
1203
|
+
Paired example: `canvas_node { action: "add", type: "markdown", content: "Evidence" }`
|
|
1204
|
+
returns registry data under `structuredContent.result.data` (excerpt; the ID varies):
|
|
1205
|
+
|
|
1206
|
+
```json
|
|
1207
|
+
{"result":{"operation":"node.add","outcome":"success","data":{"ok":true,"id":"example-node"}}}
|
|
1208
|
+
```
|
|
1209
|
+
|
|
1210
|
+
By contrast, `canvas_help {}` returns `structuredContent.result.operations`, not
|
|
1211
|
+
`result.data`. `canvas_help { op: "node.add" }` returns metadata with `operation`,
|
|
1212
|
+
`tool`, `description` and `inputSchema` directly under `result`.
|
|
1213
|
+
For direct tools (`canvas_ax_interaction`, `canvas_ingest_activity`, `canvas_screenshot`),
|
|
1214
|
+
read fields directly from `structuredContent` according to their `outputSchema`.
|
|
1215
|
+
These are different contracts, not optional wrappers to strip recursively. Text blocks
|
|
1216
|
+
are a separate representation; an SDK/host may already return `structuredContent`.
|
|
1217
|
+
On a failed call, inspect its error response and partial results before retrying writes.
|
|
1218
|
+
|
|
1189
1219
|
Cancellation releases supported AX waits, aborts webpage fetches before late
|
|
1190
1220
|
content writes, and stops subsequent batch operations. Completed writes remain;
|
|
1191
1221
|
batch partial results retain `results` and `refs`. A created webpage can remain
|
|
@@ -1645,6 +1675,30 @@ Without `data.workState`, status cards retain their phase/tool display. Session-
|
|
|
1645
1675
|
is not provided by these authored cards. Questions can be drawn or written beside the plan;
|
|
1646
1676
|
the human can answer in the external agent host's composer, without a PMX reply card.
|
|
1647
1677
|
|
|
1678
|
+
### Live task cards
|
|
1679
|
+
|
|
1680
|
+
A live card presents an existing AX work item; it is not another task or an authored
|
|
1681
|
+
work plan. Read the task first with `canvas_ax_work { action: "list" }` on its owning
|
|
1682
|
+
board, then create a `status` presentation using that task's actual ID:
|
|
1683
|
+
|
|
1684
|
+
```json
|
|
1685
|
+
{"action":"add","type":"status","data":{"workItemId":"<existing-task-id>"}}
|
|
1686
|
+
```
|
|
1687
|
+
|
|
1688
|
+
The owner defaults to the current board. To present a task from another board, supply
|
|
1689
|
+
its explicit `data.workItemBoardId` too. Both task ID and owner are fixed at creation;
|
|
1690
|
+
moving the card does not transfer the task. Create through the current board owner
|
|
1691
|
+
(or the Amp plugin's bound board), not `destinationBoardId` background creation.
|
|
1692
|
+
|
|
1693
|
+
Omit `title`, `content`, `workState`, `detail`, `progress`, `axWorkStatus`,
|
|
1694
|
+
`liveWorkAvailable` and `liveWorkSource` from creation and updates, including nested
|
|
1695
|
+
data fields. The server derives title, detail, status and source from the task; these
|
|
1696
|
+
are read-only display fields. Update the underlying work item on its owning board with
|
|
1697
|
+
`canvas_ax_work { action: "update", id: "<existing-task-id>", status: "in-progress" }`.
|
|
1698
|
+
Position and size still belong to the card. Deleting the presentation does not cancel
|
|
1699
|
+
or delete the task. If the task is unavailable, the card displays that fact rather than
|
|
1700
|
+
becoming an editable authored card. To change the binding, create a new presentation.
|
|
1701
|
+
|
|
1648
1702
|
### Code Exploration
|
|
1649
1703
|
|
|
1650
1704
|
Understand a codebase by visualizing file relationships:
|
|
@@ -4,7 +4,7 @@ Use this reference when the `pmx-canvas` skill is installed but the `pmx-canvas`
|
|
|
4
4
|
|
|
5
5
|
## Prerequisites and version
|
|
6
6
|
|
|
7
|
-
The examples pin **PMX Canvas 0.12.
|
|
7
|
+
The examples pin **PMX Canvas 0.12.1**, which requires **Bun >=1.4.4** even when
|
|
8
8
|
installed through npm: the CLI runs through Bun, not Node. Check `bun --version`
|
|
9
9
|
first. If missing or older, follow the [Bun installation instructions](https://bun.sh/docs/installation)
|
|
10
10
|
with the user's authorization. Ensure Bun is on the MCP host's PATH as well as the
|
|
@@ -22,11 +22,11 @@ in `SKILL.md`. Do not pair newer checkout guidance with an older runtime unknowi
|
|
|
22
22
|
## Install from npm
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npm install -g pmx-canvas@0.12.
|
|
25
|
+
npm install -g pmx-canvas@0.12.1
|
|
26
26
|
pmx-canvas --version
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
Without a global install, use `bunx pmx-canvas@0.12.
|
|
29
|
+
Without a global install, use `bunx pmx-canvas@0.12.1` in place of `pmx-canvas` in
|
|
30
30
|
the commands below. Do not use unpinned `bunx pmx-canvas` for a version-specific check.
|
|
31
31
|
|
|
32
32
|
## Choose the workspace and target
|
|
@@ -96,7 +96,7 @@ discards empty env values, remove `PMX_CANVAS_URL` from its launch environment i
|
|
|
96
96
|
"mcpServers": {
|
|
97
97
|
"canvas": {
|
|
98
98
|
"command": "bunx",
|
|
99
|
-
"args": ["pmx-canvas@0.12.
|
|
99
|
+
"args": ["pmx-canvas@0.12.1", "--mcp"],
|
|
100
100
|
"env": {
|
|
101
101
|
"PMX_CANVAS_WORKSPACE_ROOT": "/absolute/path/to/project",
|
|
102
102
|
"PMX_CANVAS_PORT": "14313",
|
|
@@ -130,9 +130,59 @@ fallback ports; do not assume the configured port is the one the MCP server boun
|
|
|
130
130
|
|
|
131
131
|
## Amp: connect the agent separately from the portal
|
|
132
132
|
|
|
133
|
-
PMX
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
PMX ships an opt-in directory plugin with board binding and receipt-based steering, or
|
|
134
|
+
you can configure raw MCP for active polling. The portal is the human's browser UI;
|
|
135
|
+
neither opening it nor configuring raw MCP installs the plugin. Choose one integration
|
|
136
|
+
for the task rather than creating duplicate writers.
|
|
137
|
+
|
|
138
|
+
### Amp plugin: bound threads
|
|
139
|
+
|
|
140
|
+
When installation is requested, copy the complete installed package directory
|
|
141
|
+
`node_modules/pmx-canvas/dist/amp-plugin/pmx-canvas` to the project's
|
|
142
|
+
`.amp/plugins/pmx-canvas`. Inspect existing plugin files and preserve local changes;
|
|
143
|
+
replacement needs owner approval. Reload Amp plugins and load the qualified
|
|
144
|
+
`pmx-canvas:pmx-canvas` skill. Approve its workspace MCP command through the normal
|
|
145
|
+
human trust flow, never by bypassing it. No global plugin installation is implied.
|
|
146
|
+
|
|
147
|
+
Use `pmx_canvas_session { action: "open" }` to start/reconnect and verify the service,
|
|
148
|
+
then `bind` with an existing explicit `boardId`. `status` reports the binding and
|
|
149
|
+
shared active board; `unbind` removes only this thread's binding. Binding does not
|
|
150
|
+
open a board, change sharing, or create an access-control boundary.
|
|
151
|
+
|
|
152
|
+
Bound MCP tool calls route to that board with identity `amp:<thread-id>`, even when
|
|
153
|
+
the human views another board or Home. Use `canvas_query` for context and full
|
|
154
|
+
`canvas_node` reads for needed content. CLI calls and MCP resource reads are not
|
|
155
|
+
intercepted. Do not navigate the shared workbench through bound calls, override the
|
|
156
|
+
destination, or open the board to make a write work. A missing board or changed
|
|
157
|
+
binding fails instead of silently targeting the visible board; a binding change
|
|
158
|
+
during a turn requires a new turn.
|
|
159
|
+
|
|
160
|
+
At turn start, return the supplied context token through
|
|
161
|
+
`pmx_canvas_delivery { action: "receive", token }`. Reception records the delivered
|
|
162
|
+
map, not full card reads, understanding or approval. For a steering token, receive it,
|
|
163
|
+
read the relevant content, act, verify the result, and only then call
|
|
164
|
+
`pmx_canvas_delivery { action: "acknowledge", token }`. Do not acknowledge failed or
|
|
165
|
+
unverified work. Uncertain sends require human resolution, not blind retries or
|
|
166
|
+
deleting the transport journal.
|
|
167
|
+
|
|
168
|
+
Addressed steering can start an idle thread or queue into a busy turn only while
|
|
169
|
+
the plugin executor is awake. It does not wake a sleeping orb or hold a keep-alive
|
|
170
|
+
lease. A raw MCP polling test does not prove this native delivery path.
|
|
171
|
+
|
|
172
|
+
**Context ranking** and **Jev advice** are separate opt-ins, both off by default.
|
|
173
|
+
Their Amp commands require separate human confirmation for the current binding and
|
|
174
|
+
disclose data sent to TypeSafe Jev and the invoking thread's inference billing.
|
|
175
|
+
Ranking reorders optional summaries; advice suggests formats or review order without
|
|
176
|
+
creating output or verifying work. One consent never enables the other. Rebinding
|
|
177
|
+
does not carry either consent. Respect deterministic fallback and report it rather
|
|
178
|
+
than retrying with another provider. See the
|
|
179
|
+
[plugin contract](https://github.com/pskoett/pmx-canvas/blob/main/docs/amp-plugin.md)
|
|
180
|
+
for request fields, retry identities and native acceptance limits.
|
|
181
|
+
|
|
182
|
+
### Raw MCP: active polling
|
|
183
|
+
|
|
184
|
+
Configure MCP inside the orb or runner where Amp executes, not only on the user's
|
|
185
|
+
laptop. Merge this into that workspace's
|
|
136
186
|
`.amp/settings.json`, preserving other settings (Amp does not use the generic `.mcp.json`):
|
|
137
187
|
|
|
138
188
|
```json
|
|
@@ -140,7 +190,7 @@ Amp executes, not only on the user's laptop. Merge this into that workspace's
|
|
|
140
190
|
"amp.mcpServers": {
|
|
141
191
|
"canvas": {
|
|
142
192
|
"command": "bunx",
|
|
143
|
-
"args": ["pmx-canvas@0.12.
|
|
193
|
+
"args": ["pmx-canvas@0.12.1", "--mcp"],
|
|
144
194
|
"includeTools": ["canvas_*"],
|
|
145
195
|
"env": {
|
|
146
196
|
"PMX_CANVAS_WORKSPACE_ROOT": "/absolute/path/to/project",
|
|
@@ -174,7 +224,7 @@ The agent must not run this approval itself or move the command to global settin
|
|
|
174
224
|
`--mcp-config` to bypass workspace trust. Approval authorizes execution of this MCP
|
|
175
225
|
command; it is not a new Canvas import consent or permission to mutate arbitrary boards.
|
|
176
226
|
After approval, reload MCP connections (`reload_mcp` in Amp) and require `connected`.
|
|
177
|
-
Discover `canvas` tools with `tool_search`; the full unfiltered 0.12.
|
|
227
|
+
Discover `canvas` tools with `tool_search`; the full unfiltered 0.12.1 server has 25 tools,
|
|
178
228
|
including `canvas_help`. If still absent, inspect the server status, command/PATH and target instead
|
|
179
229
|
of reinstalling blindly. See [Amp MCP documentation](https://ampcode.com/docs/customize/mcp).
|
|
180
230
|
|
|
@@ -194,8 +244,8 @@ of reinstalling blindly. See [Amp MCP documentation](https://ampcode.com/docs/cu
|
|
|
194
244
|
4. Verify the visible result in the browser before marking the message delivered for
|
|
195
245
|
that consumer. A subsequent claim should omit it. Detach only test-owned sessions.
|
|
196
246
|
|
|
197
|
-
This proves an **active agent can poll and act**, not automatic wake-up
|
|
198
|
-
thread, background polling, or automatic agent launch for imports. An MCP connection
|
|
247
|
+
This raw-MCP check proves an **active agent can poll and act**, not automatic wake-up
|
|
248
|
+
of an idle Amp thread, background polling, or automatic agent launch for imports. An MCP connection
|
|
199
249
|
does not install a steering pump. Only configure a pump/host integration when requested;
|
|
200
250
|
its startup backlog rules are in the main skill. Tool discovery and resource reads also
|
|
201
251
|
do not establish Amp support for native MCP Skills-extension discovery or activation.
|
|
@@ -32,8 +32,8 @@ Open `/workbench?present=1` for chrome-free viewing. Right, Down, or Space advan
|
|
|
32
32
|
goes back; Escape or **Exit presentation** exits. Right-drag pans and interrupts an ongoing
|
|
33
33
|
transition without editing cards. Stops do not auto-advance. A missing node target reports an
|
|
34
34
|
error and may be skipped. Camera rendering and free pan are viewer-local, but human Back/Next
|
|
35
|
-
and arrow keys advance the shared cursor for
|
|
36
|
-
|
|
35
|
+
and arrow keys advance the target board's shared cursor for its presenting viewers; Exit leaves
|
|
36
|
+
presentation for those viewers. `present: false` does not isolate viewers of the same board.
|
|
37
37
|
Deterministic capture uses its own viewer and ignores live navigation. Recording hides the exit control.
|
|
38
38
|
|
|
39
39
|
Tours are board-scoped, persist with that board and its snapshots, participate in undo, and clear
|
|
@@ -44,11 +44,15 @@ setting or reading it.
|
|
|
44
44
|
|
|
45
45
|
## Drive a tour
|
|
46
46
|
|
|
47
|
-
The server
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
The server keeps board-local in-memory tour cursors, not one workspace-wide cursor.
|
|
48
|
+
`canvas_view { action: "tour-go", stop: 0 }` starts presenting in workbenches showing the
|
|
49
|
+
target board; `step: "next" | "previous"` moves relative to that board's cursor
|
|
50
|
+
(a human's arrow keys move the same cursor) and clamps at the ends. Pass
|
|
50
51
|
`present: false` to move only viewers already presenting. `canvas_view { action: "tour-exit" }`
|
|
51
|
-
|
|
52
|
+
exits presentation on the target board. `get-tour` reports `position` (the current stop, or null).
|
|
53
|
+
Bound background calls do not navigate the human's visible board. Cursors are not durable:
|
|
54
|
+
tour edits or activation changes can invalidate them, so read `get-tour` rather than assuming
|
|
55
|
+
a previous stop survives reopening a board.
|
|
52
56
|
|
|
53
57
|
`canvas_view { action: "move", nodeId | rect | viewport, duration, easing, padding, pullback }`
|
|
54
58
|
eases the camera without a tour. Outside a presentation the end camera becomes the board
|
|
@@ -68,8 +72,10 @@ Use a distinct `clientId` per document, an increasing positive safe-integer `int
|
|
|
68
72
|
and the actual server activation's epoch and nonnegative safe-integer generation. Ordinary
|
|
69
73
|
agent calls may omit this object. It orders requests; it is not authorization or viewer isolation.
|
|
70
74
|
|
|
71
|
-
A stale activation
|
|
72
|
-
|
|
75
|
+
A stale activation, duplicate/older intent, or presenter-bearing call on a background board
|
|
76
|
+
returns `{ ok: true, superseded: true }` with no navigation event or cursor change.
|
|
77
|
+
Ordinary unfenced background calls still target their own board, not the visible one.
|
|
78
|
+
Do not claim navigation from `ok: true` alone. Applied results
|
|
73
79
|
and events carry `catalogEpoch`, `boardGeneration` and `sequence`; presenter-aware clients use
|
|
74
80
|
these to reject stale acknowledgements and events. A structurally valid newer intent is claimed
|
|
75
81
|
before resolving the stop, so even a missing newer stop supersedes older requests.
|
|
@@ -104,7 +104,10 @@ For pinned installation, MCP configuration, managed services, and disposable ver
|
|
|
104
104
|
read [Installing PMX Canvas](installing-pmx-canvas.md).
|
|
105
105
|
In Amp, follow that reference's [Amp setup](installing-pmx-canvas.md#amp-connect-the-agent-separately-from-the-portal):
|
|
106
106
|
portal access is separate from native MCP, workspace commands need human trust approval,
|
|
107
|
-
and
|
|
107
|
+
and raw MCP does not install an idle-thread wake-up adapter. The opt-in
|
|
108
|
+
[Amp plugin](installing-pmx-canvas.md#amp-plugin-bound-threads) adds board binding and
|
|
109
|
+
receipt-based steering while its executor is awake. Use routed query tools for bound
|
|
110
|
+
context; CLI calls and resource reads are not intercepted.
|
|
108
111
|
|
|
109
112
|
## Reading bundled skills over MCP
|
|
110
113
|
|
|
@@ -130,8 +133,10 @@ the served catalog is a startup snapshot. Local mirrors still use `skills sync`
|
|
|
130
133
|
Use a disposable consumer when testing released guidance without permission to replace
|
|
131
134
|
owned mirrors. After an authorized upgrade, restart the matching HTTP daemon and `--mcp`
|
|
132
135
|
processes; Bun does not hot-reload a running process.
|
|
133
|
-
1. **
|
|
134
|
-
|
|
136
|
+
1. **Check the session's target before mutating.** With the Amp plugin, read
|
|
137
|
+
`pmx_canvas_session { action: "status" }` and keep using its bound board without opening
|
|
138
|
+
it or navigating the shared workbench. Without a binding, reuse one visible canvas surface
|
|
139
|
+
and open the intended board when active-board work requires it.
|
|
135
140
|
2. **Verify workspace identity at the actual target.** Read `GET /health` at the URL your
|
|
136
141
|
CLI/MCP/browser is using; its `workspace` must equal the intended canonical absolute root.
|
|
137
142
|
`pmx-canvas serve status --port=<port>` checks the local listener on that port, not an
|
|
@@ -149,6 +154,9 @@ the served catalog is a startup snapshot. Local mirrors still use `skills sync`
|
|
|
149
154
|
human watches intent form and can veto mid-thought. Skip it only for trivial in-place tweaks or
|
|
150
155
|
high-frequency batch churn. The default TTL (~8s) expires between agent turns: signal with
|
|
151
156
|
`ttlMs: 30000` and settle by passing `intentId` on the mutation in the same or next call.
|
|
157
|
+
Link only supported node/edge/group mutations; in a batch put the ID on the leaf's
|
|
158
|
+
`args.intentId`, not the envelope. Quiet expiry proceeds unlinked; a human veto refuses
|
|
159
|
+
the linked write. An intent is not permission or a batch-wide gate.
|
|
152
160
|
Since 0.4.5, an agent mutation WITHOUT a signal still shows a server-synthesized **auto-ghost**
|
|
153
161
|
(rendered lighter — dimmer, dotted, no veto — and settled instantly). That is a visibility
|
|
154
162
|
floor, not a replacement: only an explicit signal gives the human a real pre-mutation veto
|
package/docs/agent-plugin.md
CHANGED
|
@@ -90,6 +90,12 @@ The adapter uses the session's **working directory**, not Copilot's session-stat
|
|
|
90
90
|
`workspacePath` or the plugin installation directory. Boards remain in the project's
|
|
91
91
|
`.pmx-canvas/canvas.db`.
|
|
92
92
|
|
|
93
|
+
Copilot's native adapter labels its HTTP operations as `copilot`, including AX writes.
|
|
94
|
+
To use that same writer identity over MCP, configure the host's MCP process with
|
|
95
|
+
`PMX_CANVAS_AGENT_SOURCE=copilot`; the portable launcher forwards it to the runtime.
|
|
96
|
+
It does not assume every plugin client is Copilot. Give independent clients their own
|
|
97
|
+
source label, or use an explicit `agentId` on their operations, to keep them distinct.
|
|
98
|
+
|
|
93
99
|
The daemon belongs to the workspace and stays running when one client closes, so closing
|
|
94
100
|
the native panel cannot break another MCP client. Stop it explicitly from the project:
|
|
95
101
|
|
package/docs/amp-plugin.md
CHANGED
|
@@ -122,10 +122,9 @@ launcher. `PMX_CANVAS_URL` is an explicit target, not a fallback. An unavailable
|
|
|
122
122
|
fails rather than starting a second server. Version mismatch or a missing/unknown bundle stamp
|
|
123
123
|
also fails, including at MCP connection and subsequent requests.
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
increment.
|
|
125
|
+
The `0.12.0` package includes the required bundle stamp and generated Amp plugin. The older
|
|
126
|
+
`0.11.0` runtime lacks that stamp and cannot serve this integration. Verify the actual runtime
|
|
127
|
+
version and stamp on each connection; a local build alone does not prove registry startup.
|
|
129
128
|
|
|
130
129
|
Amp supplies the Portal URL and access controls. Open does not change sharing or multiplayer.
|
|
131
130
|
|