@north-light/crouter 0.3.170 → 0.3.172

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 (670) hide show
  1. package/dist/api/client.d.ts +37 -11
  2. package/dist/api/client.js +84 -15
  3. package/dist/api/dto/human.d.ts +53 -39
  4. package/dist/api/dto/human.js +2 -3
  5. package/dist/api/dto/inbox.d.ts +0 -1
  6. package/dist/api/dto/nodes.d.ts +12 -0
  7. package/dist/api/dto/review-comments.d.ts +137 -0
  8. package/dist/api/dto/review-comments.js +5 -0
  9. package/dist/api/dto/reviews.d.ts +109 -0
  10. package/dist/api/dto/reviews.js +5 -0
  11. package/dist/api/index.d.ts +2 -0
  12. package/dist/api/index.js +2 -0
  13. package/dist/api/routes.d.ts +17 -4
  14. package/dist/api/routes.js +21 -5
  15. package/dist/build-root.d.ts +1 -16
  16. package/dist/build-root.js +1 -25
  17. package/dist/builtin-memory/00-runtime-base.md +7 -5
  18. package/dist/builtin-memory/04-base-worker.md +1 -1
  19. package/dist/builtin-memory/04-orchestration-kernel.md +7 -7
  20. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
  21. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +1 -1
  22. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -1
  23. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -1
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -1
  25. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -1
  26. package/dist/builtin-memory/05-kinds/review/00-base.md +1 -1
  27. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +20 -0
  28. package/dist/builtin-memory/05-kinds/spec/00-base.md +3 -7
  29. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +3 -3
  30. package/dist/builtin-memory/05-kinds/spec/requirements.md +3 -3
  31. package/dist/builtin-memory/design.md +2 -2
  32. package/dist/builtin-memory/insights/capture.md +50 -0
  33. package/dist/builtin-memory/insights/init.md +45 -0
  34. package/dist/builtin-memory/insights/listen.md +9 -0
  35. package/dist/builtin-memory/internal/agent-shaping.md +2 -2
  36. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  37. package/dist/builtin-memory/internal/plugins.md +12 -11
  38. package/dist/builtin-memory/internal/storage-tiers.md +2 -2
  39. package/dist/builtin-memory/{planning.md → plan/roadmap.md} +3 -3
  40. package/dist/builtin-memory/plan.md +19 -0
  41. package/dist/builtin-memory/spec/guide.md +38 -0
  42. package/dist/builtin-memory/spec/requirements.md +31 -0
  43. package/dist/builtin-memory/spec/roadmap.md +35 -0
  44. package/dist/builtin-memory/spec.md +10 -86
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +3 -4
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +49 -5
  47. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +56 -0
  48. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +920 -0
  49. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +221 -156
  50. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +4 -5
  51. package/dist/cli.js +2 -6
  52. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +7 -35
  53. package/dist/clients/attach/__tests__/attach-keybindings.test.js +32 -16
  54. package/dist/clients/attach/__tests__/context-message.test.js +142 -6
  55. package/dist/clients/attach/__tests__/crtr-output.test.js +29 -45
  56. package/dist/clients/attach/__tests__/diagram.test.js +1 -1
  57. package/dist/clients/attach/__tests__/file-review-focus.test.js +48 -0
  58. package/dist/clients/attach/__tests__/group-activity.test.js +266 -0
  59. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +32 -0
  60. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +32 -0
  61. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -2
  62. package/dist/clients/attach/chrome/header.d.ts +10 -0
  63. package/dist/clients/attach/chrome/header.js +30 -0
  64. package/dist/clients/attach/chrome/recap.d.ts +7 -0
  65. package/dist/clients/attach/chrome/recap.js +19 -0
  66. package/dist/clients/attach/chrome/status-line.d.ts +3 -0
  67. package/dist/clients/attach/chrome/status-line.js +5 -0
  68. package/dist/clients/attach/chrome/widgets.js +11 -21
  69. package/dist/clients/attach/command.js +11 -7
  70. package/dist/clients/attach/config.d.ts +4 -0
  71. package/dist/clients/attach/config.js +3 -0
  72. package/dist/clients/attach/input/controller.d.ts +19 -0
  73. package/dist/clients/attach/input/controller.js +62 -28
  74. package/dist/clients/attach/input/titled-editor.d.ts +0 -4
  75. package/dist/clients/attach/input/titled-editor.js +2 -10
  76. package/dist/clients/attach/overlays/file-review.d.ts +9 -5
  77. package/dist/clients/attach/overlays/file-review.js +9 -70
  78. package/dist/clients/attach/overlays/help.d.ts +33 -0
  79. package/dist/clients/attach/overlays/help.js +204 -0
  80. package/dist/clients/attach/render/activity-slot.d.ts +4 -0
  81. package/dist/clients/attach/render/activity-slot.js +13 -0
  82. package/dist/clients/attach/render/chat-view.d.ts +117 -12
  83. package/dist/clients/attach/render/chat-view.js +604 -135
  84. package/dist/clients/attach/render/context-message.d.ts +2 -1
  85. package/dist/clients/attach/render/context-message.js +17 -13
  86. package/dist/clients/attach/render/crtr-output.js +1 -3
  87. package/dist/clients/attach/render/diagram.js +2 -2
  88. package/dist/clients/attach/render/edit-diff.d.ts +4 -1
  89. package/dist/clients/attach/render/edit-diff.js +7 -11
  90. package/dist/clients/attach/render/group-activity.d.ts +32 -0
  91. package/dist/clients/attach/render/group-activity.js +206 -0
  92. package/dist/clients/attach/render/group-recap.d.ts +10 -0
  93. package/dist/clients/attach/render/group-recap.js +93 -0
  94. package/dist/clients/attach/render/html-markdown.d.ts +17 -0
  95. package/dist/clients/attach/render/html-markdown.js +228 -0
  96. package/dist/clients/attach/render/measured-container.d.ts +96 -0
  97. package/dist/clients/attach/render/measured-container.js +322 -0
  98. package/dist/clients/attach/render/scroll-animation.d.ts +8 -0
  99. package/dist/clients/attach/render/scroll-animation.js +80 -0
  100. package/dist/clients/attach/render/tool-calls.js +6 -6
  101. package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
  102. package/dist/clients/attach/render/transcript-copy.js +81 -0
  103. package/dist/clients/attach/render/viewport.d.ts +29 -0
  104. package/dist/clients/attach/render/viewport.js +159 -0
  105. package/dist/clients/attach/session/bindings.d.ts +10 -7
  106. package/dist/clients/attach/session/bindings.js +23 -8
  107. package/dist/clients/attach/session/connection.js +4 -5
  108. package/dist/clients/attach/session/context.d.ts +6 -4
  109. package/dist/clients/attach/session/frame.d.ts +34 -0
  110. package/dist/clients/attach/session/frame.js +176 -0
  111. package/dist/clients/attach/session/frames.d.ts +4 -1
  112. package/dist/clients/attach/session/frames.js +14 -1
  113. package/dist/clients/attach/session/identity.js +4 -3
  114. package/dist/clients/attach/session/input-wiring.d.ts +14 -4
  115. package/dist/clients/attach/session/input-wiring.js +15 -13
  116. package/dist/clients/attach/session/invariant.d.ts +9 -0
  117. package/dist/clients/attach/session/invariant.js +15 -0
  118. package/dist/clients/attach/session/keys.d.ts +10 -2
  119. package/dist/clients/attach/session/keys.js +13 -5
  120. package/dist/clients/attach/session/layout.d.ts +10 -8
  121. package/dist/clients/attach/session/layout.js +33 -34
  122. package/dist/clients/attach/session/mouse.d.ts +18 -0
  123. package/dist/clients/attach/session/mouse.js +64 -0
  124. package/dist/clients/attach/session/pane-tag.d.ts +3 -0
  125. package/dist/clients/attach/session/pane-tag.js +51 -8
  126. package/dist/clients/attach/session/reconnect.d.ts +3 -0
  127. package/dist/clients/attach/session/reconnect.js +42 -5
  128. package/dist/clients/attach/session/surface-frame.d.ts +20 -0
  129. package/dist/clients/attach/session/surface-frame.js +73 -0
  130. package/dist/clients/attach/session/surface-host.d.ts +64 -0
  131. package/dist/clients/attach/session/surface-host.js +255 -0
  132. package/dist/clients/attach/session/whip.d.ts +17 -0
  133. package/dist/clients/attach/session/whip.js +334 -0
  134. package/dist/clients/attach/slash/dispatch.d.ts +13 -1
  135. package/dist/clients/attach/slash/dispatch.js +51 -29
  136. package/dist/clients/attach/viewer.js +907 -819
  137. package/dist/clients/conversation/conversation.d.ts +65 -0
  138. package/dist/clients/conversation/conversation.js +318 -0
  139. package/dist/clients/conversation/frames.d.ts +30 -0
  140. package/dist/clients/conversation/frames.js +52 -0
  141. package/dist/clients/conversation/region.d.ts +51 -0
  142. package/dist/clients/conversation/region.js +265 -0
  143. package/dist/clients/conversation/submit.d.ts +38 -0
  144. package/dist/clients/conversation/submit.js +51 -0
  145. package/dist/clients/inbox/__tests__/inbox-controller.test.js +247 -0
  146. package/dist/clients/inbox/__tests__/mount-panel.test.js +776 -0
  147. package/dist/clients/inbox/controller.d.ts +79 -0
  148. package/dist/clients/inbox/controller.js +448 -0
  149. package/dist/clients/inbox/deck-adapter.d.ts +29 -0
  150. package/dist/clients/inbox/deck-adapter.js +62 -0
  151. package/dist/clients/inbox/layout.d.ts +8 -0
  152. package/dist/clients/inbox/layout.js +9 -0
  153. package/dist/clients/inbox/resolve.d.ts +10 -0
  154. package/dist/clients/inbox/resolve.js +34 -0
  155. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +29 -0
  156. package/dist/clients/inbox/review/__tests__/remap.test.js +196 -0
  157. package/dist/clients/inbox/review/__tests__/review-core.test.js +341 -0
  158. package/dist/clients/inbox/review/anchors.d.ts +41 -0
  159. package/dist/clients/inbox/review/anchors.js +89 -0
  160. package/dist/clients/inbox/review/columns.d.ts +22 -0
  161. package/dist/clients/inbox/review/columns.js +40 -0
  162. package/dist/clients/inbox/review/comments-client.d.ts +66 -0
  163. package/dist/clients/inbox/review/comments-client.js +98 -0
  164. package/dist/clients/inbox/review/composition.d.ts +60 -0
  165. package/dist/clients/inbox/review/composition.js +278 -0
  166. package/dist/clients/inbox/review/document-region.d.ts +120 -0
  167. package/dist/clients/inbox/review/document-region.js +902 -0
  168. package/dist/clients/inbox/review/frame.d.ts +45 -0
  169. package/dist/clients/inbox/review/frame.js +215 -0
  170. package/dist/clients/inbox/review/keys.d.ts +67 -0
  171. package/dist/clients/inbox/review/keys.js +130 -0
  172. package/dist/clients/inbox/review/launch.d.ts +10 -0
  173. package/dist/clients/inbox/review/launch.js +129 -0
  174. package/dist/clients/inbox/review/live-source.d.ts +24 -0
  175. package/dist/clients/inbox/review/live-source.js +160 -0
  176. package/dist/clients/inbox/review/nvim.d.ts +13 -0
  177. package/dist/clients/inbox/review/nvim.js +42 -0
  178. package/dist/clients/inbox/review/remap.d.ts +51 -0
  179. package/dist/clients/inbox/review/remap.js +157 -0
  180. package/dist/clients/inbox/review/review-client.d.ts +30 -0
  181. package/dist/clients/inbox/review/review-client.js +107 -0
  182. package/dist/clients/inbox/review/roundtrip.d.ts +5 -0
  183. package/dist/clients/inbox/review/roundtrip.js +36 -0
  184. package/dist/clients/inbox/review/state.d.ts +143 -0
  185. package/dist/clients/inbox/review/state.js +282 -0
  186. package/dist/clients/inbox/review-adapter.d.ts +29 -0
  187. package/dist/clients/inbox/review-adapter.js +92 -0
  188. package/dist/clients/inbox/review-visibility.d.ts +5 -0
  189. package/dist/clients/inbox/review-visibility.js +19 -0
  190. package/dist/clients/inbox/surface.d.ts +19 -0
  191. package/dist/clients/inbox/surface.js +128 -0
  192. package/dist/clients/inbox/tui/ansi.d.ts +66 -0
  193. package/dist/clients/inbox/tui/ansi.js +317 -0
  194. package/dist/clients/inbox/tui/clipboard.d.ts +2 -0
  195. package/dist/clients/inbox/tui/clipboard.js +26 -0
  196. package/dist/clients/inbox/tui/input.d.ts +7 -0
  197. package/dist/clients/inbox/tui/input.js +653 -0
  198. package/dist/clients/inbox/tui/keys.d.ts +28 -0
  199. package/dist/clients/inbox/tui/keys.js +111 -0
  200. package/dist/clients/inbox/tui/panel.d.ts +2 -0
  201. package/dist/clients/inbox/tui/panel.js +217 -0
  202. package/dist/clients/inbox/tui/render.d.ts +37 -0
  203. package/dist/clients/inbox/tui/render.js +476 -0
  204. package/dist/clients/inbox/tui/types.d.ts +57 -0
  205. package/dist/clients/inbox/tui/types.js +1 -0
  206. package/dist/clients/inbox/tui.d.ts +6 -0
  207. package/dist/clients/inbox/tui.js +74 -0
  208. package/dist/clients/surfaces/host.d.ts +66 -0
  209. package/dist/clients/surfaces/host.js +1 -0
  210. package/dist/clients/surfaces/region.d.ts +16 -0
  211. package/dist/clients/surfaces/region.js +1 -0
  212. package/dist/clients/web/__tests__/push-engine.test.js +14 -158
  213. package/dist/clients/web/dev-server.d.ts +3 -3
  214. package/dist/clients/web/dev-server.js +9 -23
  215. package/dist/clients/web/events.js +4 -6
  216. package/dist/clients/web/push-engine.d.ts +2 -66
  217. package/dist/clients/web/push-engine.js +30 -161
  218. package/dist/clients/web/push-registry.d.ts +0 -4
  219. package/dist/clients/web/push-registry.js +2 -7
  220. package/dist/clients/web/server.js +3 -35
  221. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -108
  222. package/dist/clients/web/web-cmd.js +2 -2
  223. package/dist/commands/__tests__/human.test.js +27 -15
  224. package/dist/commands/api-client.js +3 -3
  225. package/dist/commands/canvas-browse.js +1 -1
  226. package/dist/commands/canvas-issue.js +1 -1
  227. package/dist/commands/canvas-use.js +1 -1
  228. package/dist/commands/human/doc.d.ts +2 -0
  229. package/dist/commands/human/doc.js +98 -0
  230. package/dist/commands/human/inbox.d.ts +2 -0
  231. package/dist/commands/human/inbox.js +101 -0
  232. package/dist/commands/human/prompts.d.ts +2 -3
  233. package/dist/commands/human/prompts.js +27 -180
  234. package/dist/commands/human/queue.d.ts +1 -5
  235. package/dist/commands/human/queue.js +54 -216
  236. package/dist/commands/human/review.d.ts +2 -0
  237. package/dist/commands/human/review.js +298 -0
  238. package/dist/commands/human/shared.d.ts +2 -69
  239. package/dist/commands/human/shared.js +1 -181
  240. package/dist/commands/human.js +15 -20
  241. package/dist/commands/memory/__tests__/lint.test.d.ts +1 -0
  242. package/dist/commands/memory/__tests__/lint.test.js +15 -0
  243. package/dist/commands/memory/delete.js +2 -2
  244. package/dist/commands/memory/lint.d.ts +1 -0
  245. package/dist/commands/memory/lint.js +21 -3
  246. package/dist/commands/memory/read.js +4 -4
  247. package/dist/commands/node.js +8 -7
  248. package/dist/commands/pkg/plugin-manage.js +143 -68
  249. package/dist/commands/surface-inspect.js +2 -2
  250. package/dist/commands/surface.js +6 -12
  251. package/dist/commands/sys/__tests__/setup-core.test.js +9 -5
  252. package/dist/commands/sys/__tests__/setup-front-door.test.js +7 -42
  253. package/dist/commands/sys/config.js +29 -3
  254. package/dist/commands/sys/feedback.js +1 -1
  255. package/dist/commands/sys/setup-core.d.ts +12 -11
  256. package/dist/commands/sys/setup-core.js +55 -46
  257. package/dist/commands/sys/setup-wizard.d.ts +4 -1
  258. package/dist/commands/sys/setup-wizard.js +50 -9
  259. package/dist/commands/sys/sync-deps.js +1 -1
  260. package/dist/commands/sys.js +4 -6
  261. package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -1
  262. package/dist/core/__tests__/broker-snapshot-history.test.js +9 -1
  263. package/dist/core/__tests__/dead-node-policy-table.test.js +3 -4
  264. package/dist/core/__tests__/fixtures/fake-engine.d.ts +8 -5
  265. package/dist/core/__tests__/fixtures/fake-engine.js +28 -2
  266. package/dist/core/__tests__/full/broker-provider-retry.test.js +87 -2
  267. package/dist/core/__tests__/full/broker-whip-interrupt.test.d.ts +1 -0
  268. package/dist/core/__tests__/full/broker-whip-interrupt.test.js +39 -0
  269. package/dist/core/__tests__/full/detach-focus.test.js +1 -1
  270. package/dist/core/__tests__/human-deliver-e2e.test.js +64 -64
  271. package/dist/core/__tests__/human-deliver.test.js +71 -345
  272. package/dist/core/__tests__/inline-memory-refs.test.js +2 -12
  273. package/dist/core/__tests__/memory-resolver-precedence.test.js +12 -15
  274. package/dist/core/__tests__/migration.test.js +10 -0
  275. package/dist/core/__tests__/model-pin-durability.test.js +14 -0
  276. package/dist/core/__tests__/phase4-review-migration.test.d.ts +1 -0
  277. package/dist/core/__tests__/phase4-review-migration.test.js +100 -0
  278. package/dist/core/__tests__/phase4-review-store.test.d.ts +1 -0
  279. package/dist/core/__tests__/phase4-review-store.test.js +143 -0
  280. package/dist/core/__tests__/remote-canvas-target.test.js +2 -2
  281. package/dist/core/__tests__/revive.test.js +22 -53
  282. package/dist/core/__tests__/session-cycles.test.js +48 -18
  283. package/dist/core/__tests__/spawn-no-kickoff.test.js +8 -12
  284. package/dist/core/__tests__/stop-guard.test.js +16 -1
  285. package/dist/core/__tests__/tmux-surface.test.js +21 -25
  286. package/dist/core/asset-root.d.ts +7 -0
  287. package/dist/core/asset-root.js +18 -0
  288. package/dist/core/broker-client/client.d.ts +0 -7
  289. package/dist/core/broker-client/client.js +4 -10
  290. package/dist/core/broker-client/transport-relay.d.ts +3 -4
  291. package/dist/core/broker-client/transport-relay.js +3 -4
  292. package/dist/core/canvas/__tests__/attention.test.js +1 -1
  293. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
  294. package/dist/core/canvas/__tests__/remote-transport.test.d.ts +1 -0
  295. package/dist/core/{view/__tests__/transport-remote.test.js → canvas/__tests__/remote-transport.test.js} +2 -2
  296. package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
  297. package/dist/core/canvas/attention.js +4 -4
  298. package/dist/core/canvas/canvas.d.ts +6 -11
  299. package/dist/core/canvas/canvas.js +11 -33
  300. package/dist/core/canvas/db.js +207 -38
  301. package/dist/core/canvas/extensions.d.ts +1 -1
  302. package/dist/core/canvas/extensions.js +8 -1
  303. package/dist/core/canvas/index.d.ts +0 -1
  304. package/dist/core/canvas/index.js +0 -1
  305. package/dist/core/canvas/nav-model.d.ts +1 -1
  306. package/dist/core/canvas/nav-model.js +1 -1
  307. package/dist/core/canvas/paths.d.ts +5 -0
  308. package/dist/core/canvas/paths.js +16 -0
  309. package/dist/core/canvas/remote-canvas-source.js +2 -2
  310. package/dist/core/canvas/remote-transport.d.ts +7 -0
  311. package/dist/core/{view/transport-remote.js → canvas/remote-transport.js} +3 -4
  312. package/dist/core/canvas/source.js +1 -1
  313. package/dist/core/canvas/status-glyph.js +4 -12
  314. package/dist/core/canvas/types.d.ts +10 -35
  315. package/dist/core/clipboard-text.d.ts +8 -0
  316. package/dist/core/clipboard-text.js +18 -0
  317. package/dist/core/command-manifests/registry.d.ts +1 -3
  318. package/dist/core/command-plugins/bundle.d.ts +29 -0
  319. package/dist/core/command-plugins/bundle.js +198 -0
  320. package/dist/core/command-plugins/discovery.d.ts +0 -8
  321. package/dist/core/command-plugins/discovery.js +2 -39
  322. package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
  323. package/dist/core/command-plugins/transport/http-fetch.js +17 -95
  324. package/dist/core/command.d.ts +1 -13
  325. package/dist/core/command.js +1 -16
  326. package/dist/core/config.d.ts +4 -0
  327. package/dist/core/config.js +28 -3
  328. package/dist/core/document-lines.d.ts +4 -0
  329. package/dist/core/document-lines.js +6 -0
  330. package/dist/core/feed/feed.d.ts +2 -0
  331. package/dist/core/feed/feed.js +11 -7
  332. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +1 -0
  333. package/dist/core/human/__tests__/inbox-cancel-worker.js +7 -0
  334. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +1 -0
  335. package/dist/core/human/__tests__/inbox-claim-worker.js +17 -0
  336. package/dist/core/human/__tests__/inbox-core.test.d.ts +1 -0
  337. package/dist/core/human/__tests__/inbox-core.test.js +144 -0
  338. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +1 -0
  339. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +8 -0
  340. package/dist/core/human/__tests__/visible-paths.test.d.ts +1 -0
  341. package/dist/{clients/attach → core/human}/__tests__/visible-paths.test.js +9 -0
  342. package/dist/core/human/claim.d.ts +23 -0
  343. package/dist/core/human/claim.js +67 -0
  344. package/dist/core/human/convention.d.ts +30 -0
  345. package/dist/core/human/convention.js +202 -0
  346. package/dist/core/human/deck-factories.d.ts +8 -0
  347. package/dist/core/human/deck-factories.js +15 -0
  348. package/dist/core/human/deck-schema.d.ts +70 -0
  349. package/dist/core/human/deck-schema.js +92 -0
  350. package/dist/core/human/root.d.ts +7 -0
  351. package/dist/core/human/root.js +37 -0
  352. package/dist/core/human/scan.d.ts +3 -0
  353. package/dist/core/human/scan.js +76 -0
  354. package/dist/core/human/summary.d.ts +8 -0
  355. package/dist/core/human/summary.js +44 -0
  356. package/dist/core/human/tickets.d.ts +49 -0
  357. package/dist/core/human/tickets.js +190 -0
  358. package/dist/core/human/types.d.ts +136 -0
  359. package/dist/core/human/types.js +5 -0
  360. package/dist/{clients/attach → core/human}/visible-paths.d.ts +1 -1
  361. package/dist/{clients/attach → core/human}/visible-paths.js +3 -2
  362. package/dist/core/inspector/chrome.d.ts +6 -0
  363. package/dist/core/inspector/chrome.js +14 -0
  364. package/dist/core/inspector/contract.d.ts +105 -0
  365. package/dist/core/inspector/contract.js +1 -0
  366. package/dist/core/inspector/core.d.ts +4 -5
  367. package/dist/core/inspector/core.js +3 -5
  368. package/dist/core/inspector/host.d.ts +46 -0
  369. package/dist/core/{tui → inspector}/host.js +42 -208
  370. package/dist/core/inspector/text.d.ts +2 -2
  371. package/dist/core/inspector/transport.d.ts +6 -0
  372. package/dist/core/inspector/transport.js +36 -0
  373. package/dist/core/inspector/tui.d.ts +2 -2
  374. package/dist/core/inspector/tui.js +15 -15
  375. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +11 -11
  376. package/dist/core/keybindings/__tests__/resolve.test.js +10 -19
  377. package/dist/core/keybindings/attach-control.d.ts +9 -3
  378. package/dist/core/keybindings/attach-control.js +3 -1
  379. package/dist/core/keybindings/catalog.d.ts +6 -5
  380. package/dist/core/keybindings/catalog.js +61 -133
  381. package/dist/core/keybindings/inbox.d.ts +5 -6
  382. package/dist/core/keybindings/inbox.js +9 -10
  383. package/dist/core/keybindings/index.d.ts +3 -3
  384. package/dist/core/keybindings/index.js +3 -3
  385. package/dist/core/keybindings/persistence.d.ts +5 -1
  386. package/dist/core/keybindings/persistence.js +24 -6
  387. package/dist/core/keybindings/resolve.d.ts +6 -0
  388. package/dist/core/keybindings/resolve.js +10 -3
  389. package/dist/core/memory/inline-ref-grammar.js +2 -3
  390. package/dist/core/memory-resolver.d.ts +27 -29
  391. package/dist/core/memory-resolver.js +45 -39
  392. package/dist/core/model-routes.d.ts +33 -0
  393. package/dist/core/model-routes.js +42 -3
  394. package/dist/core/preview-registry.js +17 -55
  395. package/dist/core/profiles/select.js +3 -3
  396. package/dist/core/{view/remote-canvas-target.d.ts → remote-canvas-target.d.ts} +2 -2
  397. package/dist/core/{view/remote-canvas-target.js → remote-canvas-target.js} +4 -4
  398. package/dist/core/review/__tests__/capture-origin.test.d.ts +1 -0
  399. package/dist/core/review/__tests__/capture-origin.test.js +139 -0
  400. package/dist/core/review/__tests__/comments.test.d.ts +1 -0
  401. package/dist/core/review/__tests__/comments.test.js +98 -0
  402. package/dist/core/review/__tests__/project.test.d.ts +1 -0
  403. package/dist/core/review/__tests__/project.test.js +71 -0
  404. package/dist/core/review/__tests__/remap.test.d.ts +1 -0
  405. package/dist/core/review/__tests__/remap.test.js +159 -0
  406. package/dist/core/review/__tests__/stage-identity.test.d.ts +1 -0
  407. package/dist/core/review/__tests__/stage-identity.test.js +140 -0
  408. package/dist/core/review/birth.d.ts +7 -0
  409. package/dist/core/review/birth.js +23 -0
  410. package/dist/core/review/comments.d.ts +69 -0
  411. package/dist/core/review/comments.js +295 -0
  412. package/dist/core/review/companion.d.ts +35 -0
  413. package/dist/core/review/companion.js +205 -0
  414. package/dist/core/review/document.d.ts +27 -0
  415. package/dist/core/review/document.js +138 -0
  416. package/dist/core/review/project.d.ts +13 -0
  417. package/dist/core/review/project.js +58 -0
  418. package/dist/core/review/realize.d.ts +19 -0
  419. package/dist/core/review/realize.js +217 -0
  420. package/dist/core/review/remap.d.ts +24 -0
  421. package/dist/core/review/remap.js +156 -0
  422. package/dist/core/review/signal.d.ts +5 -0
  423. package/dist/core/review/signal.js +31 -0
  424. package/dist/core/review/stage.d.ts +26 -0
  425. package/dist/core/review/stage.js +184 -0
  426. package/dist/core/review/store.d.ts +46 -0
  427. package/dist/core/review/store.js +163 -0
  428. package/dist/core/review/ticket-filter.d.ts +17 -0
  429. package/dist/core/review/ticket-filter.js +32 -0
  430. package/dist/core/review/types.d.ts +130 -0
  431. package/dist/core/review/types.js +23 -0
  432. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +1 -0
  433. package/dist/core/runtime/__tests__/session-visibility.test.js +119 -0
  434. package/dist/core/runtime/bearings.d.ts +5 -17
  435. package/dist/core/runtime/bearings.js +88 -71
  436. package/dist/core/runtime/broker-protocol.d.ts +31 -8
  437. package/dist/core/runtime/broker.d.ts +15 -1
  438. package/dist/core/runtime/broker.js +573 -141
  439. package/dist/core/runtime/canvas-extensions.d.ts +4 -5
  440. package/dist/core/runtime/canvas-extensions.js +5 -5
  441. package/dist/core/runtime/front-door.js +4 -4
  442. package/dist/core/runtime/headless-pi.d.ts +24 -0
  443. package/dist/core/runtime/headless-pi.js +152 -0
  444. package/dist/core/runtime/kickoff.d.ts +1 -5
  445. package/dist/core/runtime/kickoff.js +1 -5
  446. package/dist/core/runtime/model-registry.d.ts +3 -0
  447. package/dist/core/runtime/model-registry.js +13 -0
  448. package/dist/core/runtime/naming-persist.d.ts +4 -0
  449. package/dist/core/runtime/naming-persist.js +27 -1
  450. package/dist/core/runtime/naming.d.ts +17 -12
  451. package/dist/core/runtime/naming.js +91 -140
  452. package/dist/core/runtime/node-read.js +19 -10
  453. package/dist/core/runtime/nodes.d.ts +9 -14
  454. package/dist/core/runtime/nodes.js +3 -53
  455. package/dist/core/runtime/package-health.d.ts +6 -21
  456. package/dist/core/runtime/package-health.js +12 -123
  457. package/dist/core/runtime/placement-tmux.d.ts +2 -1
  458. package/dist/core/runtime/placement-tmux.js +6 -4
  459. package/dist/core/runtime/placement.d.ts +1 -0
  460. package/dist/core/runtime/placement.js +4 -8
  461. package/dist/core/runtime/promote.js +3 -0
  462. package/dist/core/runtime/recap.d.ts +2 -7
  463. package/dist/core/runtime/recap.js +35 -69
  464. package/dist/core/runtime/revive.js +34 -77
  465. package/dist/core/runtime/session-cycles.d.ts +4 -0
  466. package/dist/core/runtime/session-cycles.js +14 -1
  467. package/dist/core/runtime/session-visibility.d.ts +37 -0
  468. package/dist/core/runtime/session-visibility.js +83 -0
  469. package/dist/core/runtime/spawn.js +10 -22
  470. package/dist/core/runtime/stop-guard.d.ts +1 -1
  471. package/dist/core/runtime/stop-guard.js +18 -13
  472. package/dist/core/runtime/surface-bg.js +1 -1
  473. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  474. package/dist/core/runtime/tmux-chrome.js +1 -1
  475. package/dist/core/runtime/tmux.d.ts +35 -7
  476. package/dist/core/runtime/tmux.js +439 -62
  477. package/dist/core/runtime/tool-group-summary.d.ts +19 -0
  478. package/dist/core/runtime/tool-group-summary.js +88 -0
  479. package/dist/core/scope.d.ts +2 -7
  480. package/dist/core/scope.js +9 -35
  481. package/dist/core/substrate/schema.d.ts +2 -2
  482. package/dist/core/termrender/code-doc.d.ts +12 -0
  483. package/dist/core/termrender/code-doc.js +92 -0
  484. package/dist/core/termrender/display.d.ts +12 -0
  485. package/dist/core/termrender/display.js +19 -0
  486. package/dist/core/termrender/termrender.d.ts +73 -0
  487. package/dist/core/termrender/termrender.js +795 -0
  488. package/dist/core/termrender/version.d.ts +1 -0
  489. package/dist/core/termrender/version.js +1 -0
  490. package/dist/core/tui/terminal.js +1 -2
  491. package/dist/core/user-settings.d.ts +71 -3
  492. package/dist/core/user-settings.js +83 -1
  493. package/dist/daemon/api/__tests__/inbox.test.js +44 -133
  494. package/dist/daemon/api/handlers/human.d.ts +0 -10
  495. package/dist/daemon/api/handlers/human.js +104 -702
  496. package/dist/daemon/api/handlers/inbox.js +113 -142
  497. package/dist/daemon/api/handlers/review-comments.d.ts +2 -0
  498. package/dist/daemon/api/handlers/review-comments.js +500 -0
  499. package/dist/daemon/api/handlers/reviews.d.ts +2 -0
  500. package/dist/daemon/api/handlers/reviews.js +287 -0
  501. package/dist/daemon/api/map.d.ts +22 -7
  502. package/dist/daemon/api/map.js +159 -11
  503. package/dist/daemon/api/server.js +4 -0
  504. package/dist/daemon/cron-run.js +6 -9
  505. package/dist/daemon/crtrd.js +17 -33
  506. package/dist/daemon/fleet.d.ts +1 -8
  507. package/dist/daemon/fleet.js +4 -30
  508. package/dist/daemon/human/finish.d.ts +14 -0
  509. package/dist/daemon/human/finish.js +115 -0
  510. package/dist/daemon/human/sweep.d.ts +6 -0
  511. package/dist/daemon/human/sweep.js +49 -0
  512. package/dist/daemon/messaging/node-message.d.ts +18 -0
  513. package/dist/daemon/messaging/node-message.js +70 -0
  514. package/dist/daemon/review/comment-notify.d.ts +26 -0
  515. package/dist/daemon/review/comment-notify.js +107 -0
  516. package/dist/daemon/review/deliver.d.ts +7 -0
  517. package/dist/daemon/review/deliver.js +56 -0
  518. package/dist/daemon/review/finish.d.ts +22 -0
  519. package/dist/daemon/review/finish.js +254 -0
  520. package/dist/daemon/review/sweep.d.ts +11 -0
  521. package/dist/daemon/review/sweep.js +120 -0
  522. package/dist/index.d.ts +2 -0
  523. package/dist/index.js +2 -2
  524. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +42 -64
  525. package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +1 -0
  526. package/dist/pi-extensions/__tests__/canvas-recap.test.js +159 -0
  527. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +16 -38
  528. package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
  529. package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
  530. package/dist/pi-extensions/canvas-context-intro.d.ts +8 -11
  531. package/dist/pi-extensions/canvas-context-intro.js +50 -104
  532. package/dist/pi-extensions/canvas-recap.d.ts +15 -2
  533. package/dist/pi-extensions/canvas-recap.js +192 -69
  534. package/dist/pi-extensions/canvas-review-boundary.d.ts +59 -0
  535. package/dist/pi-extensions/canvas-review-boundary.js +81 -0
  536. package/dist/pi-extensions/canvas-stophook.d.ts +3 -3
  537. package/dist/pi-extensions/canvas-stophook.js +78 -128
  538. package/dist/pi-extensions/canvas-structured-output.js +52 -8
  539. package/dist/shared/generated-context.d.ts +29 -4
  540. package/dist/shared/generated-context.js +122 -7
  541. package/dist/shared/tool-groups.d.ts +23 -0
  542. package/dist/shared/tool-groups.js +60 -0
  543. package/dist/shared/working-activity.d.ts +8 -0
  544. package/dist/shared/working-activity.js +26 -0
  545. package/dist/types.d.ts +36 -2
  546. package/dist/types.js +51 -0
  547. package/dist/web-client/assets/index-CCPaLeW7.css +2 -0
  548. package/dist/web-client/assets/index-kyOWsnZK.js +86 -0
  549. package/dist/web-client/index.html +2 -2
  550. package/dist/web-client/sw.js +1 -1
  551. package/docs/compat/hearth-crtr-v4.md +2 -2
  552. package/docs/compat/hearth-crtr-v5.md +4 -2
  553. package/docs/public-api.md +3 -3
  554. package/package.json +21 -14
  555. package/runtime.lock.json +4661 -1453
  556. package/scripts/postinstall.mjs +15 -2
  557. package/dist/builtin-pi-packages/pi-mode-switch/README.md +0 -36
  558. package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +0 -36
  559. package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +0 -449
  560. package/dist/builtin-pi-packages/pi-mode-switch/package.json +0 -14
  561. package/dist/builtin-pi-packages/pi-mode-switch/tsconfig.json +0 -9
  562. package/dist/builtin-views/_lib/states.mjs +0 -161
  563. package/dist/builtin-views/canvas/core.mjs +0 -657
  564. package/dist/builtin-views/canvas/text.mjs +0 -58
  565. package/dist/builtin-views/canvas/tui.mjs +0 -168
  566. package/dist/builtin-views/canvas/web.jsx +0 -121
  567. package/dist/builtin-views/chat/core.mjs +0 -684
  568. package/dist/builtin-views/chat/text.mjs +0 -101
  569. package/dist/builtin-views/chat/tui.mjs +0 -360
  570. package/dist/builtin-views/chat/web.jsx +0 -362
  571. package/dist/builtin-views/git-pr/core.mjs +0 -673
  572. package/dist/builtin-views/git-pr/text.mjs +0 -84
  573. package/dist/builtin-views/git-pr/tui.mjs +0 -301
  574. package/dist/builtin-views/git-pr/web.jsx +0 -216
  575. package/dist/builtin-views/inbox/_lib/render.mjs +0 -175
  576. package/dist/builtin-views/inbox/core.mjs +0 -1273
  577. package/dist/builtin-views/inbox/text.mjs +0 -73
  578. package/dist/builtin-views/inbox/tui.mjs +0 -314
  579. package/dist/builtin-views/inbox/web.jsx +0 -188
  580. package/dist/builtin-views/linkedin/core.mjs +0 -906
  581. package/dist/builtin-views/linkedin/text.mjs +0 -69
  582. package/dist/builtin-views/linkedin/tui.mjs +0 -413
  583. package/dist/builtin-views/linkedin/web.jsx +0 -206
  584. package/dist/builtin-views/prompt-review/core.mjs +0 -735
  585. package/dist/builtin-views/prompt-review/text.mjs +0 -15
  586. package/dist/builtin-views/prompt-review/tui.mjs +0 -196
  587. package/dist/builtin-views/prompt-review/web.jsx +0 -484
  588. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.js +0 -50
  589. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.ts +0 -53
  590. package/dist/builtin-views/workspace-sidebar/core.mjs +0 -670
  591. package/dist/builtin-views/workspace-sidebar/text.mjs +0 -53
  592. package/dist/builtin-views/workspace-sidebar/tui.mjs +0 -141
  593. package/dist/builtin-views/workspace-sidebar/web.jsx +0 -109
  594. package/dist/clients/attach/session/mode.d.ts +0 -25
  595. package/dist/clients/attach/session/mode.js +0 -97
  596. package/dist/commands/sys/promptstudio.d.ts +0 -2
  597. package/dist/commands/sys/promptstudio.js +0 -65
  598. package/dist/commands/view-cycle.d.ts +0 -2
  599. package/dist/commands/view-cycle.js +0 -130
  600. package/dist/commands/view-list.d.ts +0 -2
  601. package/dist/commands/view-list.js +0 -66
  602. package/dist/commands/view-new.d.ts +0 -2
  603. package/dist/commands/view-new.js +0 -74
  604. package/dist/commands/view-pick.d.ts +0 -6
  605. package/dist/commands/view-pick.js +0 -129
  606. package/dist/commands/view-run.d.ts +0 -2
  607. package/dist/commands/view-run.js +0 -214
  608. package/dist/commands/view.d.ts +0 -2
  609. package/dist/commands/view.js +0 -31
  610. package/dist/commands/workspace.d.ts +0 -2
  611. package/dist/commands/workspace.js +0 -165
  612. package/dist/core/__tests__/chat-view-reconnect.test.js +0 -105
  613. package/dist/core/__tests__/full/consult-startup-failure.test.js +0 -124
  614. package/dist/core/canvas/__tests__/human-work-outbox.test.js +0 -123
  615. package/dist/core/canvas/human-work-outbox.d.ts +0 -73
  616. package/dist/core/canvas/human-work-outbox.js +0 -261
  617. package/dist/core/command-plugins/store.d.ts +0 -16
  618. package/dist/core/command-plugins/store.js +0 -64
  619. package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +0 -40
  620. package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
  621. package/dist/core/runtime/fault-recovery-nudge.js +0 -3
  622. package/dist/core/tui/__tests__/host-keybindings.test.js +0 -113
  623. package/dist/core/tui/host.d.ts +0 -66
  624. package/dist/core/view/__tests__/transport-cache.test.js +0 -62
  625. package/dist/core/view/bridge.d.ts +0 -10
  626. package/dist/core/view/bridge.js +0 -31
  627. package/dist/core/view/chrome.d.ts +0 -9
  628. package/dist/core/view/chrome.js +0 -22
  629. package/dist/core/view/contract.d.ts +0 -205
  630. package/dist/core/view/contract.js +0 -23
  631. package/dist/core/view/loader.d.ts +0 -31
  632. package/dist/core/view/loader.js +0 -188
  633. package/dist/core/view/stream-local.d.ts +0 -3
  634. package/dist/core/view/stream-local.js +0 -231
  635. package/dist/core/view/transport-cache.d.ts +0 -8
  636. package/dist/core/view/transport-cache.js +0 -38
  637. package/dist/core/view/transport-local.d.ts +0 -7
  638. package/dist/core/view/transport-local.js +0 -83
  639. package/dist/core/view/transport-remote.d.ts +0 -2
  640. package/dist/core/view/transport.d.ts +0 -10
  641. package/dist/core/view/transport.js +0 -15
  642. package/dist/pi-extensions/naming-tool.d.ts +0 -24
  643. package/dist/pi-extensions/naming-tool.js +0 -67
  644. package/dist/prompts/view.d.ts +0 -7
  645. package/dist/prompts/view.js +0 -172
  646. package/dist/web/ViewChrome.d.ts +0 -7
  647. package/dist/web/ViewChrome.js +0 -28
  648. package/dist/web/ViewPane.d.ts +0 -39
  649. package/dist/web/ViewPane.js +0 -48
  650. package/dist/web/index.d.ts +0 -8
  651. package/dist/web/index.js +0 -22
  652. package/dist/web/runtime.d.ts +0 -39
  653. package/dist/web/runtime.js +0 -232
  654. package/dist/web/states.d.ts +0 -24
  655. package/dist/web/states.js +0 -24
  656. package/dist/web/transport-http.d.ts +0 -5
  657. package/dist/web/transport-http.js +0 -34
  658. package/dist/web/transport-stream.d.ts +0 -3
  659. package/dist/web/transport-stream.js +0 -204
  660. package/dist/web-client/assets/index-U_NZ66VE.js +0 -79
  661. package/dist/web-client/assets/index-aaeu4adv.css +0 -2
  662. /package/dist/{builtin-views/workspace-sidebar/__tests__/core.test.d.ts → clients/attach/__tests__/file-review-focus.test.d.ts} +0 -0
  663. /package/dist/clients/attach/__tests__/{visible-paths.test.d.ts → group-activity.test.d.ts} +0 -0
  664. /package/dist/{core/__tests__/chat-view-reconnect.test.d.ts → clients/attach/__tests__/input-controller-extension-command.test.d.ts} +0 -0
  665. /package/dist/{core/__tests__/full/consult-startup-failure.test.d.ts → clients/attach/__tests__/session-identity-refresh.test.d.ts} +0 -0
  666. /package/dist/{core/canvas/__tests__/human-work-outbox.test.d.ts → clients/inbox/__tests__/inbox-controller.test.d.ts} +0 -0
  667. /package/dist/{core/keybindings/__tests__/bespoke-consumers.test.d.ts → clients/inbox/__tests__/mount-panel.test.d.ts} +0 -0
  668. /package/dist/{core/tui/__tests__/host-keybindings.test.d.ts → clients/inbox/review/__tests__/editor-roundtrip.test.d.ts} +0 -0
  669. /package/dist/{core/view/__tests__/transport-cache.test.d.ts → clients/inbox/review/__tests__/remap.test.d.ts} +0 -0
  670. /package/dist/{core/view/__tests__/transport-remote.test.d.ts → clients/inbox/review/__tests__/review-core.test.d.ts} +0 -0
@@ -1,670 +0,0 @@
1
- // @ts-check
2
- /**
3
- * Workspace Sidebar — the PORTABLE CORE of the `workspace-sidebar` view
4
- * (manifest · init · sources · commands · intents). The left rail of
5
- * `crtr workspace`: a narrow, cwd-scoped navigator with two sections —
6
- *
7
- * ⌗ this graph the subtree of the node the chat pane is attached to
8
- * (its forest root), rendered as an ASCII tree.
9
- * ↪ elsewhere the OTHER top-level nodes (forest roots) started in this
10
- * cwd — root rows only, ⚑ inbox flags.
11
- *
12
- * Runs in BOTH Node (the tmux TUI, via `tui.mjs`) and the browser (the
13
- * React+Tailwind page, via `web.jsx`), so it imports NOTHING — no `node:*`, no
14
- * crtr. The data layer is expressed as transport-agnostic `Source`/`Command`
15
- * descriptors: the core describes WHAT to run (`request()` → a SourceRequest for
16
- * `crtr`/`tmux`), the host's Transport runs it (local `execFile` for the TUI,
17
- * the HTTP bridge for web), and the pure `parse()` turns bytes → typed data. The
18
- * forest model, cwd scoping, attention rollup, and cursor logic are pure string
19
- * work that runs anywhere.
20
- *
21
- * The rail is a CONTROLLER in the TUI: the `open` intent shells
22
- * `crtr surface node focus <id> --pane <chatPane>` (a `Command`), swapping the selected
23
- * node into the OTHER pane. The chat pane + the attached node are resolved each
24
- * refresh from the window's tmux panes (the `@crtr_node` tag attach self-sets,
25
- * which survives the swap). On the web target there is no chat pane — the same
26
- * rail renders as a plain styled list; `open` no-ops with a banner.
27
- *
28
- * NOTHING throws. Sources return a `Result<T>` (typed `SourceError` on a hard
29
- * failure); `refresh` keeps the last-known rail on a transient failure.
30
- *
31
- * @module workspace-sidebar/core
32
- */
33
-
34
- /**
35
- * @typedef {import('../../core/view/contract.js').SourceError} SourceError
36
- * @typedef {import('../../core/view/contract.js').IntentCtx<SidebarState>} Ctx
37
- */
38
-
39
- // ── Status vocabulary (single source: core/canvas/browse/render.ts) ───────────
40
-
41
- const LIVE_STATUS = new Set(['active', 'idle']);
42
-
43
- // ── Types ─────────────────────────────────────────────────────────────────────
44
-
45
- /**
46
- * One canvas node, flattened from `node inspect list --json`.
47
- * @typedef {Object} CanvasNode
48
- * @property {string} nodeId
49
- * @property {string} name
50
- * @property {string} kind
51
- * @property {string} mode
52
- * @property {string} lifecycle
53
- * @property {string} status active | idle | done | dead | canceled.
54
- * @property {string} cwd Originating cwd — the workspace scope key.
55
- * @property {string|null} parent Spawn/subscription parent id (null ⇒ a root).
56
- * @property {string} created ISO 8601 birth timestamp (drives ordering).
57
- */
58
-
59
- /**
60
- * One LOGICAL rail row (each presenter paints it in its own idiom). A node row
61
- * is selectable; header/chrome rows are inert chrome.
62
- * @typedef {{kind:'header', text:string}
63
- * | {kind:'chrome', text:string}
64
- * | {kind:'node', nodeId:string, name:string, status:string, prefix:string, attached:boolean, asks:number}} RailRow
65
- */
66
-
67
- /**
68
- * The view's immutable state (the core owns it; intents replace it via ctx.set).
69
- * @typedef {Object} SidebarState
70
- * @property {string} cwd Workspace scope key (process.cwd()).
71
- * @property {string} targetOverride Optional explicit chat pane id (options.target); '' if unset.
72
- * @property {string} chatPane tmux pane id of the chat pane, resolved each refresh.
73
- * @property {string|null} attachedNode Node the chat pane currently views (@crtr_node), or null.
74
- * @property {string|null} currentRoot Forest root of `this graph`.
75
- * @property {RailRow[]} rows Flattened render list (chrome + node rows).
76
- * @property {number} cursor Index into `rows` (always lands on a node row).
77
- * @property {number} scroll draw.list scroll, stored back each frame.
78
- * @property {number} graphsHere Live forest roots in this cwd.
79
- * @property {number} nodesHere Total nodes in this cwd.
80
- * @property {number} asksHere Total pending asks across the rendered set.
81
- * @property {number} lastFetch Epoch ms of the last successful refresh.
82
- * @property {SourceError|null} srcError Non-null ⇒ the node source failed (typed).
83
- */
84
-
85
- // ── Result helpers (inlined — the core imports nothing) ───────────────────────
86
-
87
- /** @template T @param {T} data @returns {{ok:true, data:T}} */
88
- function ok(data) {
89
- return { ok: true, data };
90
- }
91
- /** @param {SourceError} error @returns {{ok:false, error:SourceError}} */
92
- function fail(error) {
93
- return { ok: false, error };
94
- }
95
-
96
- /** @param {string} s @returns {string} */
97
- function firstLine(s) {
98
- const lines = String(s || '').split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
99
- return lines.length ? lines[0] : '';
100
- }
101
-
102
- /** @param {unknown} v @returns {string} */
103
- function str(v) {
104
- return v == null ? '' : String(v);
105
- }
106
-
107
- /** @param {number} n @param {string} w @returns {string} */
108
- export function plural(n, w) {
109
- return `${n} ${w}${n === 1 ? '' : 's'}`;
110
- }
111
-
112
- /** @param {any} n @returns {CanvasNode} */
113
- function toNode(n) {
114
- const o = n || {};
115
- return {
116
- nodeId: str(o.node_id),
117
- name: str(o.name) || '(unnamed)',
118
- kind: str(o.kind) || '?',
119
- mode: str(o.mode) || '?',
120
- lifecycle: str(o.lifecycle) || '?',
121
- status: str(o.status) || '?',
122
- cwd: str(o.cwd),
123
- parent: o.parent ? str(o.parent) : null,
124
- created: str(o.created),
125
- };
126
- }
127
-
128
- // ── Typed SourceError displays (presenters render `display` verbatim) ─────────
129
-
130
- /** @type {SourceError} */
131
- const CRTR_MISSING = {
132
- kind: 'crtr-missing',
133
- display: {
134
- headline: 'crtr unavailable',
135
- explanation: 'The crtr binary was not found on PATH.',
136
- nextStep: 'Install crtr (or set it on PATH), then press g.',
137
- level: 'error',
138
- blocking: true,
139
- },
140
- };
141
- /** @param {string} msg @returns {SourceError} */
142
- function crtrFailed(msg) {
143
- return {
144
- kind: 'crtr-failed',
145
- display: {
146
- headline: 'Canvas unavailable',
147
- explanation: msg || 'crtr could not read the graph.',
148
- nextStep: 'Press g to retry.',
149
- level: 'error',
150
- blocking: false,
151
- },
152
- };
153
- }
154
-
155
- // ── Sources (reads): a request descriptor + a pure parse ──────────────────────
156
-
157
- /**
158
- * Every node on the canvas (all statuses). The view resolves each node's
159
- * authoritative `subscribes_to` edges separately: `this graph` follows the
160
- * attached node across cwd boundaries, while `elsewhere` is scoped to the
161
- * workspace cwd. The PRIMARY instrument —
162
- * its parse owns the two hard failures (crtr missing / a failing crtr command).
163
- * @type {import('../../core/view/contract.js').Source<CanvasNode[]>}
164
- */
165
- export const nodesSource = {
166
- id: 'nodes',
167
- request: () => ({ kind: 'exec', bin: 'crtr', args: ['node', 'inspect', 'list', '--json'] }),
168
- parse: (raw) => {
169
- if (!raw.ok) return fail(CRTR_MISSING);
170
- if (raw.exitCode !== 0) return fail(crtrFailed(firstLine(raw.stderr || raw.stdout)));
171
- const out = String(raw.stdout || '').trim();
172
- let data;
173
- try {
174
- data = out === '' ? {} : JSON.parse(out);
175
- } catch {
176
- return fail(crtrFailed('could not parse `crtr node inspect list` output as JSON'));
177
- }
178
- const arr = data && Array.isArray(data.nodes) ? data.nodes : [];
179
- return ok(arr.map(toNode));
180
- },
181
- };
182
-
183
- /**
184
- * The canvas's authoritative subscription children. `parent` is immutable spawn
185
- * provenance, but subscribe/unsubscribe mutate this edge map, so it alone
186
- * defines the rail topology.
187
- * @type {import('../../core/view/contract.js').Source<Map<string, string[]>>}
188
- */
189
- export const subscriptionsSource = {
190
- id: 'subscriptions',
191
- request: () => ({ kind: 'exec', bin: 'crtr', args: ['canvas', 'snapshot', '--json'] }),
192
- parse: (raw) => {
193
- if (!raw.ok || raw.exitCode !== 0) return fail(crtrFailed(firstLine(raw.stderr || raw.stdout)));
194
- try {
195
- const data = JSON.parse(String(raw.stdout || '').trim() || '{}');
196
- const subscriptions = data && data.subscriptions && typeof data.subscriptions === 'object' ? data.subscriptions : {};
197
- const out = new Map();
198
- for (const [nodeId, childIds] of Object.entries(subscriptions)) {
199
- out.set(nodeId, Array.isArray(childIds) ? childIds.map(str).filter(Boolean) : []);
200
- }
201
- return ok(out);
202
- } catch {
203
- return fail(crtrFailed('could not parse `crtr canvas snapshot` output as JSON'));
204
- }
205
- },
206
- };
207
-
208
- /**
209
- * Per-node pending-ask counts for a visible set, in ONE pass: the current
210
- * graph's whole sub-DAG (`--view <root>`) unioned with explicit `nodeIds` (the
211
- * other roots in this cwd). BEST-EFFORT — any failure yields {} so the rail
212
- * still renders without ⚑ flags.
213
- * @type {import('../../core/view/contract.js').Source<Record<string,number>, {viewRoot:string|null, nodeIds:string[]}>}
214
- */
215
- export const attentionSource = {
216
- id: 'attention',
217
- request: ({ viewRoot, nodeIds }) => {
218
- const args = ['canvas', 'attention', 'map', '--json'];
219
- if (viewRoot) args.push('--view', viewRoot);
220
- const extra = (nodeIds || []).filter(Boolean);
221
- if (extra.length) args.push('--nodes', extra.join(','));
222
- return { kind: 'exec', bin: 'crtr', args };
223
- },
224
- parse: (raw) => {
225
- if (!raw.ok || raw.exitCode !== 0) return ok({});
226
- let data;
227
- try {
228
- data = JSON.parse(String(raw.stdout || '').trim() || '{}');
229
- } catch {
230
- return ok({});
231
- }
232
- const counts = data && data.counts && typeof data.counts === 'object' ? data.counts : {};
233
- /** @type {Record<string, number>} */
234
- const out = {};
235
- for (const [k, v] of Object.entries(counts)) out[k] = typeof v === 'number' ? v : 0;
236
- return ok(out);
237
- },
238
- };
239
-
240
- /**
241
- * The host's working directory — the workspace scope key the rail filters on.
242
- * Resolved through the transport (which runs exec in the host's cwd) so it is
243
- * uniform across BOTH targets: `process.cwd()` is a Node-only facility the
244
- * browser can't read, so the web target would otherwise scope to '' and show an
245
- * empty rail. BEST-EFFORT — a failure falls back to the init-time cwd.
246
- * @type {import('../../core/view/contract.js').Source<string>}
247
- */
248
- export const cwdSource = {
249
- id: 'cwd',
250
- request: () => ({ kind: 'exec', bin: 'pwd', args: [] }),
251
- parse: (raw) => ok(raw.ok && raw.exitCode === 0 ? String(raw.stdout || '').trim() : ''),
252
- };
253
-
254
- /**
255
- * The tmux panes in the rail's window, each with its `@crtr_node` tag. The chat
256
- * pane the rail drives is the one attach has tagged (the tag survives the
257
- * swap-pane `crtr surface node focus` does). BEST-EFFORT — no tmux / a failure yields []
258
- * so the rail still renders (just without a chat-pane controller; the web target
259
- * always lands here). The self-pane never carries `@crtr_node` (the rail tags
260
- * `@crtr_view`), so "first pane with a node tag" is the chat pane without any
261
- * self-exclusion.
262
- * @type {import('../../core/view/contract.js').Source<Array<{pane:string, node:string}>>}
263
- */
264
- export const panesSource = {
265
- id: 'tmux-panes',
266
- request: () => ({ kind: 'exec', bin: 'tmux', args: ['list-panes', '-F', '#{pane_id}\t#{@crtr_node}'] }),
267
- parse: (raw) => {
268
- if (!raw.ok || raw.exitCode !== 0) return ok([]);
269
- /** @type {Array<{pane:string, node:string}>} */
270
- const rows = [];
271
- for (const line of String(raw.stdout || '').split(/\r?\n/)) {
272
- if (!line) continue;
273
- const tab = line.indexOf('\t');
274
- const pane = (tab < 0 ? line : line.slice(0, tab)).trim();
275
- const node = tab < 0 ? '' : line.slice(tab + 1).trim();
276
- if (pane) rows.push({ pane, node });
277
- }
278
- return ok(rows);
279
- },
280
- };
281
-
282
- // ── Commands (writes): invoked by an intent ───────────────────────────────────
283
-
284
- /**
285
- * Focus a node into the chat pane (`crtr surface node focus <id> --pane <pane>`) — the
286
- * swap-pane call the Alt+G graph overlay uses. The swap lands in the OTHER pane,
287
- * so the rail neither waits on nor renders its result.
288
- * @type {import('../../core/view/contract.js').Command<boolean, {nodeId:string, pane:string}>}
289
- */
290
- export const focusCommand = {
291
- id: 'focus',
292
- request: ({ nodeId, pane }) => ({ kind: 'exec', bin: 'crtr', args: ['surface', 'node', 'focus', nodeId, '--pane', pane] }),
293
- parse: (raw) => ok(raw.ok && raw.exitCode === 0),
294
- };
295
-
296
- // ── Forest model (over a supplied node set; pure) ─────────────────────────────
297
-
298
- /** @param {CanvasNode} a @param {CanvasNode} b @returns {number} */
299
- function byBirth(a, b) {
300
- return a.created < b.created ? -1 : a.created > b.created ? 1 : 0;
301
- }
302
-
303
- /**
304
- * Build id→node, subscription parent→children, and roots for a node set. A
305
- * root has no incoming `subscribes_to` edge inside that set.
306
- * @param {CanvasNode[]} nodes
307
- * @param {Map<string, string[]>} subscriptions
308
- */
309
- function buildForest(nodes, subscriptions) {
310
- /** @type {Map<string, CanvasNode>} */
311
- const byId = new Map();
312
- for (const n of nodes) byId.set(n.nodeId, n);
313
- /** @type {Map<string, CanvasNode[]>} */
314
- const children = new Map();
315
- /** @type {Map<string, string[]>} */
316
- const parents = new Map();
317
- for (const parent of nodes) {
318
- for (const childId of subscriptions.get(parent.nodeId) || []) {
319
- const child = byId.get(childId);
320
- if (!child) continue;
321
- const kids = children.get(parent.nodeId);
322
- if (kids) kids.push(child);
323
- else children.set(parent.nodeId, [child]);
324
- const managers = parents.get(childId);
325
- if (managers) managers.push(parent.nodeId);
326
- else parents.set(childId, [parent.nodeId]);
327
- }
328
- }
329
- for (const arr of children.values()) arr.sort(byBirth);
330
- for (const managers of parents.values()) managers.sort((a, b) => byBirth(/** @type {CanvasNode} */ (byId.get(a)), /** @type {CanvasNode} */ (byId.get(b))));
331
- const roots = nodes.filter((n) => !parents.has(n.nodeId)).sort(byBirth);
332
- return { byId, children, parents, roots };
333
- }
334
-
335
- /**
336
- * Climb from `id` to an authoritative subscription root. Cycle-guarded.
337
- * A multi-manager DAG uses its oldest manager for this tree presentation.
338
- * @param {string} id @param {Map<string, string[]>} parents @returns {string}
339
- */
340
- function climbRoot(id, parents) {
341
- const seen = new Set();
342
- let cur = id;
343
- while (true) {
344
- if (seen.has(cur)) return cur;
345
- seen.add(cur);
346
- const manager = (parents.get(cur) || [])[0];
347
- if (!manager) return cur;
348
- cur = manager;
349
- }
350
- }
351
-
352
- /**
353
- * @param {string} id @param {Map<string,CanvasNode[]>} children
354
- * @param {Map<string,CanvasNode>} byId @param {Set<string>} [guard] @returns {boolean}
355
- */
356
- function subtreeLive(id, children, byId, guard = new Set()) {
357
- if (guard.has(id)) return false;
358
- guard.add(id);
359
- const n = byId.get(id);
360
- let res = !!n && LIVE_STATUS.has(n.status);
361
- if (!res) {
362
- for (const c of children.get(id) || []) {
363
- if (subtreeLive(c.nodeId, children, byId, guard)) {
364
- res = true;
365
- break;
366
- }
367
- }
368
- }
369
- guard.delete(id);
370
- return res;
371
- }
372
-
373
- // ── Row builders (pure → logical RailRow[]) ───────────────────────────────────
374
-
375
- /** @param {CanvasNode} n @param {string} prefix @param {boolean} attached @param {number} asks @returns {RailRow} */
376
- function nodeRow(n, prefix, attached, asks) {
377
- return { kind: 'node', nodeId: n.nodeId, name: n.name, status: n.status, prefix, attached, asks };
378
- }
379
- /** @param {string} text @returns {RailRow} */
380
- function headerRow(text) {
381
- return { kind: 'header', text };
382
- }
383
- /** @param {string} [text] @returns {RailRow} */
384
- function chromeRow(text) {
385
- return { kind: 'chrome', text: text || '' };
386
- }
387
-
388
- /**
389
- * Build `this graph` from the complete canvas and `elsewhere` from the cwd
390
- * scope. Both use mutable subscription edges, so unsubscribe removes a child
391
- * immediately and a new subscription appears without metadata changes.
392
- * @param {CanvasNode[]} nodes
393
- * @param {CanvasNode[]} mine
394
- * @param {Map<string, string[]>} subscriptions
395
- * @param {string|null} attachedNode
396
- */
397
- function buildRail(nodes, mine, subscriptions, attachedNode) {
398
- const graph = buildForest(nodes, subscriptions);
399
- const scoped = buildForest(mine, subscriptions);
400
-
401
- // `this graph` root: the attached node's root in the complete canvas if
402
- // known, else the newest LIVE root in this cwd, else the newest cwd root.
403
- /** @type {string|null} */
404
- let currentRoot = null;
405
- if (attachedNode && graph.byId.has(attachedNode)) {
406
- currentRoot = climbRoot(attachedNode, graph.parents);
407
- } else {
408
- const live = scoped.roots.filter((r) => subtreeLive(r.nodeId, scoped.children, scoped.byId));
409
- const pool = live.length ? live : scoped.roots;
410
- if (pool.length) currentRoot = pool[pool.length - 1].nodeId; // newest
411
- }
412
-
413
- return {
414
- byId: graph.byId,
415
- children: graph.children,
416
- currentRoot,
417
- roots: scoped.roots,
418
- scopedById: scoped.byId,
419
- scopedChildren: scoped.children,
420
- liveRoots: scoped.roots.filter((r) => subtreeLive(r.nodeId, scoped.children, scoped.byId)),
421
- };
422
- }
423
-
424
- // ── Cursor model (skips chrome rows) ───────────────────────────────────────────
425
-
426
- /** @param {RailRow[]} rows @returns {number[]} */
427
- function selectableIdx(rows) {
428
- /** @type {number[]} */
429
- const out = [];
430
- for (let i = 0; i < rows.length; i++) if (rows[i].kind === 'node') out.push(i);
431
- return out;
432
- }
433
-
434
- /**
435
- * Re-home the cursor after a rebuild: same nodeId if still present, else the
436
- * attached node, else the first selectable row.
437
- * @param {RailRow[]} rows @param {string|null} prevId @param {string|null} attachedNode @returns {number}
438
- */
439
- function reanchor(rows, prevId, attachedNode) {
440
- const sel = selectableIdx(rows);
441
- if (sel.length === 0) return 0;
442
- const want = prevId || attachedNode;
443
- const found = want ? rows.findIndex((r) => r.kind === 'node' && r.nodeId === want) : -1;
444
- return found >= 0 ? found : sel[0];
445
- }
446
-
447
- /** @param {SidebarState} s @param {1|-1} dir @returns {SidebarState} */
448
- function moveCursor(s, dir) {
449
- const sel = selectableIdx(s.rows);
450
- if (sel.length === 0) return s;
451
- const pos = sel.indexOf(s.cursor);
452
- if (pos < 0) return { ...s, cursor: sel[0] };
453
- const next = Math.max(0, Math.min(sel.length - 1, pos + dir));
454
- return { ...s, cursor: sel[next] };
455
- }
456
-
457
- // ── The portable core ──────────────────────────────────────────────────────────
458
-
459
- /** @type {import('../../core/view/contract.js').ViewCore<SidebarState>} */
460
- const core = {
461
- manifest: {
462
- id: 'workspace-sidebar',
463
- title: 'Workspace',
464
- description: 'Left rail for `crtr workspace` — this graph + other agents in this cwd',
465
- refreshMs: 2500,
466
- },
467
-
468
- /** Cheap + synchronous initial state — NO fetch. @param {Readonly<Record<string,string>>} opts @returns {SidebarState} */
469
- init(opts) {
470
- return {
471
- cwd: typeof process !== 'undefined' && process.cwd ? process.cwd() : '',
472
- targetOverride: String((opts && opts.target) || ''),
473
- chatPane: '',
474
- attachedNode: null,
475
- currentRoot: null,
476
- rows: [],
477
- cursor: 0,
478
- scroll: 0,
479
- graphsHere: 0,
480
- nodesHere: 0,
481
- asksHere: 0,
482
- lastFetch: 0,
483
- srcError: null,
484
- };
485
- },
486
-
487
- sources: { cwdSource, nodesSource, subscriptionsSource, attentionSource, panesSource },
488
- commands: { focusCommand },
489
-
490
- intents: {
491
- /**
492
- * Resolve the chat pane + attached node from tmux, pull the node graph,
493
- * scope to this cwd, and rebuild the two-section rail. Runs in the host's
494
- * single-flight lane. A blocking node-source failure with no prior rail
495
- * drops to a guided takeover; a transient failure KEEPS the last-known rail.
496
- * @param {Ctx} ctx
497
- */
498
- async refresh(ctx) {
499
- ctx.signal.setStatus('Loading…');
500
-
501
- // Resolve the chat pane (the @crtr_node-tagged sibling; the launch-time
502
- // --target is the fallback when no pane is tagged yet) + its attached node.
503
- const panes = await ctx.resolve(panesSource);
504
- let chatPane = '';
505
- /** @type {string|null} */
506
- let attachedNode = null;
507
- if (panes.ok) {
508
- const tagged = panes.data.find((p) => p.node);
509
- if (tagged) {
510
- chatPane = tagged.pane;
511
- attachedNode = tagged.node;
512
- }
513
- }
514
- if (!chatPane && ctx.state.targetOverride) chatPane = ctx.state.targetOverride;
515
-
516
- // The workspace scope key — resolved through the transport (uniform across
517
- // TUI + web), falling back to the init-time cwd.
518
- const cwdR = await ctx.resolve(cwdSource);
519
- const cwd = cwdR.ok && cwdR.data ? cwdR.data : ctx.state.cwd;
520
-
521
- const rn = await ctx.resolve(nodesSource);
522
- if (!rn.ok) {
523
- const err = rn.error;
524
- const hadRail = ctx.state.rows.length > 0;
525
- const keep = !err.display.blocking && hadRail;
526
- ctx.set((s) => {
527
- /** @type {SidebarState} */
528
- const next = { ...s, cwd, chatPane, attachedNode, srcError: err };
529
- if (!keep) {
530
- next.rows = [];
531
- next.currentRoot = null;
532
- next.graphsHere = 0;
533
- next.nodesHere = 0;
534
- next.asksHere = 0;
535
- }
536
- return next;
537
- });
538
- // A takeover (empty rail) owns the rect + names the cause; a kept rail
539
- // raises the cause as a banner.
540
- if (keep) ctx.signal.setBanner(err.display.explanation, err.display.level);
541
- else ctx.signal.clearBanner();
542
- ctx.signal.setStatus(null);
543
- ctx.signal.setSubtitle(null);
544
- return;
545
- }
546
-
547
- const sr = await ctx.resolve(subscriptionsSource);
548
- if (!sr.ok) {
549
- ctx.set((s) => ({ ...s, cwd, chatPane, attachedNode, srcError: sr.error }));
550
- ctx.signal.setBanner(sr.error.display.explanation, sr.error.display.level);
551
- ctx.signal.setStatus(null);
552
- ctx.signal.setSubtitle(null);
553
- return;
554
- }
555
-
556
- const mine = rn.data.filter((n) => n.cwd === cwd);
557
- const { byId, children, roots, scopedById, scopedChildren, currentRoot, liveRoots } = buildRail(rn.data, mine, sr.data, attachedNode);
558
-
559
- // Attention in one pass: the current sub-DAG + EVERY root here (so a
560
- // blocked-but-not-live root still surfaces its ⚑). Best-effort.
561
- const rootIds = roots.map((r) => r.nodeId);
562
- let asks = /** @type {Record<string,number>} */ ({});
563
- if (currentRoot || rootIds.length) {
564
- const a = await ctx.resolve(attentionSource, { viewRoot: currentRoot, nodeIds: rootIds });
565
- if (a.ok) asks = a.data;
566
- }
567
- let asksHere = 0;
568
- for (const v of Object.values(asks)) asksHere += v;
569
-
570
- // `elsewhere` = other roots still LIVE OR with a pending ask. Live first,
571
- // then newest.
572
- const others = roots.filter(
573
- (r) => r.nodeId !== currentRoot && (subtreeLive(r.nodeId, scopedChildren, scopedById) || (asks[r.nodeId] || 0) > 0),
574
- );
575
- others.sort((a, b) => {
576
- const la = subtreeLive(a.nodeId, scopedChildren, scopedById) ? 1 : 0;
577
- const lb = subtreeLive(b.nodeId, scopedChildren, scopedById) ? 1 : 0;
578
- if (la !== lb) return lb - la;
579
- return a.created < b.created ? 1 : -1; // newest first
580
- });
581
-
582
- // ── Build the flat render list ───────────────────────────────────────
583
- /** @type {RailRow[]} */
584
- const rows = [];
585
- rows.push(headerRow('⌗ this graph'));
586
- if (currentRoot && byId.has(currentRoot)) {
587
- /** @type {Set<string>} */
588
- const visited = new Set();
589
- /** @param {CanvasNode} node @param {string} indent @param {boolean} isLast @param {boolean} isRoot */
590
- const walk = (node, indent, isLast, isRoot) => {
591
- if (visited.has(node.nodeId)) return;
592
- visited.add(node.nodeId);
593
- const prefix = isRoot ? '' : indent + (isLast ? '└─ ' : '├─ ');
594
- rows.push(nodeRow(node, prefix, node.nodeId === attachedNode, asks[node.nodeId] || 0));
595
- const kids = children.get(node.nodeId) || [];
596
- const childIndent = isRoot ? '' : indent + (isLast ? ' ' : '│ ');
597
- for (let i = 0; i < kids.length; i++) walk(kids[i], childIndent, i === kids.length - 1, false);
598
- };
599
- walk(/** @type {CanvasNode} */ (byId.get(currentRoot)), '', true, true);
600
- } else {
601
- rows.push(chromeRow(' no agent here yet'));
602
- }
603
-
604
- rows.push(chromeRow('')); // section gap
605
- rows.push(headerRow(`↪ elsewhere${others.length ? ` · ${others.length}` : ''}`));
606
- if (others.length) {
607
- for (const r of others) rows.push(nodeRow(r, '', false, asks[r.nodeId] || 0));
608
- } else {
609
- rows.push(chromeRow(' —'));
610
- }
611
-
612
- const prevRow = ctx.state.rows[ctx.state.cursor];
613
- const cursor = reanchor(rows, prevRow && prevRow.kind === 'node' ? prevRow.nodeId : null, attachedNode);
614
-
615
- ctx.set((s) => ({
616
- ...s,
617
- cwd,
618
- chatPane,
619
- attachedNode,
620
- currentRoot,
621
- rows,
622
- cursor,
623
- graphsHere: liveRoots.length,
624
- nodesHere: mine.length,
625
- asksHere,
626
- lastFetch: Date.now(),
627
- srcError: null,
628
- }));
629
-
630
- ctx.signal.setSubtitle(liveRoots.length > 0 ? `${plural(liveRoots.length, 'live graph')}` : null);
631
- if (asksHere > 0) ctx.signal.setBanner(`${plural(asksHere, 'ask')} waiting on a human — see the ⚑ rows`, 'action');
632
- else ctx.signal.clearBanner();
633
- ctx.signal.setStatus(null);
634
- },
635
-
636
- /** @param {Ctx} ctx */
637
- cursorDown: (ctx) => ctx.set((s) => moveCursor(s, 1)),
638
- /** @param {Ctx} ctx */
639
- cursorUp: (ctx) => ctx.set((s) => moveCursor(s, -1)),
640
- /** @param {Ctx} ctx @param {number} [i] */
641
- select: (ctx, i) =>
642
- ctx.set((s) => {
643
- if (typeof i !== 'number') return s;
644
- return selectableIdx(s.rows).includes(i) ? { ...s, cursor: i } : s;
645
- }),
646
-
647
- /**
648
- * Swap the cursor's node into the chat pane (TUI ↵). No chat pane wired (the
649
- * web target, or a rail not launched via `crtr workspace`) ⇒ a guidance
650
- * banner, no-op.
651
- * @param {Ctx} ctx
652
- */
653
- async open(ctx) {
654
- const s = ctx.state;
655
- const row = s.rows[s.cursor];
656
- if (!row || row.kind !== 'node') return;
657
- if (!s.chatPane) {
658
- ctx.signal.setBanner('No chat pane wired — run this rail via `crtr workspace`.', 'error');
659
- return;
660
- }
661
- await ctx.execute(focusCommand, { nodeId: row.nodeId, pane: s.chatPane });
662
- ctx.signal.setStatus(`→ ${row.name}`);
663
- },
664
-
665
- /** @param {Ctx} ctx */
666
- quit: (ctx) => ctx.signal.quit(),
667
- },
668
- };
669
-
670
- export default core;