pmx-canvas 0.8.2 → 0.9.1

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 (338) 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 +59 -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/human-store.d.ts +2 -1
  53. package/dist/types/client/state/intent-bridge.d.ts +11 -8
  54. package/dist/types/client/state/knowledge-store.d.ts +22 -0
  55. package/dist/types/client/state/near-pin-store.d.ts +44 -1
  56. package/dist/types/client/state/presence-store.d.ts +4 -4
  57. package/dist/types/client/state/presentation.d.ts +28 -0
  58. package/dist/types/client/state/relation-store.d.ts +10 -0
  59. package/dist/types/client/state/session-store.d.ts +41 -2
  60. package/dist/types/client/state/workspace-settings.d.ts +7 -0
  61. package/dist/types/client/types.d.ts +13 -1
  62. package/dist/types/client/utils/keyboard.d.ts +2 -0
  63. package/dist/types/client/utils/time-ago.d.ts +4 -0
  64. package/dist/types/mcp/context-uri-template.d.ts +3 -1
  65. package/dist/types/server/agent-presence.d.ts +10 -3
  66. package/dist/types/server/ax-context.d.ts +1 -1
  67. package/dist/types/server/canvas-db.d.ts +30 -7
  68. package/dist/types/server/canvas-operations.d.ts +24 -2
  69. package/dist/types/server/canvas-provenance.d.ts +22 -2
  70. package/dist/types/server/canvas-serialization.d.ts +2 -0
  71. package/dist/types/server/canvas-state.d.ts +93 -15
  72. package/dist/types/server/canvas-validation.d.ts +1 -1
  73. package/dist/types/server/context-brief.d.ts +94 -6
  74. package/dist/types/server/context-reads.d.ts +33 -7
  75. package/dist/types/server/edit-summary.d.ts +20 -0
  76. package/dist/types/server/index.d.ts +71 -10
  77. package/dist/types/server/knowledge-lifecycle.d.ts +221 -0
  78. package/dist/types/server/lifecycle-status.d.ts +10 -0
  79. package/dist/types/server/memory-graph.d.ts +9 -0
  80. package/dist/types/server/mutation-history.d.ts +2 -0
  81. package/dist/types/server/operations/ops/ax-shared.d.ts +1 -1
  82. package/dist/types/server/operations/ops/boards.d.ts +2 -1
  83. package/dist/types/server/operations/ops/lifecycle.d.ts +2 -0
  84. package/dist/types/server/operations/ops/memory-graph.d.ts +2 -0
  85. package/dist/types/server/operations/ops/nodes.d.ts +5 -0
  86. package/dist/types/server/operations/ops/query.d.ts +23 -0
  87. package/dist/types/server/operations/registry.d.ts +1 -0
  88. package/dist/types/server/placement.d.ts +7 -0
  89. package/dist/types/server/scope-fence.d.ts +2 -1
  90. package/dist/types/server/spatial-analysis.d.ts +6 -3
  91. package/dist/types/server/tour-control.d.ts +32 -0
  92. package/dist/types/server/wiki-links.d.ts +14 -0
  93. package/dist/types/server/workbench-auth.d.ts +2 -0
  94. package/dist/types/shared/agent-context.d.ts +2 -0
  95. package/dist/types/shared/agent-presence.d.ts +15 -12
  96. package/dist/types/shared/auto-arrange.d.ts +1 -0
  97. package/dist/types/shared/boards.d.ts +4 -4
  98. package/dist/types/shared/knowledge-lifecycle.d.ts +41 -0
  99. package/dist/types/shared/knowledge-presets.d.ts +6 -0
  100. package/dist/types/shared/lifecycle-status.d.ts +24 -0
  101. package/dist/types/shared/memory-graph.d.ts +53 -0
  102. package/dist/types/shared/relations.d.ts +68 -0
  103. package/dist/types/shared/semantic-attention.d.ts +2 -0
  104. package/dist/types/shared/tour.d.ts +38 -0
  105. package/dist/types/shared/workspace-settings.d.ts +11 -0
  106. package/docs/RELEASE.md +21 -3
  107. package/docs/adr-001-bun-only-runtime.md +7 -1
  108. package/docs/adr-002-shared-product-separate-runtimes.md +93 -0
  109. package/docs/api-reference.md +109 -0
  110. package/docs/ax-host-adapter-contract.md +1 -1
  111. package/docs/ax-state-contract.md +5 -4
  112. package/docs/cli.md +153 -15
  113. package/docs/demos/pmx-canvas-demo.mp4 +0 -0
  114. package/docs/design/AgentContext.dc.html +3 -3
  115. package/docs/design/BoardPins.dc.html +37 -22
  116. package/docs/design/Categories.dc.html +208 -0
  117. package/docs/design/CategoryEditor.dc.html +33 -0
  118. package/docs/design/Chrome.dc.html +52 -9
  119. package/docs/design/ContextChip.dc.html +224 -0
  120. package/docs/design/ContextChip600.dc.html +136 -0
  121. package/docs/design/EmptyState.dc.html +45 -0
  122. package/docs/design/Flows.dc.html +23 -1
  123. package/docs/design/HeaderMarks.dc.html +183 -0
  124. package/docs/design/Home.dc.html +19 -1
  125. package/docs/design/HomeGraph.dc.html +86 -202
  126. package/docs/design/HomeMap.dc.html +23 -1
  127. package/docs/design/HomeTeam.dc.html +32 -14
  128. package/docs/design/Lifecycle.dc.html +22 -0
  129. package/docs/design/Lifecycle600.dc.html +18 -0
  130. package/docs/design/LifecycleVariants.dc.html +157 -0
  131. package/docs/design/LinkAuthorship.dc.html +139 -0
  132. package/docs/design/LinksChanged.dc.html +203 -0
  133. package/docs/design/LinksOptions.dc.html +137 -0
  134. package/docs/design/LinksOptions600.dc.html +134 -0
  135. package/docs/design/NearPin.dc.html +9 -10
  136. package/docs/design/Pane600.dc.html +4 -3
  137. package/docs/design/Relations.dc.html +3 -2
  138. package/docs/design/Restore.dc.html +152 -0
  139. package/docs/design/SeeChange.dc.html +267 -0
  140. package/docs/design/Uses.dc.html +12 -6
  141. package/docs/design/canvas.json +146 -19
  142. package/docs/design.md +449 -16
  143. package/docs/environment.md +0 -1
  144. package/docs/evals/curation-effect.md +128 -0
  145. package/docs/http-api.md +459 -37
  146. package/docs/mcp.md +146 -18
  147. package/docs/node-types.md +58 -3
  148. package/docs/plans/design-gaps-2026-10-08.md +53 -0
  149. package/docs/plans/plan-009-tech-debt-backlog.md +379 -0
  150. package/docs/plans/plan-016-context-made-visible-wave-1.md +150 -5
  151. package/docs/plans/plan-017-knowledge-categories-and-lifecycle.md +175 -0
  152. package/docs/plans/plan-018-connected-memory-wave-2.md +594 -0
  153. package/docs/plans/plan-019-post-0.9-roadmap.md +198 -0
  154. package/docs/product-context-vision-2026-09.md +17 -1
  155. package/docs/product-vision-2026-09.md +1082 -43
  156. package/docs/product-vision-review-2026-09.md +13 -1
  157. package/docs/screenshots/workbench-live-dark.png +0 -0
  158. package/docs/screenshots/workbench-live-light.png +0 -0
  159. package/docs/sdk.md +62 -2
  160. package/package.json +1 -1
  161. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
  162. package/plugins/pmx-canvas/plugin.json +1 -1
  163. package/plugins/pmx-canvas/runtime.json +1 -1
  164. package/plugins/pmx-canvas/tools.json +601 -22
  165. package/skills/pmx-canvas/SKILL.md +216 -42
  166. package/skills/pmx-canvas/evals/evals.json +224 -0
  167. package/skills/pmx-canvas/references/full-reference.md +120 -21
  168. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
  169. package/skills/pmx-canvas/references/importing-context.md +132 -0
  170. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  171. package/skills/pmx-canvas/references/tours-and-recording.md +16 -1
  172. package/skills/pmx-canvas-testing/SKILL.md +20 -0
  173. package/src/cli/agent.ts +2 -0
  174. package/src/cli/commands/ax.ts +12 -0
  175. package/src/cli/commands/boards.ts +88 -11
  176. package/src/cli/commands/edges.ts +28 -0
  177. package/src/cli/commands/groups.ts +7 -0
  178. package/src/cli/commands/nodes.ts +1 -0
  179. package/src/cli/commands/query.ts +34 -2
  180. package/src/cli/commands/record.ts +199 -48
  181. package/src/cli/index.ts +6 -1
  182. package/src/client/App.tsx +177 -70
  183. package/src/client/canvas/AttentionHistory.tsx +0 -2
  184. package/src/client/canvas/BarHint.tsx +40 -2
  185. package/src/client/canvas/BoardCopyDialog.tsx +1 -1
  186. package/src/client/canvas/BoardFolderDialog.tsx +7 -7
  187. package/src/client/canvas/BoardLinkDialog.tsx +138 -33
  188. package/src/client/canvas/BoardPinButton.tsx +33 -0
  189. package/src/client/canvas/BoardSwitcher.tsx +26 -40
  190. package/src/client/canvas/CanvasNode.tsx +360 -237
  191. package/src/client/canvas/CanvasViewport.tsx +45 -7
  192. package/src/client/canvas/CommandBar.tsx +29 -23
  193. package/src/client/canvas/CommandPalette.tsx +5 -12
  194. package/src/client/canvas/ConnectionBanner.tsx +3 -3
  195. package/src/client/canvas/ContextChip.tsx +296 -0
  196. package/src/client/canvas/ContextMenu.tsx +63 -5
  197. package/src/client/canvas/CrossBoardReferences.tsx +60 -0
  198. package/src/client/canvas/EdgeLayer.tsx +339 -76
  199. package/src/client/canvas/EmptyState.tsx +33 -18
  200. package/src/client/canvas/ExpandedNodeOverlay.tsx +72 -40
  201. package/src/client/canvas/ExternalWriters.tsx +57 -42
  202. package/src/client/canvas/HomeGraphView.tsx +942 -0
  203. package/src/client/canvas/HomeMapView.tsx +641 -0
  204. package/src/client/canvas/HomeReviewView.tsx +167 -0
  205. package/src/client/canvas/HomeView.tsx +687 -160
  206. package/src/client/canvas/IntentLayer.tsx +19 -12
  207. package/src/client/canvas/KnowledgeDialog.tsx +488 -0
  208. package/src/client/canvas/LifecycleChrome.tsx +133 -0
  209. package/src/client/canvas/LifecycleFields.tsx +91 -0
  210. package/src/client/canvas/LifecyclePanel.tsx +543 -0
  211. package/src/client/canvas/MemoryInspector.tsx +104 -0
  212. package/src/client/canvas/Minimap.tsx +3 -3
  213. package/src/client/canvas/NearPinLayer.tsx +187 -0
  214. package/src/client/canvas/NodeContextMark.tsx +175 -97
  215. package/src/client/canvas/Presentation.tsx +23 -57
  216. package/src/client/canvas/RelationPresetsDialog.tsx +413 -0
  217. package/src/client/canvas/RelationsPanel.tsx +82 -0
  218. package/src/client/canvas/SelectionBar.tsx +3 -6
  219. package/src/client/canvas/SessionPanel.tsx +90 -50
  220. package/src/client/canvas/SessionReceipt.tsx +311 -39
  221. package/src/client/canvas/ShortcutOverlay.tsx +1 -1
  222. package/src/client/canvas/SnapshotPanel.tsx +27 -36
  223. package/src/client/canvas/ToolRail.tsx +367 -192
  224. package/src/client/canvas/TopBar.tsx +354 -124
  225. package/src/client/canvas/canvas-area.ts +10 -3
  226. package/src/client/canvas/graph-geometry.ts +195 -0
  227. package/src/client/canvas/graph-model.ts +254 -0
  228. package/src/client/canvas/memory-layout.ts +106 -0
  229. package/src/client/canvas/use-chrome-height.ts +20 -0
  230. package/src/client/canvas/use-focus-trap.ts +31 -5
  231. package/src/client/canvas/use-memory-graph.ts +58 -0
  232. package/src/client/canvas/use-node-drag.ts +2 -1
  233. package/src/client/canvas/use-pan-zoom.ts +64 -7
  234. package/src/client/icons.tsx +0 -63
  235. package/src/client/mcp-app/style.css +0 -6
  236. package/src/client/nodes/AxStepControls.tsx +74 -50
  237. package/src/client/nodes/BoardNode.tsx +5 -1
  238. package/src/client/nodes/ContextNode.tsx +18 -11
  239. package/src/client/nodes/ExtAppFrame.tsx +6 -3
  240. package/src/client/nodes/FileNode.tsx +46 -42
  241. package/src/client/nodes/HtmlNode.tsx +32 -0
  242. package/src/client/nodes/ImageNode.tsx +1 -1
  243. package/src/client/nodes/InlineFormatBar.tsx +6 -9
  244. package/src/client/nodes/InlineMarkdownEditor.tsx +56 -17
  245. package/src/client/nodes/MarkdownNode.tsx +377 -109
  246. package/src/client/nodes/McpAppNode.tsx +50 -20
  247. package/src/client/nodes/MdFormatBar.tsx +21 -18
  248. package/src/client/nodes/PromptNode.tsx +1 -1
  249. package/src/client/nodes/ResponseNode.tsx +1 -1
  250. package/src/client/nodes/viewer-runtime-state.ts +54 -22
  251. package/src/client/state/attention-bridge.ts +64 -15
  252. package/src/client/state/boards-store.ts +193 -39
  253. package/src/client/state/canvas-store.ts +99 -12
  254. package/src/client/state/context-chip-store.ts +70 -0
  255. package/src/client/state/context-status-store.ts +53 -0
  256. package/src/client/state/human-store.ts +13 -7
  257. package/src/client/state/intent-bridge.ts +51 -30
  258. package/src/client/state/knowledge-store.ts +43 -0
  259. package/src/client/state/near-pin-store.ts +115 -6
  260. package/src/client/state/presence-store.ts +7 -10
  261. package/src/client/state/presentation.ts +91 -0
  262. package/src/client/state/relation-store.ts +81 -0
  263. package/src/client/state/session-store.ts +144 -18
  264. package/src/client/state/sse-bridge.ts +235 -32
  265. package/src/client/state/workspace-settings.ts +11 -0
  266. package/src/client/theme/global.css +2724 -476
  267. package/src/client/types.ts +12 -0
  268. package/src/client/utils/keyboard.ts +10 -0
  269. package/src/client/utils/time-ago.ts +14 -0
  270. package/src/json-render/renderer/index.tsx +31 -0
  271. package/src/mcp/canvas-app.ts +12 -2
  272. package/src/mcp/context-uri-template.ts +7 -4
  273. package/src/mcp/server.ts +63 -41
  274. package/src/mcp/workbench-app.ts +39 -6
  275. package/src/server/agent-presence.ts +128 -28
  276. package/src/server/ax-context.ts +27 -13
  277. package/src/server/board-export.ts +12 -1
  278. package/src/server/canvas-db.ts +331 -42
  279. package/src/server/canvas-operations.ts +195 -83
  280. package/src/server/canvas-provenance.ts +53 -22
  281. package/src/server/canvas-serialization.ts +2 -0
  282. package/src/server/canvas-state.ts +950 -122
  283. package/src/server/canvas-validation.ts +9 -2
  284. package/src/server/context-brief.ts +345 -38
  285. package/src/server/context-reads.ts +178 -30
  286. package/src/server/demo-state.json +355 -24
  287. package/src/server/edit-summary.ts +74 -0
  288. package/src/server/html-surface.ts +8 -1
  289. package/src/server/index.ts +181 -11
  290. package/src/server/knowledge-lifecycle.ts +304 -0
  291. package/src/server/lifecycle-status.ts +232 -0
  292. package/src/server/memory-graph.ts +166 -0
  293. package/src/server/mutation-history.ts +18 -6
  294. package/src/server/operations/composites.ts +32 -11
  295. package/src/server/operations/http.ts +7 -2
  296. package/src/server/operations/index.ts +4 -0
  297. package/src/server/operations/mcp.ts +26 -1
  298. package/src/server/operations/ops/ax-presence.ts +1 -1
  299. package/src/server/operations/ops/ax-read.ts +57 -6
  300. package/src/server/operations/ops/ax-timeline.ts +28 -2
  301. package/src/server/operations/ops/backup.ts +5 -3
  302. package/src/server/operations/ops/batch.ts +35 -4
  303. package/src/server/operations/ops/boards.ts +188 -47
  304. package/src/server/operations/ops/canvas-wire.ts +31 -1
  305. package/src/server/operations/ops/edges.ts +36 -2
  306. package/src/server/operations/ops/groups.ts +6 -1
  307. package/src/server/operations/ops/lifecycle.ts +262 -0
  308. package/src/server/operations/ops/memory-graph.ts +45 -0
  309. package/src/server/operations/ops/nodes.ts +107 -24
  310. package/src/server/operations/ops/query.ts +281 -68
  311. package/src/server/operations/ops/snapshots.ts +73 -1
  312. package/src/server/operations/ops/validate.ts +5 -1
  313. package/src/server/operations/ops/viewport.ts +97 -3
  314. package/src/server/operations/registry.ts +74 -25
  315. package/src/server/placement.ts +29 -0
  316. package/src/server/scope-fence.ts +78 -6
  317. package/src/server/server.ts +115 -16
  318. package/src/server/spatial-analysis.ts +48 -23
  319. package/src/server/tour-control.ts +82 -0
  320. package/src/server/wiki-links.ts +137 -0
  321. package/src/server/workbench-auth.ts +11 -0
  322. package/src/shared/agent-context.ts +3 -0
  323. package/src/shared/agent-presence.ts +15 -15
  324. package/src/shared/auto-arrange.ts +2 -0
  325. package/src/shared/boards.ts +4 -4
  326. package/src/shared/knowledge-lifecycle.ts +22 -0
  327. package/src/shared/knowledge-presets.ts +80 -0
  328. package/src/shared/lifecycle-status.ts +26 -0
  329. package/src/shared/memory-graph.ts +74 -0
  330. package/src/shared/relations.ts +98 -0
  331. package/src/shared/semantic-attention.ts +15 -1
  332. package/src/shared/tour.ts +23 -5
  333. package/src/shared/workspace-settings.ts +13 -0
  334. package/dist/types/client/canvas/ContextPinBar.d.ts +0 -1
  335. package/dist/types/client/canvas/FocusFieldLayer.d.ts +0 -1
  336. package/dist/types/client/canvas/kind-colors.d.ts +0 -3
  337. package/dist/types/server/agent-context.d.ts +0 -22
  338. package/src/client/canvas/ContextPinBar.tsx +0 -25
@@ -13,7 +13,7 @@
13
13
  * richer hooks may `set` a phase, cursor, or focus explicitly.
14
14
  */
15
15
  import { z } from 'zod';
16
- import { type AgentPhase, type AgentPresence, type AgentPresenceSnapshot, type ContextBudget } from '../shared/agent-presence.js';
16
+ import { type AgentPhase, type AgentPresence, type AgentPresenceSnapshot } from '../shared/agent-presence.js';
17
17
  import type { PmxAxActivityKind } from './ax-state.js';
18
18
  type PresenceEmitter = (event: string, payload: Record<string, unknown>) => void;
19
19
  /** A legal writer label: short, alphanumeric/dash, letter-first (header and env values). */
@@ -94,8 +94,6 @@ export declare const PRESENCE_SET_SHAPE: {
94
94
  total: z.ZodNumber;
95
95
  }, z.core.$strip>>>;
96
96
  };
97
- /** Token estimate of the pinned-context payload — the same serialization the MCP resource ships. */
98
- export declare function estimateContextBudget(): ContextBudget;
99
97
  /** Returns the id of the pre-session snapshot the server took, if any. */
100
98
  type SessionStartListener = (presence: AgentPresence) => string | null;
101
99
  export type SessionEndReason = 'human' | 'agent' | 'idle-timeout';
@@ -173,11 +171,20 @@ export declare class AgentPresenceRegistry {
173
171
  * (a gate opened or resolved) without any writer being touched.
174
172
  */
175
173
  refresh(): void;
174
+ /** Bumped when an agent read is recorded: the live lens's read list changed. */
175
+ private readVersion;
176
+ /** A read landed (server.ts's read listener): re-count and re-emit. */
177
+ noteRead(): void;
178
+ /** A board opened: attached sessions record it as they find it, before any write lands. */
179
+ boardOpened(): void;
176
180
  /** Remove a writer (session-end). */
177
181
  detach(sessionId: string): boolean;
178
182
  snapshot(now?: number): AgentPresenceSnapshot;
183
+ /** Latest attached session: a newly attached reviewer must check fast context again. */
184
+ reviewSessionStartedAt(): number | null;
179
185
  /** Test / shutdown hook. */
180
186
  reset(): void;
187
+ /** `withTouches`: only emitted snapshots carry the session's touches (they read the DB). */
181
188
  private publicView;
182
189
  private hasPendingGate;
183
190
  private evictOverflow;
@@ -22,7 +22,7 @@ export interface PmxAxSurfaceSnapshot {
22
22
  * human review text is redacted below.
23
23
  */
24
24
  export declare function buildCanvasAxSurfaceSnapshot(): PmxAxSurfaceSnapshot;
25
- export declare function buildCanvasAxPinnedContext(): PmxAxPinnedContext;
25
+ export declare function buildCanvasAxPinnedContext(qualifications?: Record<string, import("../shared/lifecycle-status.js").LifecycleQualification>): PmxAxPinnedContext;
26
26
  export declare function buildCanvasAxContext(consumer?: string): PmxAxContext & {
27
27
  boardId: string | null;
28
28
  };
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { Database } from 'bun:sqlite';
8
8
  import type { ActorAttribution } from './attribution.js';
9
+ import { type RelationDefinition } from '../shared/relations.js';
9
10
  import { type Tour } from '../shared/tour.js';
10
11
  import { type CanvasThemeName } from '../shared/themes.js';
11
12
  import type { CanvasAnnotation, CanvasEdge, CanvasNodeState, CanvasSnapshot, CanvasSnapshotListOptions, ViewportState } from './canvas-state.js';
@@ -76,28 +77,50 @@ export declare function loadStateFromDB(db: Database, boardId?: string): Persist
76
77
  export interface CanvasBoard {
77
78
  id: string;
78
79
  name: string;
79
- /** A human-chosen shelf on Home ("Planning", "Research"); null is uncategorized. */
80
- category: string | null;
80
+ /** A human-chosen folder on Home ("Planning", "Research"); null is unfiled. */
81
+ folder: string | null;
81
82
  createdAt: string;
82
83
  lastOpenedAt: string | null;
83
84
  nodeCount: number;
84
85
  /** Markdown node used as this board's introduction. */
85
86
  readmeNodeId: string | null;
87
+ /** Human-dragged position in Home Map; null uses the generated folder layout. */
88
+ mapPosition?: {
89
+ x: number;
90
+ y: number;
91
+ } | null;
92
+ /** The source of a recurring/template board, separate from ordinary portals. */
93
+ previousBoardId?: string | null;
94
+ relationVocabulary?: RelationDefinition[];
95
+ /** Pinned into the agent's working set (vision move 0a); null when not pinned. */
96
+ pin: ContextPinMeta | null;
86
97
  }
87
98
  /** Most recently opened first, then never-opened boards, newest first. */
88
99
  export declare function listBoardsFromDB(db: Database): CanvasBoard[];
89
100
  export declare function getBoardFromDB(db: Database, id: string): CanvasBoard | null;
90
- export declare function createBoardInDB(db: Database, name: string, category?: string | null): CanvasBoard;
91
- /** Rename and/or re-shelve a board; `category: null` removes it from its category. */
101
+ export declare function createBoardInDB(db: Database, name: string, folder?: string | null): CanvasBoard;
102
+ /** Pin a board into the working set, or unpin it with null. False when the board does not exist. */
103
+ export declare function setBoardPinInDB(db: Database, id: string, meta: ContextPinMeta | null): boolean;
104
+ /** Rename and/or re-shelve a board; `folder: null` unfiles it. */
92
105
  export declare function updateBoardInDB(db: Database, id: string, patch: {
93
106
  name?: string;
94
- category?: string | null;
107
+ folder?: string | null;
95
108
  readmeNodeId?: string | null;
109
+ mapPosition?: {
110
+ x: number;
111
+ y: number;
112
+ } | null;
113
+ previousBoardId?: string | null;
114
+ relationVocabulary?: RelationDefinition[];
96
115
  }): boolean;
97
116
  /** Create and populate an inactive board as one SQLite transaction. */
98
- export declare function createBoardWithStateInDB(db: Database, name: string, category: string | null, state: PersistedCanvasState, readmeNodeId: string | null): CanvasBoard;
117
+ export declare function createBoardWithStateInDB(db: Database, name: string, folder: string | null, state: PersistedCanvasState, readmeNodeId: string | null, invalidateTarget?: (boardId: string, nodeId: string) => void): CanvasBoard;
118
+ /** Derived incoming-link metadata only: the target owns its clock and its body. */
119
+ export declare function invalidateLinksInDB(db: Database, boardId: string, nodeId: string): number | undefined;
120
+ /** A target's appearance/disappearance changes its incoming saved relations on source cards. */
121
+ export declare function invalidateIncomingLinksInDB(db: Database, boardId: string, nodeId: string | null, invalidate: (boardId: string, nodeId: string) => void): void;
99
122
  /** Deletes a board with its rows and its snapshots. */
100
- export declare function deleteBoardFromDB(db: Database, id: string): boolean;
123
+ export declare function deleteBoardFromDB(db: Database, id: string, invalidateTarget?: (boardId: string, nodeId: string) => void): boolean;
101
124
  export declare function readMetaFromDB(db: Database, key: string): string | null;
102
125
  /** Write a workspace-wide meta value; null removes it. */
103
126
  export declare function writeMetaToDB(db: Database, key: string, value: string | null): void;
@@ -38,6 +38,7 @@ export interface CanvasStructuredNodeUpdateInput extends Omit<CanvasGraphNodeUpd
38
38
  chartHeight?: unknown;
39
39
  }
40
40
  interface CanvasAddNodeInput {
41
+ prepareOnlyNodes?: CanvasNodeState[];
41
42
  type: CanvasNodeState['type'];
42
43
  title?: string;
43
44
  content?: string;
@@ -89,6 +90,10 @@ export declare function describeCreateSize(requestedWidth: number | undefined, r
89
90
  height: number;
90
91
  }): CanvasSizeAdjustment | undefined;
91
92
  interface CanvasCreateGroupInput {
93
+ destinationBoardId?: string;
94
+ requestId?: string;
95
+ expectedBoardId?: string | null;
96
+ intentId?: string;
92
97
  title?: string;
93
98
  childIds?: string[];
94
99
  x?: number;
@@ -101,6 +106,7 @@ interface CanvasCreateGroupInput {
101
106
  interface CanvasNodeLookupInput {
102
107
  id?: string;
103
108
  search?: string;
109
+ board?: string;
104
110
  }
105
111
  export declare function hasStructuredNodeUpdateFields(input: Record<string, unknown>): boolean;
106
112
  export declare function buildStructuredNodeUpdate(node: CanvasNodeState, input: CanvasStructuredNodeUpdateInput): {
@@ -226,16 +232,23 @@ export declare function deleteCanvasSnapshot(id: string): {
226
232
  };
227
233
  export declare function gcCanvasSnapshots(options?: Parameters<typeof canvasState.gcSnapshots>[0]): ReturnType<typeof canvasState.gcSnapshots>;
228
234
  export declare function addCanvasEdge(input: {
235
+ destinationBoardId?: string;
236
+ requestId?: string;
237
+ expectedBoardId?: string | null;
238
+ intentId?: string;
229
239
  from?: string;
230
240
  to?: string;
241
+ toBoardId?: string;
231
242
  fromSearch?: string;
232
243
  toSearch?: string;
233
244
  type: CanvasEdge['type'];
245
+ kind?: string;
246
+ reason?: string;
234
247
  label?: string;
235
248
  style?: CanvasEdge['style'];
236
249
  animated?: boolean;
237
250
  }): CanvasEdge;
238
- export declare function updateCanvasEdge(id: string, patch: Partial<Pick<CanvasEdge, 'type' | 'label' | 'style' | 'animated'>>): CanvasEdge;
251
+ export declare function updateCanvasEdge(id: string, patch: Partial<Pick<CanvasEdge, 'type' | 'kind' | 'reason' | 'label' | 'style' | 'animated'>>): CanvasEdge;
239
252
  export declare function removeCanvasEdge(id: string): {
240
253
  removed: boolean;
241
254
  };
@@ -244,6 +257,12 @@ export declare function createCanvasGroup(input: CanvasCreateGroupInput): {
244
257
  node: CanvasNodeState;
245
258
  sizeAdjustment?: CanvasSizeAdjustment;
246
259
  };
260
+ /** One logical creation identity across node, frame and link operations. */
261
+ export declare function storedCreationTarget(input: object, operation: string): {
262
+ boardId: string;
263
+ requestId: string | undefined;
264
+ fingerprint: string;
265
+ };
247
266
  export declare function groupCanvasNodes(groupId: string, childIds: string[], options?: {
248
267
  childLayout?: CanvasArrangeMode;
249
268
  }): {
@@ -305,7 +324,10 @@ export declare function createCanvasGraphNode(input: GraphNodeInput): {
305
324
  node: CanvasNodeState;
306
325
  sizeAdjustment?: CanvasSizeAdjustment;
307
326
  };
308
- export declare function setClientViewportSize(width: unknown, height: unknown): void;
327
+ export declare function setClientViewportSize(width: unknown, height: unknown, insets?: {
328
+ top: number;
329
+ bottom: number;
330
+ }): void;
309
331
  export declare function getClientViewportSize(): {
310
332
  width: number;
311
333
  height: number;
@@ -1,13 +1,33 @@
1
+ import { z } from 'zod';
1
2
  export type CanvasNodeType = 'markdown' | 'mcp-app' | 'webpage' | 'json-render' | 'graph' | 'board' | 'prompt' | 'response' | 'status' | 'context' | 'ledger' | 'trace' | 'file' | 'diff' | 'mermaid' | 'image' | 'html' | 'group';
2
- export type CanvasNodeProvenanceSourceKind = 'workspace-file' | 'webpage-url' | 'mcp-tool' | 'artifact-file' | 'image-url';
3
- export type CanvasNodeRefreshStrategy = 'file-watch' | 'file-read-write' | 'image-reload' | 'webpage-refresh' | 'mcp-app-rehydrate' | 'artifact-reopen';
3
+ export type CanvasNodeProvenanceSourceKind = 'workspace-file' | 'webpage-url' | 'mcp-tool' | 'artifact-file' | 'image-url' | 'recipe';
4
+ export type CanvasNodeRefreshStrategy = 'file-watch' | 'file-read-write' | 'image-reload' | 'webpage-refresh' | 'mcp-app-rehydrate' | 'artifact-reopen' | 'agent-request';
5
+ declare const observedSourceSchema: z.ZodObject<{
6
+ boardId: z.ZodString;
7
+ cardId: z.ZodString;
8
+ contentRevision: z.ZodOptional<z.ZodNumber>;
9
+ observedAt: z.ZodOptional<z.ZodISODateTime>;
10
+ availability: z.ZodOptional<z.ZodEnum<{
11
+ live: "live";
12
+ cached: "cached";
13
+ unavailable: "unavailable";
14
+ }>>;
15
+ }, z.core.$strip>;
16
+ declare const recipeSchema: z.ZodObject<{
17
+ tool: z.ZodString;
18
+ input: z.ZodOptional<z.ZodUnknown>;
19
+ prompt: z.ZodString;
20
+ }, z.core.$strip>;
4
21
  export interface CanvasNodeProvenance {
5
22
  sourceKind: CanvasNodeProvenanceSourceKind;
6
23
  sourceUri: string;
7
24
  refreshStrategy: CanvasNodeRefreshStrategy;
8
25
  snapshotContent: boolean;
9
26
  syncedAt?: string;
27
+ sources?: Array<z.infer<typeof observedSourceSchema>>;
28
+ recipe?: z.infer<typeof recipeSchema>;
10
29
  details?: Record<string, unknown>;
11
30
  }
12
31
  export declare function inferCanvasNodeProvenance(nodeType: CanvasNodeType, data: Record<string, unknown>): CanvasNodeProvenance | null;
13
32
  export declare function normalizeCanvasNodeData<T extends Record<string, unknown>>(nodeType: CanvasNodeType, data: T): T;
33
+ export {};
@@ -1,6 +1,8 @@
1
1
  import type { CanvasAnnotation, CanvasLayout, CanvasNodeState, ViewportState } from './canvas-state.js';
2
2
  import { type CanvasNodeProvenance } from './canvas-provenance.js';
3
+ import type { LifecycleQualification } from '../shared/lifecycle-status.js';
3
4
  export interface SerializedCanvasNode extends CanvasNodeState {
5
+ qualification?: LifecycleQualification;
4
6
  kind: string;
5
7
  title: string | null;
6
8
  content: string | null;
@@ -11,8 +11,12 @@
11
11
  * `.pmx-canvas-snapshots/`, loose blob files) are no longer imported as of 0.4.0 —
12
12
  * the one-shot boot migration into SQLite was retired.
13
13
  */
14
+ import { type WorkspaceSettings } from '../shared/workspace-settings.js';
15
+ import { KnowledgeLifecycle, type Lifecycle } from './knowledge-lifecycle.js';
14
16
  import { type Tour } from '../shared/tour.js';
15
- import { type CanvasBoard, type ContextPinMeta, type PersistedCanvasState, type CanvasTheme, type AxTimelineQuery } from './canvas-db.js';
17
+ import { type WikiBoard } from './wiki-links.js';
18
+ import { type WikiLink } from '../shared/memory-graph.js';
19
+ import { updateBoardInDB, type CanvasBoard, type ContextPinMeta, type PersistedCanvasState, type CanvasTheme, type AxTimelineQuery } from './canvas-db.js';
16
20
  import { type DocumentImport, type DocumentImportStatus, type ImportSection, type Attachment } from './document-import.js';
17
21
  import { type PmxAxActivityKind, type PmxAxElicitation, type PmxAxModeRequest, type PmxAxMode, type PmxAxCommandDescriptor, type PmxAxPolicy, type PmxAxFocusState, type PmxAxSource, type PmxAxState, type PmxAxWorkItem, type PmxAxWorkItemStatus, type PmxAxApprovalGate, type PmxAxReviewAnnotation, type PmxAxReviewKind, type PmxAxReviewSeverity, type PmxAxReviewStatus, type PmxAxReviewAnchorType, type PmxAxReviewRegion, type PmxAxEvent, type PmxAxEventKind, type PmxAxEvidence, type PmxAxEvidenceKind, type PmxAxSteeringMessage, type PmxAxHostCapability, type PmxAxTimelineSummary } from './ax-state.js';
18
22
  import { type ActorAttribution } from './attribution.js';
@@ -75,6 +79,12 @@ export interface CanvasNodeState {
75
79
  lastEditedBy?: ActorAttribution;
76
80
  /** Board-monotonic revision of this node's latest semantic content. */
77
81
  contentRevision?: number;
82
+ /** Time of that semantic change; absent for content created before this clock was recorded. */
83
+ contentChangedAt?: string;
84
+ /** Initial authored freshness, not evidence validation. Imports and undated existing content have none. */
85
+ freshnessStartedAt?: string;
86
+ /** Board-monotonic revision of this node's latest link change, kept apart from its text. */
87
+ linksRevision?: number;
78
88
  }
79
89
  export interface NodeDeletionTombstone {
80
90
  nodeId: string;
@@ -101,10 +111,25 @@ export interface CanvasEdge {
101
111
  id: string;
102
112
  from: string;
103
113
  to: string;
114
+ /** Target on another board. Source and mutation ownership stay on the active board. */
115
+ toBoardId?: string;
104
116
  type: 'relation' | 'depends-on' | 'flow' | 'references';
117
+ /** Open semantic relation kind, independent of the structural edge type. */
118
+ kind?: string;
119
+ reason?: string;
120
+ /** Source content observed when an explicit dependency was authored. Never refreshed by reads. */
121
+ sourceRevision?: number;
105
122
  label?: string;
106
123
  style?: 'solid' | 'dashed' | 'dotted';
107
124
  animated?: boolean;
125
+ /** Board revision of this link's latest add, retype or relabel (0 = never stamped). */
126
+ revision?: number;
127
+ /** Who made that change, and when: the link's author until a person changes it again. */
128
+ changedBy?: ActorAttribution;
129
+ changedAt?: string;
130
+ /** Who first drew the link, and when (docs/design/LinkAuthorship.dc.html). */
131
+ createdBy?: ActorAttribution;
132
+ createdAt?: string;
108
133
  }
109
134
  export interface CanvasAnnotationPoint {
110
135
  x: number;
@@ -229,6 +254,7 @@ declare class CanvasStateManager {
229
254
  private _db;
230
255
  private _dbPath;
231
256
  private _saveTimer;
257
+ readonly knowledge: KnowledgeLifecycle;
232
258
  /** Workspace root backing persistence and workspace-relative path resolution. */
233
259
  get workspaceRoot(): string;
234
260
  /** Set the workspace root to enable auto-persistence. */
@@ -269,10 +295,14 @@ declare class CanvasStateManager {
269
295
  /** The open board, or null on Home. */
270
296
  get activeBoardId(): string | null;
271
297
  getActiveBoard(): CanvasBoard | null;
272
- /**
273
- * One board's content without opening it: the open board from memory, any
274
- * other straight from SQLite. Null when there is no such board.
275
- */
298
+ /** Synchronous, owner-controlled static creation. No board activation or runtime hydration. */
299
+ createStoredNode(boardId: string, requestId: string | undefined, fingerprint: string, build: (nodes: CanvasNodeState[]) => CanvasNodeState): CanvasNodeState;
300
+ private stampStoredNode;
301
+ createStoredGroup(boardId: string, requestId: string | undefined, fingerprint: string, build: (nodes: CanvasNodeState[]) => CanvasNodeState, childLayout?: 'grid' | 'column' | 'flow'): CanvasNodeState;
302
+ createStoredEdge(boardId: string, requestId: string | undefined, fingerprint: string, build: (nodes: CanvasNodeState[]) => CanvasEdge): CanvasEdge;
303
+ /** Stored creations share one durable receipt/commit boundary, never a temporary board switch. */
304
+ private createStoredCreation;
305
+ /** Read a board without activating it. This projection is not a write payload. */
276
306
  readBoard(id: string, includeBlobs?: boolean): {
277
307
  board: CanvasBoard;
278
308
  state: PersistedCanvasState;
@@ -305,17 +335,21 @@ declare class CanvasStateManager {
305
335
  getContextBriefCursor(boardId: string, consumer: string): number | null;
306
336
  advanceContextBriefCursor(boardId: string, consumer: string, revision: number): void;
307
337
  /** Creates a board without opening it. */
308
- createBoard(name: string, category?: string | null): CanvasBoard | null;
309
- updateBoard(id: string, patch: {
310
- name?: string;
311
- category?: string | null;
312
- }): boolean;
338
+ createBoard(name: string, folder?: string | null): CanvasBoard | null;
339
+ updateBoard(id: string, patch: Pick<Parameters<typeof updateBoardInDB>[2], 'name' | 'folder' | 'mapPosition' | 'relationVocabulary'>): boolean;
313
340
  setBoardReadme(id: string, nodeId: string | null): boolean;
341
+ /**
342
+ * Pin a board into the agent's working set (vision move 0a). Workspace-level:
343
+ * survives board switches and restarts. A repeat pin keeps its first
344
+ * attribution, like card pins. False when the board does not exist.
345
+ */
346
+ pinBoard(id: string, reason?: string): boolean;
347
+ unpinBoard(id: string): boolean;
314
348
  /** Bounded inactive-board creation; never replaces the state the human has open. */
315
349
  createBoardFromBoard(input: {
316
350
  sourceBoardId: string;
317
351
  name: string;
318
- category?: string | null;
352
+ folder?: string | null;
319
353
  nodeIds?: string[];
320
354
  includeReadme?: boolean;
321
355
  includeStructure?: boolean;
@@ -337,6 +371,7 @@ declare class CanvasStateManager {
337
371
  /** Debounced save — coalesces rapid mutations into a single write. */
338
372
  private scheduleSave;
339
373
  flushToDisk(): void;
374
+ private persistedState;
340
375
  /** Write current state to SQLite immediately. */
341
376
  private saveToDisk;
342
377
  private _lastPersistenceError;
@@ -379,19 +414,49 @@ declare class CanvasStateManager {
379
414
  clearAllSnapshots(): void;
380
415
  private restampRestoredContent;
381
416
  private semanticData;
417
+ /** A small name/ID catalog, read only when Markdown is saved, never on a drag frame. */
418
+ wikiCatalog(): WikiBoard[];
419
+ /** Backfill only uninitialized live rows, not snapshots or authoritative empty/unresolved bindings. */
420
+ private initializePersistedWikiLinks;
421
+ private bindWikiLinks;
382
422
  private nodeContentChanged;
383
423
  private setSemanticNode;
384
424
  private recordDeletion;
385
425
  get viewport(): ViewportState;
386
- addNode(node: CanvasNodeState): void;
426
+ addNode(node: CanvasNodeState, savedWikiLinks?: WikiLink[]): void;
427
+ private recordNodeCreation;
387
428
  addJsonRenderNode(node: CanvasNodeState): void;
388
429
  addGraphNode(node: CanvasNodeState): void;
389
- updateNode(id: string, patch: Partial<CanvasNodeState>): void;
430
+ /** Metadata stays on the stored node: no blob hydration, wiki resolution or group reflow. */
431
+ setNodeLifecycle(id: string, value: Lifecycle | null): void;
432
+ updateNode(id: string, patch: Partial<CanvasNodeState>, savedWikiLinks?: WikiLink[] | null): void;
390
433
  removeNode(id: string): void;
391
434
  getNode(id: string): CanvasNodeState | undefined;
435
+ /** Who made and last edited each card, and its content revision — no content, no copies. */
436
+ nodeStamps(): Array<Pick<CanvasNodeState, 'id' | 'createdBy' | 'lastEditedBy' | 'contentRevision'>>;
392
437
  getNodeForPersistence(id: string): CanvasNodeState | undefined;
438
+ /**
439
+ * Links are tracked apart from text (connection changes, option C of
440
+ * docs/design/LinksOptions.dc.html): a link change advances both endpoints'
441
+ * links revision, never their content revision, so cards keep their read
442
+ * marks while the next incremental brief resends them with their new
443
+ * relations. Generated auto-edges (code graph, board map) do not count.
444
+ * Returns the stamp for the changed link.
445
+ */
446
+ private touchRelations;
447
+ private invalidateRelationTarget;
448
+ /** Saved wiki relationships have the same source/target clocks as native links. */
449
+ private touchWikiRelations;
450
+ private invalidateIncomingRelations;
393
451
  addEdge(edge: CanvasEdge): boolean;
394
- updateEdge(id: string, patch: Partial<Pick<CanvasEdge, 'type' | 'label' | 'style' | 'animated'>>): CanvasEdge | null;
452
+ private relationSourceRevision;
453
+ updateEdge(id: string, patch: Partial<Pick<CanvasEdge, 'type' | 'kind' | 'reason' | 'label' | 'style' | 'animated'>>): CanvasEdge | null;
454
+ /**
455
+ * An edge as undo/redo puts it back. A relation change restores the link as it
456
+ * was, author included, under a new revision so the next brief carries it; a
457
+ * style-only change keeps the current stamp, so it never hides a later relabel.
458
+ */
459
+ private replayEdge;
395
460
  removeEdge(id: string): boolean;
396
461
  getEdges(): CanvasEdge[];
397
462
  getEdgesForNode(nodeId: string): CanvasEdge[];
@@ -409,6 +474,8 @@ declare class CanvasStateManager {
409
474
  };
410
475
  setViewport(v: Partial<ViewportState>): void;
411
476
  get theme(): CanvasTheme;
477
+ getWorkspaceSettings(): WorkspaceSettings;
478
+ updateWorkspaceSettings(patch: Partial<WorkspaceSettings>): WorkspaceSettings;
412
479
  setTheme(theme: CanvasTheme): CanvasTheme;
413
480
  get contextPinnedNodeIds(): Set<string>;
414
481
  getAxState(): PmxAxState;
@@ -614,10 +681,21 @@ declare class CanvasStateManager {
614
681
  getAxTimelineSummary(): PmxAxTimelineSummary;
615
682
  /** Records one agent context read (diagnostics; never notifies, so a read cannot trigger reads). */
616
683
  recordContextRead(input: ContextReadInput, boardId?: string | null): ContextRead | null;
617
- /** The delivered ids that are nodes on the read board, each with its content revision now. */
684
+ /**
685
+ * The delivered ids that are nodes on the read board: those read in full with
686
+ * their content revision now, and every one that arrived (summaries included)
687
+ * with its links revision now.
688
+ */
618
689
  private readRevisions;
690
+ /** Per node on a board, the newest links revision an agent read carried. */
691
+ getSeenLinks(boardId?: string | null): Record<string, number>;
619
692
  /** Per node on a board, the latest agent read that delivered its content. */
620
693
  getNodeReadStatus(boardId?: string | null): NodeReadStatus[];
694
+ /** The latest agent read on a board, of any kind, or null. */
695
+ getBoardLastRead(boardId?: string | null): {
696
+ lastReadAt: string;
697
+ lastReadBy: string;
698
+ } | null;
621
699
  /** Nodes on a board whose content an agent read at or after `since` (ISO). */
622
700
  getReadNodeIdsSince(boardId: string | null, since: string): string[];
623
701
  getContextReads(limit?: number): {
@@ -46,4 +46,4 @@ export interface CanvasValidationResult {
46
46
  sizeWarnings: number;
47
47
  };
48
48
  }
49
- export declare function validateCanvasLayout(layout: CanvasLayout): CanvasValidationResult;
49
+ export declare function validateCanvasLayout(layout: CanvasLayout, remoteEndpointExists?: (boardId: string, cardId: string) => boolean): CanvasValidationResult;
@@ -1,7 +1,8 @@
1
+ import type { LifecycleQualification } from '../shared/lifecycle-status.js';
1
2
  import type { CanvasNodeState, NodeDeletionTombstone } from './canvas-state.js';
2
- export type ContextBriefReason = 'pinned' | 'near' | 'changed' | 'human' | 'ask' | 'steer' | 'linked' | 'category';
3
- /** A near entry carries a short summary, never full content: pin the node to send that. */
4
- export declare const NEAR_SUMMARY_LENGTH = 280;
3
+ export type ContextBriefReason = 'overview' | 'pinned' | 'near' | 'changed' | 'pinned-board' | 'human' | 'ask' | 'steer' | 'linked' | 'folder';
4
+ /** How long a card's summary is in the brief: enough to know what it is. */
5
+ export declare const BRIEF_SUMMARY_LENGTH = 280;
5
6
  export interface ContextBriefSourceEntry {
6
7
  sourceBoardId: string;
7
8
  nodeId: string;
@@ -16,7 +17,7 @@ export interface ContextBriefSourceEntry {
16
17
  export interface ContextBriefLibraryBoard {
17
18
  boardId: string;
18
19
  name: string;
19
- category: string | null;
20
+ folder: string | null;
20
21
  readme?: {
21
22
  nodeId: string;
22
23
  title: string;
@@ -33,12 +34,70 @@ export interface ContextBriefLibraryBoard {
33
34
  /** IDs of link cards on the active board which explicitly target this board. */
34
35
  linkIds: string[];
35
36
  }
37
+ /**
38
+ * A board in the working set (vision move 0a), sent as a map: enough to know what
39
+ * it is and how it relates, so the agent decides what to pull in full.
40
+ */
41
+ export interface ContextBriefPinnedBoard {
42
+ boardId: string;
43
+ name: string;
44
+ folder: string | null;
45
+ readmeSummary: string | null;
46
+ readmeNodeId?: string;
47
+ /** Pinned cards as title + short summary, each pullable by id. */
48
+ cards: Array<{
49
+ nodeId: string;
50
+ title: string;
51
+ summary: string;
52
+ }>;
53
+ /** Names of the boards it links to and is linked from. */
54
+ links: string[];
55
+ backlinks: string[];
56
+ }
57
+ /** The open board at a glance: what it is and how it relates to other boards. */
58
+ export interface ContextBriefOverview {
59
+ folder: string | null;
60
+ readmeSummary: string | null;
61
+ readmeNodeId?: string;
62
+ links: string[];
63
+ backlinks: string[];
64
+ }
65
+ export interface ContextBriefEdge {
66
+ from: string;
67
+ to: string;
68
+ toBoardId?: string;
69
+ /** Readable qualified target title, resolved by the shared memory graph. */
70
+ remoteTitle?: string;
71
+ type: string;
72
+ kind?: string;
73
+ reason?: string;
74
+ label?: string | null;
75
+ /** Board revision of the link's latest add, retype or relabel, and who made it. */
76
+ revision?: number;
77
+ changedBy?: {
78
+ actor: string;
79
+ source: string;
80
+ agentId?: string;
81
+ };
82
+ /** Equal to changedAt while the link is as first drawn: "new" rather than "changed". */
83
+ createdAt?: string;
84
+ changedAt?: string;
85
+ }
36
86
  export interface ContextBriefInput {
87
+ qualifications?: Readonly<Record<string, LifecycleQualification>>;
37
88
  activeBoard: {
38
89
  boardId: string;
39
90
  name: string;
40
- category: string | null;
91
+ folder: string | null;
41
92
  };
93
+ /** The brief is a map, not a dump: overview and relations let the agent choose what to pull. */
94
+ overview?: ContextBriefOverview;
95
+ /** Edges on the open board, carried as each card's relations. */
96
+ edges?: readonly ContextBriefEdge[];
97
+ /** Saved wiki/portal connections from the shared library projection. */
98
+ memoryRelations?: Readonly<Record<string, string[]>>;
99
+ /** Why each pin was pinned, when someone said. */
100
+ pinReasons?: Readonly<Record<string, string>>;
42
101
  nodes: readonly CanvasNodeState[];
43
102
  pinnedNodeIds: readonly string[];
44
103
  contentRevision: number;
@@ -47,11 +106,15 @@ export interface ContextBriefInput {
47
106
  /** null means a first read. Other values must be non-negative safe integers. */
48
107
  since: number | null;
49
108
  libraryBoards: readonly ContextBriefLibraryBoard[];
109
+ /** Pinned boards, each sent as a map (see ContextBriefPinnedBoard). */
110
+ pinnedBoards?: readonly ContextBriefPinnedBoard[];
50
111
  entries?: readonly ContextBriefSourceEntry[];
51
112
  /** Maximum JavaScript string length (UTF-16 code units), including the JSON envelope. */
52
113
  budget: number;
53
114
  }
54
115
  export interface CompiledContextEntry {
116
+ qualification?: LifecycleQualification;
117
+ readmeQualification?: LifecycleQualification;
55
118
  sourceBoardId: string;
56
119
  nodeId: string;
57
120
  reason: ContextBriefReason;
@@ -66,6 +129,17 @@ export interface CompiledContextEntry {
66
129
  };
67
130
  /** The body was shortened to fit; the same revision remains eligible on the next pull. */
68
131
  truncated?: true;
132
+ /** A title + short summary of a card the agent may pull in full; seen, not read. */
133
+ summaryOnly?: true;
134
+ /** Relations were capped or not included; do not acknowledge the complete links revision. */
135
+ linksComplete?: false;
136
+ /** Link clock of the actual delivered relations, not the later recording time. */
137
+ linksRevision?: number;
138
+ /**
139
+ * On a later read, what changed on this card since the cursor
140
+ * (docs/design/LinksChanged.dc.html): its text, its links, or both.
141
+ */
142
+ changes?: Array<'text' | 'links'>;
69
143
  provenance?: {
70
144
  kind: 'imported';
71
145
  source: string;
@@ -78,7 +152,7 @@ export interface ContextBriefDocument {
78
152
  board: {
79
153
  boardId: string;
80
154
  name: string;
81
- category: string | null;
155
+ folder: string | null;
82
156
  };
83
157
  cursor: {
84
158
  requested: number | null;
@@ -89,6 +163,20 @@ export interface ContextBriefDocument {
89
163
  valid: boolean;
90
164
  };
91
165
  entries: CompiledContextEntry[];
166
+ /** Independent of the content cursor. Only complete snapshots replace cached qualification. */
167
+ lifecycle?: {
168
+ scope: 'workspace';
169
+ complete: boolean;
170
+ instruction?: string;
171
+ retired: string[];
172
+ unknown: string[];
173
+ review: Array<{
174
+ key: string;
175
+ due: boolean;
176
+ reasons: string[];
177
+ sources: LifecycleQualification['sources'];
178
+ }>;
179
+ };
92
180
  deletions: Array<{
93
181
  sourceBoardId: string;
94
182
  nodeId: string;