pmx-canvas 0.8.0 → 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 (341) 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 +66 -0
  4. package/Readme.md +131 -532
  5. package/dist/canvas/global.css +2759 -510
  6. package/dist/canvas/index.js +168 -107
  7. package/dist/canvas/mcp-app.html +2936 -632
  8. package/dist/json-render/index.css +81 -1
  9. package/dist/json-render/index.js +20 -20
  10. package/dist/types/client/canvas/BarHint.d.ts +12 -2
  11. package/dist/types/client/canvas/BoardLinkDialog.d.ts +3 -1
  12. package/dist/types/client/canvas/BoardPinButton.d.ts +10 -0
  13. package/dist/types/client/canvas/BoardSwitcher.d.ts +1 -1
  14. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  15. package/dist/types/client/canvas/CommandBar.d.ts +3 -4
  16. package/dist/types/client/canvas/ConnectionBanner.d.ts +2 -1
  17. package/dist/types/client/canvas/ContextChip.d.ts +3 -0
  18. package/dist/types/client/canvas/CrossBoardReferences.d.ts +5 -0
  19. package/dist/types/client/canvas/EdgeLayer.d.ts +14 -3
  20. package/dist/types/client/canvas/EmptyState.d.ts +4 -4
  21. package/dist/types/client/canvas/HomeGraphView.d.ts +2 -0
  22. package/dist/types/client/canvas/HomeMapView.d.ts +1 -0
  23. package/dist/types/client/canvas/HomeReviewView.d.ts +6 -0
  24. package/dist/types/client/canvas/HomeView.d.ts +9 -7
  25. package/dist/types/client/canvas/KnowledgeDialog.d.ts +4 -0
  26. package/dist/types/client/canvas/LifecycleChrome.d.ts +5 -0
  27. package/dist/types/client/canvas/LifecycleFields.d.ts +7 -0
  28. package/dist/types/client/canvas/LifecyclePanel.d.ts +1 -0
  29. package/dist/types/client/canvas/MemoryInspector.d.ts +7 -0
  30. package/dist/types/client/canvas/NearPinLayer.d.ts +14 -0
  31. package/dist/types/client/canvas/NodeContextMark.d.ts +40 -7
  32. package/dist/types/client/canvas/RelationPresetsDialog.d.ts +4 -0
  33. package/dist/types/client/canvas/RelationsPanel.d.ts +4 -0
  34. package/dist/types/client/canvas/SessionPanel.d.ts +2 -0
  35. package/dist/types/client/canvas/canvas-area.d.ts +1 -1
  36. package/dist/types/client/canvas/graph-geometry.d.ts +27 -0
  37. package/dist/types/client/canvas/graph-model.d.ts +37 -0
  38. package/dist/types/client/canvas/memory-layout.d.ts +23 -0
  39. package/dist/types/client/canvas/use-chrome-height.d.ts +2 -0
  40. package/dist/types/client/canvas/use-focus-trap.d.ts +1 -0
  41. package/dist/types/client/canvas/use-memory-graph.d.ts +8 -0
  42. package/dist/types/client/canvas/use-pan-zoom.d.ts +4 -1
  43. package/dist/types/client/icons.d.ts +0 -10
  44. package/dist/types/client/nodes/AxStepControls.d.ts +1 -1
  45. package/dist/types/client/nodes/HtmlNode.d.ts +1 -0
  46. package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +4 -4
  47. package/dist/types/client/nodes/MarkdownNode.d.ts +5 -1
  48. package/dist/types/client/nodes/McpAppNode.d.ts +4 -4
  49. package/dist/types/client/nodes/viewer-runtime-state.d.ts +1 -1
  50. package/dist/types/client/state/boards-store.d.ts +81 -9
  51. package/dist/types/client/state/canvas-store.d.ts +14 -1
  52. package/dist/types/client/state/context-chip-store.d.ts +22 -0
  53. package/dist/types/client/state/context-status-store.d.ts +35 -0
  54. package/dist/types/client/state/intent-bridge.d.ts +11 -8
  55. package/dist/types/client/state/knowledge-store.d.ts +22 -0
  56. package/dist/types/client/state/near-pin-store.d.ts +44 -1
  57. package/dist/types/client/state/presence-store.d.ts +4 -4
  58. package/dist/types/client/state/presentation.d.ts +28 -0
  59. package/dist/types/client/state/relation-store.d.ts +10 -0
  60. package/dist/types/client/state/session-store.d.ts +41 -2
  61. package/dist/types/client/state/workspace-settings.d.ts +7 -0
  62. package/dist/types/client/types.d.ts +13 -1
  63. package/dist/types/client/utils/keyboard.d.ts +2 -0
  64. package/dist/types/client/utils/time-ago.d.ts +4 -0
  65. package/dist/types/mcp/context-uri-template.d.ts +3 -1
  66. package/dist/types/server/agent-presence.d.ts +10 -3
  67. package/dist/types/server/ax-context.d.ts +1 -1
  68. package/dist/types/server/canvas-db.d.ts +30 -7
  69. package/dist/types/server/canvas-operations.d.ts +24 -2
  70. package/dist/types/server/canvas-provenance.d.ts +22 -2
  71. package/dist/types/server/canvas-serialization.d.ts +2 -0
  72. package/dist/types/server/canvas-state.d.ts +93 -15
  73. package/dist/types/server/canvas-validation.d.ts +1 -1
  74. package/dist/types/server/context-brief.d.ts +94 -6
  75. package/dist/types/server/context-reads.d.ts +33 -7
  76. package/dist/types/server/edit-summary.d.ts +20 -0
  77. package/dist/types/server/index.d.ts +71 -10
  78. package/dist/types/server/knowledge-lifecycle.d.ts +221 -0
  79. package/dist/types/server/lifecycle-status.d.ts +10 -0
  80. package/dist/types/server/memory-graph.d.ts +9 -0
  81. package/dist/types/server/mutation-history.d.ts +2 -0
  82. package/dist/types/server/operations/ops/ax-shared.d.ts +1 -1
  83. package/dist/types/server/operations/ops/boards.d.ts +2 -1
  84. package/dist/types/server/operations/ops/lifecycle.d.ts +2 -0
  85. package/dist/types/server/operations/ops/memory-graph.d.ts +2 -0
  86. package/dist/types/server/operations/ops/nodes.d.ts +5 -0
  87. package/dist/types/server/operations/ops/query.d.ts +23 -0
  88. package/dist/types/server/operations/registry.d.ts +1 -0
  89. package/dist/types/server/placement.d.ts +7 -0
  90. package/dist/types/server/scope-fence.d.ts +2 -1
  91. package/dist/types/server/spatial-analysis.d.ts +6 -3
  92. package/dist/types/server/tour-control.d.ts +32 -0
  93. package/dist/types/server/wiki-links.d.ts +14 -0
  94. package/dist/types/server/workbench-auth.d.ts +2 -0
  95. package/dist/types/shared/agent-context.d.ts +2 -0
  96. package/dist/types/shared/agent-presence.d.ts +15 -12
  97. package/dist/types/shared/auto-arrange.d.ts +1 -0
  98. package/dist/types/shared/boards.d.ts +4 -4
  99. package/dist/types/shared/knowledge-lifecycle.d.ts +41 -0
  100. package/dist/types/shared/knowledge-presets.d.ts +6 -0
  101. package/dist/types/shared/lifecycle-status.d.ts +24 -0
  102. package/dist/types/shared/memory-graph.d.ts +53 -0
  103. package/dist/types/shared/relations.d.ts +68 -0
  104. package/dist/types/shared/semantic-attention.d.ts +2 -0
  105. package/dist/types/shared/tour.d.ts +38 -0
  106. package/dist/types/shared/workspace-settings.d.ts +11 -0
  107. package/docs/RELEASE.md +21 -3
  108. package/docs/adr-001-bun-only-runtime.md +7 -1
  109. package/docs/adr-002-shared-product-separate-runtimes.md +93 -0
  110. package/docs/api-reference.md +109 -0
  111. package/docs/ax-host-adapter-contract.md +1 -1
  112. package/docs/ax-state-contract.md +5 -4
  113. package/docs/cli.md +153 -15
  114. package/docs/demos/pmx-canvas-demo.mp4 +0 -0
  115. package/docs/design/AgentContext.dc.html +3 -3
  116. package/docs/design/BoardPins.dc.html +37 -22
  117. package/docs/design/Categories.dc.html +208 -0
  118. package/docs/design/CategoryEditor.dc.html +33 -0
  119. package/docs/design/Chrome.dc.html +55 -9
  120. package/docs/design/ContextChip.dc.html +224 -0
  121. package/docs/design/ContextChip600.dc.html +136 -0
  122. package/docs/design/EmptyState.dc.html +45 -0
  123. package/docs/design/Flows.dc.html +23 -1
  124. package/docs/design/HeaderMarks.dc.html +183 -0
  125. package/docs/design/Home.dc.html +19 -1
  126. package/docs/design/HomeGraph.dc.html +86 -202
  127. package/docs/design/HomeMap.dc.html +23 -1
  128. package/docs/design/HomeTeam.dc.html +32 -14
  129. package/docs/design/Lifecycle.dc.html +22 -0
  130. package/docs/design/Lifecycle600.dc.html +18 -0
  131. package/docs/design/LifecycleVariants.dc.html +157 -0
  132. package/docs/design/LinkAuthorship.dc.html +139 -0
  133. package/docs/design/LinksChanged.dc.html +203 -0
  134. package/docs/design/LinksOptions.dc.html +137 -0
  135. package/docs/design/LinksOptions600.dc.html +134 -0
  136. package/docs/design/NearPin.dc.html +9 -10
  137. package/docs/design/Pane600.dc.html +4 -3
  138. package/docs/design/Relations.dc.html +3 -2
  139. package/docs/design/Restore.dc.html +152 -0
  140. package/docs/design/SeeChange.dc.html +267 -0
  141. package/docs/design/Uses.dc.html +12 -6
  142. package/docs/design/canvas.json +146 -19
  143. package/docs/design.md +454 -18
  144. package/docs/environment.md +0 -1
  145. package/docs/evals/curation-effect.md +128 -0
  146. package/docs/http-api.md +465 -38
  147. package/docs/mcp.md +150 -19
  148. package/docs/node-types.md +58 -3
  149. package/docs/plans/design-gaps-2026-10-08.md +53 -0
  150. package/docs/plans/plan-009-tech-debt-backlog.md +379 -0
  151. package/docs/plans/plan-016-context-made-visible-wave-1.md +150 -5
  152. package/docs/plans/plan-017-knowledge-categories-and-lifecycle.md +175 -0
  153. package/docs/plans/plan-018-connected-memory-wave-2.md +594 -0
  154. package/docs/plans/plan-019-post-0.9-roadmap.md +198 -0
  155. package/docs/product-context-vision-2026-09.md +17 -1
  156. package/docs/product-vision-2026-09.md +1082 -43
  157. package/docs/product-vision-review-2026-09.md +13 -1
  158. package/docs/screenshots/workbench-live-dark.png +0 -0
  159. package/docs/screenshots/workbench-live-light.png +0 -0
  160. package/docs/sdk.md +62 -2
  161. package/package.json +1 -1
  162. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
  163. package/plugins/pmx-canvas/plugin.json +1 -1
  164. package/plugins/pmx-canvas/runtime.json +1 -1
  165. package/plugins/pmx-canvas/tools.json +601 -22
  166. package/skills/pmx-canvas/SKILL.md +234 -43
  167. package/skills/pmx-canvas/evals/evals.json +62 -0
  168. package/skills/pmx-canvas/references/ax-html-control-surface.md +6 -0
  169. package/skills/pmx-canvas/references/full-reference.md +120 -21
  170. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
  171. package/skills/pmx-canvas/references/importing-context.md +132 -0
  172. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  173. package/skills/pmx-canvas/references/tours-and-recording.md +16 -1
  174. package/skills/pmx-canvas-testing/SKILL.md +20 -0
  175. package/src/cli/agent.ts +2 -0
  176. package/src/cli/commands/ax.ts +12 -0
  177. package/src/cli/commands/boards.ts +87 -11
  178. package/src/cli/commands/edges.ts +28 -0
  179. package/src/cli/commands/groups.ts +7 -0
  180. package/src/cli/commands/nodes.ts +4 -2
  181. package/src/cli/commands/query.ts +34 -2
  182. package/src/cli/commands/record.ts +199 -48
  183. package/src/cli/index.ts +7 -1
  184. package/src/client/App.tsx +177 -70
  185. package/src/client/canvas/AttentionHistory.tsx +0 -2
  186. package/src/client/canvas/BarHint.tsx +40 -2
  187. package/src/client/canvas/BoardCopyDialog.tsx +1 -1
  188. package/src/client/canvas/BoardFolderDialog.tsx +7 -7
  189. package/src/client/canvas/BoardLinkDialog.tsx +138 -33
  190. package/src/client/canvas/BoardPinButton.tsx +33 -0
  191. package/src/client/canvas/BoardSwitcher.tsx +26 -40
  192. package/src/client/canvas/CanvasNode.tsx +360 -237
  193. package/src/client/canvas/CanvasViewport.tsx +45 -7
  194. package/src/client/canvas/CommandBar.tsx +29 -23
  195. package/src/client/canvas/CommandPalette.tsx +5 -12
  196. package/src/client/canvas/ConnectionBanner.tsx +3 -3
  197. package/src/client/canvas/ContextChip.tsx +296 -0
  198. package/src/client/canvas/ContextMenu.tsx +63 -5
  199. package/src/client/canvas/CrossBoardReferences.tsx +60 -0
  200. package/src/client/canvas/EdgeLayer.tsx +339 -76
  201. package/src/client/canvas/EmptyState.tsx +33 -18
  202. package/src/client/canvas/ExpandedNodeOverlay.tsx +72 -40
  203. package/src/client/canvas/ExternalWriters.tsx +57 -42
  204. package/src/client/canvas/HomeGraphView.tsx +942 -0
  205. package/src/client/canvas/HomeMapView.tsx +641 -0
  206. package/src/client/canvas/HomeReviewView.tsx +167 -0
  207. package/src/client/canvas/HomeView.tsx +687 -160
  208. package/src/client/canvas/IntentLayer.tsx +19 -12
  209. package/src/client/canvas/KnowledgeDialog.tsx +488 -0
  210. package/src/client/canvas/LifecycleChrome.tsx +133 -0
  211. package/src/client/canvas/LifecycleFields.tsx +91 -0
  212. package/src/client/canvas/LifecyclePanel.tsx +533 -0
  213. package/src/client/canvas/MemoryInspector.tsx +104 -0
  214. package/src/client/canvas/Minimap.tsx +3 -3
  215. package/src/client/canvas/NearPinLayer.tsx +187 -0
  216. package/src/client/canvas/NodeContextMark.tsx +175 -97
  217. package/src/client/canvas/Presentation.tsx +23 -57
  218. package/src/client/canvas/RelationPresetsDialog.tsx +413 -0
  219. package/src/client/canvas/RelationsPanel.tsx +82 -0
  220. package/src/client/canvas/SelectionBar.tsx +3 -6
  221. package/src/client/canvas/SessionPanel.tsx +90 -50
  222. package/src/client/canvas/SessionReceipt.tsx +311 -39
  223. package/src/client/canvas/ShortcutOverlay.tsx +1 -1
  224. package/src/client/canvas/SnapshotPanel.tsx +27 -36
  225. package/src/client/canvas/ToolRail.tsx +367 -192
  226. package/src/client/canvas/TopBar.tsx +354 -124
  227. package/src/client/canvas/canvas-area.ts +10 -3
  228. package/src/client/canvas/graph-geometry.ts +195 -0
  229. package/src/client/canvas/graph-model.ts +254 -0
  230. package/src/client/canvas/memory-layout.ts +106 -0
  231. package/src/client/canvas/use-chrome-height.ts +20 -0
  232. package/src/client/canvas/use-focus-trap.ts +31 -5
  233. package/src/client/canvas/use-memory-graph.ts +58 -0
  234. package/src/client/canvas/use-node-drag.ts +2 -1
  235. package/src/client/canvas/use-pan-zoom.ts +64 -7
  236. package/src/client/icons.tsx +0 -63
  237. package/src/client/mcp-app/style.css +0 -6
  238. package/src/client/nodes/AxStepControls.tsx +74 -50
  239. package/src/client/nodes/BoardNode.tsx +5 -1
  240. package/src/client/nodes/ContextNode.tsx +18 -11
  241. package/src/client/nodes/ExtAppFrame.tsx +0 -1
  242. package/src/client/nodes/FileNode.tsx +46 -42
  243. package/src/client/nodes/HtmlNode.tsx +44 -2
  244. package/src/client/nodes/ImageNode.tsx +1 -1
  245. package/src/client/nodes/InlineFormatBar.tsx +6 -9
  246. package/src/client/nodes/InlineMarkdownEditor.tsx +56 -17
  247. package/src/client/nodes/MarkdownNode.tsx +377 -109
  248. package/src/client/nodes/McpAppNode.tsx +50 -20
  249. package/src/client/nodes/MdFormatBar.tsx +21 -18
  250. package/src/client/nodes/PromptNode.tsx +1 -1
  251. package/src/client/nodes/ResponseNode.tsx +1 -1
  252. package/src/client/nodes/viewer-runtime-state.ts +54 -22
  253. package/src/client/state/attention-bridge.ts +64 -15
  254. package/src/client/state/boards-store.ts +193 -39
  255. package/src/client/state/canvas-store.ts +99 -12
  256. package/src/client/state/context-chip-store.ts +70 -0
  257. package/src/client/state/context-status-store.ts +53 -0
  258. package/src/client/state/intent-bridge.ts +51 -30
  259. package/src/client/state/knowledge-store.ts +43 -0
  260. package/src/client/state/near-pin-store.ts +115 -6
  261. package/src/client/state/presence-store.ts +7 -10
  262. package/src/client/state/presentation.ts +91 -0
  263. package/src/client/state/relation-store.ts +81 -0
  264. package/src/client/state/session-store.ts +144 -18
  265. package/src/client/state/sse-bridge.ts +206 -29
  266. package/src/client/state/workspace-settings.ts +11 -0
  267. package/src/client/theme/global.css +2759 -510
  268. package/src/client/types.ts +12 -0
  269. package/src/client/utils/keyboard.ts +10 -0
  270. package/src/client/utils/time-ago.ts +14 -0
  271. package/src/json-render/renderer/index.css +6 -1
  272. package/src/json-render/renderer/index.tsx +31 -1
  273. package/src/mcp/canvas-app.ts +12 -2
  274. package/src/mcp/context-uri-template.ts +7 -4
  275. package/src/mcp/server.ts +63 -41
  276. package/src/mcp/workbench-app.ts +39 -6
  277. package/src/server/agent-presence.ts +128 -28
  278. package/src/server/ax-context.ts +27 -13
  279. package/src/server/board-export.ts +12 -1
  280. package/src/server/canvas-db.ts +331 -42
  281. package/src/server/canvas-operations.ts +196 -84
  282. package/src/server/canvas-provenance.ts +53 -22
  283. package/src/server/canvas-serialization.ts +2 -0
  284. package/src/server/canvas-state.ts +950 -122
  285. package/src/server/canvas-validation.ts +9 -2
  286. package/src/server/context-brief.ts +345 -38
  287. package/src/server/context-reads.ts +179 -30
  288. package/src/server/demo-state.json +355 -24
  289. package/src/server/edit-summary.ts +74 -0
  290. package/src/server/html-surface.ts +8 -1
  291. package/src/server/index.ts +203 -13
  292. package/src/server/knowledge-lifecycle.ts +304 -0
  293. package/src/server/lifecycle-status.ts +232 -0
  294. package/src/server/memory-graph.ts +166 -0
  295. package/src/server/mutation-history.ts +18 -6
  296. package/src/server/operations/composites.ts +32 -11
  297. package/src/server/operations/http.ts +7 -2
  298. package/src/server/operations/index.ts +4 -0
  299. package/src/server/operations/mcp.ts +32 -1
  300. package/src/server/operations/ops/ax-presence.ts +1 -1
  301. package/src/server/operations/ops/ax-read.ts +57 -6
  302. package/src/server/operations/ops/ax-timeline.ts +28 -2
  303. package/src/server/operations/ops/backup.ts +5 -3
  304. package/src/server/operations/ops/batch.ts +35 -4
  305. package/src/server/operations/ops/boards.ts +188 -47
  306. package/src/server/operations/ops/canvas-wire.ts +31 -1
  307. package/src/server/operations/ops/edges.ts +36 -2
  308. package/src/server/operations/ops/groups.ts +6 -1
  309. package/src/server/operations/ops/json-render.ts +5 -1
  310. package/src/server/operations/ops/lifecycle.ts +262 -0
  311. package/src/server/operations/ops/memory-graph.ts +45 -0
  312. package/src/server/operations/ops/nodes.ts +107 -24
  313. package/src/server/operations/ops/query.ts +281 -68
  314. package/src/server/operations/ops/snapshots.ts +73 -1
  315. package/src/server/operations/ops/validate.ts +5 -1
  316. package/src/server/operations/ops/viewport.ts +97 -3
  317. package/src/server/operations/registry.ts +77 -26
  318. package/src/server/placement.ts +29 -0
  319. package/src/server/scope-fence.ts +78 -6
  320. package/src/server/server.ts +115 -16
  321. package/src/server/spatial-analysis.ts +48 -23
  322. package/src/server/tour-control.ts +82 -0
  323. package/src/server/wiki-links.ts +137 -0
  324. package/src/server/workbench-auth.ts +11 -0
  325. package/src/shared/agent-context.ts +3 -0
  326. package/src/shared/agent-presence.ts +15 -15
  327. package/src/shared/auto-arrange.ts +2 -0
  328. package/src/shared/boards.ts +4 -4
  329. package/src/shared/knowledge-lifecycle.ts +22 -0
  330. package/src/shared/knowledge-presets.ts +80 -0
  331. package/src/shared/lifecycle-status.ts +26 -0
  332. package/src/shared/memory-graph.ts +74 -0
  333. package/src/shared/relations.ts +98 -0
  334. package/src/shared/semantic-attention.ts +15 -1
  335. package/src/shared/tour.ts +23 -5
  336. package/src/shared/workspace-settings.ts +13 -0
  337. package/dist/types/client/canvas/ContextPinBar.d.ts +0 -1
  338. package/dist/types/client/canvas/FocusFieldLayer.d.ts +0 -1
  339. package/dist/types/client/canvas/kind-colors.d.ts +0 -3
  340. package/dist/types/server/agent-context.d.ts +0 -22
  341. package/src/client/canvas/ContextPinBar.tsx +0 -25
@@ -1,10 +1,11 @@
1
1
  import { useEffect, useState } from 'preact/hooks';
2
+ import { BarHint } from './BarHint';
2
3
  import { IconChevronRight, IconUndo } from '../icons';
3
4
  import { useNow } from './use-now';
4
5
  import { agentPhaseLabel } from '../../shared/agent-presence.js';
5
6
  import { formatCountdown, gateRemainingMs } from '../../shared/approval-gates.js';
6
7
  import { focusNode, selectedNodeIds } from '../state/canvas-store';
7
- import { activeSession, agentPresences, writerColor } from '../state/presence-store';
8
+ import { activeSession, agentPresences, attachedSessions, writerColor } from '../state/presence-store';
8
9
  import {
9
10
  type ApprovalGateView,
10
11
  endSession,
@@ -16,9 +17,9 @@ import {
16
17
  resolveGate,
17
18
  scopeFence,
18
19
  setScopeFence,
20
+ sessionPanelOpened,
19
21
  sessionWorkItems,
20
22
  type TimelineEntry,
21
- timelineCategory,
22
23
  type TimelineEntryKind,
23
24
  type TimelineFilter,
24
25
  timelineEntries,
@@ -101,13 +102,7 @@ function WorkItemRow({ item }: { item: WorkItemView }) {
101
102
  <li class={`session-item status-${glyph}`} data-work-item-id={item.id}>
102
103
  <span class="session-glyph" aria-hidden="true" />
103
104
  <div class="session-item-main">
104
- <button
105
- type="button"
106
- class="session-item-title"
107
- title={nodeId ? 'Focus the linked node' : undefined}
108
- disabled={!nodeId}
109
- onClick={() => nodeId && focusNode(nodeId)}
110
- >
105
+ <button type="button" class="session-item-title" disabled={!nodeId} onClick={() => nodeId && focusNode(nodeId)}>
111
106
  {item.title}
112
107
  </button>
113
108
  {item.detail && <div class="session-item-detail">{item.detail}</div>}
@@ -131,13 +126,7 @@ function GateRow({ gate, now }: { gate: ApprovalGateView; now: number }) {
131
126
  <li class="session-item status-awaiting session-gate" data-gate-id={gate.id}>
132
127
  <span class="session-glyph" aria-hidden="true" />
133
128
  <div class="session-item-main">
134
- <button
135
- type="button"
136
- class="session-item-title"
137
- title={nodeId ? 'Focus the linked node' : undefined}
138
- disabled={!nodeId}
139
- onClick={() => nodeId && focusNode(nodeId)}
140
- >
129
+ <button type="button" class="session-item-title" disabled={!nodeId} onClick={() => nodeId && focusNode(nodeId)}>
141
130
  {gate.title}
142
131
  </button>
143
132
  {gate.detail && <div class="session-item-detail">{gate.detail}</div>}
@@ -248,15 +237,19 @@ function ScopeRow() {
248
237
  ) : (
249
238
  <>
250
239
  <span class="session-scope-text">Unscoped — the agent may write anywhere</span>
251
- <button
252
- type="button"
253
- class="session-scope-action"
254
- disabled={busy || selected === 0}
255
- title={selected === 0 ? 'Select nodes on the canvas first' : 'Fence the agent to the selected nodes'}
256
- onClick={() => apply([...selectedNodeIds.value])}
240
+ <BarHint
241
+ label={selected === 0 ? 'Select nodes on the canvas first' : 'Fence the agent to the selected nodes'}
242
+ align="end"
257
243
  >
258
- Fence to selection{selected > 0 ? ` (${selected})` : ''}
259
- </button>
244
+ <button
245
+ type="button"
246
+ class="session-scope-action"
247
+ disabled={busy || selected === 0}
248
+ onClick={() => apply([...selectedNodeIds.value])}
249
+ >
250
+ Fence to selection{selected > 0 ? ` (${selected})` : ''}
251
+ </button>
252
+ </BarHint>
260
253
  </>
261
254
  )}
262
255
  </div>
@@ -277,9 +270,7 @@ function TimelineRow({ entry }: { entry: TimelineEntry }) {
277
270
  <span class="session-timeline-dot" aria-hidden="true" />
278
271
  <div class="session-timeline-main">
279
272
  <div class="session-timeline-head">
280
- <span class="session-timeline-label" title={TIMELINE_FILTER_HINTS[timelineCategory(entry.kind)]}>
281
- {entry.label}
282
- </span>
273
+ <span class="session-timeline-label">{entry.label}</span>
283
274
  {/* With several assistants on one board, "Assistant · 23:11" answers
284
275
  nothing — every row names its writer. */}
285
276
  {entry.who && (
@@ -308,11 +299,62 @@ function TimelineRow({ entry }: { entry: TimelineEntry }) {
308
299
  );
309
300
  }
310
301
 
302
+ /** Approvals and write scope are safety controls, not an optional beta. */
303
+ export function AgentControls() {
304
+ const gates = pendingGates.value;
305
+ const now = useNow();
306
+ if (!sessionPanelOpened.value && gates.length === 0) return null;
307
+ return (
308
+ <aside class="session-panel" aria-label="Agent controls">
309
+ <header class="session-panel-header">
310
+ <span class="session-panel-title">Agent controls</span>
311
+ <span class="top-bar-spacer" />
312
+ <button
313
+ type="button"
314
+ class="session-collapse"
315
+ aria-label="Collapse agent controls"
316
+ onClick={() => (sessionPanelOpened.value = false)}
317
+ disabled={gates.length > 0}
318
+ >
319
+ <IconChevronRight />
320
+ </button>
321
+ </header>
322
+ <ScopeRow />
323
+ <div class="session-panel-scroll">
324
+ <ul class="session-list" aria-label="Approvals">
325
+ {gates.map((gate) => (
326
+ <GateRow key={gate.id} gate={gate} now={now} />
327
+ ))}
328
+ {heldGates.value.map((gate) => (
329
+ <HeldGateRow key={gate.id} gate={gate} />
330
+ ))}
331
+ {resolvedGates.value.map((gate) => (
332
+ <ResolvedGateRow key={gate.id} gate={gate} />
333
+ ))}
334
+ </ul>
335
+ {attachedSessions.value.map((session) => (
336
+ <div key={session.sessionId} class="session-item">
337
+ <span class="session-item-main">{session.label}</span>
338
+ <button type="button" class="session-end" onClick={() => void endSession(session)}>
339
+ End attachment
340
+ </button>
341
+ </div>
342
+ ))}
343
+ </div>
344
+ </aside>
345
+ );
346
+ }
347
+
311
348
  export function SessionPanel() {
312
349
  // A gate may temporarily expand the panel without turning that expansion
313
350
  // into a user preference. Once the last gate settles, only an explicitly
314
351
  // opened panel remains open.
315
- const [manuallyOpened, setManuallyOpened] = useState(false);
352
+ useEffect(
353
+ () => () => {
354
+ sessionPanelOpened.value = false;
355
+ },
356
+ [],
357
+ );
316
358
  const session = activeSession.value;
317
359
  const items = sessionWorkItems.value;
318
360
  const gates = pendingGates.value;
@@ -332,22 +374,23 @@ export function SessionPanel() {
332
374
  void refreshTimeline();
333
375
  }, []);
334
376
 
335
- const expanded = manuallyOpened || gates.length > 0;
377
+ const expanded = sessionPanelOpened.value || gates.length > 0;
336
378
  if (!expanded) {
337
379
  return (
338
380
  <aside class="session-panel is-collapsed" aria-label="Session (collapsed)">
339
381
  <button
340
382
  type="button"
341
383
  class="session-collapse"
342
- onClick={() => setManuallyOpened(true)}
343
- title="Expand session panel"
384
+ onClick={() => {
385
+ sessionPanelOpened.value = true;
386
+ }}
387
+ aria-label="Expand session panel"
344
388
  >
345
389
  ‹
346
390
  </button>
347
391
  {session && (
348
392
  <span
349
393
  class={`session-collapsed-live phase-${session.phase}`}
350
- title={agentPhaseLabel(session)}
351
394
  aria-label={`Session live: ${agentPhaseLabel(session)}`}
352
395
  >
353
396
  <span class="session-live-dot" aria-hidden="true" />
@@ -364,27 +407,27 @@ export function SessionPanel() {
364
407
  <header class="session-panel-header">
365
408
  <span class="session-panel-title">Session</span>
366
409
  {session && (
367
- <span class={`session-live phase-${session.phase}`} title={agentPhaseLabel(session)}>
368
- <span class="session-live-dot" aria-hidden="true" />
369
- live
370
- </span>
410
+ <BarHint label={agentPhaseLabel(session)} tapToOpen>
411
+ <span class={`session-live phase-${session.phase}`}>
412
+ <span class="session-live-dot" aria-hidden="true" />
413
+ live
414
+ </span>
415
+ </BarHint>
371
416
  )}
372
417
  <span class="top-bar-spacer" />
373
418
  {session && (
374
- <button
375
- type="button"
376
- class="session-end"
377
- title="End this session — a receipt and a snapshot of the board follow"
378
- onClick={() => void endSession(session)}
379
- >
380
- End
381
- </button>
419
+ <BarHint label="End this session" body="A receipt and a snapshot of the board follow." align="end">
420
+ <button type="button" class="session-end" onClick={() => void endSession(session)}>
421
+ End
422
+ </button>
423
+ </BarHint>
382
424
  )}
383
425
  <button
384
426
  type="button"
385
427
  class="session-collapse"
386
- onClick={() => setManuallyOpened(false)}
387
- title="Collapse session panel"
428
+ onClick={() => {
429
+ sessionPanelOpened.value = false;
430
+ }}
388
431
  aria-label="Collapse session panel"
389
432
  >
390
433
  <IconChevronRight />
@@ -401,9 +444,7 @@ export function SessionPanel() {
401
444
  if (!undoable) return null;
402
445
  return (
403
446
  <div class="session-undo-row" data-testid="session-undo-row">
404
- <span class="session-undo-text" title={undoable.body}>
405
- Agent edit on top: {undoable.body}
406
- </span>
447
+ <span class="session-undo-text">Agent edit on top: {undoable.body}</span>
407
448
  <button type="button" class="session-undo-btn" onClick={() => void undoAgentEdit(undoable)}>
408
449
  <IconUndo size={14} /> Undo
409
450
  </button>
@@ -490,7 +531,6 @@ export function SessionPanel() {
490
531
  type="button"
491
532
  class={`activity-filter${timelineFilter.value === chip.id ? ' is-active' : ''}`}
492
533
  aria-pressed={timelineFilter.value === chip.id}
493
- title={chip.hint}
494
534
  onMouseEnter={() => setHoveredFilter(chip.id)}
495
535
  onMouseLeave={() => setHoveredFilter((current) => (current === chip.id ? null : current))}
496
536
  onFocus={() => setHoveredFilter(chip.id)}