pmx-canvas 0.1.23 → 0.1.25
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 +591 -0
- package/CHANGELOG.md +123 -0
- package/Readme.md +36 -5
- package/dist/canvas/global.css +36 -3
- package/dist/canvas/index.js +54 -54
- package/dist/types/client/nodes/ExtAppFrame.d.ts +1 -0
- package/dist/types/client/nodes/McpAppNode.d.ts +1 -0
- package/dist/types/client/nodes/iframe-document-url.d.ts +8 -0
- package/dist/types/client/state/intent-bridge.d.ts +4 -0
- package/dist/types/client/types.d.ts +1 -0
- package/dist/types/json-render/catalog.d.ts +1 -1
- package/dist/types/mcp/canvas-access.d.ts +9 -0
- package/dist/types/server/ax-context.d.ts +3 -0
- package/dist/types/server/ax-state.d.ts +43 -0
- package/dist/types/server/canvas-db.d.ts +5 -0
- package/dist/types/server/canvas-operations.d.ts +4 -0
- package/dist/types/server/canvas-state.d.ts +20 -3
- package/dist/types/server/index.d.ts +6 -0
- package/dist/types/server/mutation-history.d.ts +1 -1
- package/docs/cli.md +13 -0
- package/docs/http-api.md +24 -0
- package/docs/mcp.md +20 -2
- package/docs/plans/plan-004-pmx-ax-primitives.md +463 -0
- package/docs/screenshot.png +0 -0
- package/docs/sdk.md +5 -0
- package/package.json +2 -1
- package/skills/pmx-canvas/SKILL.md +14 -0
- package/skills/pmx-canvas/references/codex-app-adapter.md +110 -0
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +125 -0
- package/src/cli/agent.ts +34 -0
- package/src/cli/index.ts +2 -1
- package/src/client/App.tsx +2 -0
- package/src/client/canvas/CanvasNode.tsx +7 -0
- package/src/client/canvas/CommandPalette.tsx +2 -1
- package/src/client/canvas/use-node-drag.ts +29 -7
- package/src/client/canvas/use-node-resize.ts +27 -7
- package/src/client/nodes/ExtAppFrame.tsx +51 -10
- package/src/client/nodes/HtmlNode.tsx +5 -2
- package/src/client/nodes/McpAppNode.tsx +13 -1
- package/src/client/nodes/iframe-document-url.ts +58 -0
- package/src/client/state/intent-bridge.ts +8 -0
- package/src/client/state/sse-bridge.ts +3 -3
- package/src/client/theme/global.css +36 -3
- package/src/client/types.ts +1 -0
- package/src/mcp/canvas-access.ts +38 -0
- package/src/mcp/server.ts +113 -4
- package/src/server/ax-context.ts +38 -0
- package/src/server/ax-state.ts +130 -0
- package/src/server/canvas-db.ts +36 -1
- package/src/server/canvas-operations.ts +96 -4
- package/src/server/canvas-state.ts +123 -4
- package/src/server/index.ts +29 -2
- package/src/server/mutation-history.ts +12 -0
- package/src/server/server.ts +312 -14
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: PMX AX Primitives and Copilot Adapter Plan
|
|
3
|
+
status: draft
|
|
4
|
+
date: 2026-06-02
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# PMX AX Primitives and Copilot Adapter Plan
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
PMX Canvas should own the agent-experience primitives as core PMX concepts, not
|
|
12
|
+
as GitHub Copilot concepts. GitHub Copilot becomes the first native host
|
|
13
|
+
adapter: it renders the existing PMX workbench in a Copilot canvas and maps
|
|
14
|
+
Copilot SDK features onto the neutral PMX AX contract.
|
|
15
|
+
|
|
16
|
+
This plan keeps PMX Canvas agent-agnostic and backward-compatible while adding:
|
|
17
|
+
|
|
18
|
+
- core AX state and serializers
|
|
19
|
+
- HTTP, SDK, MCP, and CLI surfaces for the AX primitives
|
|
20
|
+
- a committed `.github/extensions/pmx-canvas/` Copilot canvas adapter
|
|
21
|
+
- CLI support to scaffold/install the same adapter in other PMX Canvas projects
|
|
22
|
+
|
|
23
|
+
Codex is intentionally out of scope for this pass, but the core contract should
|
|
24
|
+
make a later Codex adapter straightforward.
|
|
25
|
+
|
|
26
|
+
Implementation should proceed in vertical slices: each primitive lands across
|
|
27
|
+
state, persistence, HTTP, SDK, MCP, CLI, docs, and tests before moving to the
|
|
28
|
+
next primitive group. This avoids half-wired surfaces and keeps the existing PMX
|
|
29
|
+
"one operation, all access paths" rule intact.
|
|
30
|
+
|
|
31
|
+
## Interview Decisions
|
|
32
|
+
|
|
33
|
+
- First pass surfaces: core model, HTTP, SDK, MCP, CLI, and GitHub Copilot
|
|
34
|
+
adapter.
|
|
35
|
+
- Out of scope: Codex adapter. Copilot should be a real adapter for the
|
|
36
|
+
existing PMX Canvas experience, not a demo-only scaffold.
|
|
37
|
+
- Compatibility: preserve existing APIs and state formats; add optional AX
|
|
38
|
+
fields/endpoints/tables in a backward-compatible way.
|
|
39
|
+
- Persistence: AX state lives inside the existing `.pmx-canvas/canvas.db`
|
|
40
|
+
persistence model alongside nodes, edges, context pins, annotations, and
|
|
41
|
+
snapshots.
|
|
42
|
+
- Copilot distribution: commit a project extension under
|
|
43
|
+
`.github/extensions/pmx-canvas/` and add CLI support to scaffold/install that
|
|
44
|
+
adapter for other projects later.
|
|
45
|
+
|
|
46
|
+
## Core AX Primitive Contract
|
|
47
|
+
|
|
48
|
+
| PMX AX primitive | Core meaning | Persistence/snapshot semantics | First adapter mapping |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| `canvas-surface` | A live PMX workbench surface with nodes, edges, viewport, annotations, pins, and snapshots. | Existing canvas state and snapshots. | Copilot `createCanvas().open()` returns the running `/workbench` URL. |
|
|
51
|
+
| `pinned-context` | Human-curated node set plus bounded agent-readable summaries and neighborhoods. | Existing context pin state and snapshots. | Copilot hooks return it as `additionalContext`; MCP keeps `canvas://pinned-context`. |
|
|
52
|
+
| `focus` | Current node or node set the human/agent wants attention on. | Canvas-bound state; snapshot with canvas. | Copilot canvas action/HTTP/CLI can focus without requiring app-specific state. |
|
|
53
|
+
| `agent-action` | Normalized operation request against PMX state. | Operation request/result is timeline state; effects persist through target primitive. | Copilot canvas actions/tools proxy to PMX HTTP/SDK/MCP operations. |
|
|
54
|
+
| `steering-message` | User instruction emitted from the PMX surface to the active agent session. | Timeline state; persisted in DB but not restored by snapshots. | Copilot adapter maps it to `session.send()` or `sendAndWait()`. |
|
|
55
|
+
| `approval-gate` | A PMX-owned request for human approval/rejection before a high-impact AX action. | Canvas-bound state while pending/resolved; snapshot with canvas. | Copilot adapter exposes approval UI/actions and may map safe cases to SDK permission hooks. |
|
|
56
|
+
| `work-item` | Visible task/plan/status primitive tied to nodes or agent work. | Canvas-bound state; snapshot with canvas. | Existing status/markdown nodes can render it; adapters can update it through AX APIs. |
|
|
57
|
+
| `evidence-item` | Inspectable artifact such as logs, tool result, screenshot, file, diff, or test output. | Timeline state; persisted in DB with retention, not restored by snapshots. | Copilot session/tool events become evidence nodes/items. |
|
|
58
|
+
| `review-annotation` | Human or agent comment/finding anchored to a node/file/region. | Canvas-bound state; snapshot with canvas. | PMX annotations/nodes remain source of truth; Copilot can render and update them. |
|
|
59
|
+
| `agent-event` | Normalized timeline event for prompts, assistant messages, tool starts/results, failures, approvals, and steering. | Timeline state; persisted in DB with retention, not restored by snapshots. | Copilot `session.on(...)` events are normalized into PMX AX events. |
|
|
60
|
+
| `host-capability` | What the current host can do: canvas, hooks, tools, session messaging, permissions, files, UI prompts. | Session/host state; persisted only when useful for diagnostics. | Copilot `session.capabilities` maps to neutral capability flags. |
|
|
61
|
+
|
|
62
|
+
### State partitions
|
|
63
|
+
|
|
64
|
+
- **Canvas-bound AX state:** `focus`, `work-item`, `approval-gate`,
|
|
65
|
+
`review-annotation`, and existing pins. These participate in canvas
|
|
66
|
+
snapshots and restore.
|
|
67
|
+
- **Timeline AX state:** `agent-event`, `evidence-item`, `agent-action`
|
|
68
|
+
records, and `steering-message`. These persist in the PMX DB for diagnostics
|
|
69
|
+
and continuity but are not restored by canvas snapshots.
|
|
70
|
+
- **Host/session AX state:** `host-capability`. This is reported by adapters
|
|
71
|
+
and exposed for diagnostics, but it should not make core depend on any host.
|
|
72
|
+
|
|
73
|
+
## Architecture
|
|
74
|
+
|
|
75
|
+
### Make the change easy first
|
|
76
|
+
|
|
77
|
+
Add a small core AX module before wiring endpoints:
|
|
78
|
+
|
|
79
|
+
- `src/server/ax-state.ts`
|
|
80
|
+
- AX primitive types
|
|
81
|
+
- normalizers and validation helpers
|
|
82
|
+
- context/export serializers
|
|
83
|
+
- event/action/evidence/approval/work-item helpers
|
|
84
|
+
|
|
85
|
+
This avoids scattering AX-specific object shapes across `canvas-state.ts`,
|
|
86
|
+
`server.ts`, `index.ts`, `mcp/server.ts`, and `cli/agent.ts`.
|
|
87
|
+
|
|
88
|
+
### Vertical slice sequencing
|
|
89
|
+
|
|
90
|
+
Use primitive groups as the unit of implementation:
|
|
91
|
+
|
|
92
|
+
1. AX context and focus: reuse existing pins and prove context export across
|
|
93
|
+
HTTP, SDK, MCP, CLI, and Copilot hook injection.
|
|
94
|
+
2. Steering and agent events: prove adapter-to-session messaging and timeline
|
|
95
|
+
recording without changing canvas rendering.
|
|
96
|
+
3. Work items and approvals: add user-visible collaboration state and approval
|
|
97
|
+
enforcement for AX actions that explicitly opt into approval.
|
|
98
|
+
4. Evidence and review annotations: add richer diagnostics and review surfaces.
|
|
99
|
+
5. Host capabilities and adapter polish: expose what each host can support and
|
|
100
|
+
improve native Copilot ergonomics.
|
|
101
|
+
|
|
102
|
+
Each group should be complete across all applicable access paths before the
|
|
103
|
+
next group starts.
|
|
104
|
+
|
|
105
|
+
### Server-authoritative state
|
|
106
|
+
|
|
107
|
+
`CanvasStateManager` remains the source of truth. AX state should be loaded,
|
|
108
|
+
mutated, snapshotted, restored, and notified through the same server-side path
|
|
109
|
+
as canvas nodes and context pins.
|
|
110
|
+
|
|
111
|
+
### Adapter boundary
|
|
112
|
+
|
|
113
|
+
Core must not import `@github/copilot-sdk`. The Copilot adapter lives under
|
|
114
|
+
`.github/extensions/pmx-canvas/extension.mjs` and talks to PMX Canvas through
|
|
115
|
+
HTTP plus normal Copilot SDK APIs.
|
|
116
|
+
|
|
117
|
+
The adapter should:
|
|
118
|
+
|
|
119
|
+
1. discover a running PMX Canvas server through an explicit contract
|
|
120
|
+
2. open the existing `/workbench` URL in a Copilot canvas
|
|
121
|
+
3. expose Copilot canvas actions that proxy PMX AX and canvas operations
|
|
122
|
+
4. inject PMX pinned/AX context on prompt submission
|
|
123
|
+
5. map session events and steering messages to PMX AX events/evidence
|
|
124
|
+
|
|
125
|
+
The discovery contract should be implemented before adapter features:
|
|
126
|
+
|
|
127
|
+
1. use adapter input or environment (`PMX_CANVAS_URL` / `PMX_CANVAS_PORT`) when
|
|
128
|
+
provided
|
|
129
|
+
2. probe the repo default loopback server (`127.0.0.1:4313`) and any configured
|
|
130
|
+
port
|
|
131
|
+
3. read PMX daemon metadata under `.pmx-canvas/` when available
|
|
132
|
+
4. fail with a visible `session.log()` diagnostic and an actionable canvas error
|
|
133
|
+
instead of opening a blank iframe
|
|
134
|
+
|
|
135
|
+
## Affected Files/Areas
|
|
136
|
+
|
|
137
|
+
### Core state and persistence
|
|
138
|
+
|
|
139
|
+
- `src/server/ax-state.ts` - new core AX primitive model and serializers
|
|
140
|
+
- `src/server/canvas-state.ts` - own AX state, persistence integration,
|
|
141
|
+
notifications, snapshots, restore, clear
|
|
142
|
+
- `src/server/canvas-db.ts` - add migration-safe AX tables or JSON state row
|
|
143
|
+
and snapshot persistence
|
|
144
|
+
- `src/server/canvas-serialization.ts` and/or `src/server/agent-context.ts` -
|
|
145
|
+
reuse existing pinned-context summaries in the AX context export
|
|
146
|
+
|
|
147
|
+
### Core operations and SDK
|
|
148
|
+
|
|
149
|
+
- `src/server/canvas-operations.ts` - add shared operation helpers for AX
|
|
150
|
+
mutations
|
|
151
|
+
- `src/server/index.ts` - add `PmxCanvas` SDK methods for AX state, context,
|
|
152
|
+
actions, approvals, evidence, events, work items, capabilities, and steering
|
|
153
|
+
- `src/mcp/canvas-access.ts` - add local/remote access methods for AX APIs
|
|
154
|
+
|
|
155
|
+
### HTTP and SSE
|
|
156
|
+
|
|
157
|
+
- `src/server/server.ts` - add routes such as:
|
|
158
|
+
- `GET /api/canvas/ax`
|
|
159
|
+
- `PATCH /api/canvas/ax`
|
|
160
|
+
- `GET /api/canvas/ax/context`
|
|
161
|
+
- `POST /api/canvas/ax/action`
|
|
162
|
+
- `POST /api/canvas/ax/event`
|
|
163
|
+
- `POST /api/canvas/ax/evidence`
|
|
164
|
+
- `POST /api/canvas/ax/approval`
|
|
165
|
+
- `POST /api/canvas/ax/steer`
|
|
166
|
+
- emit `ax-state-changed` / `ax-event-created` SSE events where useful
|
|
167
|
+
- keep existing `/api/canvas/context-pins` and `/api/canvas/pinned-context`
|
|
168
|
+
stable; AX context should build on them
|
|
169
|
+
|
|
170
|
+
### MCP
|
|
171
|
+
|
|
172
|
+
- `src/mcp/server.ts`
|
|
173
|
+
- add AX resource(s), likely `canvas://ax` and `canvas://ax-context`
|
|
174
|
+
- add tools such as `canvas_get_ax`, `canvas_update_ax`,
|
|
175
|
+
`canvas_record_ax_event`, `canvas_add_evidence`,
|
|
176
|
+
`canvas_request_approval`, and `canvas_send_steering`
|
|
177
|
+
- update resource notifications for AX changes
|
|
178
|
+
|
|
179
|
+
### CLI
|
|
180
|
+
|
|
181
|
+
- `src/cli/index.ts` - add top-level command group routing, likely `ax`
|
|
182
|
+
and/or `copilot`
|
|
183
|
+
- `src/cli/agent.ts` - add agent-native JSON commands:
|
|
184
|
+
- `pmx-canvas ax status`
|
|
185
|
+
- `pmx-canvas ax context`
|
|
186
|
+
- `pmx-canvas ax event add`
|
|
187
|
+
- `pmx-canvas ax evidence add`
|
|
188
|
+
- `pmx-canvas ax approval request|resolve`
|
|
189
|
+
- `pmx-canvas ax work add|update|list`
|
|
190
|
+
- `pmx-canvas copilot install-extension`
|
|
191
|
+
|
|
192
|
+
### Copilot adapter
|
|
193
|
+
|
|
194
|
+
- `.github/extensions/pmx-canvas/extension.mjs`
|
|
195
|
+
- register a canvas through `joinSession({ canvases: [...] })`
|
|
196
|
+
- use `createCanvas` from `@github/copilot-sdk/extension`
|
|
197
|
+
- bind a loopback-safe workbench URL from the PMX server
|
|
198
|
+
- expose action handlers for PMX operations
|
|
199
|
+
- add `onUserPromptSubmitted` and `onSessionStart` hooks for AX context
|
|
200
|
+
- subscribe to session events and record normalized AX events/evidence
|
|
201
|
+
- use `session.log()`, never `console.log()`
|
|
202
|
+
- a bundled extension template path in the published package, for example
|
|
203
|
+
`src/cli/templates/copilot-extension/pmx-canvas/extension.mjs` or an
|
|
204
|
+
equivalent package-included location
|
|
205
|
+
|
|
206
|
+
### Client/browser
|
|
207
|
+
|
|
208
|
+
- `src/client/types.ts` - add client-side AX types if the workbench needs to
|
|
209
|
+
render AX state directly
|
|
210
|
+
- `src/client/state/sse-bridge.ts` - consume AX SSE events if browser UI
|
|
211
|
+
should react live
|
|
212
|
+
- Existing workbench UI should stay intact; Copilot embeds it rather than
|
|
213
|
+
reimplementing the canvas renderer.
|
|
214
|
+
|
|
215
|
+
### Docs and package contents
|
|
216
|
+
|
|
217
|
+
- `Readme.md`
|
|
218
|
+
- `docs/http-api.md`
|
|
219
|
+
- `docs/sdk.md`
|
|
220
|
+
- `docs/mcp.md`
|
|
221
|
+
- `docs/cli.md`
|
|
222
|
+
- `skills/pmx-canvas/SKILL.md`
|
|
223
|
+
- `package.json` - include the Copilot extension template in published package
|
|
224
|
+
files if the current package configuration would otherwise omit it
|
|
225
|
+
|
|
226
|
+
## Implementation Checklist
|
|
227
|
+
|
|
228
|
+
### Phase 0: Adapter/API spike and scaffolding
|
|
229
|
+
|
|
230
|
+
- [x] Re-check the local `create-canvas` skill and Copilot SDK docs/types before
|
|
231
|
+
writing the extension entrypoint.
|
|
232
|
+
- [x] Use `extensions_manage scaffold` for the project extension baseline, then
|
|
233
|
+
edit it into `.github/extensions/pmx-canvas/extension.mjs`.
|
|
234
|
+
- [x] Define the PMX server discovery contract for the adapter.
|
|
235
|
+
- [x] Add or choose a package-included extension template path for CLI
|
|
236
|
+
installation.
|
|
237
|
+
|
|
238
|
+
### Phase 1: AX context and focus vertical slice
|
|
239
|
+
|
|
240
|
+
- [x] Define `src/server/ax-state.ts` with primitive types, normalizers, and
|
|
241
|
+
context/focus serializers.
|
|
242
|
+
- [x] Add canvas-bound AX focus state to `CanvasStateManager` without changing
|
|
243
|
+
existing node, edge, annotation, pin, or snapshot behavior.
|
|
244
|
+
- [x] Persist focus state in SQLite using additive schema changes only.
|
|
245
|
+
- [x] Snapshot and restore canvas-bound AX focus state.
|
|
246
|
+
- [x] Add HTTP endpoints and SSE events for AX context/focus.
|
|
247
|
+
- [x] Add `PmxCanvas` SDK methods for AX context/focus.
|
|
248
|
+
- [x] Add `CanvasAccess` local/remote methods for AX context/focus.
|
|
249
|
+
- [x] Add MCP resources/tools and resource notifications for AX context/focus.
|
|
250
|
+
- [x] Add CLI `ax context` and `ax focus` commands.
|
|
251
|
+
- [x] Make the Copilot adapter open the live PMX workbench and inject AX context
|
|
252
|
+
from prompt hooks.
|
|
253
|
+
|
|
254
|
+
### Phase 2: Steering and agent-event vertical slice
|
|
255
|
+
|
|
256
|
+
- [ ] Add timeline persistence for steering messages and agent events with a
|
|
257
|
+
retention policy.
|
|
258
|
+
- [ ] Add HTTP/SDK/MCP/CLI operations for recording and reading AX timeline
|
|
259
|
+
events.
|
|
260
|
+
- [ ] Add Copilot adapter steering actions that call `session.send()` only from
|
|
261
|
+
explicit user/action flows.
|
|
262
|
+
- [ ] Subscribe to useful Copilot session events and record normalized
|
|
263
|
+
`agent-event` entries.
|
|
264
|
+
|
|
265
|
+
### Phase 3: Work items and approval gates vertical slice
|
|
266
|
+
|
|
267
|
+
- [ ] Add canvas-bound work-item and approval-gate state.
|
|
268
|
+
- [ ] Persist and snapshot work items and approval gates.
|
|
269
|
+
- [ ] Add HTTP/SDK/MCP/CLI operations for work-item and approval lifecycle.
|
|
270
|
+
- [ ] Enforce approvals for AX actions explicitly marked as requiring approval;
|
|
271
|
+
existing non-AX canvas endpoints remain unchanged.
|
|
272
|
+
- [ ] Add Copilot adapter UI/actions for approval request and resolution.
|
|
273
|
+
|
|
274
|
+
### Phase 4: Evidence, review annotations, and host capabilities
|
|
275
|
+
|
|
276
|
+
- [ ] Add timeline evidence-item persistence and retention.
|
|
277
|
+
- [ ] Add review-annotation state or map the AX shape onto existing annotations
|
|
278
|
+
where possible.
|
|
279
|
+
- [ ] Add host-capability reporting across HTTP/SDK/MCP/CLI.
|
|
280
|
+
- [ ] Record Copilot tool/session evidence where low-risk and useful.
|
|
281
|
+
|
|
282
|
+
### Phase 5: Docs, template install, and verification
|
|
283
|
+
|
|
284
|
+
- [ ] Add `pmx-canvas copilot install-extension` or equivalent scaffold command.
|
|
285
|
+
- [ ] Ensure the extension template is included in published package contents.
|
|
286
|
+
- [ ] Update docs and the pmx-canvas skill to describe AX primitives and the
|
|
287
|
+
Copilot adapter.
|
|
288
|
+
- [ ] Add parity/static tests for state persistence, HTTP, SDK, MCP, CLI,
|
|
289
|
+
adapter scaffold behavior, and no Copilot imports in core.
|
|
290
|
+
- [ ] Run the repo-standard verification ladder after implementation.
|
|
291
|
+
|
|
292
|
+
## Success Criteria
|
|
293
|
+
|
|
294
|
+
- PMX Canvas core can represent and persist AX primitives without any GitHub
|
|
295
|
+
Copilot dependency.
|
|
296
|
+
- Existing PMX Canvas behavior remains backward-compatible: current HTTP, MCP,
|
|
297
|
+
CLI, SDK, browser, snapshots, and pinned-context flows keep working.
|
|
298
|
+
- HTTP, SDK, MCP, and CLI expose the same AX primitives consistently.
|
|
299
|
+
- The GitHub Copilot app can open PMX Canvas natively through a project canvas
|
|
300
|
+
extension and render the existing workbench.
|
|
301
|
+
- The Copilot adapter can:
|
|
302
|
+
- inject PMX AX/pinned context on prompt submission
|
|
303
|
+
- proxy core canvas/AX actions
|
|
304
|
+
- update pins/basic canvas state
|
|
305
|
+
- send steering instructions to the agent session
|
|
306
|
+
- record useful Copilot session/tool events as AX events/evidence
|
|
307
|
+
- Canvas-bound AX state is included in snapshots; timeline AX state persists in
|
|
308
|
+
the PMX DB but is not restored by snapshots.
|
|
309
|
+
- Codex is not implemented, but no core type or persistence decision prevents a
|
|
310
|
+
later Codex adapter.
|
|
311
|
+
|
|
312
|
+
## Risk Assessment
|
|
313
|
+
|
|
314
|
+
| Risk | Impact | Mitigation |
|
|
315
|
+
|---|---|---|
|
|
316
|
+
| AX model becomes Copilot-shaped instead of PMX-shaped. | Future Codex/MCP/HTTP reuse becomes expensive. | Keep all Copilot imports and names out of core; use neutral PMX primitives and adapter mapping only. |
|
|
317
|
+
| Persistence changes break existing `.pmx-canvas/canvas.db` files. | Existing users lose or corrupt canvas state. | Add new tables/rows with `CREATE TABLE IF NOT EXISTS`; keep current tables and existing payload shapes stable. |
|
|
318
|
+
| Duplicating pinned-context logic creates drift. | Different agents receive different context. | Reuse `agent-context.ts` and existing pinned-context summaries for AX context export. |
|
|
319
|
+
| Copilot adapter tries to reimplement the workbench UI. | Large fragile UI duplicate. | Embed the existing `/workbench` URL and use adapter code only for SDK hooks/actions/session events. |
|
|
320
|
+
| Extension process cannot run Bun/PMX server in some environments. | Copilot canvas opens without a backend. | Prefer discovering an existing PMX server; add explicit startup diagnostics and clear error states. Use loopback URLs only. |
|
|
321
|
+
| `session.send()` from hooks causes loops. | Adapter can recursively prompt the agent. | Do not call `session.send()` synchronously from prompt hooks; steering actions should be user/action initiated. |
|
|
322
|
+
| MCP/CLI/SDK parity drifts. | Agents see different capabilities by host. | Follow the existing repo rule: new operation lands in state manager, SDK, HTTP, MCP, and CLI together. |
|
|
323
|
+
| SQLite schema changes assume migrations that do not exist. | Older DBs fail to load. | Use additive tables/columns only unless a real migration path is added; do not bump schema version without a tested migrator. |
|
|
324
|
+
| AX timeline grows without bounds. | DB size and context export become noisy. | Add a retention/query limit policy for timeline primitives; context export should include bounded summaries only. |
|
|
325
|
+
|
|
326
|
+
## Test Strategy
|
|
327
|
+
|
|
328
|
+
### Unit tests
|
|
329
|
+
|
|
330
|
+
- `tests/unit/canvas-state.test.ts`
|
|
331
|
+
- AX state persists and reloads
|
|
332
|
+
- AX state is included in snapshots and restored
|
|
333
|
+
- clearing canvas handles AX state according to the chosen semantics
|
|
334
|
+
- `tests/unit/server-api.test.ts`
|
|
335
|
+
- HTTP AX endpoints return stable JSON
|
|
336
|
+
- AX context reuses pinned node summaries
|
|
337
|
+
- SSE emits AX events when AX state changes
|
|
338
|
+
- `tests/unit/pmx-canvas-sdk.test.ts`
|
|
339
|
+
- `PmxCanvas` exposes AX methods and mutates core state correctly
|
|
340
|
+
- `tests/unit/mcp-server.test.ts`
|
|
341
|
+
- MCP lists AX resources/tools
|
|
342
|
+
- MCP tools can read/update AX state
|
|
343
|
+
- resource notifications include AX changes
|
|
344
|
+
- `tests/unit/cli-node.test.ts` or a new CLI test file
|
|
345
|
+
- `pmx-canvas ax ...` commands return JSON and fail loudly on invalid input
|
|
346
|
+
- `pmx-canvas copilot install-extension --dry-run` previews the target path
|
|
347
|
+
- Static/parity tests
|
|
348
|
+
- no core/server/shared files import `@github/copilot-sdk`
|
|
349
|
+
- every committed AX operation has SDK, HTTP, MCP, and CLI coverage or an
|
|
350
|
+
explicit documented exception
|
|
351
|
+
- the Copilot extension template is included in the package file list
|
|
352
|
+
|
|
353
|
+
### Adapter tests
|
|
354
|
+
|
|
355
|
+
- Add a focused test around the generated Copilot extension file/template:
|
|
356
|
+
- extension file exists at `.github/extensions/pmx-canvas/extension.mjs`
|
|
357
|
+
- it imports only `@github/copilot-sdk/extension` and Node built-ins
|
|
358
|
+
- it contains no `console.log`
|
|
359
|
+
- declared canvas/actions avoid reserved `canvas.*` action names
|
|
360
|
+
- server discovery failures produce visible adapter diagnostics
|
|
361
|
+
|
|
362
|
+
Full runtime Copilot SDK execution may not be practical in normal Bun tests, so
|
|
363
|
+
the minimum automated test should verify the scaffold/template and the PMX HTTP
|
|
364
|
+
contract it relies on.
|
|
365
|
+
|
|
366
|
+
### Integration/e2e
|
|
367
|
+
|
|
368
|
+
- Existing web canvas Playwright test after client changes.
|
|
369
|
+
- HTTP smoke:
|
|
370
|
+
- start PMX server
|
|
371
|
+
- add nodes
|
|
372
|
+
- pin nodes
|
|
373
|
+
- read `/api/canvas/ax/context`
|
|
374
|
+
- invoke an AX event/evidence/approval mutation
|
|
375
|
+
- Snapshot smoke:
|
|
376
|
+
- create canvas-bound AX state
|
|
377
|
+
- save snapshot
|
|
378
|
+
- mutate AX state
|
|
379
|
+
- restore snapshot
|
|
380
|
+
- confirm canvas-bound AX state restored and timeline state remains bounded
|
|
381
|
+
- MCP smoke:
|
|
382
|
+
- start MCP server
|
|
383
|
+
- list AX resources/tools
|
|
384
|
+
- read AX context
|
|
385
|
+
|
|
386
|
+
## Validation and Diagnostics
|
|
387
|
+
|
|
388
|
+
- Build/typecheck must catch shared type drift:
|
|
389
|
+
- `bun run typecheck`
|
|
390
|
+
- `bun run build`
|
|
391
|
+
- Unit tests should cover the changed surfaces:
|
|
392
|
+
- `bun test tests/unit/canvas-state.test.ts tests/unit/server-api.test.ts tests/unit/pmx-canvas-sdk.test.ts tests/unit/mcp-server.test.ts tests/unit/cli-node.test.ts`
|
|
393
|
+
- If client code changes, run the canvas bundle build and browser tests per repo
|
|
394
|
+
guidance.
|
|
395
|
+
- For manual Copilot adapter validation:
|
|
396
|
+
- reload extensions
|
|
397
|
+
- verify `pmx-canvas` appears in canvas capabilities
|
|
398
|
+
- open the Copilot canvas
|
|
399
|
+
- confirm the PMX workbench loads
|
|
400
|
+
- pin a node and confirm the next prompt receives AX context
|
|
401
|
+
- invoke a basic adapter action and confirm PMX state changes
|
|
402
|
+
|
|
403
|
+
Diagnostics expectations:
|
|
404
|
+
|
|
405
|
+
- Extension failures should be visible through `extensions_manage inspect`.
|
|
406
|
+
- Adapter should use `session.log()` for user-visible errors.
|
|
407
|
+
- HTTP/CLI/MCP failures should include actionable errors, not silent no-ops.
|
|
408
|
+
|
|
409
|
+
## Knowledge Map
|
|
410
|
+
|
|
411
|
+
| Step | Knowledge Source | Confidence |
|
|
412
|
+
|---|---|---|
|
|
413
|
+
| Define neutral AX primitives | Prompt/context from interview plus existing PMX pinned-context architecture | High |
|
|
414
|
+
| Persist AX state in core | Codebase: `canvas-state.ts`, `canvas-db.ts`, tests/helpers persistence patterns | High |
|
|
415
|
+
| Expose HTTP/SDK/MCP/CLI surfaces | Codebase: existing 1:1 operation pattern in `server.ts`, `index.ts`, `mcp/server.ts`, `cli/agent.ts` | High |
|
|
416
|
+
| Build Copilot canvas adapter | Reachable SDK docs: `create-canvas` skill, `extensions.md`, `agent-author.md`, `canvas.d.ts`, `session.d.ts`; verify again in Phase 0 | High |
|
|
417
|
+
| Inject context in Copilot | Reachable SDK docs: `onUserPromptSubmitted` and `additionalContext` | High |
|
|
418
|
+
| Programmatic steering in Copilot | Reachable SDK docs: `session.send()` / `sendAndWait()` and gotchas | High |
|
|
419
|
+
| Runtime validation inside actual GitHub Copilot app | Host tooling available through extension management and canvas tools; runtime still requires manual inspection | Medium |
|
|
420
|
+
| Codex adapter | Out of scope; future host-specific docs needed | Not planned |
|
|
421
|
+
|
|
422
|
+
## Open Questions
|
|
423
|
+
|
|
424
|
+
- [ ] Should `canvas_clear` remove timeline AX events/evidence, or only
|
|
425
|
+
canvas-bound AX state? This can proceed with the conservative default:
|
|
426
|
+
clear canvas-bound state and keep timeline history subject to retention.
|
|
427
|
+
- [ ] Should `approval-gate` integrate deeply with Copilot permission hooks in
|
|
428
|
+
this first pass or only expose PMX approvals through adapter UI/actions?
|
|
429
|
+
This can proceed by implementing PMX approvals first and mapping
|
|
430
|
+
permission hooks only where low-risk.
|
|
431
|
+
|
|
432
|
+
## Rejected Alternatives
|
|
433
|
+
|
|
434
|
+
### Put Copilot SDK concepts directly in PMX core
|
|
435
|
+
|
|
436
|
+
Rejected because PMX Canvas must remain usable by any agent. Core should expose
|
|
437
|
+
neutral AX concepts; Copilot translates them to SDK hooks, canvases, tools, and
|
|
438
|
+
session events.
|
|
439
|
+
|
|
440
|
+
### Store AX in `.pmx-canvas/ax.json`
|
|
441
|
+
|
|
442
|
+
Rejected by interview decision. AX should persist with existing PMX Canvas state
|
|
443
|
+
in SQLite and snapshots, so project state remains coherent.
|
|
444
|
+
|
|
445
|
+
### Rebuild the PMX workbench UI inside the Copilot extension
|
|
446
|
+
|
|
447
|
+
Rejected because the existing PMX browser app already implements full canvas
|
|
448
|
+
functionality. The adapter should embed and bridge it rather than fork the UI.
|
|
449
|
+
|
|
450
|
+
## Refinement Notes
|
|
451
|
+
|
|
452
|
+
### Draft pass
|
|
453
|
+
|
|
454
|
+
Initial plan aligns the broad implementation with existing repo rules: state is
|
|
455
|
+
server-authoritative, MCP tools map to SDK/HTTP/state operations, and the
|
|
456
|
+
Copilot adapter is isolated from core.
|
|
457
|
+
|
|
458
|
+
### Fresh-eyes pass 1
|
|
459
|
+
|
|
460
|
+
Refined the plan from a breadth-first implementation into phased vertical
|
|
461
|
+
slices, split canvas-bound AX state from timeline AX state, made server
|
|
462
|
+
discovery and template packaging explicit, added static/parity tests, and
|
|
463
|
+
resolved the snapshot-vs-timeline contradiction before implementation.
|
package/docs/screenshot.png
CHANGED
|
Binary file
|
package/docs/sdk.md
CHANGED
|
@@ -83,6 +83,11 @@ await canvas.runBatch([
|
|
|
83
83
|
canvas.arrange('grid');
|
|
84
84
|
console.log(canvas.validate());
|
|
85
85
|
console.log(canvas.getLayout());
|
|
86
|
+
|
|
87
|
+
// AX context for host adapters
|
|
88
|
+
canvas.setAxFocus({ nodeIds: [n1], source: 'sdk' });
|
|
89
|
+
console.log(canvas.getAxState());
|
|
90
|
+
console.log(canvas.getAxContext());
|
|
86
91
|
```
|
|
87
92
|
|
|
88
93
|
## WebView automation
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmx-canvas",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
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",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"src/",
|
|
20
20
|
"skills/",
|
|
21
21
|
"docs/",
|
|
22
|
+
".github/extensions/pmx-canvas/",
|
|
22
23
|
"dist/canvas/",
|
|
23
24
|
"dist/json-render/",
|
|
24
25
|
"dist/types/",
|
|
@@ -65,6 +65,16 @@ If this skill is installed before the `pmx-canvas` command exists, install the p
|
|
|
65
65
|
`references/installing-pmx-canvas.md` for local development, npm/global install, and MCP config
|
|
66
66
|
options.
|
|
67
67
|
|
|
68
|
+
## Adapter References
|
|
69
|
+
|
|
70
|
+
PMX Canvas core is host-agnostic. When a host-specific adapter is available, read the matching
|
|
71
|
+
reference before using adapter-native features:
|
|
72
|
+
|
|
73
|
+
- `references/github-copilot-app-adapter.md` — GitHub Copilot app project extension, native canvas
|
|
74
|
+
panel, AX context injection, and live-test checklist.
|
|
75
|
+
- `references/codex-app-adapter.md` — Codex app native Browser + MCP adapter, AX context reading,
|
|
76
|
+
focus labeling, and live-test checklist.
|
|
77
|
+
|
|
68
78
|
The canvas auto-starts on first MCP tool call when running in MCP mode (`pmx-canvas --mcp`).
|
|
69
79
|
For manual start:
|
|
70
80
|
|
|
@@ -156,6 +166,8 @@ pmx-canvas web-artifact build --title "Dashboard" --app-file ./App.tsx --deps re
|
|
|
156
166
|
pmx-canvas node list --type web-artifact --summary
|
|
157
167
|
pmx-canvas node list --type external-app --summary
|
|
158
168
|
pmx-canvas pin --list
|
|
169
|
+
pmx-canvas ax context
|
|
170
|
+
pmx-canvas ax focus <node-id>
|
|
159
171
|
pmx-canvas snapshot save --name "before-refactor"
|
|
160
172
|
pmx-canvas code-graph
|
|
161
173
|
pmx-canvas spatial
|
|
@@ -175,6 +187,8 @@ pmx-canvas spatial
|
|
|
175
187
|
`"DVT O3"` can be ambiguous; prefer the full visible title such as `"DVT O3 — GitOps"`.
|
|
176
188
|
- `search`, `layout`, `status`, `arrange`, `focus` — inspect and navigate the canvas. Prefer
|
|
177
189
|
`focus --no-pan` when you only need to select/raise a node without hijacking the human's camera.
|
|
190
|
+
- `ax status|context|focus` — inspect the host-agnostic AX layer; `ax context`
|
|
191
|
+
combines pinned context and AX focus for adapter prompt injection.
|
|
178
192
|
- `fit [id ...]` — set the server viewport to fit the whole canvas or selected nodes before screenshots or whole-board review
|
|
179
193
|
- `screenshot --output <path>` — top-level shortcut for `webview screenshot`; supports `--format png|jpeg|webp` and `--quality`
|
|
180
194
|
- `json-render --schema|--examples` — inspect the json-render component catalog with `--component`/`--field` filters; same data as `node schema --type json-render` in a more direct shape
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Codex App Adapter
|
|
2
|
+
|
|
3
|
+
Use this reference when PMX Canvas is running natively in the Codex app. The adapter is intentionally
|
|
4
|
+
thin: PMX Canvas remains the state owner, Codex uses MCP for agent operations/context, and the Codex
|
|
5
|
+
in-app Browser renders the live PMX workbench.
|
|
6
|
+
|
|
7
|
+
## Adapter Identity
|
|
8
|
+
|
|
9
|
+
- Host: Codex app
|
|
10
|
+
- Visual surface: Codex in-app Browser opened to the PMX `/workbench` URL
|
|
11
|
+
- Agent surface: PMX Canvas MCP server (`pmx-canvas --mcp`)
|
|
12
|
+
- Fallback surface: PMX Canvas CLI for manual scripts when MCP is unavailable
|
|
13
|
+
- AX source label: `codex`
|
|
14
|
+
|
|
15
|
+
This is not a separate PMX renderer and does not require a Codex extension API. Codex already has
|
|
16
|
+
the two native surfaces PMX needs: MCP resources/tools for the agent, and the in-app Browser for the
|
|
17
|
+
human-visible canvas. Prefer MCP over the CLI for Codex-native use because MCP exposes structured
|
|
18
|
+
tools, resources, and `canvas://ax-context`; use the CLI only as a fallback or for shell scripts.
|
|
19
|
+
|
|
20
|
+
## What The Adapter Does
|
|
21
|
+
|
|
22
|
+
- Opens the live PMX workbench in the Codex in-app Browser.
|
|
23
|
+
- Uses MCP tools/resources for all agent-side operations.
|
|
24
|
+
- Reads `canvas://ax-context` or `canvas_get_ax` for pinned and focused context.
|
|
25
|
+
- Sets AX focus through `canvas_set_ax_focus` with `source: "codex"` when the focus change comes
|
|
26
|
+
from Codex-hosted steering.
|
|
27
|
+
- Keeps all persistent PMX state in `.pmx-canvas/canvas.db`; Codex does not own canvas state.
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
Use MCP as the primary Codex adapter path.
|
|
32
|
+
|
|
33
|
+
Add the PMX MCP server to the Codex workspace config:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"canvas": {
|
|
39
|
+
"command": "bunx",
|
|
40
|
+
"args": ["pmx-canvas", "--mcp"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For local repo development, use the source entrypoint instead:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"canvas": {
|
|
52
|
+
"command": "bun",
|
|
53
|
+
"args": ["run", "src/mcp/server.ts"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The MCP server auto-starts the HTTP workbench on first tool call. Open the returned workbench URL
|
|
60
|
+
in the Codex in-app Browser, usually `http://127.0.0.1:4313/workbench` or
|
|
61
|
+
`http://localhost:4313/workbench`.
|
|
62
|
+
|
|
63
|
+
## Codex-Native Workflow
|
|
64
|
+
|
|
65
|
+
1. Open `/workbench` in the Codex in-app Browser as the first visible action. If PMX is not running
|
|
66
|
+
yet, start/connect the MCP server first only long enough to get the workbench URL, then open the
|
|
67
|
+
browser before mutating the board.
|
|
68
|
+
2. Start or keep using the PMX MCP server for agent operations.
|
|
69
|
+
3. Use the browser canvas for human spatial curation: pin nodes, move nodes, group nodes, and
|
|
70
|
+
inspect rendered artifacts.
|
|
71
|
+
4. Use MCP tools for agent operations: create/update nodes, pin nodes, read layout, and read AX
|
|
72
|
+
context.
|
|
73
|
+
5. When Codex wants to mark the current attention target, call:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"nodeIds": ["node-123"],
|
|
78
|
+
"source": "codex"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
against `canvas_set_ax_focus`.
|
|
83
|
+
|
|
84
|
+
## Context Contract
|
|
85
|
+
|
|
86
|
+
Codex agents should treat PMX AX context as host-native working context:
|
|
87
|
+
|
|
88
|
+
- `canvas://pinned-context` is the explicit human-curated node set.
|
|
89
|
+
- `canvas://ax-context` combines pins, focus, and surface metadata.
|
|
90
|
+
- `canvas_get_ax` returns both persisted AX state and agent-ready context.
|
|
91
|
+
- Focus is a current attention target, not a command to ignore the rest of the repository.
|
|
92
|
+
|
|
93
|
+
## Live-Test Checklist
|
|
94
|
+
|
|
95
|
+
1. Open `http://127.0.0.1:4313/workbench` in the Codex in-app Browser first so the user can see
|
|
96
|
+
all later canvas mutations.
|
|
97
|
+
2. Confirm the PMX MCP server is configured for the workspace.
|
|
98
|
+
3. Call `canvas_get_ax` and confirm it returns `ok: true`.
|
|
99
|
+
4. Add or reuse a node, then pin it from the browser or with `canvas_pin_nodes`.
|
|
100
|
+
5. Read `canvas://ax-context` and confirm the pinned node appears.
|
|
101
|
+
6. Call `canvas_set_ax_focus` with `source: "codex"` and a real node ID.
|
|
102
|
+
7. Read `canvas_get_ax` again and confirm `state.focus.source` is `codex`.
|
|
103
|
+
8. Refresh the browser and confirm the workbench still shows the same state.
|
|
104
|
+
|
|
105
|
+
## Adapter Boundary
|
|
106
|
+
|
|
107
|
+
Do not add Codex-specific APIs to PMX Canvas core. Core owns neutral AX primitives; Codex maps them
|
|
108
|
+
through MCP and the in-app Browser. If Codex later exposes a dedicated extension or prompt-injection
|
|
109
|
+
hook, implement that as a separate adapter layer that reads the same `/api/canvas/ax/context` or
|
|
110
|
+
`canvas://ax-context` contract.
|