pmx-canvas 0.5.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/Readme.md +10 -7
- package/dist/canvas/global.css +101 -7
- package/dist/canvas/index.js +171 -128
- package/dist/canvas/mermaid-entry.js +1303 -1303
- package/dist/json-render/index.js +101 -102
- package/dist/types/client/canvas/use-pan-zoom.d.ts +2 -1
- package/docs/adr-001-bun-only-runtime.md +1 -1
- package/docs/bun-webview-integration.md +2 -2
- package/docs/node-types.md +1 -1
- package/docs/product-context-vision-2026-09.md +207 -0
- package/docs/product-review-2026-09.md +174 -0
- package/docs/product-vision-2026-09.md +200 -0
- package/docs/screenshot.png +0 -0
- package/package.json +2 -2
- package/skills/pmx-canvas/SKILL.md +62 -36
- package/skills/pmx-canvas/evals/evals.json +1 -1
- package/skills/pmx-canvas/references/excalidraw-diagram-authoring.md +5 -0
- package/skills/pmx-canvas/references/full-reference.md +5 -4
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +126 -18
- package/skills/pmx-canvas-testing/SKILL.md +13 -4
- package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +18 -8
- package/src/client/canvas/CanvasNode.tsx +9 -12
- package/src/client/canvas/CanvasViewport.tsx +20 -33
- package/src/client/canvas/ContextMenu.tsx +13 -0
- package/src/client/canvas/EdgeLayer.tsx +2 -2
- package/src/client/canvas/SessionPanel.tsx +23 -4
- package/src/client/canvas/ShortcutOverlay.tsx +2 -2
- package/src/client/canvas/TopBar.tsx +85 -45
- package/src/client/canvas/use-pan-zoom.ts +23 -3
- package/src/client/nodes/ExtAppFrame.tsx +97 -28
- package/src/client/state/canvas-store.ts +17 -5
- package/src/client/state/sse-bridge.ts +3 -1
- package/src/client/theme/global.css +101 -7
- package/src/server/canvas-operations.ts +2 -2
- package/src/server/operations/mcp.ts +45 -31
- package/src/server/operations/ops/ax-presence.ts +3 -0
- package/src/server/operations/ops/viewport.ts +6 -1
- package/src/server/scope-fence.ts +1 -1
- package/src/server/server.ts +9 -9
- package/src/server/web-artifacts/scripts/bundle-artifact.sh +29 -8
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,56 @@
|
|
|
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.6.2] - 2026-09-09
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- Double-left-click opens the board, node, or edge menu; right-button dragging pans with a grabbing-hand cursor, while single-left-click still selects.
|
|
11
|
+
- Rename nodes through their action menu instead of double-clicking the title.
|
|
12
|
+
- The Session panel starts compact, opens for pending approvals, and closes after they settle unless the user opened it manually.
|
|
13
|
+
- Skill guidance distinguishes product-source testing from consumer testing and requested app dimensions from persisted post-mount sizes.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Focusing a node stays clear of the minimap and command bar instead of being interrupted by server layout or window-size updates.
|
|
18
|
+
- Relative file paths resolve against the configured workspace rather than the daemon's process directory.
|
|
19
|
+
- Published artifact builds automatically clear a corrupted Parcel cache and retry once; genuine build errors still fail.
|
|
20
|
+
- Expanded embedded apps accept their first click reliably during loading in Chromium.
|
|
21
|
+
- The extreme resize corner is hittable, and all timeline filter chips fit on one row.
|
|
22
|
+
- WebView startup errors now retain the Chrome constructor failure in `lastError`.
|
|
23
|
+
|
|
24
|
+
### Known limitations
|
|
25
|
+
|
|
26
|
+
- Native Copilot/WebKit Excalidraw tiles can still appear blank despite a successful paint probe; expand-close remains a workaround, not a confirmed first-render fix.
|
|
27
|
+
|
|
28
|
+
## [0.6.1] - 2026-09-07
|
|
29
|
+
|
|
30
|
+
The Bun 1.4.2 upgrade and fixes from the 0.5.1 field reports (Amp orb, Copilot app).
|
|
31
|
+
Version 0.6.0 was tagged but not published; this release includes its full changes.
|
|
32
|
+
|
|
33
|
+
### Breaking
|
|
34
|
+
|
|
35
|
+
- Bun 1.4.2 or newer is now required. Upgrade Bun before installing this release.
|
|
36
|
+
|
|
37
|
+
### Internal
|
|
38
|
+
|
|
39
|
+
- Fresh orbs prepare and cache the pinned toolchain, dependencies, and Chromium during setup.
|
|
40
|
+
- CI uses Bun 1.4.2, and browser tests handle delayed transport startup and early iframe input reliably.
|
|
41
|
+
- WebView integration tests allow server navigation timeouts and cleanup to complete on slower hosts.
|
|
42
|
+
- Installation and skill guidance now explain workspace targeting, managed services, and safe disposable smoke tests.
|
|
43
|
+
- Added the September product review and vision documents, including the direction for personal and shared context.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- MCP calls now reject removed or dead fields (such as `dockPosition`) with the same error HTTP returns, instead of silently dropping them.
|
|
48
|
+
- `canvas_ax_state { action: "set-presence" }` accepts `contextUsage` over MCP, so agents can report their real token window from any transport.
|
|
49
|
+
- Focusing a node (including the automatic focus when an MCP app opens) keeps the whole node clear of the command bar and minimap, zooming out when it would not fit.
|
|
50
|
+
- Panning from a node can no longer start a stray text drag that minted webpage nodes from card text; pan now works across the entire node surface.
|
|
51
|
+
- Embedded app tiles verify painted pixels, not just a laid-out canvas — a blank Excalidraw surface now fails honestly, keeps its overlay, and offers Retry instead of logging a false `content-verified`.
|
|
52
|
+
- The web-artifact bundler recovers from a corrupted Parcel cache in a reused build project (clear and retry cold) instead of failing every later build.
|
|
53
|
+
- Idle agents no longer park their cursor pills over the board — a cursor fades out when its agent goes idle and returns the moment it works again.
|
|
54
|
+
- On a many-agent board the top bar shows the most active agents plus one census chip with the total (e.g. `+13 · 16 agents`), instead of one chip per agent flooding the bar and pushing the zoom controls over the session panel.
|
|
55
|
+
|
|
6
56
|
## [0.5.1] - 2026-08-28
|
|
7
57
|
|
|
8
58
|
Fixes from the 0.5.0 field reports (Amp orb, Copilot app, Codex app).
|
package/Readme.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pmx-canvas
|
|
2
2
|
|
|
3
|
+
pmx-canvas is a visual workspace for planning, discovery, analysis, coordination,
|
|
4
|
+
and orchestrating work with agents—from exploring an idea to directing its
|
|
5
|
+
execution and carrying the learning forward.
|
|
6
|
+
|
|
3
7
|
**A moldable canvas for agent-assisted thinking.** An infinite 2D surface
|
|
4
8
|
where files, plans, status, charts, fetched web pages, annotations, code
|
|
5
9
|
diffs, and diagrams live side by side. Every node carries its own renderer; agents
|
|
@@ -32,7 +36,7 @@ communication — proximity means relatedness, pinning means *focus here*.
|
|
|
32
36
|
Drag, group, arrange, and **pin** nodes spatially. Connect nodes with typed
|
|
33
37
|
edges — flow, depends-on, relation, references — drawn as smooth curves that
|
|
34
38
|
leave each card perpendicular to its border and bend toward their target.
|
|
35
|
-
Edges stay editable in place:
|
|
39
|
+
Edges stay editable in place: double-click one to relabel, retype, restyle, or
|
|
36
40
|
delete it, or click it and press Delete. Curation is the channel
|
|
37
41
|
from human intent to agent context — the agent reads `canvas://pinned-context`
|
|
38
42
|
and `canvas://spatial-context` (proximity clusters, reading order, pinned
|
|
@@ -234,7 +238,7 @@ hooks, canvas, and session APIs onto PMX's AX primitives — no core changes.
|
|
|
234
238
|
|
|
235
239
|
## Prerequisites
|
|
236
240
|
|
|
237
|
-
- [Bun](https://bun.sh) >= 1.
|
|
241
|
+
- [Bun](https://bun.sh) >= 1.4.2
|
|
238
242
|
|
|
239
243
|
The published SDK entrypoint is Bun-first. Node.js consumers should use the
|
|
240
244
|
CLI, MCP server, or HTTP API.
|
|
@@ -355,16 +359,15 @@ services:
|
|
|
355
359
|
```bash
|
|
356
360
|
# .agents/setup — install the CLI (pin the exact version: a fresh orb running
|
|
357
361
|
# @latest can silently pick up a newer release than the one you validated)
|
|
358
|
-
npm install -g pmx-canvas@0.
|
|
362
|
+
npm install -g pmx-canvas@0.6.2
|
|
359
363
|
```
|
|
360
364
|
|
|
361
365
|
The server binds the portal-assigned `$PORT` automatically (gated on the
|
|
362
366
|
`AMP_ORB` env the orb always sets, so a stray `PORT` elsewhere never changes
|
|
363
367
|
the default), restores `.pmx-canvas/canvas.db`, and the portal manifest picks
|
|
364
|
-
it up — no port flags or `$PORT` interpolation in the service command.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
error. The canvas detects the orb and the portal's nested-iframe
|
|
368
|
+
it up — no port flags or `$PORT` interpolation in the service command. The
|
|
369
|
+
orb image needs Bun >= 1.4.2; WebView automation (`pmx-canvas screenshot`)
|
|
370
|
+
also needs a working Chrome installation. The canvas detects the orb and the portal's nested-iframe
|
|
368
371
|
embed on its own: live updates arrive over the proxy-safe polling transport,
|
|
369
372
|
and iframe-backed nodes (HTML, mermaid, graph, json-render, web artifacts)
|
|
370
373
|
render inline via `srcdoc` with their theme styling included. Two things can't
|
package/dist/canvas/global.css
CHANGED
|
@@ -986,10 +986,21 @@ body,
|
|
|
986
986
|
/* NOT overflow:hidden — the BarHint tooltips hang below the bar and were
|
|
987
987
|
clipped invisible for everyone (the e2e asserted opacity, which cannot
|
|
988
988
|
see ancestor clipping). Children ellipsize themselves; the narrow-screen
|
|
989
|
-
collapse is media-query display, not clipping.
|
|
989
|
+
collapse is media-query display, not clipping. overflow-x: clip is the
|
|
990
|
+
one safe axis (visible/clip is the valid mixed pair): tooltips still
|
|
991
|
+
hang below, but bar content can never paint over the session panel
|
|
992
|
+
again (0.5.1 user feedback — the agent-chip flood pushed the zoom
|
|
993
|
+
cluster out of the bar). */
|
|
994
|
+
overflow-x: clip;
|
|
990
995
|
min-width: 0;
|
|
991
996
|
z-index: 9998;
|
|
992
997
|
}
|
|
998
|
+
/* CHIP BarHint anchors must pass shrink through to their chip (flex min-auto
|
|
999
|
+
sizing) or an unshrinkable anchor re-creates the overflow. Chip anchors
|
|
1000
|
+
ONLY — a blanket min-width: 0 crushed the zoom buttons to slivers. */
|
|
1001
|
+
.top-bar .toolbar-tooltip-anchor:has(.agent-chip) {
|
|
1002
|
+
min-width: 0;
|
|
1003
|
+
}
|
|
993
1004
|
|
|
994
1005
|
.top-bar-title {
|
|
995
1006
|
font-size: 13px;
|
|
@@ -1104,14 +1115,46 @@ body,
|
|
|
1104
1115
|
font-size: 11px;
|
|
1105
1116
|
font-weight: 600;
|
|
1106
1117
|
white-space: nowrap;
|
|
1118
|
+
/* Rigid: the chip never shrinks and never lies about its min size (a
|
|
1119
|
+
min-width: 0 here let BarHint anchors collapse under their chips, and
|
|
1120
|
+
neighboring chips painted over each other). The .agent-chips wrapper is
|
|
1121
|
+
the ONE squeeze point — it clips whole trailing chips at its edge. */
|
|
1107
1122
|
flex-shrink: 0;
|
|
1108
|
-
min-width: 0;
|
|
1109
1123
|
max-width: 280px;
|
|
1110
1124
|
}
|
|
1125
|
+
/* Many-agent bar (0.5.1 user feedback): the visible chips sit in ONE
|
|
1126
|
+
clipping flex wrapper. Chips keep their natural readable width; when the
|
|
1127
|
+
bar is overconstrained the WRAPPER shrinks and clips at its edge, so chip
|
|
1128
|
+
content can never shove or paint over the census chip, the context meter,
|
|
1129
|
+
or the zoom cluster (16 unshrinkable chips used to push the zoom controls
|
|
1130
|
+
out of the bar and over the session panel). */
|
|
1131
|
+
.agent-chips {
|
|
1132
|
+
display: inline-flex;
|
|
1133
|
+
align-items: center;
|
|
1134
|
+
gap: 12px;
|
|
1135
|
+
min-width: 0;
|
|
1136
|
+
overflow: hidden;
|
|
1137
|
+
}
|
|
1138
|
+
/* Rigid anchors: nested-flex min-content lets a BarHint anchor collapse
|
|
1139
|
+
under its chip (ellipsizing spans zero the chip's min-content), and the
|
|
1140
|
+
chip then paints into the next anchor. Only the wrapper above may give. */
|
|
1141
|
+
.agent-chips .toolbar-tooltip-anchor {
|
|
1142
|
+
flex-shrink: 0;
|
|
1143
|
+
}
|
|
1111
1144
|
.agent-chip.phase-idle {
|
|
1112
1145
|
background: none;
|
|
1113
1146
|
border-color: var(--c-line);
|
|
1114
1147
|
}
|
|
1148
|
+
/* The census chip is the "how many" answer — it never compresses away. Its
|
|
1149
|
+
BarHint anchor must hold width too: a shrinking anchor around an
|
|
1150
|
+
unshrinkable chip lets the chip paint over the next bar item. */
|
|
1151
|
+
.agent-chip-more {
|
|
1152
|
+
flex-shrink: 0;
|
|
1153
|
+
}
|
|
1154
|
+
.top-bar .toolbar-tooltip-anchor:has(.agent-chip-more) {
|
|
1155
|
+
flex-shrink: 0;
|
|
1156
|
+
min-width: max-content;
|
|
1157
|
+
}
|
|
1115
1158
|
.agent-chip-dot {
|
|
1116
1159
|
width: 7px;
|
|
1117
1160
|
height: 7px;
|
|
@@ -1134,6 +1177,11 @@ body,
|
|
|
1134
1177
|
font-weight: 400;
|
|
1135
1178
|
color: var(--c-muted);
|
|
1136
1179
|
white-space: nowrap;
|
|
1180
|
+
/* Leaf-level truncation: a compressed chip must ellipsize the agent name,
|
|
1181
|
+
never paint it past the pill (0.5.1 user feedback, many-agent bar). */
|
|
1182
|
+
overflow: hidden;
|
|
1183
|
+
text-overflow: ellipsis;
|
|
1184
|
+
min-width: 0;
|
|
1137
1185
|
}
|
|
1138
1186
|
|
|
1139
1187
|
/* On-canvas cursor + phase chip (world layer; counter-scaled inner) */
|
|
@@ -1146,7 +1194,9 @@ body,
|
|
|
1146
1194
|
top: 0;
|
|
1147
1195
|
z-index: 9000;
|
|
1148
1196
|
pointer-events: none;
|
|
1149
|
-
transition:
|
|
1197
|
+
transition:
|
|
1198
|
+
transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
1199
|
+
opacity 320ms ease;
|
|
1150
1200
|
color: var(--presence-color);
|
|
1151
1201
|
}
|
|
1152
1202
|
.agent-cursor.is-worker {
|
|
@@ -1160,6 +1210,20 @@ body,
|
|
|
1160
1210
|
font-size: 9px;
|
|
1161
1211
|
padding: 1px 6px;
|
|
1162
1212
|
}
|
|
1213
|
+
/* Idle cursors leave the board (user feedback, 0.5.1 cycle): with many agents
|
|
1214
|
+
attached, a wall of parked "Idle" pills covers real node content. The
|
|
1215
|
+
element stays MOUNTED — counts, twin-merge, and cursor-follow logic are
|
|
1216
|
+
untouched, and visibility (not display) keeps its layout box so position
|
|
1217
|
+
polls still resolve — but it paints nothing; any non-idle phase fades it
|
|
1218
|
+
back in. Placed after .is-worker so opacity: 0 wins that collision. */
|
|
1219
|
+
.agent-cursor.phase-idle {
|
|
1220
|
+
opacity: 0;
|
|
1221
|
+
visibility: hidden;
|
|
1222
|
+
transition:
|
|
1223
|
+
transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
1224
|
+
opacity 320ms ease,
|
|
1225
|
+
visibility 0s linear 320ms;
|
|
1226
|
+
}
|
|
1163
1227
|
.agent-chip-workers {
|
|
1164
1228
|
margin-left: 4px;
|
|
1165
1229
|
padding: 0 5px;
|
|
@@ -1313,7 +1377,7 @@ body,
|
|
|
1313
1377
|
animation: session-panel-in 180ms ease;
|
|
1314
1378
|
}
|
|
1315
1379
|
.session-panel.is-collapsed {
|
|
1316
|
-
width:
|
|
1380
|
+
width: 40px;
|
|
1317
1381
|
align-items: center;
|
|
1318
1382
|
padding-top: 10px;
|
|
1319
1383
|
gap: 10px;
|
|
@@ -1326,6 +1390,17 @@ body,
|
|
|
1326
1390
|
text-transform: uppercase;
|
|
1327
1391
|
color: var(--c-dim);
|
|
1328
1392
|
}
|
|
1393
|
+
.session-collapsed-live {
|
|
1394
|
+
display: inline-flex;
|
|
1395
|
+
flex-direction: column;
|
|
1396
|
+
align-items: center;
|
|
1397
|
+
gap: 4px;
|
|
1398
|
+
font: 9px var(--mono);
|
|
1399
|
+
color: var(--c-dim);
|
|
1400
|
+
}
|
|
1401
|
+
.session-collapsed-live .session-live-dot {
|
|
1402
|
+
background: var(--c-ok);
|
|
1403
|
+
}
|
|
1329
1404
|
|
|
1330
1405
|
.session-panel-header {
|
|
1331
1406
|
height: var(--hud-bar-height);
|
|
@@ -1653,7 +1728,7 @@ body,
|
|
|
1653
1728
|
}
|
|
1654
1729
|
.session-timeline-filters .activity-filter {
|
|
1655
1730
|
flex-shrink: 0;
|
|
1656
|
-
padding: 2px
|
|
1731
|
+
padding: 2px 3px;
|
|
1657
1732
|
}
|
|
1658
1733
|
|
|
1659
1734
|
.session-timeline-row {
|
|
@@ -2830,9 +2905,20 @@ body,
|
|
|
2830
2905
|
}
|
|
2831
2906
|
|
|
2832
2907
|
/* Pan tool / held Space: the world layer goes pointer-inert so drags land on
|
|
2833
|
-
the viewport container itself and pan — nodes cannot swallow the drag.
|
|
2908
|
+
the viewport container itself and pan — nodes cannot swallow the drag.
|
|
2909
|
+
user-select too: text selection sweeps straight through pointer-inert
|
|
2910
|
+
content, and a selection made mid-pan later becomes a native text drag the
|
|
2911
|
+
drop handler mints webpage nodes from (0.5.1 Amp finding D). */
|
|
2834
2912
|
.canvas-viewport.pan-mode .canvas-world {
|
|
2835
2913
|
pointer-events: none;
|
|
2914
|
+
-webkit-user-select: none;
|
|
2915
|
+
user-select: none;
|
|
2916
|
+
}
|
|
2917
|
+
/* The resize handle and connect ports carry their own pointer-events: auto,
|
|
2918
|
+
which punches through the inert world — a pan started on them never pans. */
|
|
2919
|
+
.canvas-viewport.pan-mode .node-resize-handle,
|
|
2920
|
+
.canvas-viewport.pan-mode .node-port {
|
|
2921
|
+
pointer-events: none;
|
|
2836
2922
|
}
|
|
2837
2923
|
.canvas-viewport.pan-mode:active {
|
|
2838
2924
|
cursor: grabbing;
|
|
@@ -3670,6 +3756,12 @@ body,
|
|
|
3670
3756
|
}
|
|
3671
3757
|
|
|
3672
3758
|
/* Node resize handle */
|
|
3759
|
+
.canvas-node:has(.node-resize-handle) {
|
|
3760
|
+
/* Keep the four-pixel corner grab inside the shell's inner clip, not on
|
|
3761
|
+
its rounded border. The other corners retain the standard card radius. */
|
|
3762
|
+
border-bottom-right-radius: 8px;
|
|
3763
|
+
}
|
|
3764
|
+
|
|
3673
3765
|
.canvas-node .node-resize-handle {
|
|
3674
3766
|
position: absolute;
|
|
3675
3767
|
bottom: 0;
|
|
@@ -3714,7 +3806,9 @@ html.is-node-dragging .attention-field-layer {
|
|
|
3714
3806
|
}
|
|
3715
3807
|
|
|
3716
3808
|
html.is-node-dragging,
|
|
3717
|
-
html.is-node-dragging
|
|
3809
|
+
html.is-node-dragging *,
|
|
3810
|
+
html.is-canvas-panning,
|
|
3811
|
+
html.is-canvas-panning * {
|
|
3718
3812
|
cursor: grabbing !important;
|
|
3719
3813
|
user-select: none !important;
|
|
3720
3814
|
-webkit-user-select: none !important;
|