pmx-canvas 0.7.3 → 0.8.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 (244) hide show
  1. package/.github/extensions/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
  2. package/.github/extensions/pmx-canvas/extension.mjs +25 -172
  3. package/.github/extensions/pmx-canvas/mcp-bootstrap.ts +198 -0
  4. package/.github/extensions/pmx-canvas/runtime.d.mts +41 -0
  5. package/.github/extensions/pmx-canvas/runtime.json +3 -0
  6. package/.github/extensions/pmx-canvas/runtime.mjs +194 -0
  7. package/.github/extensions/pmx-canvas/start-mcp.mjs +51 -0
  8. package/.github/extensions/pmx-canvas/tools.json +2560 -0
  9. package/CHANGELOG.md +64 -0
  10. package/Readme.md +21 -7
  11. package/dist/canvas/fonts/OFL.txt +93 -0
  12. package/dist/canvas/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  13. package/dist/canvas/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  14. package/dist/canvas/fonts/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
  15. package/dist/canvas/fonts/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
  16. package/dist/canvas/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
  17. package/dist/canvas/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
  18. package/dist/canvas/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
  19. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-400-normal.woff2 +0 -0
  20. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-500-normal.woff2 +0 -0
  21. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-600-normal.woff2 +0 -0
  22. package/dist/canvas/global.css +726 -674
  23. package/dist/canvas/index.js +90 -88
  24. package/dist/canvas/mcp-app.html +7879 -0
  25. package/dist/canvas/mermaid-entry.js +1 -1
  26. package/dist/canvas/surface-theme.css +151 -46
  27. package/dist/json-render/index.css +81 -1
  28. package/dist/json-render/index.js +1 -1
  29. package/dist/types/cli/commands/record.d.ts +1 -1
  30. package/dist/types/client/canvas/NodeContextMark.d.ts +24 -0
  31. package/dist/types/client/canvas/SessionReceipt.d.ts +3 -1
  32. package/dist/types/client/icons.d.ts +1 -2
  33. package/dist/types/client/mcp-app/index.d.ts +1 -0
  34. package/dist/types/client/nodes/HtmlNode.d.ts +1 -0
  35. package/dist/types/client/nodes/ax-node-actions.d.ts +2 -2
  36. package/dist/types/client/nodes/markdown-sanitize.d.ts +2 -0
  37. package/dist/types/client/nodes/use-workbench-asset.d.ts +2 -0
  38. package/dist/types/client/state/attention-store.d.ts +0 -5
  39. package/dist/types/client/state/context-status-store.d.ts +53 -0
  40. package/dist/types/client/state/intent-bridge.d.ts +3 -0
  41. package/dist/types/client/state/near-pin-store.d.ts +16 -0
  42. package/dist/types/client/state/presence-store.d.ts +5 -0
  43. package/dist/types/client/state/session-store.d.ts +33 -3
  44. package/dist/types/client/state/workbench-transport.d.ts +16 -0
  45. package/dist/types/client/theme/tokens.d.ts +1 -3
  46. package/dist/types/client/types.d.ts +9 -0
  47. package/dist/types/json-render/server.d.ts +1 -1
  48. package/dist/types/mcp/app-server.d.ts +3 -0
  49. package/dist/types/mcp/canvas-access.d.ts +1 -1
  50. package/dist/types/mcp/canvas-app.d.ts +4 -0
  51. package/dist/types/mcp/workbench-app.d.ts +4 -0
  52. package/dist/types/server/agent-presence.d.ts +1 -1
  53. package/dist/types/server/ax-state.d.ts +1 -1
  54. package/dist/types/server/canvas-db.d.ts +8 -0
  55. package/dist/types/server/canvas-geometry.d.ts +25 -0
  56. package/dist/types/server/canvas-operations.d.ts +1 -11
  57. package/dist/types/server/canvas-state.d.ts +25 -3
  58. package/dist/types/server/context-brief.d.ts +8 -1
  59. package/dist/types/server/context-reads.d.ts +30 -7
  60. package/dist/types/server/index.d.ts +6 -1
  61. package/dist/types/server/mcp-app-runtime.d.ts +1 -0
  62. package/dist/types/server/operations/http.d.ts +2 -0
  63. package/dist/types/server/operations/invoker.d.ts +4 -2
  64. package/dist/types/server/operations/ops/nodes.d.ts +0 -6
  65. package/dist/types/server/server.d.ts +1 -0
  66. package/dist/types/server/spatial-analysis.d.ts +2 -0
  67. package/dist/types/shared/agent-context.d.ts +22 -0
  68. package/dist/types/shared/agent-presence.d.ts +3 -10
  69. package/dist/types/shared/canvas-app.d.ts +54 -0
  70. package/dist/types/shared/themes.d.ts +1 -1
  71. package/docs/RELEASE.md +7 -3
  72. package/docs/agent-plugin.md +123 -0
  73. package/docs/ax-state-contract.md +40 -0
  74. package/docs/cli.md +7 -2
  75. package/docs/design/AgentContext.dc.html +186 -0
  76. package/docs/design/Before.dc.html +208 -0
  77. package/docs/design/BoardPins.dc.html +151 -0
  78. package/docs/design/Chrome.dc.html +211 -0
  79. package/docs/design/Context.dc.html +239 -0
  80. package/docs/design/Flows.dc.html +181 -0
  81. package/docs/design/Home.dc.html +209 -0
  82. package/docs/design/HomeGraph.dc.html +211 -0
  83. package/docs/design/HomeMap.dc.html +117 -0
  84. package/docs/design/HomeTeam.dc.html +176 -0
  85. package/docs/design/Light.dc.html +28 -0
  86. package/docs/design/Main.dc.html +280 -0
  87. package/docs/design/NearPin.dc.html +260 -0
  88. package/docs/design/Pane600.dc.html +120 -0
  89. package/docs/design/Relations.dc.html +297 -0
  90. package/docs/design/Themes.dc.html +121 -0
  91. package/docs/design/TokenSystem.dc.html +136 -0
  92. package/docs/design/Tokens.dc.html +163 -0
  93. package/docs/design/Types1.dc.html +177 -0
  94. package/docs/design/Types2.dc.html +226 -0
  95. package/docs/design/Types3.dc.html +195 -0
  96. package/docs/design/Uses.dc.html +152 -0
  97. package/docs/design/Vision.dc.html +116 -0
  98. package/docs/design/Zoom.dc.html +82 -0
  99. package/docs/design/canvas.json +274 -0
  100. package/docs/design.md +217 -0
  101. package/docs/environment.md +1 -1
  102. package/docs/http-api.md +86 -16
  103. package/docs/mcp.md +202 -4
  104. package/docs/node-types.md +34 -10
  105. package/docs/plans/plan-009-tech-debt-backlog.md +1 -1
  106. package/docs/plans/plan-015-design-foundation-wave-0.md +177 -0
  107. package/docs/plans/plan-016-context-made-visible-wave-1.md +148 -0
  108. package/docs/product-vision-2026-09.md +47 -7
  109. package/docs/screenshot.png +0 -0
  110. package/docs/sdk.md +1 -0
  111. package/package.json +10 -4
  112. package/plugins/pmx-canvas/LICENSE +21 -0
  113. package/plugins/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
  114. package/plugins/pmx-canvas/assets/preview.png +0 -0
  115. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +930 -0
  116. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +3 -0
  117. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.mjs +194 -0
  118. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/steering-delivery.mjs +79 -0
  119. package/plugins/pmx-canvas/mcp.json +12 -0
  120. package/plugins/pmx-canvas/plugin.json +24 -0
  121. package/plugins/pmx-canvas/runtime.json +3 -0
  122. package/plugins/pmx-canvas/runtime.mjs +194 -0
  123. package/plugins/pmx-canvas/start-mcp.mjs +51 -0
  124. package/plugins/pmx-canvas/tools.json +2560 -0
  125. package/skills/pmx-canvas/SKILL.md +29 -9
  126. package/skills/pmx-canvas/evals/evals.json +62 -0
  127. package/skills/pmx-canvas/references/ax-html-control-surface.md +6 -0
  128. package/skills/pmx-canvas/references/full-reference.md +11 -7
  129. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +20 -8
  130. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  131. package/skills/pmx-canvas-testing/SKILL.md +5 -4
  132. package/src/cli/commands/copilot.ts +5 -0
  133. package/src/cli/commands/nodes.ts +3 -2
  134. package/src/cli/commands/view.ts +1 -1
  135. package/src/cli/index.ts +10 -4
  136. package/src/client/App.tsx +6 -1
  137. package/src/client/canvas/AgentPresenceLayer.tsx +3 -3
  138. package/src/client/canvas/AnnotationLayer.tsx +1 -1
  139. package/src/client/canvas/CanvasNode.tsx +32 -49
  140. package/src/client/canvas/CanvasViewport.tsx +0 -2
  141. package/src/client/canvas/CommandPalette.tsx +3 -2
  142. package/src/client/canvas/ContextMenu.tsx +11 -0
  143. package/src/client/canvas/EdgeLayer.tsx +1 -1
  144. package/src/client/canvas/ExportDialog.tsx +33 -6
  145. package/src/client/canvas/IntentLayer.tsx +2 -2
  146. package/src/client/canvas/Minimap.tsx +12 -7
  147. package/src/client/canvas/NodeContextMark.tsx +156 -0
  148. package/src/client/canvas/SessionPanel.tsx +4 -7
  149. package/src/client/canvas/SessionReceipt.tsx +114 -17
  150. package/src/client/canvas/ShortcutOverlay.tsx +6 -1
  151. package/src/client/canvas/SnapshotPanel.tsx +11 -2
  152. package/src/client/canvas/ToolRail.tsx +12 -9
  153. package/src/client/canvas/TopBar.tsx +16 -11
  154. package/src/client/icons.tsx +2 -12
  155. package/src/client/mcp-app/index.tsx +137 -0
  156. package/src/client/mcp-app/style.css +10 -0
  157. package/src/client/nodes/AttachmentNode.tsx +8 -1
  158. package/src/client/nodes/AxStepControls.tsx +1 -1
  159. package/src/client/nodes/ContextNode.tsx +9 -9
  160. package/src/client/nodes/ExtAppFrame.tsx +13 -8
  161. package/src/client/nodes/FileNode.tsx +8 -5
  162. package/src/client/nodes/HtmlNode.tsx +12 -2
  163. package/src/client/nodes/ImageNode.tsx +4 -2
  164. package/src/client/nodes/InlineMarkdownEditor.tsx +2 -1
  165. package/src/client/nodes/LedgerNode.tsx +2 -2
  166. package/src/client/nodes/MarkdownNode.tsx +44 -9
  167. package/src/client/nodes/McpAppNode.tsx +6 -4
  168. package/src/client/nodes/PromptNode.tsx +5 -17
  169. package/src/client/nodes/ResponseNode.tsx +3 -15
  170. package/src/client/nodes/StatusNode.tsx +2 -2
  171. package/src/client/nodes/StatusSummary.tsx +3 -1
  172. package/src/client/nodes/TraceNode.tsx +6 -4
  173. package/src/client/nodes/WebpageNode.tsx +1 -1
  174. package/src/client/nodes/ax-node-actions.ts +2 -2
  175. package/src/client/nodes/iframe-document-url.ts +3 -2
  176. package/src/client/nodes/markdown-sanitize.ts +10 -0
  177. package/src/client/nodes/surface-url.ts +10 -0
  178. package/src/client/nodes/use-surface-frame.ts +3 -1
  179. package/src/client/nodes/use-workbench-asset.ts +26 -0
  180. package/src/client/state/attention-bridge.ts +0 -8
  181. package/src/client/state/attention-store.ts +0 -17
  182. package/src/client/state/canvas-store.ts +4 -2
  183. package/src/client/state/context-status-store.ts +66 -0
  184. package/src/client/state/human-store.ts +2 -0
  185. package/src/client/state/iframe-mode.ts +5 -0
  186. package/src/client/state/intent-bridge.ts +10 -4
  187. package/src/client/state/near-pin-store.ts +53 -0
  188. package/src/client/state/presence-store.ts +5 -10
  189. package/src/client/state/session-store.ts +106 -9
  190. package/src/client/state/sse-bridge.ts +26 -7
  191. package/src/client/state/theme-override.ts +1 -1
  192. package/src/client/state/workbench-transport.ts +36 -0
  193. package/src/client/theme/global.css +726 -674
  194. package/src/client/theme/surface-theme.css +151 -46
  195. package/src/client/theme/tokens.ts +7 -11
  196. package/src/client/types.ts +10 -0
  197. package/src/json-render/renderer/index.css +6 -1
  198. package/src/json-render/renderer/index.tsx +0 -1
  199. package/src/json-render/server.ts +71 -14
  200. package/src/mcp/app-server.ts +64 -0
  201. package/src/mcp/canvas-access.ts +14 -11
  202. package/src/mcp/canvas-app.ts +318 -0
  203. package/src/mcp/server.ts +1 -1
  204. package/src/mcp/workbench-app.ts +211 -0
  205. package/src/server/agent-presence.ts +45 -6
  206. package/src/server/ax-context.ts +1 -1
  207. package/src/server/ax-state.ts +1 -1
  208. package/src/server/board-export.ts +5 -2
  209. package/src/server/canvas-db.ts +46 -12
  210. package/src/server/canvas-geometry.ts +64 -0
  211. package/src/server/canvas-operations.ts +7 -25
  212. package/src/server/canvas-state.ts +105 -15
  213. package/src/server/canvas-validation.ts +19 -4
  214. package/src/server/context-brief.ts +39 -2
  215. package/src/server/context-reads.ts +87 -15
  216. package/src/server/demo-state.json +31 -31
  217. package/src/server/html-surface.ts +4 -5
  218. package/src/server/index.ts +41 -5
  219. package/src/server/mcp-app-runtime.ts +11 -0
  220. package/src/server/operations/composites.ts +4 -3
  221. package/src/server/operations/http.ts +4 -4
  222. package/src/server/operations/invoker.ts +13 -4
  223. package/src/server/operations/mcp.ts +6 -0
  224. package/src/server/operations/ops/ax-read.ts +1 -1
  225. package/src/server/operations/ops/ax-timeline.ts +37 -0
  226. package/src/server/operations/ops/boards.ts +1 -1
  227. package/src/server/operations/ops/canvas-wire.ts +3 -6
  228. package/src/server/operations/ops/intent.ts +31 -2
  229. package/src/server/operations/ops/json-render.ts +6 -2
  230. package/src/server/operations/ops/nodes.ts +8 -76
  231. package/src/server/operations/ops/query.ts +8 -2
  232. package/src/server/operations/ops/snapshots.ts +4 -1
  233. package/src/server/operations/ops/viewport.ts +29 -5
  234. package/src/server/operations/registry.ts +41 -5
  235. package/src/server/scope-fence.ts +55 -10
  236. package/src/server/server.ts +83 -5
  237. package/src/server/spatial-analysis.ts +2 -2
  238. package/src/server/workboard.ts +6 -1
  239. package/src/{server → shared}/agent-context.ts +2 -2
  240. package/src/shared/agent-presence.ts +3 -15
  241. package/src/shared/canvas-app.ts +62 -0
  242. package/src/shared/themes.ts +5 -5
  243. package/src/client/canvas/FocusFieldLayer.tsx +0 -116
  244. package/src/client/canvas/kind-colors.ts +0 -23
package/docs/design.md ADDED
@@ -0,0 +1,217 @@
1
+ # Design: the system and when it gets built
2
+
3
+ *Updated 2026-10-04. Companion to [the vision](product-vision-2026-09.md): the vision
4
+ says what the product does and in what order; this file says how it looks and which
5
+ design work ships with which part of that order. Design never ships ahead of the
6
+ function that produces its data, and function never ships with today's styling when
7
+ its design is already drawn.*
8
+
9
+ The drawings are the **look-and-feel proposal canvas**: edited as a private Design
10
+ artifact (<https://claude.ai/artifact/NbLiHkjK9d57Se55vskoc3>) and kept in the repo
11
+ as source under [`design/`](design/), so agents and contributors can read the exact
12
+ sizes, colours and copy. The drawings are the visual authority; this file is the
13
+ contract and the schedule.
14
+
15
+ **Before you build a surface** (any agent or contributor):
16
+
17
+ 1. Find its artboard in [The drawings](#the-drawings) and read the source for exact sizes,
18
+ colours, spacing and copy.
19
+ 2. Find its wave in the [Build plan](#build-plan) and confirm the function that produces its
20
+ data ships in the same change.
21
+ 3. Apply the [Principles](#principles), above all the fixed meaning colours.
22
+ 4. Meet the [Definition of done](#definition-of-done-for-any-design-work) before calling it done.
23
+
24
+ ## Token system
25
+
26
+ Drawn on [`TokenSystem.dc.html`](design/TokenSystem.dc.html); per-theme meaning colours on
27
+ [`Themes.dc.html`](design/Themes.dc.html).
28
+
29
+ ### Today
30
+
31
+ About 55 custom properties in `src/client/theme/global.css`, almost all colour:
32
+
33
+ - **Palette:** `--c-bg`, `--c-panel`, `--c-panel-soft`, `--c-line`, `--c-text`, `--c-text-soft`,
34
+ `--c-muted`, `--c-dim`.
35
+ - **Status colours that components borrow for meaning:** `--c-accent`, `--c-ok`, `--c-warn`,
36
+ `--c-warn-alt`, `--c-danger`, `--c-purple`, `--c-thinking`, `--c-subagent`.
37
+ - **22 fixed alpha copies:** `--c-warn-10…60` (nine), `--c-accent-8…40` (eight), `--c-ok-10…25`,
38
+ `--c-danger-12`.
39
+ - **Surfaces and effects:** `--c-panel-glass`, `--c-panel-overlay`, `--c-surface-*`,
40
+ `--c-input-bg`, `--c-shadow`, `--c-shadow-heavy`, `--c-glow-accent`.
41
+ - **The only non-colour tokens:** `--font`, `--mono`, `--radius`, `--radius-sm`,
42
+ `--hud-bar-height`.
43
+ - **A second scheme for embedded viewers:** `--color-*` in `surface-theme.css`, collapsed to dark
44
+ or light.
45
+
46
+ What that causes: meaning is borrowed (pins and agent attention both use `--c-warn`, which
47
+ `global.css` references 93 times, while the light theme hard-codes `#4BBCFF` for pins); there is no
48
+ type, spacing or shadow scale (20 font sizes, 12 radii and 195 raw hex colours sit in the CSS);
49
+ every new tint needs a new token; embedded viewers draw their own palette; `--c-subagent`
50
+ (`#00E5FF`) sits next to the pin blue; and nothing checks any of it.
51
+
52
+ ### Proposed: three layers
53
+
54
+ Components reference tokens only. Raw colour values live only in the theme files.
55
+
56
+ 1. **Palette** — defined by each theme, names kept: `--c-bg`, `--c-panel`, `--c-panel-soft`,
57
+ `--c-line`, `--c-text`, `--c-text-soft`, `--c-muted`, `--c-dim`, `--c-accent`,
58
+ `--c-on-accent`, `--c-ok`, `--c-danger`. The accent is the theme's flavour (primary buttons,
59
+ selection) and never carries a meaning below.
60
+ 2. **Meaning** — one hue in every theme, tuned only for lightness; used only for its meaning:
61
+
62
+ | Token | Means | Harbor (dark) | Daylight (light) |
63
+ |---|---|---|---|
64
+ | `--c-pin` | In the agent's context | `#4BBCFF` | `#1A7ABF` |
65
+ | `--c-agent` | What the agent did (replaces `--c-thinking`) | `#B388FF` | `#7C4DDB` |
66
+ | `--c-warn` | Needs a look: warning, stale, out of date | `#f4c542` | `#94600A` |
67
+ | `--c-rel-supports` | Evidence for | `#5FCFC0` | `#1E8C80` |
68
+ | `--c-rel-contradicts` | Evidence against | `#E59B6B` | `#B8572A` |
69
+ | `--c-rel-cites` | Where a claim or number comes from | `#7C9CFF` | tune in wave 0 |
70
+ | `--c-rel-derived` | Data lineage, flow | `#D5DEEA` | tune in wave 0 |
71
+ | `--c-rel-informs` | Answers, depends on | `#E58FB0` | tune in wave 0 |
72
+ | `--c-rel-related` | Loose link (dotted) | `#8ea3bd` | tune in wave 0 |
73
+
74
+ The other seven themes' values are drawn on the Themes board and fixed by the token test.
75
+ 3. **Scale** — the same in every theme:
76
+ - Fonts: `--font-ui` IBM Plex Sans, `--font-code` IBM Plex Mono, both bundled.
77
+ - Type: `--fs-meta` 11, `--fs-ui` 12, `--fs-body` 13, `--fs-title` 15, `--fs-heading` 20.
78
+ - Spacing: `--space-1` 4, `--space-2` 8, `--space-3` 12, `--space-4` 16, `--space-6` 24,
79
+ `--space-8` 32.
80
+ - Radius: `--r-control` 6, `--r-node` 10, `--r-overlay` 14, `--r-pill` 999.
81
+ - Elevation: `--e-1` nodes, `--e-2` floating chrome and menus. No glows. The one per-theme
82
+ exception (decided 2026-10-05): the drawn black shadows are for dark surfaces; Daylight and
83
+ Sepia use ink-tinted ones (`rgba(8, 21, 36, …)` at 10/8% and 18%).
84
+
85
+ ### Moving from today to proposed (wave 0)
86
+
87
+ - Tints are derived — `color-mix(in srgb, var(--c-pin) 12%, transparent)` — so the 22 alpha
88
+ copies, `--c-warn-alt` and `--c-glow-accent` go.
89
+ - `--c-thinking` becomes `--c-agent`.
90
+ - **Kinds carry no colour.** Type icons use `--c-muted`; the glyph tells the kind, plus the kind
91
+ word on zoomed-out tiles (Zoom board). Minimap rects and group-chip kind dots are neutral, and
92
+ only meaning colours mark them (pinned, agent at work). `KIND_COLOR`, `--kind-accent` and
93
+ `--c-purple` go. Nine kind hues cannot all stay clear of ten meaning colours in nine themes,
94
+ and every hue a kind borrows is one a meaning loses.
95
+ - **Writers are told apart by name and initial, not hue.** An agent writer's cursor, avatar and
96
+ activity line use `--c-agent`, a subagent's `--c-subagent`, a human's `--c-text-soft`;
97
+ `WRITER_PALETTE` goes. Two agents on one board share the violet and differ by label.
98
+ - The frame host hands embedded viewers the same tokens, replacing `--color-*`.
99
+ - **Decided 2026-10-05:** `--c-subagent` stays as its own meaning colour, a fuchsia beside the
100
+ agent violet (`#E879F9` on dark themes, `#A83BB0` on Daylight and Sepia, `#ff99ff` on High
101
+ contrast) instead of a second cyan next to the pin blue. It reads as agent work, is told
102
+ apart from the main agent at a glance, and is held apart from every other meaning colour by
103
+ the token test.
104
+ - **Checks:** a token test that keeps meaning colours apart from each other and from the palette,
105
+ with at least 3:1 contrast on `--c-panel`, in all nine themes; a check that rejects raw hex
106
+ outside the theme files; a check that every control computes `--font-ui`.
107
+
108
+ ## The drawings
109
+
110
+ Each `.dc.html` file is one artboard; `canvas.json` is the canvas layout (positions,
111
+ titles, notes). They render in the Design canvas (they need its runtime); in the repo
112
+ they are read as source. When an artboard changes in the canvas, re-export it here in
113
+ the same change.
114
+
115
+ | File | Shows | Wave |
116
+ |---|---|---|
117
+ | [`Before.dc.html`](design/Before.dc.html) | The demo board as it renders today | — |
118
+ | [`Main.dc.html`](design/Main.dc.html), [`Light.dc.html`](design/Light.dc.html) | The same board with the foundation applied, dark and light | 0 |
119
+ | [`Tokens.dc.html`](design/Tokens.dc.html) | Typeface, type scale, radii, elevation, one meaning per colour | 0 |
120
+ | [`TokenSystem.dc.html`](design/TokenSystem.dc.html) | The token system today vs proposed: palette, meaning, scale | 0 |
121
+ | [`Themes.dc.html`](design/Themes.dc.html) | Meaning colours across all nine themes, proposed names | 0 |
122
+ | [`Chrome.dc.html`](design/Chrome.dc.html) | Rail at 690 px, node header (expand and context pin always visible, the rest under ⋯), section headings, floating chrome | 0 |
123
+ | [`Context.dc.html`](design/Context.dc.html) | Nodes in context: every state, the count chip, the command bar | 0–1 |
124
+ | [`NearPin.dc.html`](design/NearPin.dc.html) | Near a pin: the dotted “near” chip on a pinned node's unpinned neighbours, tethers on hover, the moment of change, combinations, 600 px; ships with the brief carrying neighbours (title + summary, reason “near <pin>”) | 1 |
125
+ | [`AgentContext.dc.html`](design/AgentContext.dc.html) | What the agent did: read, created, edited, suggested, out of date; lens and receipt | 1 |
126
+ | [`BoardPins.dc.html`](design/BoardPins.dc.html) | Board pins: where you pin a board, the tiered brief, the context chip across boards | 1 |
127
+ | [`Home.dc.html`](design/Home.dc.html) | Home — Folders: library tree, pinned boards, README, board details | 1 |
128
+ | [`HomeMap.dc.html`](design/HomeMap.dc.html), [`HomeGraph.dc.html`](design/HomeGraph.dc.html) | Home — Map and Graph views of the library | 2 |
129
+ | [`HomeTeam.dc.html`](design/HomeTeam.dc.html) | Home on a team server: workspace and personal libraries, per-user pins, moving a board into the workspace, locked links (look ahead) | Later (Part 3, step 5) |
130
+ | [`Relations.dc.html`](design/Relations.dc.html) | Relations on a research board, today vs proposed; edge anatomy; relation inks | 3 |
131
+ | [`Flows.dc.html`](design/Flows.dc.html) | Data lineage with staleness, what a finding rests on, opening a group | 3, 5 |
132
+ | [`Uses.dc.html`](design/Uses.dc.html) | One relation layer for research, dependencies, decisions and agent flows | 3 |
133
+ | [`Types1.dc.html`](design/Types1.dc.html)–[`Types3.dc.html`](design/Types3.dc.html) | Every node type, today vs proposed | 0, 4 |
134
+ | [`Zoom.dc.html`](design/Zoom.dc.html) | Fit-all readability when frames are unmounted | 4 |
135
+ | [`Pane600.dc.html`](design/Pane600.dc.html) | Home and a board at the narrow end, 600 px | all |
136
+ | [`Vision.dc.html`](design/Vision.dc.html) | How each design area maps to the vision, and the open decisions | — |
137
+
138
+ ## Principles
139
+
140
+ - **One meaning per colour, the same in every theme.** Blue = in the agent's
141
+ context (pinned, by you or the agent). Violet = what the agent did (read, created,
142
+ edited, suggested). Amber = needs a look (warning, stale, out of date). Relation
143
+ inks (supports, contradicts, cites, derived from, informs…) never reuse those
144
+ three. Each theme keeps its own surfaces and accent; the meaning colours keep
145
+ their hue and are tuned only for lightness. A token test keeps them apart in all
146
+ nine themes.
147
+ - **Context pins at two levels, one look.** A card pin sends that card's content; a board
148
+ pin brings the whole board into the agent's working set, from anywhere in the library
149
+ ([vision move 0a](product-vision-2026-09.md#0a-board-pins-a-working-set-across-boards-sm)).
150
+ Both use the outline pin (not in context) and the filled blue badge (in context), and the
151
+ context chip counts both: "4 cards · 3 boards in context".
152
+ - **Every mark has a glyph and a word**, so it reads without colour, and explains
153
+ itself on hover.
154
+ - **One font and one scale.** IBM Plex Sans and Mono, bundled with the app (no CDN);
155
+ every control inherits the font, including embedded JSON forms. Self-contained
156
+ viewers embed the font bytes for hosted and offline use. Type 11/12/13/15/20; radii 6/10/14/pill; two
157
+ shadow levels. No glow is used as elevation.
158
+ - **Quiet chrome, with expand and the context pin always in reach.** Every node header
159
+ shows its kind, title, expand (`⤢`, Enter — on the types that expand: markdown,
160
+ mcp-app, webpage, json-render, graph, context, ledger, file, diff, mermaid, image,
161
+ html) and context pin: an outline pin in a circle when the node is not in context
162
+ (click or `P` to add), the filled blue badge when it is (click to remove), always in
163
+ the same place. The other controls (ask agent, open in new tab, collapse, set as
164
+ README, close) appear on hover under ⋯ and ×. Their slots stay reserved while
165
+ hidden, so hover or keyboard focus cannot move the pin onto another action.
166
+ Section labels are a heading display of the markdown node. Rarely used tools
167
+ live in one settings menu on the rail.
168
+ - **Relations are the edge layer, not node types.** Design work adds no node type;
169
+ the vision's own `ask` node (move 3) is separate.
170
+ - **Any size, from a side pane to a full window.** The workbench lives in narrow agent-host
171
+ panes, the resizable side browser in the Claude desktop app, and full browser windows. Every
172
+ drawing shows the narrow end (600 px) and a full window before it is built, and the build
173
+ is checked at 600, 1024 and 1920 px (proposal board
174
+ "At 600 px" for the narrow end). Decided 2026-10-05, replacing the single 600 px reference.
175
+
176
+ ## Build plan
177
+
178
+ Each wave pairs a vision move with the design that shows it. A wave is done only
179
+ when both halves pass its check. Status reflects 0.7.0 (see the vision's
180
+ implementation table).
181
+
182
+ | Wave | Vision | Function (build) | Design (proposal boards) | Done when |
183
+ |---|---|---|---|---|
184
+ | **0. Foundation** — ships alone, first | Moves 5, 9, 10 | Bundle Plex; controls inherit the font; type/radius/shadow tokens; meaning tokens per theme; theme renames (`dark` → Harbor, `light` → Daylight, neutral; no aliases); pin style that survives selection and attention; violet header bar replaces amber halos and focus fields | Today / Proposed, Tokens, Themes, Rail and node header, Nodes in context | No control renders in a fallback font; token test passes for all nine themes; reference cases pass at 600, 1024 and 1920 px; demo board regenerated |
185
+ | **1. Context made visible** — next batch, with the curation evaluation | Part 1 bet, moves 0a, 2, 7 | Surface `context_reads` (already recorded since 0.7.0: who read, which nodes were delivered) per node and per board as read / not read / changed since read, using revisions; who pinned; activity lens and session receipt from presence activity and revisions; board pins (`board_pins`, tiered brief, `canvas_board pin/unpin`) and Home's pinned-boards section | What the agent did with context, Nodes in context, Board pins, Home (Folders) | From the board alone, a person can answer "did the agent read what I pinned, and is its copy current?" The evaluation in `docs/evals/` reads the same data |
186
+ | **2. Connected memory views** — next batch, remaining wiki/graph work | Moves 0, 14 | Board map projection (generated like the code graph), wiki links, direct cross-board card edges, previous-board chains | Home Map, Home Graph | Map and Graph are generated from the library; orphans visible; works at 600 px and in a full window |
187
+ | **3. Relations layer** | Moves 0, 1, 13 | Edge `reason` and an open `kind` with a per-board vocabulary; relations carried in the brief's text form; "derived from" with staleness from provenance and recipes; relation queries for the inspector | Relations, Lineage, One relation layer | Hovering a node explains each link; a changed source turns downstream nodes amber; the agent's brief includes relations |
188
+ | **4. Frame host and viewers** | Moves 5, 9 | One frame host passing the full theme tokens; json-render defaults to the canvas theme with an opt-out for design experiments; zoomed-out cards for unmounted frames | Node types 1–3, Zoomed out | No viewer draws its own background; 20 portals mount no more frames than none; fit-all is readable |
189
+ | **5. Agent output and groups as pages** | Moves 3, 0 | Work items, gates and asks as nodes; make board / inline board; opening a group keeps its outside links | One relation layer (agent flow), Lineage (open a group) | Agent output is styled by the same shell and tokens; a group opened as a board shows its outside stubs |
190
+ | **Later — share ladder** | Part 3 | Read-only link, comments, second writer; at step 5, workspace and personal libraries with per-user pins | HomeTeam (look ahead): Home with two roots (Workspace, Personal), your pins across both, an explicit move with its effects spelled out, locked cards for boards a viewer cannot read | Exports and shared views inherit the tokens; a viewer sees the same meaning colours; nothing personal crosses into the workspace without an explicit share or move |
191
+
192
+ **Folders and portals (decided 2026-10-06).** Home uses folders as the visible hierarchy (where a
193
+ board lives, one place); portals and links are how boards relate: a many-to-many graph the agent
194
+ navigates through links and backlinks on `canvas://boards`, and that Map and Graph draw. This
195
+ replaces the review's portal-derived levels as the navigation tree. Where a board's folder and its
196
+ links disagree, the Map shows it (folders as regions) rather than forcing them to match.
197
+
198
+ ## Definition of done for any design work
199
+
200
+ 1. It is drawn in the proposal canvas first, at 600 px and at full-window width.
201
+ 2. It is built to the drawing, with the function it shows (see the plan above).
202
+ 3. It passes in all nine themes and at the three Chromium widths, 600, 1024 and 1920 px.
203
+ 4. It touches no meaning colour except through the meaning tokens.
204
+ 5. The demo board is regenerated (`bun run scripts/generate-demo-board.ts`) and
205
+ `tests/unit/demo.test.ts` passes.
206
+ 6. User-facing docs (`docs/node-types.md`, `docs/http-api.md`, `docs/mcp.md`) and the
207
+ skills reflect it.
208
+
209
+ ## History
210
+
211
+ - **Rail-chrome v2 (August 2026).** The rail, top bar, presence layer, session panel,
212
+ command bar, external steering and canvas-quality waves shipped from the design
213
+ handoff that lived in `design/rail-chrome-v2/`. That folder was retired on
214
+ 2026-10-04: its presence contract now lives in
215
+ [`ax-state-contract.md`](ax-state-contract.md#agent-presence-contract), this file
216
+ holds the design direction, and the mockups and plan remain in git history
217
+ (`git log -- design/`).
@@ -28,7 +28,7 @@ optional; defaults are listed.
28
28
 
29
29
  | Variable | Read by | Effect |
30
30
  |---|---|---|
31
- | `PMX_CANVAS_THEME` | server | Startup theme: `dark` (default), `light`, `high-contrast`, `midnight`, `sepia`, `arctic`, `ember`, `forest`, `volt`. |
31
+ | `PMX_CANVAS_THEME` | server | Startup theme: `harbor` (default), `daylight`, `high-contrast`, `midnight`, `sepia`, `arctic`, `ember`, `forest`, `volt`. |
32
32
  | `AMP_ORB` | server | Set by Amp orb services. When present, the served canvas page tells the browser it is running in an orb, which skips the iframe embed probe, forces `srcdoc` surface rendering when embedded (the orb portal blocks `src`-URL child iframes and the probe is unreliable there), and defaults the event transport to polling instead of SSE (the portal proxy buffers streams; `?transport=sse` overrides for diagnosis). |
33
33
  | `PORT` | server | Portal-assigned service port, honored ONLY when `AMP_ORB` is also set (Amp orbs) — after `--port`, `PMX_WEB_CANVAS_PORT`, and `PMX_CANVAS_PORT`, before the 4313 default. A stray `PORT` in normal shells never changes the port. |
34
34
  | `PMX_CANVAS_DISABLE_BROWSER_OPEN` | server | `1` suppresses auto-opening the browser (used by tests/CI). |
package/docs/http-api.md CHANGED
@@ -3,6 +3,13 @@
3
3
  REST endpoints for all canvas operations + an SSE event stream. Works from
4
4
  any language. Default base URL: `http://localhost:4313`.
5
5
 
6
+ `GET /health` includes `contracts: ["pmx-embedded-workbench-v4"]` when the daemon
7
+ enforces `expectedBoardId` and `expectedContentRevision` preconditions, bulk-write
8
+ fences/locks using validated geometry and affected automatic parent frames only,
9
+ and the `allowExternalMcp: false` operation restriction (including
10
+ deferred backend rehydration). The experimental MCP App requires this contract
11
+ when attaching to a daemon; package version equality alone is insufficient.
12
+
6
13
  A non-empty request body that is not valid JSON returns
7
14
  `400 { "ok": false, "error": "Malformed JSON body." }` on every route; empty
8
15
  bodies are treated as an empty request. As of 0.4.0 every error response is a
@@ -215,7 +222,10 @@ curl http://localhost:4313/api/canvas/state
215
222
  # Search the library (omit scope for the active board)
216
223
  curl "http://localhost:4313/api/canvas/search?q=auth&limit=10&scope=library"
217
224
 
218
- # Validate the current layout
225
+ # Validate the current layout. Reports collisions, groupFrameOverlaps (a group
226
+ # frame covering a node that is not one of its members, nested members
227
+ # included — e.g. after a group auto-fits around enlarged children),
228
+ # containmentViolations, missingEdgeEndpoints, and advisory sizeWarnings.
219
229
  curl http://localhost:4313/api/canvas/validate
220
230
 
221
231
  # Inspect running-server schemas
@@ -276,6 +286,17 @@ switch command: if it no longer matches the active board, the request returns
276
286
  `409` without creating a node or opening a board from Home. The file-drop UI
277
287
  uses this to prevent delayed uploads from landing on a different board.
278
288
 
289
+ Operation-registry requests may also carry `expectedBoardId` (a board ID or
290
+ null for Home). A mismatch returns `409` before auto-opening a board or running
291
+ the operation. This is a precondition, not a board switch or permission grant.
292
+ `PATCH /api/canvas/node/:id` accepts optional `expectedContentRevision`, matched
293
+ against the node's top-level `contentRevision`; stale content returns `409`
294
+ without changing the node. Conditional edits cannot request webpage refresh.
295
+ The private MCP App uses these guards to reject stale board actions and note drafts.
296
+
297
+ Replacing a JSON-render node's `spec` preserves its current title; include `title`
298
+ to rename it explicitly. A new authored spec still resets the viewer's local drafts.
299
+
279
300
  Mermaid nodes accept `data: { "fit": "contain" | "none" }` on both
280
301
  `POST /api/canvas/node` and `PATCH /api/canvas/node/:id`. The default, `contain`,
281
302
  shrinks overflowing diagrams without changing aspect ratio; `none` keeps 100%
@@ -364,6 +385,12 @@ curl -X POST http://localhost:4313/api/canvas/viewport \
364
385
  -H "Content-Type: application/json" \
365
386
  -d '{"x":64,"y":96,"scale":0.8}'
366
387
 
388
+ # Centre world point (400, 300) in the visible canvas area at zoom 0.8
389
+ # (omit scale to keep the current zoom). Responds with the resulting viewport.
390
+ curl -X POST http://localhost:4313/api/canvas/viewport \
391
+ -H "Content-Type: application/json" \
392
+ -d '{"center":{"x":400,"y":300},"scale":0.8}'
393
+
367
394
  # Fit selected nodes (omit nodeIds to fit the whole canvas)
368
395
  curl -X POST http://localhost:4313/api/canvas/fit \
369
396
  -H "Content-Type: application/json" \
@@ -377,17 +404,30 @@ curl -X POST http://localhost:4313/api/canvas/focus \
377
404
 
378
405
  Viewport `x`/`y`, fit `width`/`height`, and fit padding are interpreted against
379
406
  the **canvas area**, excluding the tool rail, top bar, and other surrounding
380
- page chrome—not the full browser window. Camera, fit, and focus-only requests
407
+ page chrome—not the full browser window.
408
+
409
+ `{x, y, scale}` is the transform of the canvas world inside the canvas area:
410
+ a world point `(wx, wy)` appears at canvas-area point `(wx * scale + x,
411
+ wy * scale + y)`. The canvas area starts right of the 52 px tool rail and below
412
+ the 44 px top bar in the default layout, so to put world `(wx, wy)` at browser
413
+ window point `(sx, sy)` send `x = sx - 52 - wx * scale` and
414
+ `y = sy - 44 - wy * scale`. `center` does this for the middle of the canvas
415
+ area, using the size the open workbench last reported (1440×900 when no tab has
416
+ reported one); it cannot be combined with `x`/`y`. Floating overlays inside the
417
+ canvas area (command bar, minimap) are not subtracted. Camera, fit, and focus-only requests
381
418
  do not create or refresh agent writer presence. Use the explicit presence API
382
419
  when an agent should publish a cursor or `focusNodeId`.
383
420
 
384
421
  ## Pins
385
422
 
386
423
  ```bash
387
- # Pin nodes for agent context
424
+ # Pin nodes for agent context (mode: set | add | remove; default set). Each newly
425
+ # pinned node records who pinned it and when; an optional reason (max 280 chars)
426
+ # is kept with it and shown to the human on hover. Pins that stay keep their
427
+ # original attribution.
388
428
  curl -X POST http://localhost:4313/api/canvas/context-pins \
389
429
  -H "Content-Type: application/json" \
390
- -d '{"nodeIds":["node-1","node-2"]}'
430
+ -d '{"nodeIds":["node-1","node-2"],"mode":"add","reason":"the chart the finding rests on"}'
391
431
 
392
432
  # Get pinned context
393
433
  curl http://localhost:4313/api/canvas/pinned-context
@@ -400,7 +440,10 @@ curl 'http://localhost:4313/api/canvas/context?consumer=codex&budget=16000'
400
440
  `consumer` is optional. Supply a stable unique value only for a durable,
401
441
  board-scoped cursor; without `consumer` or `since`, each request starts from the
402
442
  beginning. An explicit `since` never advances a cursor. The brief prioritizes
403
- pins, then relevant current-board changes and asks, then compact linked or
443
+ pins, then each pin's neighbours (reason `near`: up to five unpinned cards within
444
+ 600 px, nearest first, as title + a short summary with `near: { pinNodeId,
445
+ pinTitle }`; pin a card to send its full content), then relevant current-board
446
+ changes and asks, then compact linked or
404
447
  same-folder board context. Every item carries source board/card IDs. If card text
405
448
  is clipped, use those IDs with the board/node read route rather than guessing
406
449
  from the excerpt. Reading inactive boards does not open them.
@@ -464,14 +507,25 @@ curl "http://localhost:4313/api/canvas/ax/timeline?limit=50"
464
507
  # nodes were in what came back (newest first, default 50, max 500; the per-consumer
465
508
  # summary covers the whole retained log of 5,000 reads). Agent reads of pinned
466
509
  # context, AX context, AX state, summary, spatial context and layout are recorded
467
- # automatically; the workbench's own reads are not.
510
+ # automatically, as are individual GET /api/canvas/node/:id reads (only the
511
+ # delivered node). The workbench's own reads are not. A projecting client may
512
+ # pass contextDelivery=false on node GET to avoid marking unseen content read.
468
513
  curl "http://localhost:4313/api/canvas/ax/context-reads?limit=50"
469
514
 
515
+ # Read status — per node on a board (default: the open board), the latest agent
516
+ # read that delivered its content: when, who, and the content revision it had.
517
+ # A node whose current contentRevision is newer was changed since it was read.
518
+ # pins maps each pinned node with a known pinner to { pinnedBy, pinnedAt, reason }.
519
+ curl "http://localhost:4313/api/canvas/ax/context-status?board=<board-id>"
520
+
470
521
  # Context reads — a proxy (an MCP server attached to this daemon, a host adapter)
471
522
  # records the read its agent actually made. Its own fetches send
472
523
  # `x-pmx-proxied-read: 1` so they are not recorded twice.
473
524
  # Pass boardId captured at read time (null for Home); omitting it uses the
474
525
  # currently open board. MCP bytes measure the final formatted text response.
526
+ # readNodeIds lists every serialized node in what the agent received (pinned or
527
+ # not); the server keeps those on the board and stamps their revisions. Omitted,
528
+ # it defaults to deliveredNodeIds.
475
529
  curl -X POST http://localhost:4313/api/canvas/ax/context-reads \
476
530
  -H "Content-Type: application/json" \
477
531
  -d '{"channel":"adapter","resource":"copilot:prompt-context","consumer":"copilot","pinnedNodeIds":["node-1"],"deliveredNodeIds":["node-1"],"bytes":2048}'
@@ -530,7 +584,7 @@ without the workbench's own `x-pmx-workbench: 1` marker) registers its caller
530
584
  as a `tooling` writer, the activity feed drives attach/detach and phase
531
585
  (`session-start`, `session-end`, `tool-start`, `tool-result`), and adapters
532
586
  with richer hooks can set a phase, cursor, or focus explicitly. Writers fade
533
- 90 s after their last write; attached sessions expire after 30 min of quiet
587
+ 5 min after their last write; attached sessions expire after 30 min of quiet
534
588
  without a `session-end`.
535
589
 
536
590
  ```bash
@@ -611,20 +665,30 @@ the stream carries one `agent-session-ended` frame:
611
665
  ```json
612
666
  { "label": "Copilot", "parentAgentId": null, "endedAt": "…", "endedBy": "agent",
613
667
  "unchanged": false, "counts": { "items": 4, "done": 3, "cancelled": 1, "rejected": 0, "held": 0 },
614
- "snapshot": { "id": "…", "name": "Before session · Copilot · 14:00" } }
668
+ "snapshot": { "id": "…", "name": "Before session · Copilot · 14:00" },
669
+ "context": { "read": [{ "id": "…", "title": "Brief" }], "pinned": [{ "id": "…", "title": "Chart", "reason": "…" }],
670
+ "created": [], "edited": [], "changedSinceRead": [{ "id": "…", "title": "Brief" }] } }
615
671
  ```
616
672
 
673
+ `context` is what the session did with the board's context: nodes whose content an
674
+ agent read since the session attached, pins the agent made (with their reason), nodes
675
+ it created and edited (against the pre-session snapshot), and pinned nodes changed
676
+ after their latest read. A session that only read or pinned is not `unchanged`.
677
+
617
678
  `items`/`done` count the work items on the board; cancelled items, rejected
618
679
  gates, and held gates have separate counts. `snapshot` is null when the board was
619
680
  empty at attach or unchanged at end (the redundant snapshot is removed).
620
681
  The browser shows a receipt only for a changed top-level session: `unchanged: true`
621
- and worker endings (`parentAgentId` set) never open or replace a popup. An empty
682
+ and worker endings (`parentAgentId` set) never open, replace, or extend a popup —
683
+ the orchestrator's receipt covers the board since it attached. An empty
622
684
  board that stays empty is unchanged too. This only filters the popup: session-end
623
685
  events, timeline records, and changed-session snapshots remain available.
624
- There is at most one receipt, replaced by the next qualifying ending and kept until
625
- dismissed so restore/diff actions do not disappear on a timer. Its *View
626
- diff* is `GET /api/canvas/snapshots/<id>/diff` against that snapshot, and
627
- restoring the snapshot undoes the session. Adapters should end their session
686
+ There is at most one receipt. Qualifying endings that arrive while it is up merge
687
+ into it ("3 sessions ended", their labels, the union of their context); a merged
688
+ receipt has no *View diff* and points to History, which keeps each session's
689
+ snapshot. The receipt is kept until dismissed so restore/diff actions do not
690
+ disappear on a timer. A single session's *View diff* is `GET /api/canvas/snapshots/<id>/diff` against that
691
+ snapshot, and restoring the snapshot undoes the session. Adapters should end their session
628
692
  explicitly so the human gets the receipt promptly rather than after the idle
629
693
  expiry. The browser's *Start agent session* button is this same endpoint
630
694
  (`source: "browser"`, `attached: true`) — subsequent agent-less writes are
@@ -786,7 +850,10 @@ registry's kind validation. Pick the operation by method + path:
786
850
  # (default 8000, max 60000), so cleanup is optional.
787
851
  curl -X POST http://localhost:4313/api/canvas/ax/intent \
788
852
  -H "Content-Type: application/json" \
789
- -d '{"kind":"create","position":{"x":400,"y":300},"nodeType":"markdown","label":"Add evidence","reason":"collecting run logs"}'
853
+ -d '{"kind":"create","nodeType":"markdown","label":"Add evidence","reason":"collecting run logs"}'
854
+ # A create may omit "position": the ghost forms where the canvas will auto-place
855
+ # the node (returned in intent.position), and a create linked by intentId with no
856
+ # x/y lands there. Pass "position" only when you know where the node goes.
790
857
 
791
858
  # Update the ghost (position/label/reason/confidence/ttlMs; vetoed:true dissolves
792
859
  # it AND poisons the id so a later linked settle is rejected)
@@ -834,7 +901,10 @@ all consume this stream. Auto-reconnect with exponential backoff.
834
901
  `agent-presence` frames carry the full presence snapshot (the same body as
835
902
  `GET /api/canvas/ax/presence`) on every change, including TTL expiry — a
836
903
  client never needs its own expiry timer. `agent-session-ended` carries the
837
- session receipt (see [Agent presence](#agent-presence)).
904
+ session receipt (see [Agent presence](#agent-presence)). `context-status-changed`
905
+ (`{ boardId }`) says an agent read landed; the workbench refetches
906
+ `GET /api/canvas/ax/context-status`. It is never an MCP notification, so a read
907
+ cannot cause more reads.
838
908
 
839
909
  Every frame's payload is wrapped in an envelope that sets `sessionId` (the
840
910
  workbench session, used for reconnect/reload detection) and `timestamp` —
@@ -869,7 +939,7 @@ override the orb default).
869
939
 
870
940
  `/workbench?theme=<name>` gives that browser session its own theme without
871
941
  touching the server-global theme other clients see — embedding hosts use it to
872
- match their chrome (the bundled Copilot extension opens `?theme=light`).
942
+ match their chrome (the bundled Copilot extension opens `?theme=daylight`).
873
943
  `?theme=auto` follows the host's `prefers-color-scheme` live. Picking a theme
874
944
  from the toolbar ends the override and saves globally as usual.
875
945