pmx-canvas 0.8.2 → 0.9.0

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 (335) hide show
  1. package/.github/extensions/pmx-canvas/runtime.json +1 -1
  2. package/.github/extensions/pmx-canvas/tools.json +601 -22
  3. package/CHANGELOG.md +49 -0
  4. package/Readme.md +131 -532
  5. package/dist/canvas/global.css +2724 -476
  6. package/dist/canvas/index.js +168 -107
  7. package/dist/canvas/mcp-app.html +2899 -596
  8. package/dist/json-render/index.js +20 -20
  9. package/dist/types/client/canvas/BarHint.d.ts +12 -2
  10. package/dist/types/client/canvas/BoardLinkDialog.d.ts +3 -1
  11. package/dist/types/client/canvas/BoardPinButton.d.ts +10 -0
  12. package/dist/types/client/canvas/BoardSwitcher.d.ts +1 -1
  13. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  14. package/dist/types/client/canvas/CommandBar.d.ts +3 -4
  15. package/dist/types/client/canvas/ConnectionBanner.d.ts +2 -1
  16. package/dist/types/client/canvas/ContextChip.d.ts +3 -0
  17. package/dist/types/client/canvas/CrossBoardReferences.d.ts +5 -0
  18. package/dist/types/client/canvas/EdgeLayer.d.ts +14 -3
  19. package/dist/types/client/canvas/EmptyState.d.ts +4 -4
  20. package/dist/types/client/canvas/HomeGraphView.d.ts +2 -0
  21. package/dist/types/client/canvas/HomeMapView.d.ts +1 -0
  22. package/dist/types/client/canvas/HomeReviewView.d.ts +6 -0
  23. package/dist/types/client/canvas/HomeView.d.ts +9 -7
  24. package/dist/types/client/canvas/KnowledgeDialog.d.ts +4 -0
  25. package/dist/types/client/canvas/LifecycleChrome.d.ts +5 -0
  26. package/dist/types/client/canvas/LifecycleFields.d.ts +7 -0
  27. package/dist/types/client/canvas/LifecyclePanel.d.ts +1 -0
  28. package/dist/types/client/canvas/MemoryInspector.d.ts +7 -0
  29. package/dist/types/client/canvas/NearPinLayer.d.ts +14 -0
  30. package/dist/types/client/canvas/NodeContextMark.d.ts +40 -7
  31. package/dist/types/client/canvas/RelationPresetsDialog.d.ts +4 -0
  32. package/dist/types/client/canvas/RelationsPanel.d.ts +4 -0
  33. package/dist/types/client/canvas/SessionPanel.d.ts +2 -0
  34. package/dist/types/client/canvas/canvas-area.d.ts +1 -1
  35. package/dist/types/client/canvas/graph-geometry.d.ts +27 -0
  36. package/dist/types/client/canvas/graph-model.d.ts +37 -0
  37. package/dist/types/client/canvas/memory-layout.d.ts +23 -0
  38. package/dist/types/client/canvas/use-chrome-height.d.ts +2 -0
  39. package/dist/types/client/canvas/use-focus-trap.d.ts +1 -0
  40. package/dist/types/client/canvas/use-memory-graph.d.ts +8 -0
  41. package/dist/types/client/canvas/use-pan-zoom.d.ts +4 -1
  42. package/dist/types/client/icons.d.ts +0 -10
  43. package/dist/types/client/nodes/AxStepControls.d.ts +1 -1
  44. package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +4 -4
  45. package/dist/types/client/nodes/MarkdownNode.d.ts +5 -1
  46. package/dist/types/client/nodes/McpAppNode.d.ts +4 -4
  47. package/dist/types/client/nodes/viewer-runtime-state.d.ts +1 -1
  48. package/dist/types/client/state/boards-store.d.ts +81 -9
  49. package/dist/types/client/state/canvas-store.d.ts +14 -1
  50. package/dist/types/client/state/context-chip-store.d.ts +22 -0
  51. package/dist/types/client/state/context-status-store.d.ts +35 -0
  52. package/dist/types/client/state/intent-bridge.d.ts +11 -8
  53. package/dist/types/client/state/knowledge-store.d.ts +22 -0
  54. package/dist/types/client/state/near-pin-store.d.ts +44 -1
  55. package/dist/types/client/state/presence-store.d.ts +4 -4
  56. package/dist/types/client/state/presentation.d.ts +28 -0
  57. package/dist/types/client/state/relation-store.d.ts +10 -0
  58. package/dist/types/client/state/session-store.d.ts +41 -2
  59. package/dist/types/client/state/workspace-settings.d.ts +7 -0
  60. package/dist/types/client/types.d.ts +13 -1
  61. package/dist/types/client/utils/keyboard.d.ts +2 -0
  62. package/dist/types/client/utils/time-ago.d.ts +4 -0
  63. package/dist/types/mcp/context-uri-template.d.ts +3 -1
  64. package/dist/types/server/agent-presence.d.ts +10 -3
  65. package/dist/types/server/ax-context.d.ts +1 -1
  66. package/dist/types/server/canvas-db.d.ts +30 -7
  67. package/dist/types/server/canvas-operations.d.ts +24 -2
  68. package/dist/types/server/canvas-provenance.d.ts +22 -2
  69. package/dist/types/server/canvas-serialization.d.ts +2 -0
  70. package/dist/types/server/canvas-state.d.ts +93 -15
  71. package/dist/types/server/canvas-validation.d.ts +1 -1
  72. package/dist/types/server/context-brief.d.ts +94 -6
  73. package/dist/types/server/context-reads.d.ts +33 -7
  74. package/dist/types/server/edit-summary.d.ts +20 -0
  75. package/dist/types/server/index.d.ts +71 -10
  76. package/dist/types/server/knowledge-lifecycle.d.ts +221 -0
  77. package/dist/types/server/lifecycle-status.d.ts +10 -0
  78. package/dist/types/server/memory-graph.d.ts +9 -0
  79. package/dist/types/server/mutation-history.d.ts +2 -0
  80. package/dist/types/server/operations/ops/ax-shared.d.ts +1 -1
  81. package/dist/types/server/operations/ops/boards.d.ts +2 -1
  82. package/dist/types/server/operations/ops/lifecycle.d.ts +2 -0
  83. package/dist/types/server/operations/ops/memory-graph.d.ts +2 -0
  84. package/dist/types/server/operations/ops/nodes.d.ts +5 -0
  85. package/dist/types/server/operations/ops/query.d.ts +23 -0
  86. package/dist/types/server/operations/registry.d.ts +1 -0
  87. package/dist/types/server/placement.d.ts +7 -0
  88. package/dist/types/server/scope-fence.d.ts +2 -1
  89. package/dist/types/server/spatial-analysis.d.ts +6 -3
  90. package/dist/types/server/tour-control.d.ts +32 -0
  91. package/dist/types/server/wiki-links.d.ts +14 -0
  92. package/dist/types/server/workbench-auth.d.ts +2 -0
  93. package/dist/types/shared/agent-context.d.ts +2 -0
  94. package/dist/types/shared/agent-presence.d.ts +15 -12
  95. package/dist/types/shared/auto-arrange.d.ts +1 -0
  96. package/dist/types/shared/boards.d.ts +4 -4
  97. package/dist/types/shared/knowledge-lifecycle.d.ts +41 -0
  98. package/dist/types/shared/knowledge-presets.d.ts +6 -0
  99. package/dist/types/shared/lifecycle-status.d.ts +24 -0
  100. package/dist/types/shared/memory-graph.d.ts +53 -0
  101. package/dist/types/shared/relations.d.ts +68 -0
  102. package/dist/types/shared/semantic-attention.d.ts +2 -0
  103. package/dist/types/shared/tour.d.ts +38 -0
  104. package/dist/types/shared/workspace-settings.d.ts +11 -0
  105. package/docs/RELEASE.md +21 -3
  106. package/docs/adr-001-bun-only-runtime.md +7 -1
  107. package/docs/adr-002-shared-product-separate-runtimes.md +93 -0
  108. package/docs/api-reference.md +109 -0
  109. package/docs/ax-host-adapter-contract.md +1 -1
  110. package/docs/ax-state-contract.md +5 -4
  111. package/docs/cli.md +153 -15
  112. package/docs/demos/pmx-canvas-demo.mp4 +0 -0
  113. package/docs/design/AgentContext.dc.html +3 -3
  114. package/docs/design/BoardPins.dc.html +37 -22
  115. package/docs/design/Categories.dc.html +208 -0
  116. package/docs/design/CategoryEditor.dc.html +33 -0
  117. package/docs/design/Chrome.dc.html +52 -9
  118. package/docs/design/ContextChip.dc.html +224 -0
  119. package/docs/design/ContextChip600.dc.html +136 -0
  120. package/docs/design/EmptyState.dc.html +45 -0
  121. package/docs/design/Flows.dc.html +23 -1
  122. package/docs/design/HeaderMarks.dc.html +183 -0
  123. package/docs/design/Home.dc.html +19 -1
  124. package/docs/design/HomeGraph.dc.html +86 -202
  125. package/docs/design/HomeMap.dc.html +23 -1
  126. package/docs/design/HomeTeam.dc.html +32 -14
  127. package/docs/design/Lifecycle.dc.html +22 -0
  128. package/docs/design/Lifecycle600.dc.html +18 -0
  129. package/docs/design/LifecycleVariants.dc.html +157 -0
  130. package/docs/design/LinkAuthorship.dc.html +139 -0
  131. package/docs/design/LinksChanged.dc.html +203 -0
  132. package/docs/design/LinksOptions.dc.html +137 -0
  133. package/docs/design/LinksOptions600.dc.html +134 -0
  134. package/docs/design/NearPin.dc.html +9 -10
  135. package/docs/design/Pane600.dc.html +4 -3
  136. package/docs/design/Relations.dc.html +3 -2
  137. package/docs/design/Restore.dc.html +152 -0
  138. package/docs/design/SeeChange.dc.html +267 -0
  139. package/docs/design/Uses.dc.html +12 -6
  140. package/docs/design/canvas.json +146 -19
  141. package/docs/design.md +449 -16
  142. package/docs/environment.md +0 -1
  143. package/docs/evals/curation-effect.md +128 -0
  144. package/docs/http-api.md +459 -37
  145. package/docs/mcp.md +146 -18
  146. package/docs/node-types.md +58 -3
  147. package/docs/plans/design-gaps-2026-10-08.md +53 -0
  148. package/docs/plans/plan-009-tech-debt-backlog.md +379 -0
  149. package/docs/plans/plan-016-context-made-visible-wave-1.md +150 -5
  150. package/docs/plans/plan-017-knowledge-categories-and-lifecycle.md +175 -0
  151. package/docs/plans/plan-018-connected-memory-wave-2.md +594 -0
  152. package/docs/plans/plan-019-post-0.9-roadmap.md +198 -0
  153. package/docs/product-context-vision-2026-09.md +17 -1
  154. package/docs/product-vision-2026-09.md +1082 -43
  155. package/docs/product-vision-review-2026-09.md +13 -1
  156. package/docs/screenshots/workbench-live-dark.png +0 -0
  157. package/docs/screenshots/workbench-live-light.png +0 -0
  158. package/docs/sdk.md +62 -2
  159. package/package.json +1 -1
  160. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
  161. package/plugins/pmx-canvas/plugin.json +1 -1
  162. package/plugins/pmx-canvas/runtime.json +1 -1
  163. package/plugins/pmx-canvas/tools.json +601 -22
  164. package/skills/pmx-canvas/SKILL.md +216 -42
  165. package/skills/pmx-canvas/references/full-reference.md +120 -21
  166. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
  167. package/skills/pmx-canvas/references/importing-context.md +132 -0
  168. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  169. package/skills/pmx-canvas/references/tours-and-recording.md +16 -1
  170. package/skills/pmx-canvas-testing/SKILL.md +20 -0
  171. package/src/cli/agent.ts +2 -0
  172. package/src/cli/commands/ax.ts +12 -0
  173. package/src/cli/commands/boards.ts +87 -11
  174. package/src/cli/commands/edges.ts +28 -0
  175. package/src/cli/commands/groups.ts +7 -0
  176. package/src/cli/commands/nodes.ts +1 -0
  177. package/src/cli/commands/query.ts +34 -2
  178. package/src/cli/commands/record.ts +199 -48
  179. package/src/cli/index.ts +6 -1
  180. package/src/client/App.tsx +177 -70
  181. package/src/client/canvas/AttentionHistory.tsx +0 -2
  182. package/src/client/canvas/BarHint.tsx +40 -2
  183. package/src/client/canvas/BoardCopyDialog.tsx +1 -1
  184. package/src/client/canvas/BoardFolderDialog.tsx +7 -7
  185. package/src/client/canvas/BoardLinkDialog.tsx +138 -33
  186. package/src/client/canvas/BoardPinButton.tsx +33 -0
  187. package/src/client/canvas/BoardSwitcher.tsx +26 -40
  188. package/src/client/canvas/CanvasNode.tsx +360 -237
  189. package/src/client/canvas/CanvasViewport.tsx +45 -7
  190. package/src/client/canvas/CommandBar.tsx +29 -23
  191. package/src/client/canvas/CommandPalette.tsx +5 -12
  192. package/src/client/canvas/ConnectionBanner.tsx +3 -3
  193. package/src/client/canvas/ContextChip.tsx +296 -0
  194. package/src/client/canvas/ContextMenu.tsx +63 -5
  195. package/src/client/canvas/CrossBoardReferences.tsx +60 -0
  196. package/src/client/canvas/EdgeLayer.tsx +339 -76
  197. package/src/client/canvas/EmptyState.tsx +33 -18
  198. package/src/client/canvas/ExpandedNodeOverlay.tsx +72 -40
  199. package/src/client/canvas/ExternalWriters.tsx +57 -42
  200. package/src/client/canvas/HomeGraphView.tsx +942 -0
  201. package/src/client/canvas/HomeMapView.tsx +641 -0
  202. package/src/client/canvas/HomeReviewView.tsx +167 -0
  203. package/src/client/canvas/HomeView.tsx +687 -160
  204. package/src/client/canvas/IntentLayer.tsx +19 -12
  205. package/src/client/canvas/KnowledgeDialog.tsx +488 -0
  206. package/src/client/canvas/LifecycleChrome.tsx +133 -0
  207. package/src/client/canvas/LifecycleFields.tsx +91 -0
  208. package/src/client/canvas/LifecyclePanel.tsx +533 -0
  209. package/src/client/canvas/MemoryInspector.tsx +104 -0
  210. package/src/client/canvas/Minimap.tsx +3 -3
  211. package/src/client/canvas/NearPinLayer.tsx +187 -0
  212. package/src/client/canvas/NodeContextMark.tsx +175 -97
  213. package/src/client/canvas/Presentation.tsx +23 -57
  214. package/src/client/canvas/RelationPresetsDialog.tsx +413 -0
  215. package/src/client/canvas/RelationsPanel.tsx +82 -0
  216. package/src/client/canvas/SelectionBar.tsx +3 -6
  217. package/src/client/canvas/SessionPanel.tsx +90 -50
  218. package/src/client/canvas/SessionReceipt.tsx +311 -39
  219. package/src/client/canvas/ShortcutOverlay.tsx +1 -1
  220. package/src/client/canvas/SnapshotPanel.tsx +27 -36
  221. package/src/client/canvas/ToolRail.tsx +367 -192
  222. package/src/client/canvas/TopBar.tsx +354 -124
  223. package/src/client/canvas/canvas-area.ts +10 -3
  224. package/src/client/canvas/graph-geometry.ts +195 -0
  225. package/src/client/canvas/graph-model.ts +254 -0
  226. package/src/client/canvas/memory-layout.ts +106 -0
  227. package/src/client/canvas/use-chrome-height.ts +20 -0
  228. package/src/client/canvas/use-focus-trap.ts +31 -5
  229. package/src/client/canvas/use-memory-graph.ts +58 -0
  230. package/src/client/canvas/use-node-drag.ts +2 -1
  231. package/src/client/canvas/use-pan-zoom.ts +64 -7
  232. package/src/client/icons.tsx +0 -63
  233. package/src/client/mcp-app/style.css +0 -6
  234. package/src/client/nodes/AxStepControls.tsx +74 -50
  235. package/src/client/nodes/BoardNode.tsx +5 -1
  236. package/src/client/nodes/ContextNode.tsx +18 -11
  237. package/src/client/nodes/ExtAppFrame.tsx +0 -1
  238. package/src/client/nodes/FileNode.tsx +46 -42
  239. package/src/client/nodes/HtmlNode.tsx +32 -0
  240. package/src/client/nodes/ImageNode.tsx +1 -1
  241. package/src/client/nodes/InlineFormatBar.tsx +6 -9
  242. package/src/client/nodes/InlineMarkdownEditor.tsx +56 -17
  243. package/src/client/nodes/MarkdownNode.tsx +377 -109
  244. package/src/client/nodes/McpAppNode.tsx +50 -20
  245. package/src/client/nodes/MdFormatBar.tsx +21 -18
  246. package/src/client/nodes/PromptNode.tsx +1 -1
  247. package/src/client/nodes/ResponseNode.tsx +1 -1
  248. package/src/client/nodes/viewer-runtime-state.ts +54 -22
  249. package/src/client/state/attention-bridge.ts +64 -15
  250. package/src/client/state/boards-store.ts +193 -39
  251. package/src/client/state/canvas-store.ts +99 -12
  252. package/src/client/state/context-chip-store.ts +70 -0
  253. package/src/client/state/context-status-store.ts +53 -0
  254. package/src/client/state/intent-bridge.ts +51 -30
  255. package/src/client/state/knowledge-store.ts +43 -0
  256. package/src/client/state/near-pin-store.ts +115 -6
  257. package/src/client/state/presence-store.ts +7 -10
  258. package/src/client/state/presentation.ts +91 -0
  259. package/src/client/state/relation-store.ts +81 -0
  260. package/src/client/state/session-store.ts +144 -18
  261. package/src/client/state/sse-bridge.ts +206 -29
  262. package/src/client/state/workspace-settings.ts +11 -0
  263. package/src/client/theme/global.css +2724 -476
  264. package/src/client/types.ts +12 -0
  265. package/src/client/utils/keyboard.ts +10 -0
  266. package/src/client/utils/time-ago.ts +14 -0
  267. package/src/json-render/renderer/index.tsx +31 -0
  268. package/src/mcp/canvas-app.ts +12 -2
  269. package/src/mcp/context-uri-template.ts +7 -4
  270. package/src/mcp/server.ts +63 -41
  271. package/src/mcp/workbench-app.ts +39 -6
  272. package/src/server/agent-presence.ts +128 -28
  273. package/src/server/ax-context.ts +27 -13
  274. package/src/server/board-export.ts +12 -1
  275. package/src/server/canvas-db.ts +331 -42
  276. package/src/server/canvas-operations.ts +195 -83
  277. package/src/server/canvas-provenance.ts +53 -22
  278. package/src/server/canvas-serialization.ts +2 -0
  279. package/src/server/canvas-state.ts +950 -122
  280. package/src/server/canvas-validation.ts +9 -2
  281. package/src/server/context-brief.ts +345 -38
  282. package/src/server/context-reads.ts +178 -30
  283. package/src/server/demo-state.json +355 -24
  284. package/src/server/edit-summary.ts +74 -0
  285. package/src/server/html-surface.ts +8 -1
  286. package/src/server/index.ts +181 -11
  287. package/src/server/knowledge-lifecycle.ts +304 -0
  288. package/src/server/lifecycle-status.ts +232 -0
  289. package/src/server/memory-graph.ts +166 -0
  290. package/src/server/mutation-history.ts +18 -6
  291. package/src/server/operations/composites.ts +32 -11
  292. package/src/server/operations/http.ts +7 -2
  293. package/src/server/operations/index.ts +4 -0
  294. package/src/server/operations/mcp.ts +26 -1
  295. package/src/server/operations/ops/ax-presence.ts +1 -1
  296. package/src/server/operations/ops/ax-read.ts +57 -6
  297. package/src/server/operations/ops/ax-timeline.ts +28 -2
  298. package/src/server/operations/ops/backup.ts +5 -3
  299. package/src/server/operations/ops/batch.ts +35 -4
  300. package/src/server/operations/ops/boards.ts +188 -47
  301. package/src/server/operations/ops/canvas-wire.ts +31 -1
  302. package/src/server/operations/ops/edges.ts +36 -2
  303. package/src/server/operations/ops/groups.ts +6 -1
  304. package/src/server/operations/ops/lifecycle.ts +262 -0
  305. package/src/server/operations/ops/memory-graph.ts +45 -0
  306. package/src/server/operations/ops/nodes.ts +107 -24
  307. package/src/server/operations/ops/query.ts +281 -68
  308. package/src/server/operations/ops/snapshots.ts +73 -1
  309. package/src/server/operations/ops/validate.ts +5 -1
  310. package/src/server/operations/ops/viewport.ts +97 -3
  311. package/src/server/operations/registry.ts +74 -25
  312. package/src/server/placement.ts +29 -0
  313. package/src/server/scope-fence.ts +78 -6
  314. package/src/server/server.ts +115 -16
  315. package/src/server/spatial-analysis.ts +48 -23
  316. package/src/server/tour-control.ts +82 -0
  317. package/src/server/wiki-links.ts +137 -0
  318. package/src/server/workbench-auth.ts +11 -0
  319. package/src/shared/agent-context.ts +3 -0
  320. package/src/shared/agent-presence.ts +15 -15
  321. package/src/shared/auto-arrange.ts +2 -0
  322. package/src/shared/boards.ts +4 -4
  323. package/src/shared/knowledge-lifecycle.ts +22 -0
  324. package/src/shared/knowledge-presets.ts +80 -0
  325. package/src/shared/lifecycle-status.ts +26 -0
  326. package/src/shared/memory-graph.ts +74 -0
  327. package/src/shared/relations.ts +98 -0
  328. package/src/shared/semantic-attention.ts +15 -1
  329. package/src/shared/tour.ts +23 -5
  330. package/src/shared/workspace-settings.ts +13 -0
  331. package/dist/types/client/canvas/ContextPinBar.d.ts +0 -1
  332. package/dist/types/client/canvas/FocusFieldLayer.d.ts +0 -1
  333. package/dist/types/client/canvas/kind-colors.d.ts +0 -3
  334. package/dist/types/server/agent-context.d.ts +0 -22
  335. package/src/client/canvas/ContextPinBar.tsx +0 -25
@@ -1,29 +1,185 @@
1
1
  # Product Vision — September 2026
2
2
 
3
3
  **Status:** Direction accepted. Decisions are recorded where they were made (2026-09-06, 2026-09-23, 2026-09-24, 2026-09-26); a move not marked decided is still a proposal.
4
- **Date:** 2026-09-05; release scope updated 2026-09-29; ChatGPT plugin decision added 2026-10-03
4
+ **Date:** 2026-09-05; release scope updated 2026-09-29; ChatGPT plugin decision added 2026-10-03; first hosted version direction added 2026-10-10; implementation progress updated 2026-10-13; architecture direction clarified 2026-10-15; post-0.9.0 sequence added 2026-10-19
5
5
  **Scope:** Where `pmx-canvas` should go, what must be fixed now, what to add, what to delete, and what is architecturally wrong. Written against `main` `e17776f6` (clean tree); revised against `561e6ec5` (v0.6.3).
6
6
  **Revisions:** 2026-09-23 (the [vision review](product-vision-review-2026-09.md) folded in; it keeps the reasoning and the full design sketch), 2026-09-24 (gate and reference-surface decisions; promise hardened; measurement split), 2026-09-26 (gate answers become attribution, not a lock; moved to 0.8). Details in git history.
7
7
  **Method:** My own position, drafted first, then stress-tested by a 54-agent panel: four fact-finders, six independent visions from different angles (context engineering, systems, product strategy, rendering, developer experience, minimalism), a merge into 14 moves, three adversarial refuters per move (evidence, feasibility, value), and a completeness critic. Where the panel refuted me, this document says so. Companion: [`product-review-2026-09.md`](product-review-2026-09.md) (the audit).
8
8
 
9
9
  ## Current plan
10
10
 
11
- *One page; the rest of this document is the reasoning and the detail. Updated 2026-09-28. The implementation status below is authoritative for current progress; historical diagnoses and release slots are retained as planning context, not descriptions of today's checkout.*
11
+ *One page; the rest of this document is the reasoning and the detail. Updated 2026-10-19. The implementation status below is authoritative for current progress; historical diagnoses and release slots are retained as planning context, not descriptions of today's checkout.*
12
12
 
13
13
  **The promise.** One board is both the human's durable workspace and the agent's working memory. Agents write boards, humans shape them, boards last, link into a wiki, travel as files and links, and what the human curates is what the agent reads next.
14
14
 
15
- **The bet inside it.** The first half is proven by use: every real board was agent-written and human-kept. The second half, that the board changes what an agent does, has never been observed. The plan tests it early (0.7 measures, 0.8 checks) and says in advance what happens if it fails.
16
-
17
- **Decided:** the fleet layer and every node type stay (2026-09-06); boards are the wiki and the destination is "share this board" (2026-09-23); the workbench is built and checked for any size, from a narrow side pane to a full browser window, checked in Chromium at 600, 1024 and 1920 px, replacing the 2026-09-24 single 600 px reference (2026-10-05); gate answers are open to any writer and record who answered, replacing the 2026-09-24 human-only decision (2026-09-26). Home is a view listing boards, not a board; deleting a board needs an in-page confirm; backup is built in with its own schedule (2026-09-27). Board pins are the working set across boards (2026-10-05, move 0a). A hosted team server separates workspace and personal libraries (2026-10-05, Part 3). Folders are the one browsing hierarchy and links stay a graph for relations (2026-10-06, move 0). Undecided: generated surfaces (6b).
18
-
19
- **Design track, 2026-10-04:** [design.md](design.md) pairs each remaining move with the design that shows it, in waves: a foundation (one font, scale and meaning colours across all themes) first and alone, then context made visible with the curation evaluation, the board map and graph with the wiki work, the relations layer with moves 1 and 13, and the frame host with move 5. A wave is done only when function and design both pass.
15
+ **The bet inside it.** The first half is proven by use: every real board was agent-written and human-kept. The second half, that the board changes what an agent does, has never been observed. Read instrumentation shipped early (0.7); the effect evaluation now comes at the very end of the plan (decided with the maintainer, 2026-10-19), and the plan still says in advance what happens if it fails.
16
+
17
+ **Decided:** the fleet layer and every node type stay (2026-09-06); boards are the wiki and the destination is "share this board" (2026-09-23); the workbench is built and checked for any size, from a narrow side pane to a full browser window, checked in Chromium at 600, 1024 and 1920 px, replacing the 2026-09-24 single 600 px reference (2026-10-05); gate answers are open to any writer and record who answered, replacing the 2026-09-24 human-only decision (2026-09-26). Home is a view listing boards, not a board; deleting a board needs an in-page confirm; backup is built in with its own schedule (2026-09-27). Board pins are the working set across boards (2026-10-05, move 0a). A hosted team server separates workspace and personal libraries (2026-10-05; part of the hosted version, Part 4, since 2026-10-19). Folders are the one browsing hierarchy and links stay a graph for relations (2026-10-06, move 0). Undecided: generated surfaces (6b).
18
+
19
+ **Knowledge direction, 2026-10-07:** The hosted version (Part 4, since 2026-10-19) extends the workspace/personal split to user-defined knowledge scopes (org → team → personal is one example template), with categories as a property of folders. Move 13 adopts evidence-backed context lifecycle from the context-decay framework. Local folder categories and card lifecycle are now implemented in Wave 3. Shared/private knowledge scopes remain future work; Jev-style classification is optional longer-term assistance. These later stages are not prerequisites for the model-independent local features or Wave 1.
20
+
21
+ **Design track, 2026-10-04:** [design.md](design.md) pairs each remaining move with the design that shows it, in waves: a foundation (one font, scale and meaning colours across all themes) first and alone, then context made visible (its curation evaluation moved to plan 019 step 6 on 2026-10-19), the board map and graph with the wiki work, the relations layer with moves 1 and 13, and the frame host with move 5. A wave is done only when function and design both pass.
22
+
23
+ **Wave 1 status, 2026-10-10 — context made visible: built on `main`, not released.** From the board alone a person can now see what is in the agent's context and whether its copy is current: read / not read / changed marks on pinned cards; near-a-pin (the brief carries neighbours, the dotted chip, tethers and the 600 px radius, the moment a card arrives or leaves); links that changed since a read, on the link and in the brief ("new, by codex"); board pins and Home as a library (folder tree, board cards, details, the in-context switch); the session receipt (what the agent did, per-edit descriptions with "See change", Tell <agent>, Undo per card via `snapshot.restore-node`) and the live session lens in the agent chip. Remaining: the curation evaluation, deferred to plan 019 step 6 (2026-10-19); building to the new [SeeChange](design/SeeChange.dc.html) drawing (2026-10-10); the pickup/drop pauses of a drag on large boards (per-frame cost fixed 2026-10-10). Handoff detail in plan 016. **Dropped 2026-10-10:** Suggested cards — the agent changes the canvas directly, and an ask or a suggestion already goes through the composer. Detail and deviations: [plan 016](plans/plan-016-context-made-visible-wave-1.md), [design.md](design.md).
24
+
25
+ **Near cards correction (owner decision, 2026-10-14).** Spatial curation measures
26
+ the gap between card edges, not centres: up to five nearest unpinned cards within
27
+ 600 canvas pixels of each pin. The boundary follows the whole pinned card, and
28
+ the UI and agent context share that geometry. This fixes large-card proximity
29
+ without increasing the distance limit or context cap; it is not a semantic
30
+ relation or evidence of review. This supersedes the centre-based radius above.
31
+
32
+ **Escape selection correction (owner decision, 2026-10-14).** Keyboard Escape
33
+ cancels board selection and relation/review/retired filters, or Home selection
34
+ without leaving its view or resetting the camera. The Review queue clears its
35
+ local filters. Menus and the review drawer close first; editable fields retain
36
+ their drafts. This is implemented in the current acceptance batch, not a release.
37
+ Attached-agent popovers also accept immediate Escape and return focus to the initial
38
+ button without changing the canvas scroll or underlying selection.
39
+
40
+ **Implementation and stabilization, 2026-10-12 (supersedes the remaining-work list above):** See change now
41
+ matches its drawing, and the measured page-wide pickup/drop style cost is removed; occasional
42
+ long drag tasks remain. The maintainer's real-agent curation evaluation is still deferred.
43
+
44
+ - **Wave 2 implemented scope:** saved wiki bindings, qualified cross-board card edges and graph
45
+ reads, plus live Home Map/force-directed Graph with counted filters, focus and navigation
46
+ preserved across agent board switches. Map keeps dragged positions and neutral folder regions.
47
+ - **Wave 3 implemented scope:** richer relations with per-board vocabularies, source/use queries
48
+ and provenance; folder categories and inherited card lifecycle; source-driven review, the due
49
+ engine, evidence-backed review UI, retirement/restore and inert recipe handoff. Acceptance fixes
50
+ include navigation-first Home, safe unused-category deletion, simple Review, conditional nearby
51
+ rings, wrapped relation legends and smooth hover handoff.
52
+ - **Delivered on `main`:** the [combined implementation](https://github.com/pskoett/pmx-canvas/commit/11dc311732d8c12acc86dda12b269539df8fa5b3)
53
+ and [stabilization follow-up](https://github.com/pskoett/pmx-canvas/commit/fd63c3c611e680864d444532ca3ef7bb79cd171e)
54
+ are pushed. Final local gates pass 1,444 unit, 306 client and 276 headed browser tests,
55
+ plus 20 repeated save-race cases, fresh headed CLI E2E, live human gestures and real CLI/stdio
56
+ MCP checks. Independent board vocabularies persist across switching/reload. All five
57
+ [CI jobs](https://github.com/pskoett/pmx-canvas/actions/runs/38218734543) pass, including macOS
58
+ and Windows; the startup-only WAL retry resolves their concurrent-open failures.
59
+
60
+ **Acceptance follow-up, 2026-10-12:** card and relation authorship now lives in hints,
61
+ without redundant violet stars; bare relation lines retain their author hints. Read-state
62
+ marks, pins and the session lens remain independent. Direct HTTP portal polling now wakes
63
+ on events instead of pausing two seconds between replies. Disposable two-client portal
64
+ checks measured about 11 updates/s instead of 0.48/s; the exact authenticated Amp container
65
+ remains a separate owner check. Hosted MCP-app polling remains at two seconds, and SSE is
66
+ unchanged. The same batch fixes older same-tab camera echoes interrupting newer gestures,
67
+ immediate Escape on the shortcut reference, and stale pin replay after Clear all, with
68
+ canonical server reconciliation, retained attention history and board-switch isolation.
69
+ Evidence and failed-run investigations are recorded in [plan 018](plans/plan-018-connected-memory-wave-2.md).
70
+ Final combined local gates pass 1,445 unit, 307 client and 282 headed browser cases, plus
71
+ fresh headed CLI/stdio MCP. Its [CI run](https://github.com/pskoett/pmx-canvas/actions/runs/38302301010)
72
+ passed Linux, macOS, browser E2E and CLI E2E; Windows was cancelled, so this batch is not
73
+ claimed fully cross-platform green. The earlier all-five-jobs CI verifies the preceding delivery.
74
+
75
+ **Owner-selected review surfaces, 2026-10-14 (implemented; owner acceptance pending, not released):**
76
+ C1 is the compact category inspector: a searchable neutral category list, Basics / Review policy /
77
+ Usage tabs, templates behind disclosure, Save/Cancel and a dirty-leave guard. Folder inheritance,
78
+ card lifecycle overrides and assigned-category deletion protections remain unchanged.
79
+ R2 is choose-then-customize: read-only workspace preset preview before a separate editor;
80
+ saving edits the template, and explicit Use on board copies the saved vocabulary to one board.
81
+ Existing edges and other boards remain unchanged; there is no later auto-sync.
82
+ H2 adds a dedicated Home Review tab of individual cards with authoritative card/board titles,
83
+ reasons and last-checked times. Scope is folder plus descendants or whole library; nonretired
84
+ due cards or cards with source warnings count once. Unknown policy alone stays neutral;
85
+ explicit warnings still qualify. Opening a queue item never validates it.
86
+ Owner-approved naming: **Review** in navigation, **Knowledge review** as the page title,
87
+ and **Review card** in the drawer. This checks context reliability, not task completion.
88
+ V2 keeps the real rendered card visible beside a docked review drawer (lower dock when narrow),
89
+ with one check note, Checked, still correct / Not now, and secondary Settings and history.
90
+ Stale content/source guards and dirty Markdown guards protect validation; dismissal writes
91
+ nothing. Read, content, validation and relevance clocks remain separate, and retire/restore are
92
+ audited rather than validation. Canonical drawings and decisions are in [design.md](design.md).
93
+ This selection adds no delivery, release or acceptance-gate claim to the earlier results below.
94
+
95
+ **Owner acceptance alignment, 2026-10-13:** the step-by-step rehearsal exposed toolbar
96
+ crowding with multiple sessions, inert expanded wiki links, narrow Graph control overlap,
97
+ missing Medium cadence validation and stale HTML/graph replacements. The follow-up corrects
98
+ these contracts without treating a manual rehearsal as owner acceptance. Failed attempts and
99
+ the final combined verification belong in [plan 018](plans/plan-018-connected-memory-wave-2.md).
100
+ Relation presets are shared workspace templates in **Home → Relation presets**, alongside
101
+ Categories, not per-board settings. Applying a saved preset copies meaning ink/direction to
102
+ one explicitly chosen board; editing or deleting a template never silently rewrites boards
103
+ or their connections. On a board, the dropdown is only **All relations + kinds actually
104
+ present**, with counts; there is no Custom vocabulary status. Folder categories and card
105
+ lifecycle remain separate from relation kinds. The acceptance guide follows this distinction
106
+ and retains the owner's results and notes. At that checkpoint this was unreleased work
107
+ based on 0.8.2; the current release authorization is recorded below.
108
+ The shared-Home-presets delivery passed 1,446 unit, 307 client and all 289 headed
109
+ browser cases, plus build/typecheck/lint, coverage and fresh headed CLI/stdio MCP.
110
+ Its [exact-commit CI](https://github.com/pskoett/pmx-canvas/actions/runs/38408653667) passed all
111
+ five jobs, including Windows. The fresh numbered rehearsal remains separate: it reproduced
112
+ an expanded-document blur save racing missing-board link creation. That isolated follow-up
113
+ waits for the save before capturing the source; stale-source protection is retained. Its
114
+ verification and integration state are recorded in [plan 018](plans/plan-018-connected-memory-wave-2.md).
115
+ The same rehearsal's extra 390 px check exposed wrapped Graph chrome blocking the filter
116
+ toggle and an external-writer badge crowding the context summary. The follow-up measures
117
+ the toolbar's actual extent and compacts writer text, keeping filtering, activity and context
118
+ reachable without changing their meaning. This does not replace the three reference-width
119
+ gate or establish native-host acceptance.
120
+
121
+ **Still open:** the owner's acceptance of everything since 0.8.2. The real-agent curation
122
+ evaluation moved to the end of the plan on 2026-10-19. Full Relations/Flows/Uses sketch parity is not implemented: inline edge editing,
123
+ amber lineage strokes, pair/cycle/affected badges and lineage actions remain; see
124
+ [the design contract](design.md#build-plan). Dense Fit labels still need selection/local focus
125
+ for detail. The actual Amp embedded context-pill opening, native Copilot/WebKit, native Windows
126
+ UI and registry-installed execution remain unverified. Frame-host consolidation, larger-library
127
+ scaling, board-move/audit semantics and the journal/runtime boundaries remain staged maintenance
128
+ checkpoints, not claims of a debt-free codebase. Evidence and deviations are recorded in
129
+ [plan 017](plans/plan-017-knowledge-categories-and-lifecycle.md) and
130
+ [plan 018](plans/plan-018-connected-memory-wave-2.md).
131
+
132
+ **Relation-navigation direction, 2026-10-13:** prioritize focused relationship reads and
133
+ the change → impact → evidence → review loop over additional presets or decorative graph
134
+ features. Improve authored meaning alongside this work and reuse the same semantics for
135
+ small-chain human navigation. See [the priorities and acceptance checks below](#relation-navigation-priorities).
136
+ This extends moves 0, 1 and 13; it is future direction, not newly delivered functionality
137
+ or a replacement for owner acceptance.
138
+
139
+ **MCP work relative to this checkpoint (2026-10-12).** The improvements below are
140
+ planned, not part of the delivered Waves 1–3 or new prerequisites for their acceptance.
141
+ Keep owner acceptance as the current focus. After 0.9.0 and its cleanup release, MCP
142
+ hardening is the next batch ([plan 019](plans/plan-019-post-0.9-roadmap.md)): structured results and accurate tool annotations first, then cancellation/progress
143
+ and subscription-aware context delivery (moves 6a and 1). Reuse the existing board,
144
+ revision and context-read contracts; a concrete delivery bug found during acceptance
145
+ can be fixed narrowly without pulling the whole batch forward. ChatGPT native-composer
146
+ validation and SDK v2 evaluation stay in Part 4, which now carries the team/access work;
147
+ the optional PMX session connection stays a Part 5 decision. No release number is assigned.
148
+
149
+ **Release status, 2026-10-22:** the owner authorized review, testing and release of
150
+ 0.9.0 with the acceptance fixes. The release gates still apply; green CI does not
151
+ certify the remaining native-host checks or deferred vision work.
152
+
153
+ **After 0.9.0 (decided with the maintainer, 2026-10-19).** The sequence is: a cleanup release
154
+ (tour debt, large-board costs, the bounded due evaluator), MCP hardening (moves 6a and 1),
155
+ the frame host with the Wave-0 design pass (moves 5 and 9), then Wave 5 with the remaining
156
+ relations sketch parity (moves 3 and 0), then trust and the journal. **All account and team
157
+ work belongs to the hosted version (Part 4):** the read-only share link, comments, a second
158
+ writer, accounts, roles and knowledge scopes. Local PMX stays single-user, and static export is
159
+ its sharing path. Build that work once in the shared product so it serves the ChatGPT Sites
160
+ version first and the standalone Cloudflare version (Part 5) later.
161
+ **Evaluations come at the very end for now:** the curation-effect benchmark and its
162
+ per-release reruns no longer precede or gate any of this work. Read instrumentation and the
163
+ release gates in [RELEASE.md](RELEASE.md) are unchanged. This supersedes every statement
164
+ below that puts the curation evaluation first. **Accepted risk:** several releases will build
165
+ on the curation claim before the effect is measured; the decision is to carry that risk rather
166
+ than reinstate an earlier gate. Detail and acceptance checks:
167
+ [plan 019](plans/plan-019-post-0.9-roadmap.md).
168
+
169
+ **Architecture clarification, 2026-10-15:** the architecture reviews strengthen the existing
170
+ shared-product/separate-runtime direction, not a microservice split. Moves 4, 6 and 7 now
171
+ spell out commit guarantees, writer-policy parity and authenticated authority; the
172
+ [runtime direction](#likely-repository-structure-shared-product-separate-runtimes) defines
173
+ ownership and shared contracts. These are future requirements, not implemented guarantees.
174
+ Owner acceptance remains first; fix demonstrated defects narrowly,
175
+ then prove the boundaries through a complete slice before moving packages or porting broadly.
20
176
 
21
177
  **Document import, updated 2026-09-28:** the agent-assisted v1 is implemented and verified on `main` (move 15): attach an original, explicitly request agent processing, review the returned Markdown, then add it to the board. Simple PDF, PPTX and XLSX fixtures were verified with Amp's tools. Canvas bundles no converter or OCR, does not launch an agent automatically, and does not guarantee general format fidelity.
22
178
 
23
179
  | Release scope | Content | Acceptance target (not a completion claim) |
24
180
  |---|---|---|
25
181
  | 0.7.0 — persistent boards and connected memory | Many boards, nested folders, backups, static export, README/link cards, library search, shared card text, attribution/revisions, selective copies, bounded cross-board context, agent-assisted document import, trust fixes and the 600 px gate | Release checks, installed-package smoke, browser workflows and live board checks pass; document conversion limitations and migration are explicit |
26
- | Next batch — scope/version to be agreed | Remaining wiki/graph work and real-agent curation evaluation; cheap-tool surface and binary distribution remain candidates, not completed work | A focused plan with its own acceptance checks; no automatic carry-over of the old 0.8 bundle |
182
+ | After 0.9.0: versions proposed in [plan 019](plans/plan-019-post-0.9-roadmap.md) | Cleanup, MCP hardening, frame host and Wave-0 design pass, Wave 5 with relations sketch parity, then trust and journal; the share link ships with the hosted version; the curation evaluation last | Each release ends on plan 019's checks and explicit release approval; no automatic carry-over of the old 0.8 bundle |
27
183
 
28
184
  **Release decision, 2026-09-29:** package the completed batch as **0.7.0**, not
29
185
  0.8. Static export and the connected-memory features move into this release;
@@ -46,6 +202,17 @@ and its fixes as groundwork; pause further full-plugin release work. This is a
46
202
  sequencing decision, not authorization to build or launch hosted PMX now, and it
47
203
  does not change local PMX Canvas's existing distribution.
48
204
 
205
+ **Hosted direction, 2026-10-10 (revised 2026-10-19: accounts and team features are built in
206
+ the hosted version, not before it):** the first hosted version targets ChatGPT Sites with OpenAI login and the MCP server hosted
207
+ there too. This is the first product validation, with the ChatGPT plugin as its
208
+ distribution channel. If it works and people adopt it for recurring work, the
209
+ next ambition is a full PMX Canvas service hosted directly on Cloudflare
210
+ (Part 5). Access by other agents through OAuth using their user's OpenAI login
211
+ remains a target. Sites login and its ChatGPT/Codex MCP plugin are documented;
212
+ arbitrary external-client OAuth remains a separate validation gate. See Part 4
213
+ for the live probe's discovery/registration blockers, node compatibility
214
+ assessment and acceptance targets.
215
+
49
216
  **Hold the line.** No host-compatibility work jumps the queue until 0.7 ships, with two exceptions: regressions the reference project catches, and a bug that blocks the maintainer's real work in the host they use daily (today the Copilot app, a WebKit pane the Chromium reference does not cover). The second exception is narrow on purpose: it covers a board that cannot be used, not a tile that paints late or a host the maintainer is only testing.
50
217
 
51
218
  ## The one-line vision
@@ -54,9 +221,9 @@ does not change local PMX Canvas's existing distribution.
54
221
 
55
222
  > **Think with your agents on boards that are still there next week.** Every session lands on a named board, the boards link into a wiki you can see as a map, the agent reads what you curated, and you can share or present a board with anyone.
56
223
 
57
- **Both halves, and which one is the bet.** The board being the human's durable workspace, written by agents, is proven: every real board was agent-written from the maintainer's prompts and then shaped, pinned, presented and returned to. The board being the agent's working memory, read and acted on, is a hypothesis: nothing yet shows an agent reading the board and behaving differently because of it, canvas steering has gone quiet, and the conversation lives in the host's chat. The vision holds both as one loop, so it has to prove the second half rather than let it ride on the first. Two things make that possible. Every node type needs a text form that carries its meaning, because a board that is rich for a human (decks, charts, drawings) is nearly opaque to an agent otherwise (move 1). And the loop is measured, with a rule decided in advance (Part 1, item 4).
224
+ **Both halves, and which one is the bet.** The board being the human's durable workspace, written by agents, is proven: every real board was agent-written from the maintainer's prompts and then shaped, pinned, presented and returned to. The board being the agent's working memory, read and acted on, is a hypothesis: nothing yet shows an agent reading the board and behaving differently because of it, canvas steering has gone quiet, and the conversation lives in the host's chat. The vision holds both as one loop, so it has to prove the second half rather than let it ride on the first. Two things make that possible. Every node type needs a text form that carries its meaning, because a board that is rich for a human (decks, charts, drawings) is nearly opaque to an agent otherwise (move 1). And the loop is measured release by release, with a fixed benchmark (Part 1, item 4).
58
225
 
59
- Human attention helps select the agent's context; it does not define the whole product. Explicit steering directs agents; annotations, pins, connections, and grouping inform relevance, while spatial layout and human camera attention can contribute weaker cues. The server compiles one budgeted brief for every agent turn. Everything the agent has to say to the human is a card on the board, never a row in a side table. The board owns its own store and its own history, and reaches remote agents through its own authenticated network mode. One journal records every write by either side, so time on the board can be scrubbed like a video. In the long run a board is shared: first as an exported file, then as a link, then with comments and a second writer. That is the destination, not hosted multi-tenant multiplayer (Part 3).
226
+ Human attention helps select the agent's context; it does not define the whole product. Explicit steering directs agents; annotations, pins, connections, and grouping inform relevance, while spatial layout and human camera attention can contribute weaker cues. The server compiles one brief for every agent turn, paged so it never floods a host. Everything the agent has to say to the human is a card on the board, never a row in a side table. The board owns its own store and its own history, and reaches remote agents through its own authenticated network mode. One journal records every write by either side, so time on the board can be scrubbed like a video. In the long run a board is shared: first as an exported file, then as a link, then with comments and a second writer. Export is local (Part 3); since 2026-10-19 the link, comments and a second writer are built in the hosted version (Part 4).
60
227
 
61
228
  **Purpose clarification:** pmx-canvas supports **knowledge work broadly**, including research, analysis, dashboards, planning, discovery, coordination, and orchestrating coding or other work. These are examples, not a closed list or a coding-only boundary. Its promise is to help humans and agents do the work, carry useful understanding into the next task, and see known changes and uncertainty in the context they use. The [companion vision](product-context-vision-2026-09.md#position) explored a separate memory graph and wiki; as of 2026-09-23 that role is played by the boards themselves (move 0), and its publication and audience guidance waits until sharing reaches a second writer. Contributing to memory does not automatically make every item a confirmed fact or shared organizational knowledge; attention does not grant approval or sharing permission.
62
229
 
@@ -74,7 +241,7 @@ This scope supersedes the original 0.7/0.7.x/0.8 split.
74
241
  | Connected boards (moves 0, 14) | README designation, text-only board-link cards, backlinks, library search, selective inactive board copies | Wiki syntax, board map, direct cross-board card edges, make-board/inline-board gestures remain planned |
75
242
  | Agent context (Part 1, move 1) | Shared per-type card text, persisted authorship/content revisions, bounded linked/same-folder context, opt-in durable consumer cursors, read instrumentation | Controlled retrieval checks are not the real-agent evaluation of whether curation improves outcomes; the full proposed ranker is not complete |
76
243
  | Trust (move 7) | Refused-write toasts, redirect filtering, workbench-token attribution and attributed ask answers including self-answers | Local attribution is not proof of human intent; per-writer remote authentication/sharing remains planned |
77
- | Sharing and presentation (moves 11, 12) | Static HTML export with explicit content choices; tours shipped in 0.6.5 | Read-only live share links remain planned; a colleague's use is a separate milestone from browser tests |
244
+ | Sharing and presentation (moves 11, 12) | Static HTML export with explicit content choices; tours shipped in 0.6.5 | Read-only live share links ship with the hosted version (Part 4, decided 2026-10-19); a colleague's use is a separate milestone from browser tests |
78
245
  | Document context (move 15) | Original attachments, explicit processing consent, agent draft/review/commit, source-linked searchable Markdown, cancellation, retention and export privacy | Extraction depends on host tools; no bundled converter, OCR or general chart/formula fidelity guarantee |
79
246
  | Pane UX (moves 5, 9) | Chromium 600 px reference gate and Home folder polish | Unified frame host, frame budget and broader renderer consolidation remain planned |
80
247
 
@@ -137,14 +304,14 @@ What still holds from the test boards: steering is the most exercised human verb
137
304
 
138
305
  Move 0 comes first, so real boards stop being overwritten. Then three changes that everything in Part 2 stands on (items 1, 3 and 4), each worth shipping on its own, and one that waits (item 2).
139
306
 
140
- 1. **One read.** `canvas://context?budget=N` is the only thing an agent reads per turn: pinned nodes first, then what changed since this consumer's last read (a stable seq cursor), then human-authored nodes, then open asks and undelivered steers for this consumer, then boards pinned on the board map and boards one link away (move 0), each as its README summary and pinned card titles. Finished work-item chatter, delivered steers and system notes never enter it; decisions and outcomes do, including those on past boards, because a completed decision can be the most important context a month later. Everything else stays reachable by explicit pull. It folds 10 of 14 resources into the one read and turns spatial analysis (clusters, neighborhoods, reading order) into an input to the ranker rather than a separate resource.
307
+ 1. **One read.** `canvas://context?budget=N` is the only thing an agent reads per turn, and since 2026-10-07 it is a map, not a dump: titles, short summaries and relations, the local neighbourhood of the relation graph (move 0), from which the agent pulls what it decides to read in full. It carries pinned nodes first, then what changed since this consumer's last read (a stable seq cursor), then human-authored nodes, then open asks and undelivered steers for this consumer, then boards pinned on the board map and boards one link away (move 0), each as its README summary and pinned card titles. Finished work-item chatter, delivered steers and system notes never enter it; decisions and outcomes do, including those on past boards, because a completed decision can be the most important context a month later. Everything else stays reachable by explicit pull. It folds 10 of 14 resources into the one read and turns spatial analysis (clusters, neighborhoods, reading order) into an input to the ranker rather than a separate resource. **The human sees a cost, not a budget (decided with the maintainer 2026-10-08):** the context summary shows what the brief costs in tokens, and the host's own count of the agent's whole context when an adapter reports it. There is no share, meter or clipped warning; `budget` is an internal page size, and a brief longer than one page continues on the next read.
141
308
  2. **The board fills itself (later, opt-in).** Scheduled after 1.0 and off by default: files, diffs and test output fit coding sessions, not PM boards, so a board opts in and the projection lands collapsed. Nobody on the panel proposed this and it is the cheapest radical move available: stop requiring the agent to remember to call `canvas_node`. A Claude Code hook, the Copilot extension and the Codex heartbeat project the session onto the board, meaning files touched, diffs, test output and the plan, into a session lane the human then curates from abundance. Today a node exists only when an agent decides to write one.
142
309
  3. **Author on every node.** The `nodes` table has no writer column. Source provenance is persisted in node data (`canvas-provenance.ts`: where the content came from and how it refreshes), but who wrote a node lives only in the in-memory mutation history, which dies on restart. Add `author`, human or agent id, beside the existing provenance rather than as a second provenance system. The compiler ranks human-written above agent-written, the board can show who wrote what, and a shared board needs it later anyway.
143
310
  4. **Measure the thesis.** Until this exists, "pins shape the agent's context" is a belief, not a finding. Two questions, measured separately because they fail for different reasons:
144
311
  - **Delivery: does the brief reach the agent?** Record which resources each agent session reads and whether the pinned nodes were in what it read, per host. A miss here is plumbing (the skill, an adapter's per-prompt injection, the MCP client), and the answer is to fix the adapter, not to doubt the thesis.
145
312
  - **Effect: when it arrives, does curation change the work?** One fixed eval under `docs/evals/`: the same task, with the brief delivered, on a curated and an uncurated board, scored on criteria written before the first run. With one real user, real sessions cannot carry statistical weight; the eval is the test, and real sessions only confirm or contradict it.
146
313
 
147
- The decision rule, set now so the result cannot be argued away later: only a failure on effect changes course. If the curated board does not beat the uncurated one once delivery is confirmed, the vision says so, stops investing in attention ranking and the brief beyond what already ships, and puts that effort into the human side (the wiki, sharing, tours). If it does, the brief becomes the product's headline and the attention heat (the payoff section) moves forward.
314
+ **Continuous improvement, not a verdict (decided 2026-10-07; evaluation rule corrected with the maintainer 2026-10-10).** The eval ([curation-effect](evals/curation-effect.md)) is a benchmark rerun on every release that touches the brief, pins, budgets or adapters. Track absolute answer quality on both curated and uncurated boards, delivery reliability and retrieval cost. The curation gap (curated minus uncurated score) diagnoses the contribution of curation; it is not a target to maximise. Better uncurated answers can narrow the gap without regression, and worse uncurated answers can widen it without improvement. Investigate repeatable quality or cost regressions under comparable conditions and fix broken delivery; three runs per condition are diagnostic, not a statistical release gate. Each lost rubric line feeds the improvement backlog. This replaces the 2026-09 one-off decision rule and the later gap-growth requirement. **Moved to the end, 2026-10-19:** the effect eval and its reruns wait until the end of the plan; the delivery half (read instrumentation) stays.
148
315
 
149
316
  ## Part 2: The shape I believe in
150
317
 
@@ -160,30 +327,127 @@ The move the evidence demands before any other. A workspace holds many named boa
160
327
  - **Home and levels (superseded by the line above for the tree; links unchanged).** *Revised 2026-09-27: Home is not a board but the view shown when no board is open, listing your boards most recent first and filed in categories the human (or an agent) assigns ([plan 012](plans/plan-012-many-boards-stage-1.md)); boards no portal links to form the top level. Categories are the library's first human-made structure, so the cross-board brief (Part 1, item 1) should rank boards in the open board's category above the rest.* Originally: Home is the board a workspace opens on (level 0). A **portal**, a new `board` node type, is a card that stands for another board, and a board's level is its shortest distance from Home through portals. Levels are derived, never stored; there are no fixed tiers; a board may sit under several parents; cycles are allowed; boards no portal reaches appear in an "Unplaced" lane.
161
328
  - **Links.** Portals, plus `[[Board]]` and `[[Board#Card]]` in markdown cards, resolved to ids on save so renames do not break them. Unresolved links offer "Create board"; every board lists its backlinks. Portals render text only (title, README summary, last touched, pinned card titles), never a live board, so nesting cannot multiply iframes.
162
329
  - **The board map is a board.** A generated board of boards and links, built like the code graph (`boardmap-` auto-edges, out of history, debounced), with positions the human drags kept. Pinning a board on the map pulls it into the brief (Part 1, item 1). Map pins are workspace-level: they belong to the library, not to the map board, so they feed the brief whichever board is active. It is called the board map to avoid confusion with the `graph` chart node type.
330
+ - **A changed connection is marked on the connection (decided with the maintainer 2026-10-08, option C of [LinksOptions](design/LinksOptions.dc.html)).** Text and links are tracked apart per card. A link a person adds or edits says "not seen by <agent>" on its pill until a brief carries either end; a link an agent drew says "by <agent>". The agent is whichever agent is attached (Claude, Codex, Copilot or any other), never a fixed name. Cards keep their read marks; only a text change is amber ("changed"), and the context panel lists "links changed" in neutral. A link change still reaches the next brief through the card's links revision.
331
+ - **One relation graph, two readers (decided with the maintainer 2026-10-07).** The canvas is the agent's extended memory across cards and boards, so the relations are one projection with two readers. Its nodes are boards and cards; its edges are portals and `[[links]]`, card edges and cross-board card links, with folder membership for grouping. Home's Graph view ([HomeGraph](design/HomeGraph.dc.html)) draws it for the human, with what is in the agent's context marked and a "local graph, depth N" around the focus. The agent reads the same projection as `canvas://graph{?focus,depth}`: the local graph around a board, a card or the pins, each node with its title, short summary and in-context mark, and ids that `canvas_node`/`canvas_board` pull in full. The brief (Part 1, item 1) is this graph's depth-1 neighbourhood of the open board and its pins; the agent walks further through `canvas://graph` and decides what to read. One projection, built like the code graph, so what the human sees and what the agent navigates cannot drift. Ships with wave 2's Map and Graph.
332
+
333
+ **Shared settings, local filters (decided 2026-10-13).** Relation presets belong to the
334
+ workspace's Home library, like Categories. They are editable templates, not classifications
335
+ assigned to cards and not board filter options. Explicit application copies a template's
336
+ vocabulary onto a chosen board without changing existing relation kinds or reasons. Each
337
+ board's dropdown lists its actual relation kinds and only changes the view. Unclassified
338
+ lifecycle stays unknown; it does not create a Custom vocabulary category or badge.
163
339
  - **Growth by gesture.** "Make board" turns a group into a board and leaves a portal; "Inline board" reverses it. Group, board and board of boards are one scale.
340
+ **Wave 5 maintenance checkpoint (2026-10-11):** define how board-qualified relations,
341
+ provenance and review records move before implementing these gestures. Moving a card must
342
+ preserve its outside links and audit identity; copying a claim must not invent a validation.
164
343
  - **Search across boards.** The ⌘K palette searches the whole library, not just the open board: board names, README summaries, card titles and card text, with the board each hit lives on. A wiki a human cannot search is a pile; the agent's `canvas_query` search gains the same library scope.
165
344
  - **Backup.** Once boards are the wiki, `canvas.db` holds the whole library, its history and its snapshots in one file. `pmx-canvas backup` writes a consistent copy (`VACUUM INTO`, safe while the server runs) to a folder the human chooses, keeps the last N, and runs on a schedule the human sets; `pmx-canvas restore` brings one back. It is a local file, so the no-externals rule holds. The per-board folder export in move 4 is the human-readable companion, not a substitute.
166
- - **Agent surface.** `canvas://boards` (the library: README summary, folder, links, backlinks, last touched; levels dropped 2026-10-06), a `board` target on every operation with the MCP session bound to one board, and a `canvas_board` composite (22 → 23 tools, with the freeze test and all four transports updated together).
345
+ - **Agent surface.** `canvas://boards` (the library: README summary, folder, links, backlinks, last touched; levels dropped 2026-10-06), `canvas://graph{?focus,depth}` (the relation graph above, local around a focus), a `board` target on every operation with the MCP session bound to one board, and a `canvas_board` composite (22 → 23 tools, with the freeze test and all four transports updated together).
167
346
  - **Data.** A `boards` table, `board_id` on nodes, edges, annotations, pins and snapshots, and a `board_links` projection rebuilt from portals and parsed links. The README summary is a flagged card, not a field.
168
347
  - **State, in two stages.** Stage 1 (M, not S: `board_id` on five tables, snapshots scoped per board, a `board` target on every transport): one active board per server; opening a board saves and loads; other boards are read straight from SQLite; agent writes to a non-active board are refused. Only the human changes the active board, so an agent never swaps the board the human is looking at: an agent may create a board, its session binds to whichever board is active when it starts, and a session that needs another board asks for the switch with an ask card. Stage 2 (L): state managers keyed by board, after the journal, so an agent can work on one board while the human looks at another. `CanvasStateManager` is a singleton with 400+ call sites, which is why stage 2 waits.
169
348
 
170
349
  Objection: none, the panel did not see it. Risk: the wiki sprawls. Mitigation: the Unplaced lane and staleness on the map (move 13) make neglect visible instead of silent.
171
350
 
351
+ #### Relation-navigation priorities
352
+
353
+ **Direction added at the maintainer's request, 2026-10-13, with Oracle review.** The
354
+ numbered acceptance rehearsal found useful one/two-hop context, stable cross-board identity,
355
+ Sources / Used by and source-driven review. These are foundations to improve, not absent
356
+ capabilities. Dense Fit labels and manually reconstructing affected chains remain limits.
357
+ The next investment is one working loop, not four new subsystems:
358
+
359
+ 1. **Focused relationship reads first.** Answer “What does this conclusion depend on?”
360
+ and “What uses this source?” with explanatory paths, recorded reasons, summaries and
361
+ review qualification, using board-qualified identities. Distinguish dependencies and
362
+ derivations from citations, wiki/portal navigation and board/folder membership. Include
363
+ recorded provenance sources as well as drawn relations, without inventing an authored
364
+ edge or reason. A custom label, colour or decorative arrow does not establish impact
365
+ semantics. State direction, scope, result bounds, omissions and how to continue; “no
366
+ recorded dependency” is different from “none found within this scope.” Summaries remain
367
+ discovery, not full reads or validation. Build on the existing graph and brief rather
368
+ than creating a parallel knowledge store.
369
+ 2. **Make change → impact → evidence → review the success scenario.** Show which
370
+ conclusions a changed source affects and why, open the relevant evidence, and record
371
+ deliberate per-card review or deferral. Reuse source-driven qualification and stale-review
372
+ guards, including existing contradiction/supersession triggers. Recomputing an inherited
373
+ warning is not a new validation; reviewing one card must not validate its neighbours
374
+ or the whole chain. Distinguish current source revisions from those recorded as checked.
375
+ 3. **Improve authored meaning alongside the read path.** Use existing board READMEs
376
+ to explain purpose, relationship reasons to explain the connection, and pin reasons to
377
+ explain attention. Explicit task requests ask for work. Pins, summaries and reasons are
378
+ not instructions, approval or authority. This is partly an authoring practice, not a new
379
+ taxonomy, schema or mandatory infrastructure layer.
380
+ 4. **Make local navigation readable for both readers.** Extend Sources / Used by into
381
+ small-chain exploration sharing the agent read's relationship semantics, reasons and
382
+ qualification. Bring the useful slice alongside the review loop, rather than waiting
383
+ for a complete new explorer. Preserve drafts and the human's navigation/camera; an agent
384
+ read must not move their view. Global Graph remains orientation, not the only way to
385
+ understand a dependency or inspect an affected conclusion.
386
+
387
+ **Acceptance for that future improvement:**
388
+
389
+ - A cross-board branching chain returns the intended upstream/downstream paths, qualified
390
+ identities, authored reasons and recorded provenance, with citations and membership
391
+ distinguishable. The human and agent agree for the same scope and observation.
392
+ - Cycles and high-degree cards terminate within stated bounds. Partial results explain
393
+ omissions and continuation; continuation makes progress or explicitly requires a restart
394
+ after relevant changes, rather than silently mixing incompatible observations. Missing,
395
+ unavailable, cached, retired and unknown evidence is qualified, not presented as complete
396
+ or freshly validated. Existing access boundaries apply before exposing source details.
397
+ - The rehearsal's source value 40 → 89 flags its derived conclusion but not its plain
398
+ citation. A genuine source change during review rejects stale evidence. Reviewing one
399
+ card creates no validation records for its neighbours, and summary delivery neither
400
+ clears full-content read state nor renews validation.
401
+ - A person follows an affected chain, inspects evidence, records or defers review and
402
+ returns without losing a draft or their place. Check the actual interaction in narrow
403
+ panes as well as wider windows; dense Fit, sketch parity and native-host support are
404
+ separate checks, not inferred from Chromium rehearsal.
405
+
172
406
  ### 0a. Board pins: a working set across boards (S–M)
173
407
 
174
- **Decided with the maintainer, 2026-10-05.** Pinning works at two levels with one gesture and one look. Pin a card and its content goes to the agent; pin a board and the whole board joins the agent's working set, wherever it sits in the library. This replaces "pinning a board on the map" above and settles the review's open question of board-level pins versus map pins: there is one board pin, set from Home (folders, map or graph), the board switcher, a portal card or the open board's top bar.
408
+ **Decided with the maintainer, 2026-10-05.** Pinning works at two levels with one gesture and one look. Pin a card and it goes first in the agent's map; pin a board and the whole board joins the agent's working set, wherever it sits in the library. This replaces "pinning a board on the map" above and settles the review's open question of board-level pins versus map pins: there is one board pin, set from Home (folders, map or graph), the board switcher, a portal card or the open board's top bar.
175
409
 
176
- - **What the agent gets.** The brief is tiered: the active board's pinned cards first; then each pinned board's README and its pinned cards, in full; then linked and same-folder boards as discovery only (README summary and pinned titles), as `context-brief.ts` does today. All tiers share the budget. When it runs out, a pinned board falls back to discovery and the context chip says so; nothing drops silently.
410
+ - **What the agent gets.** The brief is a map, not a dump (decided with the maintainer 2026-10-07: "the canvas is an extended memory across cards and boards; the models are smart enough to decide"). It carries the open board's overview, then every card as title + short summary with why it was pinned and its relations, pinned cards first and the cards near them next; each pinned board as a map (README summary, folder, links and backlinks, its pinned cards as summaries); then linked and same-folder boards as discovery. The agent pulls whatever it decides to read in full; a summary is "seen", a full pull is "read".
177
411
  - **Lifetime.** Board pins belong to the workspace: they survive board switches and restarts and are removed only by a person or an agent, attributed like card pins.
178
412
  - **Read, not write.** A pinned board is context. Writes still target the active board (stage 1); a board pin never widens what an agent may change.
179
413
  - **Agent surface.** `canvas://pinned-context` gains a pinned-boards section; `canvas_board` gains `pin` and `unpin`, with the HTTP route, SDK method and CLI command kept in step. Read instrumentation (`context_reads`) already records the board of each read, so "read / not read yet" works per board.
180
414
  - **Data.** A `board_pins` table: board id, who pinned, when.
181
415
  - **Design.** Wave 1 of [design.md](design.md); drawn on the BoardPins and Home boards.
416
+ - **Done 2026-10-10 (deferred from the 0.9.0 tech-debt sweep).** The context chip reads every pinned board's status in one request (`context-status?boards=…`), landed with the Home redesign.
182
417
 
183
418
  ### 1. One read, one brief (M)
184
419
 
185
420
  Above. **Every node type has a text form that carries its meaning.** The brief can only be as good as what each node says about itself. `summarizeNodeForAgentContext` (`src/server/agent-context.ts`) gives every type a text form today, but for the rich kinds it carries structure, not meaning: a graph passes its raw config JSON, an MCP app its tool input (nothing about what an Excalidraw drawing shows), an image its URL, an HTML deck whatever summary its author supplied. The requirement: each type states what it shows or claims in a few sentences, written by the agent that creates or updates the node and refreshed with it, with a mechanical fallback where none exists. A check per node type asserts the brief form of a sample node is non-empty prose, not a config dump. A board rich for the human must not be blank to the agent, or "one surface" is only true for markdown. Objection: ranking by "the human's camera" rests on a signal the product does not have; the server holds one global viewport that agents also write via `view.fit` and `view.focus`, so a camera ranker would rank the agent's own last focus. Accepted. The camera rides the per-tab human-presence heartbeat, viewport writes get an actor like every other write, and the camera is a weak tiebreak, never the primary axis. Primary axes: pins, delta since last read, author, recency.
186
421
 
422
+ **Larger-library maintenance checkpoint (2026-10-11).** Wave 3's due evaluator still scans
423
+ the library and loads each card's review history for a single-card read. Before expanding this
424
+ path to larger shared libraries, bound narrow reads to the dependency closure, batch/index
425
+ review summaries, and separate Home's folder aggregates from card detail. Measure long
426
+ dependency chains and populated histories, not only empty-history fixtures. Reuse a captured
427
+ qualification within a request, as the Wave 3 AX cleanup now does; a cross-request cache must
428
+ account separately for source revisions, cadence boundaries, session use and retirement.
429
+ The measured baseline and remaining costs are in
430
+ [the Wave 3 debt review](plans/plan-009-tech-debt-backlog.md#wave-3-maintainability-review-2026-10-11).
431
+
432
+ **MCP context delivery, staged after current acceptance (2026-10-12).** This is
433
+ follow-up hardening of the implemented context/read-accounting path, not unfinished
434
+ Wave 1 or Wave 3 functionality. Complete resource subscriptions for hosts that
435
+ support them: advertise the capability, track subscribed URIs per connection
436
+ and notify only the relevant subscribers. The current MCP server emits resource
437
+ updates without that subscription bookkeeping. An update means context may be
438
+ stale, not that the host reread it or the model used it. Preserve explicit context
439
+ reads for hosts without subscriptions. Verify subscribe, unsubscribe and connection
440
+ isolation; measure actual reads separately from notifications. This is available
441
+ on SDK v1 and does not depend on the later SDK migration.
442
+
443
+ **Live-library maintenance checkpoint (2026-10-11).** Map/Graph now preserve local navigation
444
+ while agents change the server's active board. Before stage-2 concurrent board editing, replace
445
+ that narrow browsing flag with explicit per-tab navigation and board-qualified editor ownership;
446
+ do not broaden the singleton's write authority. Before targeting large libraries, measure graph
447
+ fetch size, force settling and DOM paint with dense cross-board links. Keep the shared projection
448
+ authoritative and the simulation view-local; add a worker or viewport culling only from those
449
+ measurements, not a second relationship store.
450
+
187
451
  ### 2. The session projects itself onto the board (M)
188
452
 
189
453
  Above. Objection: none raised; the panel missed it. Risk: noise. Mitigation: the projection lands in its own lane at low rank; the compiler's tiers keep it out of the brief unless pinned or recent.
@@ -212,6 +476,34 @@ A folder export (one markdown file per note plus a board file in the product's o
212
476
 
213
477
  Objection (feasibility, refuted as written): "a log written by `executeOperation` and nothing else" does not describe this codebase (487 `canvasState.` references in 40 files; the SDK makes 87 direct calls). Accepted: the XL half (state as a fold of the journal) comes after move 6 collapses the SDK onto the registry.
214
478
 
479
+ **Journal maintenance checkpoint (2026-10-11).** Establish one authoritative mutation path
480
+ before treating state as a journal fold. Keep evidence validation and review/restore audit
481
+ distinct from undoable content history: replay, Undo and snapshot restore must not renew
482
+ validation or silently erase retirement. Preserve the separate read, content, validation and
483
+ relevance clocks through the transition and test restart/replay against those invariants.
484
+
485
+ **Commit and replay guarantees (2026-10-15).** The journal supports synchronization; it
486
+ does not establish correctness on its own. Before second-writer or hosted write guarantees:
487
+
488
+ - A successful committed write means its state change, change record and retry outcome are
489
+ durable together. Any earlier accepted/pending response is explicitly not that acknowledgment.
490
+ Publish committed changes, and recover missed notifications through authorized replay.
491
+ - Check relevant revisions at commit, including layout and cross-board effects. Content
492
+ revisions keep their semantic meaning; do not reuse them as geometry versions. Conflicts
493
+ are rejected or deliberately resolved, not automatically merged by compare-and-set.
494
+ - Retrying the same scoped request must not duplicate its effects, including a successful
495
+ prefix of a partial batch. Define each command's atomic scope and batch failure behavior;
496
+ a batch is not implicitly a transaction. Files and object storage need explicit recovery
497
+ across their separate commit boundaries.
498
+ - Specify snapshot/cursor continuity and expired-cursor recovery, and recheck permissions
499
+ on replay. Record effects without rerunning external actions; Undo is a new checked write,
500
+ not permission to overwrite intervening edits or renew validation.
501
+
502
+ Transactional state plus a change journal can deliver this before full event-sourced
503
+ reconstruction. Today's polling cursor and snapshot fallback remain useful, but are not
504
+ durable replay. This work does not block the curation evaluation or require completing
505
+ the journal before a read-only share link.
506
+
215
507
  ### 5. Keep every node type; unify how they render (M)
216
508
 
217
509
  The maintainer's rule, and it is the right one: his own usage is not evidence that a node type is unused, and a node that renders any MCP app belongs in the product. So no node type is removed, and the generic `mcp-app` node stays generic. What changes is the machinery under the iframe-backed kinds (`html`, `mcp-app`, `json-render`, `graph`, `webpage`, `mermaid`), which today is spread over six components with three copies of the AX bridge and one 1,591-line frame component whose recovery ladder has produced ten rounds of black tiles (0.6.2 ships the latest as a known limitation).
@@ -220,21 +512,53 @@ One frame host for every iframe-backed kind: mounted lazily when the node is in
220
512
 
221
513
  A frame host is necessary but not sufficient while four hosts set the definition of "works". Name one **reference surface** where every node type must render, gate releases on it, and treat embedded panes as best-effort with the visible fallback. Otherwise field reports keep setting the roadmap, as they did for all of 0.5 and 0.6.
222
514
 
223
- **Decided with the maintainer, 2026-10-05, replacing the 2026-09-24 decision: the workbench has no single reference width.** It lives in narrow agent-host panes, the resizable side browser in the Claude desktop app, and full browser windows of any size. The gate checks three widths in Chromium: 600 px (the narrow end), 1024 px (the middle, between the layout breakpoints) and 1920 px (a full window). Every node type must paint at all three or the release does not ship. (The 2026-09-24 decision made 600 px the one reference surface.) It is nearly free and covers the Claude Code and Codex panes and full windows, and Chromium is also the engine a hosted version would target first. What it misses is WebKit, where the Copilot app pane (the maintainer's host) and most black-tile rounds live, and which every iPhone and Safari viewer of a shared link will use. Those stay best-effort behind the visible fallback and retry. Recommended trigger for adding a WebKit project to the gate: whichever comes first of Part 3 step 2 (the read-only link) or the next WebKit-only bug that reaches a release. The compiled-binary window is not an option today: headed `Bun.WebView` is not implemented ([`bun-webview-integration.md`](bun-webview-integration.md)).
515
+ **Decided with the maintainer, 2026-10-05, replacing the 2026-09-24 decision: the workbench has no single reference width.** It lives in narrow agent-host panes, the resizable side browser in the Claude desktop app, and full browser windows of any size. The gate checks three widths in Chromium: 600 px (the narrow end), 1024 px (the middle, between the layout breakpoints) and 1920 px (a full window). Every node type must paint at all three or the release does not ship. (The 2026-09-24 decision made 600 px the one reference surface.) It is nearly free and covers the Claude Code and Codex panes and full windows, and Chromium is also the engine a hosted version would target first. What it misses is WebKit, where the Copilot app pane (the maintainer's host) and most black-tile rounds live, and which every iPhone and Safari viewer of a shared link will use. Those stay best-effort behind the visible fallback and retry. Recommended trigger for adding a WebKit project to the gate: whichever comes first of the hosted read-only link (Part 4) or the next WebKit-only bug that reaches a release. The compiled-binary window is not an option today: headed `Bun.WebView` is not implemented ([`bun-webview-integration.md`](bun-webview-integration.md)).
224
516
 
225
517
  Deletes: the `ExtAppFrame` recovery machinery, two of three AX-bridge copies, five per-type iframe implementations. Capabilities removed: none. Every deletion the earlier version of this move argued from "zero real uses" was withdrawn once the real boards surfaced; what remains is argued from cost and incident count only.
226
518
 
227
- ### 6a. Make the tool surface cheap (S) — ready to ship
519
+ **Wave 4 maintenance checkpoint (2026-10-11).** Consolidate frame budget, theme delivery,
520
+ fallback and retry together rather than adding another recovery path. Reuse the existing
521
+ shared AX bridge. Preserve authored drafts, input state, offscreen replacements and the
522
+ painted-refresh handoff in the current browser cases. Chromium passes do not establish native
523
+ Copilot/WebKit paint; keep that limitation explicit until separately exercised.
524
+
525
+ ### 6a. Make the tool surface cheap (S) — staged follow-up
526
+
527
+ **Current status, 2026-10-12:** direction accepted, not implemented or a gate for
528
+ Waves 1–3 acceptance. Scope the MCP hardening below as a separate follow-up before
529
+ hosted work; the broader cheap-tool proposals remain candidates, not automatic
530
+ batch scope. The schema-size figures and savings below are historical estimates;
531
+ remeasure today's expanded operations before committing to a tool redesign.
228
532
 
229
533
  Measured on this tree, `tools/list` is 49,222 bytes across 22 tools, about 12,300 tokens that every agent pays on every session before it does anything. Two tools account for a fifth of it: one advertises 51 optional properties, another 49, because a composite flattens four actions' fields into one schema. Per-action requirements exist only in prose, so a call missing a required field passes validation and fails in the handler.
230
534
 
231
- Nothing structural is needed to fix most of that. Ship per-action schemas where hosts support them and a `canvas_help { op }` that returns one operation's schema on demand, so an agent loads what it uses instead of the whole surface. Add `session.start`, returning workspace, brief and inbox in one round trip, so a useful first session is about five calls. Fix the two live descriptions that are wrong today, and add the test that an action summary always equals its own action list. Put a token budget on every agent read, which is Part 1's one read.
535
+ Nothing structural is needed to fix most of that. Ship per-action schemas where hosts support them and a `canvas_help { op }` that returns one operation's schema on demand, so an agent loads what it uses instead of the whole surface. Add `session.start`, returning workspace, brief and inbox in one round trip, so a useful first session is about five calls. Fix the two live descriptions that are wrong today, and add the test that an action summary always equals its own action list. Bound every agent read by a page size, which is Part 1's one read.
232
536
 
233
537
  This is the half the maintainer has already endorsed in direction. It removes no capability, renames nothing, and is worth roughly 10,000 tokens per session per agent.
234
538
 
539
+ **MCP contract and request reliability (2026-10-12).** Extend the existing tool
540
+ surface before changing SDK generations or undertaking 6b. General tools mostly
541
+ return JSON encoded as text; the Apps profile already has structured summaries
542
+ and safety annotations. These improvements are supported by the current SDK v1:
543
+
544
+ - Add validated `outputSchema` and `structuredContent` for stable result contracts,
545
+ including IDs, revisions and mutation outcomes. Keep model-facing content compact;
546
+ retain full UI-only payloads in `_meta` where the Apps host supports it.
547
+ - Advertise accurate read-only, destructive, idempotency and external-access hints.
548
+ A composite containing writes cannot be labelled read-only. Annotations inform
549
+ the host; permissions and revision checks remain server-enforced.
550
+ - Carry request cancellation through the operation layer into waits and cancellable
551
+ I/O. Report progress for lengthy operations when the host supports it. Stopping
552
+ remaining work does not roll back completed edits; report partial outcomes honestly.
553
+
554
+ **Acceptance:** validate representative read and mutation results against their
555
+ advertised schemas, audit mixed-action annotations, and cancel an in-flight wait
556
+ without leaving it subscribed until timeout. Keep local stdio behavior working.
557
+ These are incremental contract improvements, not a new composer or session layer.
558
+
235
559
  ### 6b. Generate every surface from the registry (L, two releases) — pending the maintainer's decision
236
560
 
237
- **Status: undecided as of 2026-09-06.** The maintainer likes the simplification and the token saving, and wants more time on the restructuring. Nothing below should start before that decision.
561
+ **Status: undecided as of 2026-09-06.** The maintainer likes the simplification and the token saving, and wants more time on the restructuring. The generated-surface redesign must not start before that decision. The shared-writer policy clarification below is independent of that redesign.
238
562
 
239
563
  The proposal: `listOperations()` becomes the single published vocabulary. Five MCP tools (`canvas_read`, `canvas_write` taking a list so batch is just a longer list, `canvas_ask`, `canvas_inbox`, `canvas_help`) replace the 22 (23 once `canvas_board` lands). The CLI becomes one generic dispatcher over operation names plus eight human commands, and the SDK becomes a typed facade over the same invoker. The API document is rendered from the registry, replacing 23,000 words of hand-written prose that has drifted at least seven times.
240
564
 
@@ -242,13 +566,23 @@ The case for it: four naming conventions for one operation (`set-focus`, `ax foc
242
566
 
243
567
  The case against, which is why it is worth thinking about: 22 named tools are self-documenting in a way that five generic ones are not, a host that renders tool names to the user shows something meaningful today, and a single write tool keyed on operation names needs a discriminated union to catch wrong-field arguments, which not every host supports yet. Generated CLI help is also usually worse than hand-written help.
244
568
 
245
- If the answer is no, 6a still stands on its own, and the one piece worth taking regardless is routing the SDK through the registry, since that is a trust fix rather than a surface change: the SDK makes 87 direct state calls today and 4 registry calls, so an SDK write skips the human edit lock, the scope fence and the activity feed.
569
+ If the answer is no, 6a still stands on its own, and the piece worth taking regardless is one mutation policy and commit boundary for every supported writer. The original 87 direct SDK state calls versus 4 registry calls are historical counts, not a current inventory; the SDK now has fence and presence handling, but its direct node-update path still bypasses the registry's human edit lock.
570
+
571
+ **SDK direction clarified, 2026-10-15.** Sharing policy does not require making every SDK
572
+ method asynchronous: synchronous checks can protect both the local SDK and registry paths.
573
+ This supersedes [plan 009's](plans/plan-009-tech-debt-backlog.md#decision-analysis-2026-07-08-maintainer-approved)
574
+ conclusion that no further convergence is needed, not its decision to retain a synchronous
575
+ local convenience API. All writers, including autonomous system writes, must share the
576
+ relevant policy and commit guarantees. Cross-runtime operations with asynchronous storage
577
+ need an explicit durable-completion contract; a Promise alone does not provide one.
578
+ Any public API change needs its own scoped, versioned decision. This does not authorize
579
+ compatibility shims, a second permanent command implementation or the undecided tool redesign.
246
580
 
247
581
  Objection (feasibility, refuted as bundled): the previous registry campaign took four pull requests plus a month of follow-up slices, so five refactors in six weeks will not land. Accepted: two releases, SDK first. Objection (evidence): "41 operations unreachable from MCP" is a field-count artifact; the real gap is about 14. Accepted.
248
582
 
249
583
  ### 7. Trust that is not a label (S, then M)
250
584
 
251
- The workbench marker is a plain header any agent with `curl` can set, so "human-only gate resolution keyed on the marker" is still theater. The server mints a secret at boot, serves it only in the workbench HTML, and human-only ops require it. Its limit, raised by the [context vision](product-context-vision-2026-09.md) and accepted: an agent running as the same user can fetch that HTML too, so the secret stops casual header-setting and makes self-approval a deliberate act of circumvention, not proof of human intent. On a local single-user board that is the honest ceiling and the docs should say so; on a shared board (Part 3 step 2 on) human-only ops key on the viewer's own token, which an agent in another person's session never holds.
585
+ The workbench marker is a plain header any agent with `curl` can set, so "human-only gate resolution keyed on the marker" is still theater. The server mints a secret at boot, serves it only in the workbench HTML, and human-only ops require it. Its limit, raised by the [context vision](product-context-vision-2026-09.md) and accepted: an agent running as the same user can fetch that HTML too, so the secret stops casual header-setting and makes self-approval a deliberate act of circumvention, not proof of human intent. On a local single-user board that is the honest ceiling and the docs should say so; on a shared board (the hosted version, Part 4) human-only ops key on the viewer's own identity, which an agent in another person's session never holds.
252
586
 
253
587
  **Superseded 2026-09-26 (see below).** ~~Decided with the maintainer, 2026-09-24: the human answers, the requester can withdraw.~~ Approving, rejecting and answering (gates, elicitations, mode requests) are human-only. A new `withdraw` lets the agent that raised an ask close it while it is still open, with a distinct `withdrawn` status that never counts as approval, so an orchestrator can tidy up at the end of a run. Every agent-facing resolve path becomes withdraw: the `canvas_ax_gate` resolve action, the CLI resolve commands, and the Copilot extension's `resolve_approval` tool (which becomes `withdraw_approval`); the orchestration skill's "resolve gates" step becomes "withdraw open gates". This matches the orchestration skill, which already treats gates as human decisions, and removes the one tool that invited self-approval. In practice the tool matters more than the secret: an agent handed `resolve_approval` will use it. The approval flow sees little real use on the board today, so the change is cheap now.
254
588
 
@@ -256,7 +590,17 @@ The workbench marker is a plain header any agent with `curl` can set, so "human-
256
590
 
257
591
  Then: file nodes are confined by default to the workspace plus explicit allow-roots (persistence hygiene, since every host already gives the agent `cat`); the webpage fetcher follows redirects by hand and refuses any hop that moves a public fetch onto a loopback or private address, and refuses link-local (cloud metadata) addresses on every hop, while a URL the caller points at a local dev server on purpose still loads; the client bridge checks `res.ok` and shows the toast on a refused write. One reservation I am not settled on: the real boards carry file nodes for documents (weekly prioritization reports) that may live outside any repository, and default confinement would have refused them; the default should probably be a per-board allow-root list that includes the folders a PM board actually reads, not the workspace alone.
258
592
 
259
- The same mechanism gives the product its own remote story, without relying on anything external. A loopback-only server means Claude Code cloud, Codex cloud and the Copilot coding agent, the agents that run longest unattended, cannot reach the board at all. With per-writer tokens minted by the server (human tokens served only to the workbench, agent tokens issued per session), the server can bind beyond loopback deliberately (`--listen` plus a token), and a remote agent is just another authenticated writer. No relay, no sync service, no version-control detour. The same tokens carry the read-only share link, the second step of the sharing path in Part 3; the first step, static export (move 11), needs none of this.
593
+ The same mechanism gives the product its own remote story, without relying on anything external. A loopback-only server means Claude Code cloud, Codex cloud and the Copilot coding agent, the agents that run longest unattended, cannot reach the board at all. With per-writer tokens minted by the server (human tokens served only to the workbench, agent tokens issued per session), the server can bind beyond loopback deliberately (`--listen` plus a token), and a remote agent is just another authenticated writer. No relay, no sync service, no version-control detour. The read-only share link no longer rides these local tokens: it ships with the hosted version (Part 4, decided 2026-10-19). Per-writer tokens and `--listen` serve the owner's remote agents; local PMX remains single-user. Static export (move 11) needs none of this.
594
+
595
+ **Authority across editions (2026-10-15).** Shared and hosted access uses an authenticated
596
+ principal (the caller and its grants), supplied by the edition's identity adapter, and one
597
+ product permission model. Self-asserted workbench markers, `agentId` and `clientId` are
598
+ cooperative signals, not authorization. Changing a label cannot change a caller's rights or
599
+ assigned territory. Scope requests explicitly to workspace, board and caller independently
600
+ of human navigation. Filter readable sources before computing titles, graph links, briefs,
601
+ lifecycle reasons or exports; scope live events and replay to authorized subscribers too.
602
+ This strengthens sharing, not a claim that the local boot token proves human intent, and
603
+ does not change the decision that permitted writers may answer attributed approval gates.
260
604
 
261
605
  Correction to my own review: a human's write cannot hit the 403 fence or the 409 lock, both sit behind `if (!meta.fromWorkbench)`; the silent-failure defect is real but smaller than I wrote.
262
606
 
@@ -272,6 +616,12 @@ The workbench runs at any size: a 500 to 600 px panel inside Claude Code, Codex
272
616
 
273
617
  Both files stay, because different agents read different files (Claude Code reads CLAUDE.md; Codex, Copilot and Amp read AGENTS.md), and they stay byte-identical under the CI gate that already enforces it. Each becomes the same 120-line contract; the AX design reference moves to `docs/ax.md` and is linked from both; each "this shipped N times" paragraph becomes a test or a Biome rule where an oracle exists. Objection: the ten-time black-tile class has no executable oracle (Playwright is Chromium-only). True, and move 5 replaces the oracle ladder with a paint deadline and a visible fallback, which a test can assert; the WebKit Playwright project, when move 5's trigger adds it, covers the rest.
274
618
 
619
+ **Maintenance with each wave (2026-10-11).** Sweep the changed subsystem for orphans,
620
+ duplicate reads and stale public contracts. Split the large server/browser integration files
621
+ by owning domain when those domains next change, retaining isolation and race coverage.
622
+ Keep human browser gestures and real agent transports alongside unit tests. This is staged
623
+ maintenance, not a broad rewrite or permission to replace behavioral checks with source matching.
624
+
275
625
  ### 11. Static export: the first step to sharing (M)
276
626
 
277
627
  A self-contained HTML file of one board: the renderer and the board's data in one file, read-only, with pan, zoom and card expand. It can be attached to an email or a chat message, or posted to a wiki page. No server and no authentication, and the app produces the file itself, so the no-externals rule holds. Iframe-backed nodes export their stored markup in sandboxed iframes, as they render today; a node whose content cannot be inlined (a live MCP app) exports as its last screenshot where capture is available (macOS today, see move 9) and otherwise as a labelled placeholder.
@@ -282,9 +632,50 @@ An export is a share, so Part 3's per-board rule applies to it. Portals export a
282
632
 
283
633
  Five of the real boards include agent-generated HTML slide decks, one with 15 slides, rebuilding as slides content that already existed as cards. A tour is an ordered path through a board's cards, seeded from the reading order `spatial-analysis.ts` already computes and editable by the human. Arrow keys move the camera card to card, and the current card fills the screen. Tours carry into exports and share links, so presenting and sharing are one feature. HTML decks stay as a capability; they stop being the only way to present.
284
634
 
285
- ### 13. Recipe cards: boards that can be refreshed (M)
635
+ **Deferred from the 0.9.0 tech-debt sweep (2026-10-08), to clean up together right after 0.9.0:** a tour's camera move saves every node's layout instead of only the viewport (`commitViewport` → `persistLayout` from the SSE camera handler) and re-reads the whole layout (`tour-control.ts`); `animateCameraPath` duplicates `animateViewport` (`canvas-store.ts`); the current-tour logic is repeated in `tour-control.ts`, `index.ts` and the viewport operation; and the SDK's `getTour()` does not return the tour position the HTTP and MCP surfaces do. They came with the tours work, not the context work, and are kept out of 0.9.0 so it does not also change tour behaviour.
636
+
637
+ ### 13. Context lifecycle and recipe cards (M, then later classification)
286
638
 
287
- The real boards are full of numbers from elsewhere: 13 metric charts, developer-experience metrics, an OKR mirror card on the live board. They go stale silently, and in a board wiki staleness is the rot. Provenance (`canvas-provenance.ts`) already records a source and refresh strategy for files, URLs, images, apps and artifacts; add one source kind, the **recipe**: the tool call and prompt that produced the card, recorded when an agent writes it. The canvas never fetches external data itself; it marks the card stale after a set age, "Refresh this board" hands the stale recipes to the attached agent, and the board map shows staleness beside last-touched time. A recipe is data, never instructions: a refresh runs only when a human asks, and the agent may decline it.
639
+ **Direction revised with the maintainer, 2026-10-07.** Folder categories, card lifecycle,
640
+ source-driven review and inert recipe handoff are implemented in Wave 3; see
641
+ [plan 017](plans/plan-017-knowledge-categories-and-lifecycle.md) for scope and
642
+ [plan 018](plans/plan-018-connected-memory-wave-2.md#remaining-wave-3-stabilization-2026-10-11)
643
+ for verification. Claim-level review, classifier assistance and shared-audience access remain
644
+ future work. This status does not authorize a release.
645
+
646
+ Every knowledge document has a lifecycle, including Markdown cards derived from imported sources. Use the maintainer's [context-decay framework](https://github.com/pskoett/pskoett-ai-skills/tree/5a836dc7163da6799fe34ed4283da6d7f0358f14/skills/context-decay): context loses usefulness in different ways, not at one universal half-life. Its rates are qualitative planning judgments, not probabilities that a claim is true.
647
+
648
+ - **What can decay.** Reality (facts change), decisions (superseded choices), dependencies (versions, owners or prerequisites change), and relevance (the task changes). A document can contain several claims with different authorities and review triggers; reviewing one never validates them all.
649
+ - **When to check.** Fast means check at use; medium means source-appropriate cadence plus event triggers; slow means maintenance or resumed work; durable means no passive expiry. Contradictions, superseding decisions and dependency changes trigger review regardless of age. Each category can supply defaults, with explicit document or claim overrides; unclassified context stays visibly unknown rather than receiving an invented expiry date.
650
+ Medium requires an explicit positive cadence in days; a blank cadence or whitespace-only
651
+ revalidation method cannot save. Relation presets do not supply lifecycle or classify cards.
652
+ - **Separate the clocks.** Last delivered/read by an agent, last content change, last evidence validation, and relevance to the current task are distinct signals. Reading, quoting, editing or running maintenance does not renew validation. Wave 1's read marks measure delivery and revision currency, not comprehension or truth.
653
+ - **Record the evidence.** Keep stable document/claim identity, authority, owner, decay type/rate, revalidation method and triggers, last validated time and evidence, review outcome, and whether that outcome has been applied. Unavailable evidence leaves the review unresolved and preserves the previous validation record.
654
+ - **Review outcomes.** Retain, revise, externalize to a maintained source, retire from active context, or leave unresolved. These are review dispositions, not an automatic age-driven state machine. Preserve sources and history; low use alone never retires a rare safeguard. Amber means “needs review,” not “false.” The brief carries that qualification rather than silently presenting stale context as validated.
655
+
656
+ The real boards are full of numbers from elsewhere: 13 metric charts, developer-experience metrics, an OKR mirror card on the live board. Provenance (`canvas-provenance.ts`) already records a source and refresh strategy for files, URLs, images, apps and artifacts; add one source kind, the **recipe**: the tool call and prompt that produced the card, recorded when an agent writes it. The canvas flags review needs from the lifecycle policy and changed sources; the board map shows them separately from last-touched time. “Refresh this board” hands relevant recipes and review reasons to the attached agent. A recipe is data, never executable instructions: refresh runs only when a human asks, and the agent may decline it. Regenerating a card is not by itself evidence validation.
657
+
658
+ **Decided model, 2026-10-07** (drawn in `Categories`, `CategoryEditor`, `Lifecycle`, `Lifecycle600`, `Restore` and `LifecycleVariants` in [design/](design/)):
659
+
660
+ - **Category is a property of a folder,** not a second taxonomy or tag system. Folders stay the one hierarchy (move 0).
661
+ - **It inherits down the tree.** A board filed under a "Decisions" folder gets that category and its lifecycle defaults without anyone tagging it; a subfolder may set its own.
662
+ - **One category list per workspace,** edited by the workspace. The product ships editable defaults and starter templates (org · team · personal, solo research, product team, empty); none of those words is hard-coded.
663
+ - **A card may override its lifecycle, never its category.** Category is set at folder (or board) level only.
664
+ - **Categories carry no colour:** a glyph and a word, like node kinds.
665
+ - **The board shows only "⧗ review due"** — on the card, with a short reason, only while a review is due (variant A). Rate, decay type, inheritance, the four clocks and review history live in the card's Lifecycle tab and in folder settings; "unknown" is reported per folder on Home, never per card. A healthy card shows no lifecycle line. "Review due" (outlined ⧗) and "changed since read" (filled △) are both amber and differ by glyph, word, fill and place.
666
+ - **Retire is reversible.** Retiring removes a card from the brief only; the card stays dimmed on the board, searchable as retired, with its history. A person restores it from the Lifecycle tab; restore is recorded and is not a validation.
667
+
668
+ **Dashboards and source lifecycles (decided with the maintainer, 2026-10-10).** A board can be a durable dashboard without everything it presents being durable or fresh. Classify the knowledge, not the dashboard format:
669
+
670
+ - **Structure can be durable.** The dashboard's layout, navigation and selection of boards need no age-based expiry. A broken target or a change in purpose can still require maintenance; durable never means permanently correct.
671
+ - **Sources keep their own lifecycle.** A portal to an operational-status board carries that source's review qualification, not the dashboard's durable default. Folder defaults apply to content filed there; they do not propagate across links. A locally authored metric card can override the dashboard folder's lifecycle independently.
672
+ - **Refreshing is not validating.** Opening the dashboard, following a link or successfully fetching a source does not reset its last-validated time. Distinguish retrieval time from the source's observation/update time and evidence validation. Cached values retain their source revision or “as of” time; an unavailable source is not presented as freshly checked.
673
+ - **Conclusions have dependencies.** “We are on track” is a separate conclusion, not just navigation. A relevant source change can flag that conclusion for review through an explicit derivation/dependency relation. A plain navigational link does not make every connected card stale, and the rest of the dashboard does not become due merely because one source changed.
674
+ - **Expose the reason where it matters.** A portal or source-backed card surfaces “source needs review” when applicable, separately from its own lifecycle, and the agent's brief carries the same qualification. Any dashboard roll-up reports affected sources, not a blanket claim that the dashboard is false or fresh. Unreadable targets retain the locked/no-title boundary; lifecycle signals never disclose protected source information.
675
+
676
+ **Model-independent first.** Categories, lifecycle metadata and review outcomes are ordinary app data, editable by people and through the existing agent interfaces. They need no classifier, particular model or external inference service. Routine private knowledge maintenance can happen during agent-assisted work, with attribution and reversible history; publishing to a wider audience remains a separate explicit action.
677
+
678
+ **Optional later: typed decision assistance.** [Typesafe's Jev](https://typesafe.ai/) is a reference for bounded classification and scoring, not a required runtime or a folder model. A future replaceable classifier could suggest a category, decay type/rate or review priority from supplied evidence, returning typed choices or rubric scores with uncertainty where supported. Low-confidence or conflicting suggestions remain for review. Classification confidence is neither evidence that the content is true nor permission to publish it. No model integration is required to ship the structure or lifecycle; external inference would need explicit configuration and consent for the data sent.
288
679
 
289
680
  ### 14. New board from this board (S)
290
681
 
@@ -334,35 +725,683 @@ With one journal, a **time scrubber** replaces snapshots, the History drawer, an
334
725
 
335
726
  ## Part 3: Long term, share this board
336
727
 
337
- **Decided with the maintainer, 2026-09-23:** the destination is "share this board", not hosted multi-tenant multiplayer. Hosted multiplayer competes head-on with established whiteboard products that have teams, funding and their own MCP integrations. What they cannot easily be is local-first, host-agnostic, and inside the agent's pane in Claude Code, Codex, Copilot and Amp; that is where this product wins. A PM board is something its owner presents to colleagues, so sharing grows from that, one step at a time, and each step is justified only by someone using the one before it.
728
+ **Re-scoped with the maintainer, 2026-10-19:** all account and team work moves to the hosted version (Part 4): the read-only link, comments, a second writer, accounts, roles and org/team/personal scopes. Local PMX stays single-user; its sharing is static export, and move 7's tokens and `--listen` serve remote agents, not other people. Steps 2–5 below and the team model after the table now describe hosted work. The dependencies still hold inside the hosted version (the journal before a second writer).
729
+
730
+ **Decided with the maintainer, 2026-09-23; scope clarified 2026-10-10; sequencing superseded 2026-10-19 (above):** ~~this phase delivers "share this board" through local and self-hosted sharing. Part 4 adds the first managed hosted offering after the team features.~~ Hosted multiplayer competes head-on with established whiteboard products that have teams, funding and their own MCP integrations. What they cannot easily be is local-first, host-agnostic, and inside the agent's pane in Claude Code, Codex, Copilot and Amp; that is where this product wins. A PM board is something its owner presents to colleagues, so sharing grows from that, one step at a time, and each step is justified only by someone using the one before it.
338
731
 
339
732
  | Step | What it is | Needs first |
340
733
  |---|---|---|
341
734
  | 1. Export | A static HTML file of one board (move 11), carrying its tour once move 12 lands | nothing |
342
- | 2. Link | A read-only share link: `--listen` plus a board-scoped read token | move 7 in full |
343
- | 3. Comments | Viewers annotate and reply; comments are cards addressed to the owner | author on every node (Part 1) |
344
- | 4. Second writer | Another human writes to a shared board, with their own agent | the journal (move 4), concurrent boards (move 0, stage 2) |
345
- | 5. Accounts | Per-board roles (read, comment, write, answer asks), single-tenant; workspace and personal libraries | a team using step 4 |
735
+ | 2. Link | **Moved to the hosted version (Part 4), 2026-10-19.** A local `--listen` link is only reachable on the owner's network or through a tunnel while the owner's machine is awake; hosting replaces its token model anyway. Static export stays the pre-hosted sharing path | hosted runtime (Part 4) with authenticated identity and per-board permissions |
736
+ | 3. Comments | **Hosted version (2026-10-19).** Viewers annotate and reply; comments are cards addressed to the owner | author on every node (Part 1), the hosted link |
737
+ | 4. Second writer | **Hosted version (2026-10-19).** Another human writes to a shared board, with their own agent | the journal (move 4), concurrent boards (move 0, stage 2) |
738
+ | 5. Accounts | **Hosted version (2026-10-19).** Full account administration, per-board roles (read, comment, write, answer asks) beyond the minimum the link needs; org, team and personal knowledge scopes | hosted identity (Sites first, Cloudflare later) |
346
739
 
347
- **What Part 2 already buys.** The journal (move 4) is the sync model: an ordered log with sequence numbers, per-consumer cursors and inverse patches is exactly what multiple clients need, and node-granular edits with compare-and-set on the node version resolve concurrent human edits without operational transforms or CRDTs. Per-writer tokens (move 7) become per-user credentials; author on every node (Part 1) becomes attribution; presence is already multi-writer with identity colors; the ask node with an attributed answer becomes an ask addressed to a person or a role.
740
+ **What Part 2 already buys.** The journal (move 4) provides ordered changes and replay for synchronization, subject to its commit, retry and authorization guarantees. Compare-and-set detects concurrent conflicts; the app must reject or deliberately resolve them, including layout and multi-card changes. Operational transforms or CRDTs are not prerequisites for this conflict-rejecting model. Per-writer tokens (move 7) become per-user credentials; author on every node (Part 1) becomes attribution; presence is already multi-writer with identity colors; the ask node with an attributed answer becomes an ask addressed to a person or a role. Existing presence labels alone do not establish authenticated users or isolated sessions.
348
741
 
349
742
  **Sharing is per board.** Sharing a board never shares what it links to. A portal to a board the viewer cannot see renders as a locked card with no title, and the viewer's brief never reaches past what they can see. This is where the [context vision's](product-context-vision-2026-09.md) publication and audience rules apply: an automatic derivative's audience cannot exceed its inputs', and publication is an explicit act, not a side effect of summarizing.
350
743
 
351
- **What is genuinely new at step 5.** Step 5 is a team server: the same binary run with `--listen` on a machine the team reaches, one store per team, not a multi-tenant service. Identity is the app's own (passkeys and email, federation optional later). If that server is not the owner's machine it has no workspace on disk, so file nodes become uploads with re-upload in place of the watcher. The brief is compiled from the attention of the people in an agent's session, not everyone's, so two people can work one board with different agents without steering each other's context.
744
+ **What is genuinely new at step 5.** ~~Step 5 is a team server: the same binary run with `--listen` on a machine the team reaches, one store per team, not a multi-tenant service. Identity is the app's own (passkeys and email, federation optional later).~~ Superseded 2026-10-19: accounts live in the hosted editions, with identity from the edition (Sites login first, PMX-chosen providers on Cloudflare later). A hosted edition has no workspace on disk, so file nodes become uploads with re-upload in place of the watcher. The brief is compiled from the attention of the people in an agent's session, not everyone's, so two people can work one board with different agents without steering each other's context.
352
745
 
353
- **Workspace and personal libraries (decided with the maintainer, 2026-10-05).** Once a team server has users (step 5), the library splits into two scopes, shown as two roots on Home, in Map and in Graph:
746
+ **User-defined knowledge scopes (revised with the maintainer, 2026-10-07).** This extends the 2026-10-05 workspace/personal decision. A workspace defines its own levels and categories; org → team → personal below is the example template, not a fixed structure, and nothing in the product hard-codes those words. Categories are folder properties with one list per workspace (move 13, decided model). The hierarchy organises Markdown knowledge on boards; SQLite remains authoritative and boards remain the wiki. A readable folder export represents that structure, not a second independently editable knowledge store.
354
747
 
355
- - **Workspace** — the meta level: the team's shared folders and boards (areas, OKRs, decisions, shared research). Members see it according to their roles.
356
- - **Personal** — each user's own folders and boards, private to that user by default. A user organises them freely without touching the workspace tree.
357
- - **Crossing the line is deliberate.** A personal board reaches other people only when its owner shares it (per-board roles) or moves it into a workspace folder. Neither happens as a side effect of a link, a pin, an agent's write or a summary — the [context vision's](product-context-vision-2026-09.md) audience rule: a derived item never reaches a wider audience than its sources.
358
- - **Links are safe in both directions.** A personal board can portal or `[[link]]` to workspace boards. A workspace board that links to a personal board shows a locked card, with no title, to everyone who cannot read it.
359
- - **Pins and the brief are per user.** Card pins and board pins (move 0a) become each user's own working set: on a shared board, my pins steer my agent, not yours. The board's README stays the shared default. A user's brief draws on their personal boards and the workspace boards they can read, never on another user's personal boards.
360
- - **Agents act as their user.** An agent session belongs to one user and has exactly that user's read and write rights in both scopes.
361
- - **Local stays one scope.** A local install has one user, so its library is the workspace and nothing changes before step 5. Step 5 adds an owner to boards and folders (none means workspace) and a user to pins.
748
+ - **Org** — shared organisational context, such as strategy, principles and policies, filed in categories the organisation defines.
749
+ - **Team** — team-owned context, such as objectives, decisions and research, with its own category set and links to relevant org knowledge.
750
+ - **Personal** — each person's working knowledge, private by default, with categories they control. Personal interpretation can link to shared sources without duplicating or silently overwriting them.
751
+ - **Categories are configurable, not inferred prerequisites.** The workspace defines one category list; folders at any level take a category, subfolders inherit it, and lifecycle defaults can be overridden per folder or card (move 13). People or connected agents can file context without a classification model. A board still has one folder; links remain many-to-many. Category names and folder ancestry do not grant access or establish truth. Authority depends on the claim: org policy, team decisions and personal experience have different sources; conflicts remain explicit.
752
+ - **Crossing scopes is deliberate.** Sharing or moving private knowledge to a team or org audience is an explicit publication action, with the destination and sources reviewed. A link, pin, agent write or summary never widens access — the [context vision's](product-context-vision-2026-09.md) audience rule: a derived item never reaches a wider audience than its sources without an explicit authorised publication review.
753
+ - **Links are safe in every direction.** A portal or `[[link]]` to unreadable knowledge shows a locked card with no title. A folder's place under org or team never makes personal descendants public; step 5 needs app-enforced membership and per-board roles, not folder-name permissions.
754
+ - **Pins and the brief are per user.** Card pins and board pins (move 0a) become each user's own working set: on a shared board, my pins steer my agent, not yours. The board's README stays the shared default. A user's brief draws only on knowledge they can read across these scopes, never on another user's private boards.
755
+ - **Agents act as their user.** An agent session belongs to one user and has exactly that user's read and write rights across scopes.
756
+ - **Stage the delivery.** Local category folders and lifecycle metadata need neither accounts nor a model. Shared org/team membership, private personal libraries and publication enforcement arrive with the hosted version, not with Wave 1. Typed classification assistance is a separate longer-term option (move 13), never a prerequisite for either stage. Home, Map and Graph need updated drawings before these scope views are built; the existing two-root HomeTeam drawing is an earlier look ahead.
362
757
 
363
758
  **The vision it enables.** A quarterly OKR board with the PM, the team leads and each of their agents on it, every card attributed, every ask answered by the person it was addressed to, and the time scrubber showing how the plan changed and who changed it, reached from a link the PM sent after the workshop.
364
759
 
365
- **The constraints that hold.** No externals: history and sync are the journal, not a third-party service. Everything in move 7 is mandatory before step 2 opens a port, and MCP-app hosting of third-party apps needs a per-board allowlist once viewers are not all the owner. Multi-tenant hosting and team-wide knowledge governance are not planned; they come back only if a second team is pulling for them.
760
+ **The constraints that hold.** Local and self-hosted PMX need no required externals: history and sync are the journal, not a third-party service. Self-hosted PMX is single-user; no supported self-hosted multi-user edition is planned. Everything in move 7 is mandatory before any server opens a port beyond loopback, and MCP-app hosting of third-party apps needs a per-board allowlist once viewers are not all the owner. Org/team/personal scopes do not themselves require an enterprise governance engine. Since 2026-10-19 they are built in the hosted version (Part 4), not before it.
761
+
762
+ ## Part 4: First hosted validation — ChatGPT Sites and plugin distribution
763
+
764
+ **Direction decided with the maintainer, 2026-10-10.** Aim to deliver the first
765
+ hosted version of PMX Canvas in **ChatGPT Sites**, with **OpenAI login**. The **MCP server is hosted there as well**, so
766
+ users can reach their boards and context without running a local PMX process
767
+ or a private tunnel.
768
+
769
+ This hosted foundation enables full development and release of the **ChatGPT
770
+ plugin**, the first distribution channel for reaching users and testing whether
771
+ PMX becomes part of their work. Validate the ChatGPT experience and adoption
772
+ before investing in the full standalone hosted service in Part 5.
773
+
774
+ **Accounts and team work are built here, for both hosted editions (decided with the
775
+ maintainer, 2026-10-19).** The read-only link, comments, a second writer, accounts, per-board
776
+ roles and org/team/personal scopes moved from Part 3 into the hosted version. Build them once
777
+ in the shared product (see [shared product, separate runtimes](#likely-repository-structure-shared-product-separate-runtimes)):
778
+ roles, membership, scopes, publication and per-board read filtering are shared rules keyed on
779
+ an edition-neutral principal, never on a Sites user ID. Each edition supplies runtime adapters,
780
+ including identity, storage, lifecycle and external capabilities (ADR-002 decisions 2–3). The
781
+ Sites version ships first; the standalone Cloudflare version (Part 5) reuses the domain rules,
782
+ schemas and contracts without depending on Sites. Each edition owns independent records and
783
+ storage, without automatic synchronization; memberships and role assignments never import as
784
+ authority (board copies apply the destination's permissions), while historical attribution
785
+ stays as provenance. Dependency checks establish source separation only: verify supported
786
+ behavior and lifecycle guarantees on Sites, and on standalone Cloudflare when that edition is
787
+ implemented. Cloudflare implementation is not a prerequisite for Sites.
788
+ Prerequisites: move 7's authorization model and the extraction gate's complete slice; the
789
+ journal (move 4) before the second writer. Authenticated identity and per-board permissions
790
+ come before the first hosted link; full account administration and scopes can follow.
791
+
792
+ **The read-only share link ships here.** It moved
793
+ from Part 3 step 2: a local `--listen` link only reaches colleagues on the owner's network or
794
+ through a tunnel while the owner's machine is awake, the same burden the plugin decision
795
+ rejects for ChatGPT users. The hosted link uses the edition's identity and PMX per-board read
796
+ rules: locked cards for unreadable boards, and briefs and exports that never reach past what
797
+ the viewer may read. Move 7's authorization model is the shared prerequisite. A colleague
798
+ following a link to a live board and seeing it change is a hosted acceptance check.
799
+
800
+ **Native composer and board context (2026-10-12).** The plugin uses ChatGPT's
801
+ native composer, not a second PMX chat box. PMX supplies board tools and context.
802
+ This acceptance belongs to the hosted pilot (Part 4), not the current local
803
+ Waves 1–3 checkpoint or renewed full-plugin work on the private tunnel preview.
804
+ The existing Apps bridge already sends selection, pins and board context through
805
+ capability-gated `updateModelContext`, with acknowledgment and retry; keep this
806
+ separate from resource-update notifications. In the actual ChatGPT surface, change
807
+ the selection, edit a pinned card and switch boards, then verify the next response
808
+ uses the intended context and current revisions. A bridge acknowledgment alone is
809
+ not proof of model use. If the host lacks the bridge capability, use explicit board
810
+ reads and document the limitation rather than promising automatic context delivery.
811
+
812
+ Other agents should eventually be able to connect directly to the same hosted
813
+ MCP endpoint through **OAuth using the user's OpenAI login**. Both paths act
814
+ as that user and respect the same board roles, knowledge scopes and personal
815
+ privacy established by the hosted team features. External-client OAuth is a separate
816
+ compatibility goal; its current blocker does not prevent validating the
817
+ ChatGPT version and plugin distribution to an eligible audience first. Public
818
+ distribution remains subject to the separate sharing and submission checks below.
819
+ Validate browser-board sharing separately from plugin installation and connection, for
820
+ each intended audience.
821
+
822
+ **Technical validation:** a user signs in with OpenAI, creates a durable hosted
823
+ board, and uses it through the ChatGPT plugin. Installation, account connection,
824
+ rendering, context synchronisation and reconnect behavior work for the declared
825
+ supported surfaces. Record node and integration limitations explicitly.
826
+
827
+ **Product validation:** people beyond the maintainer install the plugin, use
828
+ boards for real tasks and return to them across sessions. Gather evidence of
829
+ which workflows they keep using and where the ChatGPT/Sites experience limits
830
+ them. A successful deployment or a one-off demo alone does not justify Part 5.
831
+
832
+ ### Hosted product metrics
833
+
834
+ **Decided with the maintainer, 2026-10-10:** the first hosted version needs
835
+ product usage metadata and an owner/admin dashboard from the pilot onward.
836
+ The maintainer must be able to see user numbers, overall usage, feature
837
+ adoption and evidence of where PMX provides value. The metadata must also
838
+ support continuous improvement of the whole project: product decisions, UX,
839
+ reliability, performance, node capabilities and agent-context quality across
840
+ local, ChatGPT and full hosted distributions. Carry the same metric
841
+ definitions into the later full hosted version so results remain comparable.
842
+
843
+ **Platform baseline:** Sites already supplies unique-visitor and page-view
844
+ analytics over time, currently excluding Enterprise-owned Sites. These traffic
845
+ counts do not establish PMX activation, retention or curation value; the product
846
+ events below remain PMX implementation work.
847
+ Source: [Sites analytics](https://learn.chatgpt.com/docs/sites#review-site-analytics).
848
+
849
+ | Question | Product metrics |
850
+ |---|---|
851
+ | How many people use PMX? | Total registered users (first authenticated PMX use), new users, daily/weekly/monthly active users and active workspaces. Show selected periods and trends. |
852
+ | Do new users reach useful work? | Activation funnel: first authenticated use → first board created or opened → first meaningful human action or successful agent operation → return to that board in a later session. Show conversion and time between steps. |
853
+ | Do people keep using it? | Weekly retention by first-use cohort, returning users, boards revisited across sessions and retained active workspaces. Show cohort sizes and only evaluate return windows that have elapsed. |
854
+ | What do people use? | Boards created and actively used; node creation/use by type; imports, edits, pins, links, searches and shares; MCP tool calls and context reads. Separate human activity from agent activity and break down by known client/surface. |
855
+ | Does curation reach the agent? | Sessions with human curation followed by an agent context read; fraction of eligible read sessions that receive curated items; older-board context retrieved in later sessions. Keep delivery evidence separate from task outcomes. |
856
+ | Where is the value? | Repeat use of curated boards, reuse of earlier knowledge and optional task-level helpfulness/outcome feedback. Pair these signals with Part 1's controlled curation-effect evaluation; activity or correlation alone does not prove improved work. |
857
+ | What prevents useful work? | Failed operations, failed imports, reconnect failures and operation latency, grouped by feature and surface. Include stored bytes and uploaded bytes to understand usage and serving cost drivers. |
858
+
859
+ **Count people and activity honestly.** Define an active user as an authenticated
860
+ person with a meaningful product action in the period, such as an edit, pin,
861
+ search or context retrieval. Track agent-only activity attributed to a user
862
+ separately so autonomous loops do not appear as human engagement. Exclude
863
+ heartbeats, background polling and retries from engagement counts; report
864
+ anonymous visits separately. Distinguish the requesting person from the agent
865
+ session executing a tool. Installation counts belong in the funnel only if the
866
+ distribution platform supplies them; otherwise show first observed plugin use
867
+ and label unavailable acquisition data explicitly.
868
+
869
+ **Metadata contract.** Use a small versioned event vocabulary with an event ID,
870
+ server timestamp, pseudonymous user/workspace IDs, session and board IDs,
871
+ actor kind, known client/surface, operation or feature, node type where relevant,
872
+ success/failure and duration. Include product/build version, runtime and
873
+ structured error codes where relevant so regressions can be traced to releases
874
+ and environments; do not collect raw error payloads that may contain user
875
+ content. Link curation and context-read events through
876
+ scoped IDs and revisions without copying their contents. Use server-confirmed
877
+ events for completed operations and client events for visible interactions;
878
+ deduplicate retries and keep the two event sources distinguishable. Mark
879
+ maintainer, demo, test and automation traffic so it can be excluded. Unknown
880
+ clients and unobserved outcomes stay unknown rather than being inferred.
881
+
882
+ **Turn evidence into project improvements.** Make aggregated metadata available
883
+ through an authorized query/export interface as well as the dashboard, so the
884
+ maintainer and explicitly authorized development agents can investigate it.
885
+ Use a repeatable loop: identify a pattern, form a hypothesis, reproduce it with
886
+ synthetic or explicitly provided examples, make a targeted change, and compare
887
+ the relevant measures after release. Record the evidence, expected improvement
888
+ and verification in the issue or evaluation that drives the work.
889
+
890
+ Examples include simplifying an onboarding step where users stop, fixing a node
891
+ renderer with repeated failures, reducing latency on large boards, improving a
892
+ context adapter that misses pinned material, and turning recurring defects into
893
+ regression tests. Compare releases and cohorts with their sample sizes and
894
+ instrumentation coverage; validate causal claims with controlled evaluations
895
+ or experiments. Low use alone does not justify removing a node type, and hosted
896
+ usage does not represent every local workflow. Improvements to shared code
897
+ should benefit all distributions while keeping the local verification gates.
898
+ Analytics informs prioritization and evaluation; it does not automatically
899
+ change users' boards, rewrite the roadmap or grant agents access to raw content.
900
+
901
+ **Dashboard and data boundaries.** Provide date ranges, cohort views and
902
+ breakdowns by surface, feature and node type, with clear metric definitions,
903
+ denominators and collection coverage. Restrict product-wide analytics to the
904
+ service owner or explicitly authorized product admins; workspace admins see
905
+ only their own scope. Collect behavioral metadata, not board text, prompts,
906
+ file contents, titles, email addresses or credentials as analytics payloads.
907
+ Document collection, access, retention and deletion behavior before the pilot.
908
+ Local PMX keeps local SQLite and does not silently send usage to the hosted
909
+ service; any future local telemetry is a separate explicit opt-in decision.
910
+
911
+ **Acceptance:** known test journeys produce the expected user counts, funnel
912
+ steps and retention cohorts without double-counting retries or agent loops.
913
+ An authorized product admin can inspect real pilot usage and trace a metric to
914
+ its definition and contributing metadata. Verify access isolation and absence
915
+ of content/secrets in events. Report missing instrumentation as a coverage gap,
916
+ not as zero use. Product analytics ships with the ChatGPT pilot and supplies
917
+ the adoption evidence for the Part 5 decision. Demonstrate the improvement loop
918
+ with a reproducible test journey: query a known friction or failure pattern,
919
+ link it to a proposed fix and regression check, and compare versioned results.
920
+ Use the same loop on real usage as evidence accumulates.
921
+
922
+ The milestone includes the team features (since 2026-10-19) and retains local and
923
+ single-user self-hosted distribution. The assessment below separates documented platform capabilities,
924
+ source-level portability and deployed verification; none is interchangeable.
925
+
926
+ ### Platform evidence and OAuth validation
927
+
928
+ **Checked 2026-10-10.** Sites provides browser sign-in and forwards the visitor's
929
+ identity to server code. PMX must still enforce membership, board roles and
930
+ personal-library access. Sites also offers D1 for durable records and R2 for
931
+ uploaded files. These are documented platform building blocks, not proof that
932
+ the current PMX server runs there unchanged.
933
+ Sources: [Sites sign-in](https://learn.chatgpt.com/docs/sites#add-sign-in-with-chatgpt)
934
+ and [supported site shapes](https://learn.chatgpt.com/docs/sites#choose-a-supported-site-shape).
935
+
936
+ **Plugin hosting and distribution.** The public
937
+ [Sites-hosted plugin guide](https://help.openai.com/en/articles/20001547-hosting-a-plugin-with-chatgpt-sites)
938
+ documents MCP hosting, owner publication, installation, connection and tool
939
+ updates. Business/Enterprise users can share within their workspace, subject to
940
+ permissions; each recipient needs both Site and plugin access and their own
941
+ connection. Pro/personal accounts currently cannot share a Site-hosted plugin
942
+ directly through invitations or a share link. Sharing the Site does not share
943
+ the plugin. Validate an eligible pilot audience and a supported distribution
944
+ route before promising installations beyond the owner. Browser access to the Site is a
945
+ separate path: the [Sites sharing docs](https://learn.chatgpt.com/codex/sites/publishing-and-sharing)
946
+ (checked 2026-10-19) list external invitations rolling out to Plus, Pro, Business and
947
+ Enterprise, and optional public publishing, both subject to admin controls. The plugin limit
948
+ is a distribution risk, not an established limit on hosted board links; revalidate both on
949
+ the live platform before relying on them. Public directory release
950
+ is a separate goal, not an automatic consequence of publishing the Site.
951
+
952
+ The installed **Sites plugin 1.0.1** documents a stateless JSON-RPC `POST /mcp`
953
+ endpoint declared through `capabilities: ["mcp"]`. Sites authenticates callers,
954
+ checks Site access and supplies a Site-scoped user ID. Publication provisions a
955
+ private plugin for ChatGPT/Codex and refreshes its tools on republication.
956
+ Its `get_site(include_mcp_connection: true)` contract exposes both `mcp_url` and
957
+ `oauth_resource`, explicitly described for Codex connections. This establishes
958
+ an OAuth resource mechanism, but does not establish registration, callbacks or
959
+ token issuance for arbitrary third-party clients. Implementation evidence:
960
+ the installed [MCP server reference](/Users/pepe/.codex/plugins/cache/openai-curated-remote/sites/1.0.1/skills/sites/references/site-mcp-server.md),
961
+ [identity and secrets reference](/Users/pepe/.codex/plugins/cache/openai-curated-remote/sites/1.0.1/skills/sites/references/identity-and-secrets.md),
962
+ [storage reference](/Users/pepe/.codex/plugins/cache/openai-curated-remote/sites/1.0.1/skills/sites/references/storage.md)
963
+ and native Sites tool schema, inspected on the date above. These local paths
964
+ identify the installed version on the maintainer's machine. Those installed
965
+ references are implementation guidance; they are not a public compatibility
966
+ guarantee. The automatic private plugin is also not a public-directory release;
967
+ [public submission](https://developers.openai.com/plugins/deploy/submission)
968
+ has its own connection and review requirements.
969
+ The submission guide currently excludes packages containing `apps`/`.app.json`
970
+ references and requires MCP URL configuration and connection setup instead.
971
+ Therefore, the automatically created Site plugin is not evidence that its
972
+ package or OAuth connection is ready for public submission.
973
+
974
+ **OpenAI login and MCP authorization are separate steps.** The official
975
+ [plugin sign-in guide](https://developers.openai.com/siwc/chatgpt-plugin)
976
+ describes two OAuth transactions for a custom integration: signing a user into
977
+ an application and authorizing the connector to act for that user. This is
978
+ general integration guidance, not a specification of Sites' managed auth flow.
979
+ The [website sign-in guide](https://developers.openai.com/siwc/website)
980
+ limits that commercial integration to a partner trial, separate from Sites'
981
+ built-in login.
982
+ The [MCP authentication guide](https://developers.openai.com/plugins/build/auth)
983
+ requires discovery, client identification/registration, PKCE and resource-bound
984
+ tokens. A browser session, an OpenAI ID token or an API inference token is not
985
+ evidence of a valid PMX MCP access token. Sites' service bypass credential also
986
+ supplies no visitor identity and is not a substitute for per-user OAuth.
987
+
988
+ **Live probe result, 2026-10-10: OAuth is present; plug-and-play access by a
989
+ fresh external client did not pass.** A separate owner-private
990
+ [PMX MCP OAuth validation Site](https://pmx-mcp-oauth-validation-20261010.skottpedersen.chatgpt.site)
991
+ was deployed with one read-only identity-check tool and no PMX board data.
992
+ TypeScript and the Sites production build passed; deployment reported
993
+ `succeeded` and `has_mcp: true`. This tests the platform boundary, not PMX's
994
+ full server, board isolation or renderers.
995
+
996
+ | Check | Observed result |
997
+ |---|---|
998
+ | Sites connection metadata | Returned the published `/mcp` URL as both `mcp_url` and `oauth_resource`, plus a provisioned plugin ID. |
999
+ | Unauthenticated MCP request | `401` with `WWW-Authenticate: Bearer`, a resource-discovery URL and scopes `openid resource.invoke email`. |
1000
+ | Protected-resource discovery | `200` JSON naming `https://auth.openai.com` as issuer, the exact Site `/mcp` resource and scopes including `resource.invoke` and `offline_access`. |
1001
+ | Authorization-server discovery | `https://auth.openai.com/.well-known/oauth-authorization-server` returned `200` HTML rather than JSON. PMX's installed MCP SDK 1.28.0 failed discovery with `Unexpected token '<'`; its discovery path did not continue to OpenID metadata after that parse failure. |
1002
+ | OpenID discovery, fetched separately | Valid JSON advertised authorization-code/refresh grants and `S256` PKCE, but no `registration_endpoint` or `client_id_metadata_document_supported`. |
1003
+ | Fresh-client registration preflight | Given that metadata, SDK 1.28.0 rejected registration with `Incompatible auth server: does not support dynamic client registration`. No registration request or token exchange was sent. |
1004
+
1005
+ These results establish an advertised OpenAI OAuth path and two concrete
1006
+ interoperability blockers for the tested standard client path. They do not
1007
+ prove all external clients are forbidden: a supported pre-registered client
1008
+ and explicit endpoint configuration may differ. They also do not establish
1009
+ that the Site's own browser-login client ID can be reused by another agent;
1010
+ client registration, redirect URIs and resource permissions must be approved
1011
+ for that agent. Do not borrow Codex's client identity or reuse browser/service
1012
+ credentials as a workaround. No external client has yet completed consent,
1013
+ received a resource-bound token or called the probe as a user.
1014
+
1015
+ Reproduce from the Site's challenge URL and the issuer's public metadata; retain
1016
+ the date and SDK version because platform discovery can change. The next
1017
+ dependency is a supported external-client registration/configuration from
1018
+ OpenAI or a platform change, followed by the end-to-end test below. The vision's
1019
+ “other agents simply use MCP through their OpenAI login” remains a target with
1020
+ an observed blocker, not a validated launch capability.
1021
+
1022
+ **External-client acceptance gate.** Obtain the exact published MCP URL and
1023
+ OAuth resource from Sites; inspect its unauthenticated challenge and discovery
1024
+ metadata; establish a supported registration and callback path for a named
1025
+ external client. Complete browser consent and an authorization-code/PKCE
1026
+ exchange, then call a read-only identity tool through that client. Verify token
1027
+ refresh or reauthorization, revoked access and two users' isolation before
1028
+ claiming parity. A discovery document alone is only partial validation. If
1029
+ Sites does not support external clients directly, investigate a separately
1030
+ authorized MCP gateway; that is an architectural alternative requiring a new
1031
+ decision, not an implemented fallback or a reason to expose the Site publicly.
1032
+
1033
+ ### What must change in PMX's hosted runtime
1034
+
1035
+ The installed [Sites runtime guidance](/Users/pepe/.codex/plugins/cache/openai-curated-remote/sites/1.0.1/skills/sites/SKILL.md)
1036
+ (plugin 1.0.1, checked 2026-10-10) specifies Cloudflare Workers, with 128 MB
1037
+ per isolate and HTTP-based external connections. PMX currently uses
1038
+ [`Bun.serve`](../src/server/server.ts), synchronous
1039
+ [`bun:sqlite`](../src/server/canvas-db.ts), a process-wide
1040
+ [`CanvasStateManager`](../src/server/canvas-state.ts), local files and in-memory
1041
+ SSE subscribers. Hosting therefore requires porting the server to the Sites
1042
+ runtime, not just uploading the browser bundle.
1043
+
1044
+ - **Storage and identity:** use D1 for board/knowledge records and R2 for originals and generated assets, with authorization on every read and write. Scope board selection, pins, context cursors and agent sessions to users/workspaces. Sites identity establishes who called; PMX roles determine what they may do.
1045
+ - **Live state:** preserve one authoritative mutation path while replacing reliance on a long-lived process. Prove concurrent writes, event delivery, reconnect and persistence across Worker replacement. Presence, locks, approval expiry, flow advancement and MCP app sessions also need a hosted lifecycle; do not assume timers or module-level maps survive or coordinate isolates. Select the synchronization mechanism only after checking Sites' supported bindings and streaming behavior.
1046
+ - **Assets and builds:** prebuild the canvas and viewers; serve protected documents and uploaded objects by durable IDs. Local file watching, desktop open/reveal, subprocess MCP servers, Bun.WebView screenshots and runtime package builds do not transfer unchanged. A local bridge or external builder would be a separate integration.
1047
+ - **MCP and the plugin UI:** Sites' documented tool endpoint is the starting contract. Verify PMX's resources, resource templates, notifications and MCP Apps UI embedding separately; a successful tool call does not prove that `canvas://pinned-context`, the embedded workbench or nested app frames work. Existing `isHostedWorkbench()` means an MCP App host transport is installed, not that Sites deployment is supported ([transport source](../src/client/state/workbench-transport.ts)).
1048
+
1049
+ **SDK v2 evaluation belongs to hosted-runtime work (2026-10-12).** SDK generation
1050
+ and MCP protocol revision are separate choices. The current lockfile resolves SDK
1051
+ 1.28.0; [SDK v2.3.1](https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/v2.3.1)
1052
+ offers split server/client packages and a fetch-native
1053
+ [`createMcpHandler`](https://github.com/modelcontextprotocol/typescript-sdk/blob/v2.3.1/docs/serving/http.md)
1054
+ suited to Workers and Bun. Evaluate it against Sites' actual endpoint contract;
1055
+ do not require it merely for the v1-capable improvements in moves 1 and 6a. Carry
1056
+ the evaluation into Part 5 if Sites does not need or support that serving model.
1057
+
1058
+ Migration must cover SDK-consuming dependencies together: installed MCP Apps
1059
+ [1.3.1 declares an SDK v1 peer](https://github.com/modelcontextprotocol/ext-apps/blob/v1.3.1/package.json),
1060
+ so replacing core imports alone is not a compatibility plan. Verify local stdio,
1061
+ hosted tool calls and Apps rendering/context delivery with compatible dependencies
1062
+ and the target hosts before switching. A stateless MCP handler does not supply
1063
+ board persistence, authorization or user isolation; preserve those PMX contracts
1064
+ and make retried mutations safe. Do not add sampling or background-task machinery
1065
+ just to use SDK features. Adopt them only for a concrete workflow with verified host
1066
+ support; durable jobs would still need PMX-owned persistence and recovery.
1067
+
1068
+ ### Hosted pilot operating requirements
1069
+
1070
+ **Documented platform limits, checked 2026-10-10:** D1 is limited to 10 GB per
1071
+ Site; R2 has no fixed storage limit stated. HTTP, HTTPS and WebSockets are
1072
+ supported, but raw TCP is not. Sites does not offer data residency at launch.
1073
+ Source: [Sites limits](https://learn.chatgpt.com/docs/sites#understand-limits-and-unsupported-uses).
1074
+ Separate plan-specific beta quotas apply across the account's Sites; reaching
1075
+ them can restrict storage growth or public availability. Read current allowances
1076
+ in ChatGPT. Source: [beta usage limits](https://help.openai.com/en/articles/20001339-creating-and-using-chatgpt-sites).
1077
+ The reviewed docs do not specify numerical request-rate, concurrency, CPU-time,
1078
+ upload-size or connection-duration limits for Sites. Do not substitute generic
1079
+ Cloudflare plan quotas or PMX's own 20 MiB attachment cap for platform limits.
1080
+
1081
+ Use **D1 for boards and metadata, and R2 for attachments and generated assets**
1082
+ as the pilot storage architecture. Load individual boards as needed; do not
1083
+ keep every user's boards in server memory or rely on memory for durability.
1084
+
1085
+ Set PMX's own upload-size and storage allowances and analytics retention before
1086
+ opening the pilot. Enforce those allowances and explain them to users; platform
1087
+ capacity is not an unlimited product allowance. Keep analytics retention bounded
1088
+ so usage metadata does not grow indefinitely alongside board data.
1089
+
1090
+ **Live-state proof during hosted implementation.** Run this once a working
1091
+ hosted board and MCP path exist; it is not a prerequisite for agreeing on the
1092
+ vision or continuing local development. Have a browser and an agent edit the
1093
+ same board concurrently, then disconnect and reconnect both. Verify that
1094
+ accepted edits remain durable, conflicting edits are resolved or explicitly
1095
+ rejected without silent loss, and both clients converge on the authoritative
1096
+ board. Working storage alone does not establish this behavior.
1097
+
1098
+ **Acceptance before expanding access:** after that proof passes, load-test
1099
+ concurrent editing, MCP traffic and live updates together against the deployed
1100
+ hosted runtime. Verify
1101
+ durable writes, user isolation, event delivery and reconnect behavior under
1102
+ load, and record latency, failures and resource usage. Use measured results and
1103
+ the account's actual Sites quotas to set the initial operating envelope and
1104
+ decide when access can expand.
1105
+
1106
+ **Pilot recovery.** Ship board export/import and demonstrate restoring a board
1107
+ and its selected attachments from an export before users depend on hosted
1108
+ boards. Explain that recovery covers only the data included at export time;
1109
+ later changes require another export. Recheck Sites' recovery capabilities
1110
+ during implementation rather than assuming platform-managed storage provides
1111
+ a user-accessible backup.
1112
+
1113
+ **Documentation checked 2026-10-10:** Sites documents saved deployment versions
1114
+ tied to source code, not a guarantee that restoring a version restores D1 records
1115
+ or R2 objects. Its public documentation provides no recovery guarantee or
1116
+ workflow for database backups, point-in-time recovery, attachment recovery or
1117
+ backup retention; this does not establish that internal backups are absent.
1118
+ Deleting a Site is explicitly permanent. Sources:
1119
+ [Site versions](https://learn.chatgpt.com/docs/sites#understand-projects-versions-and-deployments)
1120
+ and [Site deletion](https://help.openai.com/en/articles/20001339-creating-and-using-chatgpt-sites).
1121
+ The pilot needs a tested export-based recovery path and clear limitations;
1122
+ the full service's automated backup system belongs to Part 5.
1123
+
1124
+ ### Node compatibility for the first hosted version
1125
+
1126
+ **Source audit, 2026-10-10; no deployed node certification.** The
1127
+ [`CanvasNodeState` union](../src/client/types.ts) has 18 types. “Portable” below
1128
+ means the renderer can plausibly be reused once the common hosted backend is
1129
+ in place. “Adapt” identifies a concrete current dependency to replace.
1130
+ “Conditional” requires a platform or upstream integration test. All node types
1131
+ remain in the product vision; local-only behavior is not promised as hosted
1132
+ parity.
1133
+
1134
+ | Node type | Hosted assessment | What carries over and what must be proved or changed |
1135
+ |---|---|---|
1136
+ | `markdown` | Portable; adapt path-backed content | Inline text and editing can carry over. Local-file reads/saves need cloud document content or an explicit local bridge. Preserve links, source provenance and context text. |
1137
+ | `status` | Portable | Renders supplied status data. Live changes must use authenticated hosted writes. |
1138
+ | `context` | Portable; adapt local links | Cards, pins and AX actions can carry over. Open/reveal of a desktop path needs an uploaded resource or local bridge. |
1139
+ | `ledger` | Portable | Renders supplied entries; persist and authorize their updates in the hosted store. |
1140
+ | `trace` | Portable | Renders supplied trace data; a connected agent must deliver new events. Hosting does not create that telemetry. |
1141
+ | `file` | Adapt | Reuse text/code/table rendering. Replace `/api/file`, raw/PDF byte routes and local watchers with authorized stored objects and explicit updates. Local filesystem paths are not cloud file identities. |
1142
+ | `diff` | Portable | Displays supplied unified-diff text. Reading a local Git checkout to produce the diff remains an agent/source integration. |
1143
+ | `image` | Adapt assets | Data URLs and permitted HTTPS images can render. Local paths require uploaded objects; private image loading must work without exposing credentials. Remote sources retain their own access restrictions. |
1144
+ | `html` | Adapt surfaces | HTML and the existing primitives can use their browser renderer. Port surface documents, theme/assets and the nonce-tagged AX bridge; test sandbox/CSP and real interactions. `ax-board`/`ax-flow` additionally require hosted AX state and loop execution. |
1145
+ | `mermaid` | Adapt surfaces | The bundled browser renderer can carry over. Serve its sandboxed document and script/theme routes; verify visible output in both the Site and plugin. |
1146
+ | `mcp-app` | Conditional by mode | Remote URL frames depend on embedding policy. Prebuilt web artifacts need stored asset serving. External MCP Apps need a hosted session/credential/bridge implementation; local stdio servers cannot run unchanged. See modes below. |
1147
+ | `webpage` | Portable stored preview; conditional refresh/live frame | Stored preview data can render. Port the server fetcher while preserving SSRF/redirect restrictions; it currently uses Node DNS and pinned-IP HTTP/HTTPS. Live embedding depends on the target's CSP/X-Frame-Options, login and browser cookie policy. Keep preview/link fallback. |
1148
+ | `json-render` | Adapt viewer assets | Reuse the spec-driven browser viewer, ship its JS/CSS at deploy time, and port spec/state/action routes. Preserve `specVersion` changes so updates visibly reload. |
1149
+ | `graph` | Adapt viewer assets | Uses the json-render viewer path; apply the same asset, spec refresh and AX action checks. Supplying graph data is separate from scanning a local repository. |
1150
+ | `group` | Portable | Layout and membership follow hosted board state; preserve per-member mutation authorization. |
1151
+ | `board` | Portable with scoped queries | Port portals, navigation and backlinks. Linked boards require independent access checks; unreadable targets must reveal neither title nor context. |
1152
+ | `prompt` | Conditional execution | Existing prompt display can carry over. Submission needs authenticated delivery to an agent; Sites hosting and login do not provision an agent runtime. |
1153
+ | `response` | Portable history; conditional live stream | Stored answers can render. Live responses require a host adapter and durable delivery/reconnect behavior. |
1154
+
1155
+ **File attachments are a mode, not a nineteenth type.**
1156
+ [`FileNode`](../src/client/nodes/FileNode.tsx) selects
1157
+ [`AttachmentNode`](../src/client/nodes/AttachmentNode.tsx) when `attachmentId`
1158
+ is present. Port originals to protected object storage and metadata/import
1159
+ state to D1. Preserve the 20 MiB limit, explicit processing request, agent draft,
1160
+ human review and source-linked commit. PDF/Office extraction remains dependent
1161
+ on an agent's tools; hosting supplies neither OCR nor a converter. Local code
1162
+ dependency discovery also needs content/virtual-path indexing in place of
1163
+ [`code-graph.ts`](../src/server/code-graph.ts)'s filesystem resolution.
1164
+
1165
+ **The three `mcp-app` modes need separate promises.** Prebuilt web artifacts
1166
+ are a strong candidate, but [`web-artifacts.ts`](../src/server/web-artifacts.ts)
1167
+ currently builds packages and writes local files; build elsewhere and upload
1168
+ the result. Plain URL frames remain subject to the remote site's embed policy.
1169
+ External MCP Apps use PMX's own AppBridge and
1170
+ [`mcp-app-runtime.ts`](../src/server/mcp-app-runtime.ts), which supports HTTP
1171
+ or subprocess transports and stores sessions in a process map. Remote HTTP is
1172
+ the hosted candidate; upstream OAuth, credentials, resources and reconnect are
1173
+ separate work from the user's authentication to PMX. Transport headers/env can
1174
+ currently travel in node `transportConfig`; hosted/shared boards must use
1175
+ server-only credentials and safe references instead.
1176
+
1177
+ The [Excalidraw preset](../src/server/diagram-presets.ts) already uses remote
1178
+ HTTP and is a useful integration pilot, but must pass create, interact,
1179
+ checkpoint and reload tests. Its live app shell is not a standalone Site.
1180
+ For iframe-backed nodes, test both direct Site browsing and the nested ChatGPT
1181
+ plugin surface: sandbox identity, protected asset loading, postMessage origin
1182
+ and nonce checks, theme propagation and user-visible refresh all matter.
1183
+
1184
+ Source anchors for this assessment: [native renderers](../src/client/nodes/),
1185
+ [surface and asset routes](../src/server/server.ts),
1186
+ [viewer server](../src/json-render/server.ts),
1187
+ [webpage fetcher](../src/server/webpage-node.ts),
1188
+ [external app operations](../src/server/operations/ops/app.ts), and
1189
+ [document imports](../src/server/document-import.ts).
1190
+
1191
+ **Hosted proof before claiming compatibility:** create one board containing all
1192
+ 18 types plus attachment, primitive and web-artifact variants; verify visible
1193
+ content, edits and pinned context, not only stored node data. Repeat after
1194
+ reload/reconnect and Worker replacement, with two users whose private boards
1195
+ and credentials differ. Check the 600/1024/1920 px surfaces and nine themes from
1196
+ the design gate. Record unsupported integrations explicitly. External-client
1197
+ OAuth, full MCP resource/UI support and third-party app hosting each need their
1198
+ own passing evidence before the complete hosted promise is met.
1199
+
1200
+ ### Before standalone hosting: does PMX keep its session UI?
1201
+
1202
+ **Conditional direction, 2026-10-12.** Explicit agent-session integration is
1203
+ not a requirement for the ChatGPT plugin: ChatGPT owns the conversation, and
1204
+ PMX connects the board through the supported MCP surface. Before the later
1205
+ standalone hosted version, decide whether the session part of the canvas stays.
1206
+ If sessions remain in the agent host rather than in PMX's UI, an authenticated
1207
+ MCP connection may be enough; do not build a second session layer by default.
1208
+
1209
+ If PMX keeps its session UI, retain PMX's session experience and consider a
1210
+ clearer connection to the external harness:
1211
+
1212
+ - Bind the PMX session explicitly to the host conversation, agent identity and
1213
+ target board. Presence reports liveness, not session identity; browsing another
1214
+ board must not silently retarget the agent.
1215
+ - Show actual adapter capabilities and delivery state: connected is not the
1216
+ same as able to wake an agent, and queued steering is not yet acknowledged.
1217
+ - Let agents identify the cards or artifacts to reveal, while the human controls
1218
+ whether the canvas follows. Keep durable results and receipts separate from
1219
+ temporary cursors, activity and partial output; reconcile safely on reconnect.
1220
+
1221
+ [OpenHands Agent Canvas's UI/runtime separation](https://github.com/OpenHands/OpenHands/blob/ed77be9cfa46bc5f44031d52b9830dbd1dff95fc/docs/architecture.md)
1222
+ and its small [result-reveal tool](https://github.com/OpenHands/OpenHands/blob/ed77be9cfa46bc5f44031d52b9830dbd1dff95fc/src/api/canvas-ui-client-tool.ts)
1223
+ are inspiration, not a dependency or a spatial-canvas design to copy. Agent
1224
+ execution and tool permissions stay with the harness. This is a later product
1225
+ decision, not approval to implement session integration or a blocker for the
1226
+ ChatGPT pilot.
1227
+
1228
+ ## Part 5: Further out — full PMX Canvas hosted on Cloudflare
1229
+
1230
+ **Direction decided with the maintainer, 2026-10-10.** If the ChatGPT Sites
1231
+ version works and people use it, pursue a full standalone PMX Canvas service
1232
+ hosted directly on **Cloudflare**, with its own web experience and hosted MCP
1233
+ endpoint. PMX would manage the deployment, accounts, workspace access, storage
1234
+ and live collaboration as a product. The ChatGPT Sites edition and its plugin
1235
+ remain independently supported; plugin access to the standalone service can be
1236
+ an additional distribution channel. Agents connect to each edition through its
1237
+ supported, authenticated MCP access.
1238
+
1239
+ This is a later product investment, even though Sites already uses Cloudflare
1240
+ infrastructure underneath. The first stage validates usefulness and distribution
1241
+ within ChatGPT; the later stage gives PMX control over the complete hosted
1242
+ experience. Carry forward the board model, permissions, renderers and lessons
1243
+ from Part 4. Choose Cloudflare services, authentication providers and operational
1244
+ architecture when planning that stage; OpenAI login for arbitrary external
1245
+ clients remains subject to the validation above.
1246
+
1247
+ **Gate to start:** review evidence of recurring use by people beyond the
1248
+ maintainer, successful plugin distribution and concrete needs that justify a
1249
+ standalone service, using Part 4's product metrics alongside user feedback.
1250
+ Proceed when that evidence supports the investment; if it
1251
+ does not, improve the first version before expanding the hosting scope. There
1252
+ is no automatic launch date or adoption threshold invented in this vision.
1253
+ Local and single-user self-hosted PMX remain part of the product; this service is PMX-managed, not a customer-operated team server.
1254
+
1255
+ **Full hosted backup and recovery.** Before users depend on the standalone
1256
+ Cloudflare service, establish automated backups of board data and attachments,
1257
+ define retention and recovery targets, and demonstrate restoring an accidentally
1258
+ deleted or damaged board with its assets. Keep user exports as an additional
1259
+ safeguard. Durable storage alone is not a backup, and a deployment rollback is
1260
+ not proof of data recovery.
1261
+
1262
+ ### Likely repository structure: shared product, separate runtimes
1263
+
1264
+ **Architectural direction, 2026-10-10:** a monorepo is the likely fit for
1265
+ supporting three delivery surfaces: the working local PMX Canvas, the ChatGPT
1266
+ version validated and distributed through its plugin, and later the full
1267
+ standalone hosted version. Confirm the package
1268
+ boundaries during implementation; this is not a request to reorganise the
1269
+ repository before the ChatGPT validation needs it.
1270
+
1271
+ The decision, tradeoffs and rejected alternatives are recorded in
1272
+ [ADR-002: Shared product core, separate runtime editions](adr-002-shared-product-separate-runtimes.md).
1273
+
1274
+ - **Shared product:** the board model, mutation rules, context compilation, node renderers and canvas UI should be reused across distributions. Keep runtime dependencies out of this shared code.
1275
+ - **Local runtime:** retain the Bun server, local SQLite store, filesystem access/watchers, local MCP entry point and existing CLI/SDK workflows. Local PMX must remain usable without a cloud account, hosted service or network connection for its local features.
1276
+ - **ChatGPT version / Sites runtime:** adapt the shared product to Sites' identity, storage and MCP contracts for the first validation and plugin distribution. Keep this experience working as the product grows; it is a supported delivery surface, not a disposable prototype.
1277
+ - **Cloudflare runtime:** later compose the same product into the full hosted service, with deployment, identity, storage and live-state integrations under PMX's control. Reuse suitable Sites work without making the standalone service depend on Sites.
1278
+
1279
+ **Runtime boundaries (2026-10-15).** Keep one modular product, with explicit construction
1280
+ and shutdown for each edition. Shared code does not acquire concrete storage, install global
1281
+ listeners or start local services merely by being imported. Enforce dependency direction:
1282
+ contracts and product rules do not depend on runtime entrypoints; remote clients do not
1283
+ import local execution machinery. The boundaries include:
1284
+
1285
+ - **Identity and permissions:** edition-specific authentication supplies the principal;
1286
+ shared rules enforce grants across reads, writes, derived metadata and event delivery.
1287
+ - **Durable and temporary state:** boards, work items, gate deadlines and audit records
1288
+ outlive a process; presence, connections, waits and timers have explicit owners and recovery
1289
+ behavior. A viewer's current board is not another caller's write target.
1290
+ - **External capabilities:** filesystem access, network fetches, subprocess MCP, builds and
1291
+ WebView automation belong to runtime adapters. Document supported behavior per edition,
1292
+ including expiry and live-session behavior; absent capabilities are explicit, not silent
1293
+ substitutes. Reusing a renderer does not make its sandbox or host protocol interchangeable.
1294
+
1295
+ Package boundaries are not service boundaries. Keep board, context and relation consistency
1296
+ together initially; extract a deployed service only for a concrete security, execution-lifetime,
1297
+ scaling or failure-isolation need. [ADR-001](adr-001-bun-only-runtime.md) remains the local
1298
+ Bun runtime/SDK decision, not a ban on runtime-neutral product code or the hosted editions.
1299
+ This does not introduce a Node dual-build or cloud dependency for local users.
1300
+
1301
+ **Three shared contracts:** operation requests/results, the workbench's request/event/asset
1302
+ protocol, and the editable board archive. Define and test the supported portions of each
1303
+ across editions. MCP is a host adapter over those product operations; a common registration
1304
+ module does not prove that Sites supports every local resource, subscription or embedded app.
1305
+
1306
+ **Extraction gate:** after the current acceptance checkpoint, establish these boundaries
1307
+ through one complete read/edit/commit/reconnect slice, not a broad folder move. Exercise a
1308
+ browser and agent conflict, lost-response retry, persistence failure, runtime restart,
1309
+ independent board navigation and an unreadable linked source. Preserve local offline behavior;
1310
+ a simulated async runtime does not validate Sites or Cloudflare. Recheck platform support
1311
+ and prove the slice there before expanding the port. Package names, interfaces, storage
1312
+ mechanisms and the extraction sequence belong in a scoped implementation plan.
1313
+
1314
+ **Shared-runtime maintenance checkpoint (2026-10-11).** The current lifecycle evaluator
1315
+ acquires data from the local `canvasState` singleton. When a second runtime needs it, separate
1316
+ runtime acquisition from qualification so the same rules consume an authorized board snapshot.
1317
+ Apply access checks before computing source titles, summaries and lifecycle reasons, not only
1318
+ before returning content. Categories are not permissions. Verify unreadable-source behavior
1319
+ and the local offline path before claiming the shared boundary is ready; do not split packages
1320
+ ahead of that need.
1321
+
1322
+ **Continuity for early local users.** Existing users keep their local canvas,
1323
+ boards, SQLite storage and local workflows as hosted versions arrive. Shared
1324
+ product improvements continue to reach the local version wherever the runtime
1325
+ supports them. Hosting is an additional way to use PMX, not a required migration,
1326
+ cloud account or upload of existing boards. Moving data to a hosted version is
1327
+ the user's explicit choice.
1328
+
1329
+ **Board portability and independent editions.** Local PMX, ChatGPT Sites and
1330
+ the future Cloudflare service each own their boards and storage independently.
1331
+ Sharing core code does not imply shared live state or automatic synchronization;
1332
+ each edition remains useful on its own.
1333
+
1334
+ Provide one shared, editable board export/import format across all three
1335
+ editions. Users deliberately transfer a board by exporting it from one edition
1336
+ and importing a copy into another; later edits remain independent. Preserve
1337
+ node content, layout, edges, groups, annotations, context pins, provenance and
1338
+ the attachments/assets the user chooses to include. Preserve the knowledge
1339
+ context too: relevant category definitions, folder/board assignments, the
1340
+ effective inherited lifecycle policy and its source, explicit overrides,
1341
+ validation status and evidence references, last-validated timestamps, retired
1342
+ state, and review/restore history. Include only the definitions and folder
1343
+ metadata needed for the selected boards, not the whole workspace taxonomy or
1344
+ private neighbouring boards. Export review shows what metadata and evidence
1345
+ will leave with the content. This portable archive is additional to today's
1346
+ read-only HTML export.
1347
+
1348
+ **Archive version policy:** version the interchange format and decide the supported import
1349
+ versions and explicit upgrade path before users depend on it. Reject unsupported archives
1350
+ before changing destination data; never silently discard content to fit a newer format.
1351
+ This is a user-data contract, not automatic authorization for legacy API shims or indefinite
1352
+ format support. The implementation plan must resolve that policy explicitly alongside local
1353
+ data continuity rather than infer it from the repository's no-backwards-compatibility rule.
1354
+
1355
+ **Identity and relations.** Import creates a new board by default, assigning
1356
+ destination IDs to copied boards, cards and assets while retaining their origin
1357
+ IDs as provenance. Use an explicit ID map to reconnect edges, groups, pins,
1358
+ portals and evidence references within the imported set; never match by title
1359
+ or accidentally reconnect a copied ID to an unrelated destination object.
1360
+ Linked boards are included only when explicitly selected and authorised.
1361
+ References to objects outside the archive remain marked external/unresolved,
1362
+ with only metadata authorised for export, until the user explicitly reconnects
1363
+ them. A missing target does not delete the relation or grant access to its source.
1364
+
1365
+ **Lifecycle and authority.** Show category/policy conflicts before import;
1366
+ never overwrite a destination category merely because its name matches.
1367
+ Preserve the exported effective policy by default, even if the source folder
1368
+ ancestry is absent; mapping to a destination policy is an explicit choice with
1369
+ its effects shown and recorded. Import or recovery from an archive does not
1370
+ renew validation or reactivate cards retired in that archive; the deliberate
1371
+ Lifecycle-tab restore remains a separate action. Keep original review dates, evidence and historical
1372
+ attribution, recording the import separately. Missing or inaccessible evidence
1373
+ is flagged without erasing its historical validation record or claiming a fresh
1374
+ check. Historical actors are provenance, not destination identities or roles.
1375
+
1376
+ Destination ownership and permissions apply; credentials and source access
1377
+ grants never travel with the archive. Local file references and live
1378
+ integrations may need reconnecting, with unavailable capabilities made explicit.
1379
+
1380
+ **Portability acceptance:** round-trip a representative board between the
1381
+ local and ChatGPT editions for the pilot, and add Cloudflare to the same checks
1382
+ when that edition exists. Include two linked boards, an unexported target, a
1383
+ same-named destination category with different defaults, a card with a lifecycle
1384
+ override, a retired card and a review whose evidence is unavailable. Verify ID
1385
+ remapping, retained relationships and selected attachments, explicit unresolved
1386
+ references, category conflict handling, unchanged validation dates and retired
1387
+ state, preserved review history, destination permissions and independent edits
1388
+ after import. The recovery check states which history and assets the archive
1389
+ includes; preserving review history does not imply a complete mutation journal
1390
+ or all snapshots.
1391
+
1392
+ Keep the local product as a maintained distribution, not a frozen predecessor
1393
+ or a thin client that requires the cloud. Keep the ChatGPT plugin and its user
1394
+ experience supported as its own edition when the full hosted version arrives.
1395
+ Runtime adapters should represent
1396
+ real platform differences, with explicit capability limits for features such
1397
+ as local file watching and subprocess MCP servers. Avoid separate copies of
1398
+ product logic or a broad abstraction framework built before it is needed.
1399
+
1400
+ **Acceptance:** changes to shared code pass the local verification ladder as
1401
+ well as the relevant hosted checks. A clean installed local package can still
1402
+ start, create and persist boards, render nodes and serve its local MCP tools
1403
+ without hosted credentials. Test supported common behavior across runtimes and
1404
+ document the differences; hosted progress must not silently break local PMX.
366
1405
 
367
1406
  ## Architecture diagnosis at the original review
368
1407
 
@@ -399,7 +1438,7 @@ Revised 2026-09-23 and 2026-09-24. The original 0.6 bundled five moves into 2–
399
1438
  |---|---|---|
400
1439
  | 0.7 | Many boards stage 1 with the nine real boards restored, and library backup (move 0); the S half of trust (move 7: `res.ok` toasts, redirect host filter); read instrumentation (Part 1, item 4); the Chromium 600 px reference project (5). | The nine boards open by name; a backup restores them on a clean machine; a refused write shows its reason; every node type paints at 600 px; agent reads are being recorded. |
401
1440
  | 0.7.x | Static export with the per-board rule (11). | A colleague opens an exported board with no install. This is the second-user milestone. |
402
- | 0.8 | Portals, README card, `canvas://boards`, search across boards (0), a meaningful text form for every node type (1), document drop as Markdown context (15), new board from this board (14), author on every node and attributed ask answers with the boot secret (7), the one read with its cross-board tier (Part 1), the cheap tool surface (6a), the binary (8). | "What changed since the April OKRs?" is answered from a board linked to the April board, without the agent being told which board to read; imported documents are readable, source-linked and searchable; the per-type text-form check passes; the measurement from 0.7 is read against the Part 1 decision rule and the outcome is written into this document. |
1441
+ | 0.8 | Portals, README card, `canvas://boards`, search across boards (0), a meaningful text form for every node type (1), document drop as Markdown context (15), new board from this board (14), author on every node and attributed ask answers with the boot secret (7), the one read with its cross-board tier (Part 1), the cheap tool surface (6a), the binary (8). | "What changed since the April OKRs?" is answered from a board linked to the April board, without the agent being told which board to read; imported documents are readable, source-linked and searchable; the per-type text-form check passes; the curation benchmark (Part 1, item 4) is run and its gap recorded. |
403
1442
  | 0.9 | Wiki links and the board map, make board and inline board (0), tours (12), recipe cards (13), the frame host (5). | A board with 20 portals mounts no more iframes than one without; a tour runs inside an exported file. |
404
1443
  | 1.0 | The journal and bookmarks (4), the agent's output onto the board (3), the SDK through the registry, the M half of trust with the read-only share link (7, Part 3 step 2), time scrubber, culling and frame budget (9). | A colleague follows a shared link to a live board and sees it change. |
405
1444
  | After 1.0 | Comments and a second writer (Part 3 steps 3–4), concurrent boards (0, stage 2), state as a fold of the journal, generated surfaces (6b, if decided), session projection (Part 1, item 2). | Each step starts only when the previous one is in use. |
@@ -410,7 +1449,7 @@ Revised 2026-09-23 and 2026-09-24. The original 0.6 bundled five moves into 2–
410
1449
  - The minimalist deletes the registry. Refuted three to zero: the browser alone calls 55 API paths.
411
1450
  - The rendering architect deletes the tool rail and top bar. Design for 600 px first; the rail is the good part of the chrome.
412
1451
  - Every vision, and my own first draft, proposed cutting node types on the strength of the repo's test board. The real boards refute the chart cut outright, and the maintainer's rule closes the rest: usage on one machine is not evidence of non-use. No node type is cut; consolidation is confined to how nodes render.
413
- - Four of six visions leaned on Obsidian, and five on git, as the format, the snapshot system, or the remote transport. The maintainer's rule is that this is its own app with no reliance on externals, and I agree: the app owns its history (the journal), its store (SQLite), and its remote reach (tokens and a listen mode). What survives of the folder idea is an export.
1452
+ - Four of six visions leaned on Obsidian, and five on git, as the format, the snapshot system, or the remote transport. For local and self-hosted distribution, the maintainer's rule is that this is its own app with no reliance on externals, and I agree: the app owns its history (the journal), its store (SQLite), and its remote reach (tokens and a listen mode). What survives of the folder idea is an export.
414
1453
  - Several visions invented constants (700 chars, six frames, 14k lines) with the same confidence they mocked the repo's. So did I. Every such number in this document is a starting value to tune in use, not a claim.
415
1454
 
416
1455
  ## Evidence