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.
Files changed (41) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/Readme.md +10 -7
  3. package/dist/canvas/global.css +101 -7
  4. package/dist/canvas/index.js +171 -128
  5. package/dist/canvas/mermaid-entry.js +1303 -1303
  6. package/dist/json-render/index.js +101 -102
  7. package/dist/types/client/canvas/use-pan-zoom.d.ts +2 -1
  8. package/docs/adr-001-bun-only-runtime.md +1 -1
  9. package/docs/bun-webview-integration.md +2 -2
  10. package/docs/node-types.md +1 -1
  11. package/docs/product-context-vision-2026-09.md +207 -0
  12. package/docs/product-review-2026-09.md +174 -0
  13. package/docs/product-vision-2026-09.md +200 -0
  14. package/docs/screenshot.png +0 -0
  15. package/package.json +2 -2
  16. package/skills/pmx-canvas/SKILL.md +62 -36
  17. package/skills/pmx-canvas/evals/evals.json +1 -1
  18. package/skills/pmx-canvas/references/excalidraw-diagram-authoring.md +5 -0
  19. package/skills/pmx-canvas/references/full-reference.md +5 -4
  20. package/skills/pmx-canvas/references/installing-pmx-canvas.md +126 -18
  21. package/skills/pmx-canvas-testing/SKILL.md +13 -4
  22. package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +18 -8
  23. package/src/client/canvas/CanvasNode.tsx +9 -12
  24. package/src/client/canvas/CanvasViewport.tsx +20 -33
  25. package/src/client/canvas/ContextMenu.tsx +13 -0
  26. package/src/client/canvas/EdgeLayer.tsx +2 -2
  27. package/src/client/canvas/SessionPanel.tsx +23 -4
  28. package/src/client/canvas/ShortcutOverlay.tsx +2 -2
  29. package/src/client/canvas/TopBar.tsx +85 -45
  30. package/src/client/canvas/use-pan-zoom.ts +23 -3
  31. package/src/client/nodes/ExtAppFrame.tsx +97 -28
  32. package/src/client/state/canvas-store.ts +17 -5
  33. package/src/client/state/sse-bridge.ts +3 -1
  34. package/src/client/theme/global.css +101 -7
  35. package/src/server/canvas-operations.ts +2 -2
  36. package/src/server/operations/mcp.ts +45 -31
  37. package/src/server/operations/ops/ax-presence.ts +3 -0
  38. package/src/server/operations/ops/viewport.ts +6 -1
  39. package/src/server/scope-fence.ts +1 -1
  40. package/src/server/server.ts +9 -9
  41. 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: right-click one to relabel, retype, restyle, or
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.3.14
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.5.1
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. One
365
- caveat: WebView automation (`pmx-canvas screenshot`) needs Bun >= 1.3.12 in
366
- the orb image; the canvas itself runs fine without it and says so in the
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
@@ -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: transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
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: 28px;
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 4px;
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;