@north-light/crouter 0.3.318 → 0.3.320

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 (1304) hide show
  1. package/README.md +0 -3
  2. package/dist/api/client.js +2 -912
  3. package/dist/api/dto/attach.js +0 -13
  4. package/dist/api/dto/bash-jobs.js +1 -9
  5. package/dist/api/dto/broker-ops.js +0 -6
  6. package/dist/api/dto/broker.js +0 -20
  7. package/dist/api/dto/canvas.js +0 -2
  8. package/dist/api/dto/chat-inventory.js +0 -11
  9. package/dist/api/dto/common.js +1 -15
  10. package/dist/api/dto/config.js +0 -3
  11. package/dist/api/dto/crons.js +1 -10
  12. package/dist/api/dto/files.js +0 -7
  13. package/dist/api/dto/focus.js +0 -10
  14. package/dist/api/dto/health.js +0 -2
  15. package/dist/api/dto/human-requests.js +0 -4
  16. package/dist/api/dto/human.js +0 -4
  17. package/dist/api/dto/inbox.js +0 -4
  18. package/dist/api/dto/lifecycle.js +0 -3
  19. package/dist/api/dto/mail.js +0 -1
  20. package/dist/api/dto/memory.js +0 -6
  21. package/dist/api/dto/messages.js +0 -2
  22. package/dist/api/dto/model-config.js +0 -1
  23. package/dist/api/dto/modelauth.js +0 -4
  24. package/dist/api/dto/node-outcomes.js +0 -2
  25. package/dist/api/dto/nodes.js +0 -3
  26. package/dist/api/dto/profiles.js +1 -4
  27. package/dist/api/dto/recovery.js +0 -1
  28. package/dist/api/dto/reports.js +0 -2
  29. package/dist/api/dto/review-comments.js +0 -5
  30. package/dist/api/dto/reviews.js +0 -5
  31. package/dist/api/dto/subscriptions.js +0 -2
  32. package/dist/api/dto/worktree.js +0 -6
  33. package/dist/api/errors.js +1 -40
  34. package/dist/api/index.js +1 -33
  35. package/dist/api/plugin-manifest-schema.js +0 -23
  36. package/dist/api/routes.js +1 -147
  37. package/dist/build-root.js +1 -198
  38. package/dist/cli.js +3 -99
  39. package/dist/clients/attach/ansi-cells.js +1 -137
  40. package/dist/clients/attach/chrome/bash-jobs.js +1 -31
  41. package/dist/clients/attach/chrome/canvas-panels.js +1 -194
  42. package/dist/clients/attach/chrome/completion-bell.js +1 -89
  43. package/dist/clients/attach/chrome/cron-wait.js +1 -34
  44. package/dist/clients/attach/chrome/git-info.js +2 -44
  45. package/dist/clients/attach/chrome/header.js +1 -30
  46. package/dist/clients/attach/chrome/inbox-strip.js +1 -199
  47. package/dist/clients/attach/chrome/recap.js +1 -19
  48. package/dist/clients/attach/chrome/review-wait.js +1 -22
  49. package/dist/clients/attach/chrome/roster.js +4 -275
  50. package/dist/clients/attach/chrome/status-line.js +1 -117
  51. package/dist/clients/attach/chrome/ticket-panel.js +1 -280
  52. package/dist/clients/attach/chrome/widgets.js +1 -51
  53. package/dist/clients/attach/command.js +1 -107
  54. package/dist/clients/attach/config.js +1 -274
  55. package/dist/clients/attach/input/capabilities.js +1 -104
  56. package/dist/clients/attach/input/clipboard-image.js +3 -220
  57. package/dist/clients/attach/input/completion-frecency.js +1 -141
  58. package/dist/clients/attach/input/controller.js +7 -377
  59. package/dist/clients/attach/input/overlay-owner.js +1 -199
  60. package/dist/clients/attach/input/ref-autocomplete.js +2 -176
  61. package/dist/clients/attach/input/titled-editor.js +4 -859
  62. package/dist/clients/attach/overlays/auth.js +2 -271
  63. package/dist/clients/attach/overlays/dialogs.js +2 -102
  64. package/dist/clients/attach/overlays/file-review.js +2 -128
  65. package/dist/clients/attach/overlays/graph.js +1 -661
  66. package/dist/clients/attach/overlays/help.js +1 -211
  67. package/dist/clients/attach/overlays/mcp.js +1 -302
  68. package/dist/clients/attach/overlays/pickers.js +1 -163
  69. package/dist/clients/attach/render/activity-slot.js +1 -13
  70. package/dist/clients/attach/render/assistant-message.js +1 -56
  71. package/dist/clients/attach/render/card-presentation.js +5 -218
  72. package/dist/clients/attach/render/chat-view.js +5 -1708
  73. package/dist/clients/attach/render/condensed-history.js +1 -60
  74. package/dist/clients/attach/render/context-message.js +1 -63
  75. package/dist/clients/attach/render/crtr-output.js +17 -905
  76. package/dist/clients/attach/render/diagram.js +7 -111
  77. package/dist/clients/attach/render/edit-diff.js +5 -304
  78. package/dist/clients/attach/render/glyph-codepoints.js +1 -42
  79. package/dist/clients/attach/render/group-activity.js +2 -263
  80. package/dist/clients/attach/render/group-recap.js +1 -152
  81. package/dist/clients/attach/render/markdown-source.js +5 -266
  82. package/dist/clients/attach/render/measured-container.js +1 -322
  83. package/dist/clients/attach/render/page-block.js +1 -183
  84. package/dist/clients/attach/render/scroll-animation.js +1 -80
  85. package/dist/clients/attach/render/tool-calls.js +3 -361
  86. package/dist/clients/attach/render/transcript-copy.js +2 -81
  87. package/dist/clients/attach/render/transcript-search.js +1 -152
  88. package/dist/clients/attach/render/viewport.js +1 -184
  89. package/dist/clients/attach/session/banner.js +1 -29
  90. package/dist/clients/attach/session/bindings.js +1 -71
  91. package/dist/clients/attach/session/chrome-refresh.js +1 -94
  92. package/dist/clients/attach/session/connection.js +1 -186
  93. package/dist/clients/attach/session/context.js +0 -16
  94. package/dist/clients/attach/session/editor-frame.js +1 -142
  95. package/dist/clients/attach/session/editor-inventory.js +6 -160
  96. package/dist/clients/attach/session/file-links.js +1 -68
  97. package/dist/clients/attach/session/focus-events.js +1 -12
  98. package/dist/clients/attach/session/frame.js +1 -214
  99. package/dist/clients/attach/session/frames.js +1 -188
  100. package/dist/clients/attach/session/identity.js +1 -26
  101. package/dist/clients/attach/session/input-wiring.js +1 -140
  102. package/dist/clients/attach/session/invariant.js +1 -15
  103. package/dist/clients/attach/session/keys.js +1 -77
  104. package/dist/clients/attach/session/layout.js +1 -59
  105. package/dist/clients/attach/session/mouse.js +1 -78
  106. package/dist/clients/attach/session/pane-focus.js +1 -42
  107. package/dist/clients/attach/session/pane-tag.js +1 -112
  108. package/dist/clients/attach/session/pi-assets.js +1 -24
  109. package/dist/clients/attach/session/pi-oauth-flows.js +1 -21
  110. package/dist/clients/attach/session/profile-files.js +1 -228
  111. package/dist/clients/attach/session/reconnect.js +1 -175
  112. package/dist/clients/attach/session/selection.js +3 -108
  113. package/dist/clients/attach/session/state-sync.js +1 -67
  114. package/dist/clients/attach/session/surface-frame.js +1 -73
  115. package/dist/clients/attach/session/surface-host.js +1 -255
  116. package/dist/clients/attach/session/teardown.js +5 -94
  117. package/dist/clients/attach/session/transcript-search.js +3 -151
  118. package/dist/clients/attach/session/whip-achievements.js +2 -145
  119. package/dist/clients/attach/session/whip.js +1 -362
  120. package/dist/clients/attach/slash/dispatch.js +1 -706
  121. package/dist/clients/attach/slash/prompt-preview.js +1 -121
  122. package/dist/clients/attach/viewer.js +441 -441
  123. package/dist/clients/conversation/projection.js +1 -324
  124. package/dist/clients/conversation/submit.js +1 -51
  125. package/dist/clients/inbox/controller.js +1 -701
  126. package/dist/clients/inbox/dto-adapt.js +1 -93
  127. package/dist/clients/inbox/layout.js +1 -9
  128. package/dist/clients/inbox/page-adapter.js +1 -55
  129. package/dist/clients/inbox/resolve.js +1 -35
  130. package/dist/clients/inbox/review/anchors.js +1 -89
  131. package/dist/clients/inbox/review/comments-client.js +1 -98
  132. package/dist/clients/inbox/review/companion-pane.js +1 -82
  133. package/dist/clients/inbox/review/document-surface.js +2 -1188
  134. package/dist/clients/inbox/review/frame.js +1 -216
  135. package/dist/clients/inbox/review/keys.js +1 -123
  136. package/dist/clients/inbox/review/launch.js +1 -151
  137. package/dist/clients/inbox/review/live-source.js +1 -160
  138. package/dist/clients/inbox/review/nvim.js +1 -44
  139. package/dist/clients/inbox/review/remap.js +1 -157
  140. package/dist/clients/inbox/review/review-client.js +1 -123
  141. package/dist/clients/inbox/review/roundtrip.js +3 -36
  142. package/dist/clients/inbox/review/state.js +4 -315
  143. package/dist/clients/inbox/review-adapter.js +1 -43
  144. package/dist/clients/inbox/surface.js +1 -152
  145. package/dist/clients/inbox/tui/ansi.js +3 -321
  146. package/dist/clients/inbox/tui/input.js +5 -392
  147. package/dist/clients/inbox/tui/keys.js +1 -104
  148. package/dist/clients/inbox/tui/page-body.js +1 -66
  149. package/dist/clients/inbox/tui/panel.js +1 -84
  150. package/dist/clients/inbox/tui/render.js +2 -368
  151. package/dist/clients/inbox/tui/slots.js +3 -134
  152. package/dist/clients/inbox/tui/types.js +0 -1
  153. package/dist/clients/inbox/tui.js +1 -86
  154. package/dist/clients/surfaces/host.js +0 -1
  155. package/dist/commands/api-client.js +4 -290
  156. package/dist/commands/attention.js +1 -215
  157. package/dist/commands/canvas-browse.js +1 -70
  158. package/dist/commands/canvas-config.js +2 -192
  159. package/dist/commands/canvas-history/grep.js +7 -85
  160. package/dist/commands/canvas-history/read.js +3 -50
  161. package/dist/commands/canvas-history/search.js +10 -99
  162. package/dist/commands/canvas-history/shared.js +1 -139
  163. package/dist/commands/canvas-history/stats.js +6 -68
  164. package/dist/commands/canvas-history.js +1 -32
  165. package/dist/commands/canvas-issue.js +14 -149
  166. package/dist/commands/canvas-prune.js +1 -108
  167. package/dist/commands/canvas-roster.js +1 -69
  168. package/dist/commands/canvas-snapshot.js +1 -34
  169. package/dist/commands/canvas-use.js +1 -61
  170. package/dist/commands/canvas.js +1 -49
  171. package/dist/commands/chord.js +1 -241
  172. package/dist/commands/cron.js +11 -534
  173. package/dist/commands/dashboard.js +1 -85
  174. package/dist/commands/human/components.js +3 -77
  175. package/dist/commands/human/feedback.js +1 -112
  176. package/dist/commands/human/prompts.js +1 -331
  177. package/dist/commands/human/queue.js +1 -191
  178. package/dist/commands/human/request.js +1 -266
  179. package/dist/commands/human/review.js +1 -288
  180. package/dist/commands/human/shared.js +1 -67
  181. package/dist/commands/human.js +4 -60
  182. package/dist/commands/memory/delete.js +1 -100
  183. package/dist/commands/memory/edit.js +21 -219
  184. package/dist/commands/memory/find.js +2 -244
  185. package/dist/commands/memory/history.js +5 -199
  186. package/dist/commands/memory/lint.js +1 -107
  187. package/dist/commands/memory/list.js +1 -142
  188. package/dist/commands/memory/move.js +1 -223
  189. package/dist/commands/memory/origin.js +1 -130
  190. package/dist/commands/memory/read.js +6 -232
  191. package/dist/commands/memory/shared.js +12 -802
  192. package/dist/commands/memory/write.js +13 -235
  193. package/dist/commands/memory.js +1 -30
  194. package/dist/commands/node/bash.js +5 -245
  195. package/dist/commands/node/create.js +3 -332
  196. package/dist/commands/node/inspect.js +12 -300
  197. package/dist/commands/node/lifecycle.js +2 -453
  198. package/dist/commands/node/message.js +1 -161
  199. package/dist/commands/node/outcome.js +4 -134
  200. package/dist/commands/node/pyramid.js +2 -79
  201. package/dist/commands/node/subscription.js +1 -78
  202. package/dist/commands/node/wait.js +7 -163
  203. package/dist/commands/node-context.js +2 -159
  204. package/dist/commands/node-inspect-artifacts.js +8 -109
  205. package/dist/commands/node-lifecycle-revive.js +1 -217
  206. package/dist/commands/node-snapshot.js +1 -37
  207. package/dist/commands/node-transcript.js +1 -62
  208. package/dist/commands/node-worktree.js +1 -138
  209. package/dist/commands/node.js +1 -29
  210. package/dist/commands/pkg/browse/actions.js +1 -198
  211. package/dist/commands/pkg/browse/catalog.js +1 -466
  212. package/dist/commands/pkg/browse/command-view.js +1 -191
  213. package/dist/commands/pkg/browse/detail-panel.js +1 -402
  214. package/dist/commands/pkg/browse/doc-view.js +1 -89
  215. package/dist/commands/pkg/browse/list-panel.js +2 -168
  216. package/dist/commands/pkg/browse/model.js +1 -36
  217. package/dist/commands/pkg/browse/shell.js +1 -640
  218. package/dist/commands/pkg/browse.js +1 -27
  219. package/dist/commands/pkg/market-inspect.js +1 -141
  220. package/dist/commands/pkg/market-manage.js +1 -327
  221. package/dist/commands/pkg/market.js +1 -14
  222. package/dist/commands/pkg/plugin-inspect.js +1 -168
  223. package/dist/commands/pkg/plugin-manage.js +17 -1109
  224. package/dist/commands/pkg/plugin.js +1 -14
  225. package/dist/commands/pkg/shared.js +1 -62
  226. package/dist/commands/pkg.js +1 -21
  227. package/dist/commands/profile/default.js +1 -139
  228. package/dist/commands/profile/delete.js +1 -66
  229. package/dist/commands/profile/env.js +3 -188
  230. package/dist/commands/profile/kind.js +2 -35
  231. package/dist/commands/profile/list.js +1 -43
  232. package/dist/commands/profile/meta.js +1 -67
  233. package/dist/commands/profile/new.js +1 -115
  234. package/dist/commands/profile/pause.js +1 -59
  235. package/dist/commands/profile/project.js +1 -113
  236. package/dist/commands/profile/rename.js +1 -38
  237. package/dist/commands/profile/show.js +1 -52
  238. package/dist/commands/profile.js +1 -35
  239. package/dist/commands/push.js +9 -265
  240. package/dist/commands/revive.js +10 -181
  241. package/dist/commands/surface/node/cycle.js +1 -83
  242. package/dist/commands/surface/node/focus.js +1 -81
  243. package/dist/commands/surface/node/id.js +1 -38
  244. package/dist/commands/surface/node/pin.js +1 -42
  245. package/dist/commands/surface/node/placement.js +1 -134
  246. package/dist/commands/surface-edit.js +1 -157
  247. package/dist/commands/surface-inbox.js +1 -98
  248. package/dist/commands/surface-inspect.js +1 -39
  249. package/dist/commands/surface-node.js +1 -19
  250. package/dist/commands/surface-reload.js +2 -134
  251. package/dist/commands/surface-tmux-spread.js +1 -214
  252. package/dist/commands/surface.js +1 -28
  253. package/dist/commands/sys/branch.js +1 -19
  254. package/dist/commands/sys/config.js +1 -353
  255. package/dist/commands/sys/context/admin/actions.js +2 -246
  256. package/dist/commands/sys/context/admin/detail-panel.js +1 -247
  257. package/dist/commands/sys/context/admin/docs-panel.js +1 -191
  258. package/dist/commands/sys/context/admin/list-view.js +1 -183
  259. package/dist/commands/sys/context/admin/model.js +1 -229
  260. package/dist/commands/sys/context/admin/rail-panel.js +1 -227
  261. package/dist/commands/sys/context/admin/read-view.js +2 -194
  262. package/dist/commands/sys/context/admin/shell.js +1 -910
  263. package/dist/commands/sys/context/admin.js +2 -126
  264. package/dist/commands/sys/context/doc.js +3 -197
  265. package/dist/commands/sys/context/prompt-review.js +11 -291
  266. package/dist/commands/sys/context/resolve.js +10 -489
  267. package/dist/commands/sys/context/sysprompt.js +5 -96
  268. package/dist/commands/sys/context.js +1 -20
  269. package/dist/commands/sys/daemon.js +1 -313
  270. package/dist/commands/sys/doctor.js +1 -617
  271. package/dist/commands/sys/feedback.js +7 -228
  272. package/dist/commands/sys/logs.js +3 -129
  273. package/dist/commands/sys/migrate.js +1 -94
  274. package/dist/commands/sys/panels/broker-limits-panel.js +2 -110
  275. package/dist/commands/sys/panels/dependencies-panel.js +1 -80
  276. package/dist/commands/sys/panels/keybindings-panel.js +1 -703
  277. package/dist/commands/sys/panels/models-panel.js +1 -1133
  278. package/dist/commands/sys/panels/plugins-panel.js +1 -80
  279. package/dist/commands/sys/panels/prefs-panel.js +1 -85
  280. package/dist/commands/sys/panels/profiles-panel.js +1 -601
  281. package/dist/commands/sys/panels/provider-panel.js +1 -538
  282. package/dist/commands/sys/settings-shell.js +1 -400
  283. package/dist/commands/sys/settings.js +1 -46
  284. package/dist/commands/sys/setup-core.js +6 -579
  285. package/dist/commands/sys/setup-settings-runner.js +1 -16
  286. package/dist/commands/sys/setup-wizard.js +1 -279
  287. package/dist/commands/sys/setup.js +1 -34
  288. package/dist/commands/sys/shared.js +1 -81
  289. package/dist/commands/sys/support/prepare.js +3 -239
  290. package/dist/commands/sys/support/submit.js +6 -524
  291. package/dist/commands/sys/support.js +1 -18
  292. package/dist/commands/sys/sync-deps.js +15 -498
  293. package/dist/commands/sys/sync-project-guidance.js +4 -481
  294. package/dist/commands/sys/sync-shared.js +1 -49
  295. package/dist/commands/sys/sync-skills.js +2 -311
  296. package/dist/commands/sys/sync.js +1 -18
  297. package/dist/commands/sys/update.js +1 -147
  298. package/dist/commands/sys/worktrees.js +5 -53
  299. package/dist/commands/sys.js +1 -18
  300. package/dist/core/activity-signal.js +2 -38
  301. package/dist/core/asset-root.js +1 -18
  302. package/dist/core/auth-file.js +2 -179
  303. package/dist/core/auth-interaction.js +3 -94
  304. package/dist/core/auto-update.js +4 -94
  305. package/dist/core/bash-guard.js +11 -393
  306. package/dist/core/bash-jobs.js +7 -411
  307. package/dist/core/bootstrap.js +2 -53
  308. package/dist/core/broker-client/client.js +1 -184
  309. package/dist/core/broker-client/index.js +1 -13
  310. package/dist/core/broker-client/transport-relay.js +1 -157
  311. package/dist/core/broker-client/transport-socket.js +1 -179
  312. package/dist/core/broker-client/transport.js +1 -26
  313. package/dist/core/canvas/attention.js +1 -47
  314. package/dist/core/canvas/boot-id.js +1 -26
  315. package/dist/core/canvas/boot.js +1 -186
  316. package/dist/core/canvas/browse/app.js +3 -919
  317. package/dist/core/canvas/browse/model.js +1 -477
  318. package/dist/core/canvas/browse/pins.js +1 -29
  319. package/dist/core/canvas/browse/render.js +3 -1055
  320. package/dist/core/canvas/canvas.js +15 -922
  321. package/dist/core/canvas/crons.js +11 -481
  322. package/dist/core/canvas/daemon-owner.js +2 -146
  323. package/dist/core/canvas/db.js +2 -100
  324. package/dist/core/canvas/deliveries.js +22 -283
  325. package/dist/core/canvas/delivery-contract.js +1 -8
  326. package/dist/core/canvas/executions.js +1 -68
  327. package/dist/core/canvas/extensions.js +1 -83
  328. package/dist/core/canvas/focuses.js +1 -77
  329. package/dist/core/canvas/history.js +24 -860
  330. package/dist/core/canvas/index.js +1 -15
  331. package/dist/core/canvas/install-id.js +1 -84
  332. package/dist/core/canvas/labels.js +1 -43
  333. package/dist/core/canvas/meta-file.js +1 -89
  334. package/dist/core/canvas/migrations.js +41 -1150
  335. package/dist/core/canvas/nav-model.js +1 -231
  336. package/dist/core/canvas/nav-render.js +1 -260
  337. package/dist/core/canvas/node-order.js +1 -37
  338. package/dist/core/canvas/node-recap.js +2 -67
  339. package/dist/core/canvas/node-sql-migration.js +2 -209
  340. package/dist/core/canvas/paths.js +1 -153
  341. package/dist/core/canvas/pid.js +4 -683
  342. package/dist/core/canvas/recovery.js +3 -565
  343. package/dist/core/canvas/remote-canvas-source.js +1 -288
  344. package/dist/core/canvas/remote-transport.js +1 -57
  345. package/dist/core/canvas/render-source.js +10 -635
  346. package/dist/core/canvas/sessions.js +1 -78
  347. package/dist/core/canvas/source.js +1 -47
  348. package/dist/core/canvas/status-glyph.js +1 -132
  349. package/dist/core/canvas/telemetry.js +1 -35
  350. package/dist/core/canvas/types.js +1 -6
  351. package/dist/core/canvas/waits.js +4 -68
  352. package/dist/core/canvas/worktrees.js +1 -93
  353. package/dist/core/clipboard-text.js +1 -57
  354. package/dist/core/command-hooks/artifact.js +1 -145
  355. package/dist/core/command-hooks/catalog.js +1 -38
  356. package/dist/core/command-hooks/compose.js +1 -99
  357. package/dist/core/command-hooks/discovery.js +1 -228
  358. package/dist/core/command-hooks/help.js +1 -18
  359. package/dist/core/command-hooks/index.js +1 -7
  360. package/dist/core/command-hooks/lifecycle-catalog.js +1 -9
  361. package/dist/core/command-hooks/lifecycle-create.js +1 -51
  362. package/dist/core/command-hooks/report.js +1 -28
  363. package/dist/core/command-hooks/schema.js +1 -157
  364. package/dist/core/command-hooks/transport/exec-invoke.js +1 -276
  365. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -211
  366. package/dist/core/command-manifests/manifest.js +1 -324
  367. package/dist/core/command-manifests/registry.js +1 -118
  368. package/dist/core/command-manifests/schema.js +1 -736
  369. package/dist/core/command-plugins/bundle.js +1 -261
  370. package/dist/core/command-plugins/compose.js +1 -65
  371. package/dist/core/command-plugins/discovery.js +1 -245
  372. package/dist/core/command-plugins/endpoint.js +1 -48
  373. package/dist/core/command-plugins/extensions.js +1 -166
  374. package/dist/core/command-plugins/help-addenda.js +1 -44
  375. package/dist/core/command-plugins/presence.js +1 -17
  376. package/dist/core/command-plugins/revalidate.js +2 -152
  377. package/dist/core/command-plugins/transport/exec-invoke.js +1 -215
  378. package/dist/core/command-plugins/transport/http-fetch.js +1 -68
  379. package/dist/core/command-plugins/transport/http-invoke.js +3 -546
  380. package/dist/core/command.js +10 -739
  381. package/dist/core/config.js +1 -1059
  382. package/dist/core/document-lines.js +3 -6
  383. package/dist/core/env-name.js +1 -9
  384. package/dist/core/errors.js +1 -52
  385. package/dist/core/events/emit.js +1 -17
  386. package/dist/core/events/envelope.js +1 -84
  387. package/dist/core/events/errors.js +1 -69
  388. package/dist/core/events/index.js +1 -4
  389. package/dist/core/events/operation-id.js +1 -24
  390. package/dist/core/events/read.js +1 -623
  391. package/dist/core/events/serialize.js +1 -199
  392. package/dist/core/events/source.js +1 -31
  393. package/dist/core/events/types.js +1 -11
  394. package/dist/core/exclusive-lock.js +1 -197
  395. package/dist/core/fault-classifier.js +1 -96
  396. package/dist/core/feed/feed.js +7 -202
  397. package/dist/core/feed/inbox-migrate.js +3 -135
  398. package/dist/core/feed/inbox.js +10 -122
  399. package/dist/core/feed/messages.js +6 -212
  400. package/dist/core/frontmatter.js +1 -35
  401. package/dist/core/fs-utils.js +3 -202
  402. package/dist/core/git.js +2 -103
  403. package/dist/core/help.js +9 -310
  404. package/dist/core/host-exports/builtins.js +9 -68
  405. package/dist/core/host-exports/export.js +3 -124
  406. package/dist/core/human/action-binding.js +1 -40
  407. package/dist/core/human/answer-text.js +5 -100
  408. package/dist/core/human/answer.js +1 -119
  409. package/dist/core/human/claim.js +3 -67
  410. package/dist/core/human/completion.js +1 -27
  411. package/dist/core/human/component-docs.js +78 -272
  412. package/dist/core/human/convention.js +2 -82
  413. package/dist/core/human/feedback-companion.js +1 -106
  414. package/dist/core/human/feedback.js +1 -88
  415. package/dist/core/human/page-authoring.js +1 -19
  416. package/dist/core/human/page-catalog.js +1 -172
  417. package/dist/core/human/page-errors.js +1 -7
  418. package/dist/core/human/page-eval.js +1 -125
  419. package/dist/core/human/page-html-markdown.js +8 -260
  420. package/dist/core/human/page-markdown.js +17 -295
  421. package/dist/core/human/page-schema.js +1 -373
  422. package/dist/core/human/page-synth.js +8 -27
  423. package/dist/core/human/page.js +1 -198
  424. package/dist/core/human/requests.js +15 -466
  425. package/dist/core/human/review-schema.js +1 -34
  426. package/dist/core/human/root.js +1 -11
  427. package/dist/core/human/scan.js +1 -69
  428. package/dist/core/human/summary.js +1 -5
  429. package/dist/core/human/tickets.js +1 -171
  430. package/dist/core/human/types.js +0 -1
  431. package/dist/core/human/visible-paths.js +1 -77
  432. package/dist/core/human-actions.js +1 -101
  433. package/dist/core/inspector/chrome.js +1 -14
  434. package/dist/core/inspector/contract.js +0 -1
  435. package/dist/core/inspector/core.js +2 -295
  436. package/dist/core/inspector/host.js +4 -538
  437. package/dist/core/inspector/model.js +2 -226
  438. package/dist/core/inspector/text.js +6 -45
  439. package/dist/core/inspector/transport.js +1 -36
  440. package/dist/core/inspector/tui.js +2 -295
  441. package/dist/core/installed-plugins.js +1 -78
  442. package/dist/core/io.js +7 -356
  443. package/dist/core/keybindings/attach-control.js +1 -42
  444. package/dist/core/keybindings/background-bash.js +1 -33
  445. package/dist/core/keybindings/catalog.js +1 -256
  446. package/dist/core/keybindings/inbox.js +1 -25
  447. package/dist/core/keybindings/index.js +1 -7
  448. package/dist/core/keybindings/match.js +1 -127
  449. package/dist/core/keybindings/persistence.js +1 -49
  450. package/dist/core/keybindings/resolve.js +1 -348
  451. package/dist/core/keybindings/types.js +0 -1
  452. package/dist/core/locked-file.js +1 -118
  453. package/dist/core/log.js +3 -27
  454. package/dist/core/manifest-recovery.js +1 -72
  455. package/dist/core/manifest-stale.js +1 -39
  456. package/dist/core/manifest.js +1 -20
  457. package/dist/core/memory/doc-link-grammar.js +2 -109
  458. package/dist/core/memory/extensions.js +1 -221
  459. package/dist/core/memory/history.js +6 -268
  460. package/dist/core/memory/identity.js +1 -181
  461. package/dist/core/memory/inline-ref-grammar.js +1 -98
  462. package/dist/core/memory/inline-ref-guidance.js +2 -35
  463. package/dist/core/memory/inline-ref-inventory.js +1 -59
  464. package/dist/core/memory/lint.js +2 -671
  465. package/dist/core/memory/project-namespace.js +2 -85
  466. package/dist/core/memory/repository-association.js +1 -129
  467. package/dist/core/memory/tree.js +1 -93
  468. package/dist/core/memory-resolver.js +2 -611
  469. package/dist/core/model-config.js +1 -107
  470. package/dist/core/model-routes.js +1 -201
  471. package/dist/core/nested-stores.js +2 -166
  472. package/dist/core/output.js +7 -99
  473. package/dist/core/pagination.js +1 -88
  474. package/dist/core/plugin-swap-lock.js +1 -31
  475. package/dist/core/pool-credential-store.js +1 -116
  476. package/dist/core/predicate.js +1 -191
  477. package/dist/core/preview-registry.js +2 -411
  478. package/dist/core/preview-result-path.js +1 -26
  479. package/dist/core/profiles/default-binding.js +1 -24
  480. package/dist/core/profiles/deletion-reservation.js +1 -42
  481. package/dist/core/profiles/env-store.js +2 -162
  482. package/dist/core/profiles/fuzzy-match.js +1 -92
  483. package/dist/core/profiles/manifest.js +1 -574
  484. package/dist/core/profiles/select.js +35 -741
  485. package/dist/core/profiles/state-block.js +3 -17
  486. package/dist/core/provider-error-recognition.js +1 -74
  487. package/dist/core/provider-failure.js +1 -86
  488. package/dist/core/provider-management.js +1 -22
  489. package/dist/core/remote-canvas-target.js +1 -30
  490. package/dist/core/render.js +18 -138
  491. package/dist/core/resolver.js +1 -111
  492. package/dist/core/review/birth.js +1 -52
  493. package/dist/core/review/comments.js +5 -279
  494. package/dist/core/review/companion.js +1 -215
  495. package/dist/core/review/document.js +2 -138
  496. package/dist/core/review/project.js +1 -36
  497. package/dist/core/review/realize.js +1 -71
  498. package/dist/core/review/remap.js +4 -141
  499. package/dist/core/review/signal.js +1 -12
  500. package/dist/core/review/stage.js +1 -184
  501. package/dist/core/review/store.js +1 -168
  502. package/dist/core/review/types.js +1 -23
  503. package/dist/core/runtime/advertised-command-invocation.js +1 -233
  504. package/dist/core/runtime/auth-reload.js +1 -67
  505. package/dist/core/runtime/banner.js +1 -51
  506. package/dist/core/runtime/bearings-render.js +18 -250
  507. package/dist/core/runtime/bearings.js +7 -194
  508. package/dist/core/runtime/bin-contributions.js +2 -186
  509. package/dist/core/runtime/boot-root.js +1 -107
  510. package/dist/core/runtime/branded-host.js +2 -264
  511. package/dist/core/runtime/broker/auth-reload.js +1 -157
  512. package/dist/core/runtime/broker/client-registry.js +1 -179
  513. package/dist/core/runtime/broker/daemon-ops.js +1 -88
  514. package/dist/core/runtime/broker/engine-drive.js +1 -354
  515. package/dist/core/runtime/broker/engine-routing.js +1 -211
  516. package/dist/core/runtime/broker/event-projection.js +1 -193
  517. package/dist/core/runtime/broker/extension-abort.js +1 -36
  518. package/dist/core/runtime/broker/fault-retry.js +1 -588
  519. package/dist/core/runtime/broker/frame-client.js +1 -132
  520. package/dist/core/runtime/broker/frame-dispatch.js +1 -183
  521. package/dist/core/runtime/broker/frame-engine-control.js +1 -231
  522. package/dist/core/runtime/broker/frame-memory-refs.js +1 -41
  523. package/dist/core/runtime/broker/frame-model-query.js +1 -69
  524. package/dist/core/runtime/broker/frame-read.js +1 -116
  525. package/dist/core/runtime/broker/frame-replies.js +1 -64
  526. package/dist/core/runtime/broker/frame-session.js +4 -203
  527. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -13
  528. package/dist/core/runtime/broker/inbox.js +13 -163
  529. package/dist/core/runtime/broker/node-named.js +1 -27
  530. package/dist/core/runtime/broker/read-ops.js +1 -171
  531. package/dist/core/runtime/broker/rebind.js +1 -318
  532. package/dist/core/runtime/broker/tool-groups.js +1 -246
  533. package/dist/core/runtime/broker/turn-admission.js +1 -31
  534. package/dist/core/runtime/broker/turn-ignition.js +1 -84
  535. package/dist/core/runtime/broker-cli.js +3 -81
  536. package/dist/core/runtime/broker-extension-render.js +5 -135
  537. package/dist/core/runtime/broker-inventory.js +1 -116
  538. package/dist/core/runtime/broker-persona-guidance.js +4 -154
  539. package/dist/core/runtime/broker-protocol.js +3 -152
  540. package/dist/core/runtime/broker-request.js +1 -85
  541. package/dist/core/runtime/broker-sdk.js +1 -129
  542. package/dist/core/runtime/broker.js +1 -1214
  543. package/dist/core/runtime/canvas-extensions.js +1 -96
  544. package/dist/core/runtime/chat-inventory-rows.js +1 -105
  545. package/dist/core/runtime/close.js +1 -265
  546. package/dist/core/runtime/command-expansion.js +9 -104
  547. package/dist/core/runtime/command-surface.js +1 -117
  548. package/dist/core/runtime/connectivity.js +1 -73
  549. package/dist/core/runtime/deliver-live.js +1 -88
  550. package/dist/core/runtime/fault-recovery.js +1 -83
  551. package/dist/core/runtime/fault.js +1 -17
  552. package/dist/core/runtime/fleet.js +1 -58
  553. package/dist/core/runtime/front-door-env.js +1 -16
  554. package/dist/core/runtime/front-door.js +7 -183
  555. package/dist/core/runtime/headless-pi.js +1 -161
  556. package/dist/core/runtime/host.js +1 -457
  557. package/dist/core/runtime/interactive-deliver.js +1 -51
  558. package/dist/core/runtime/invocation.js +0 -10
  559. package/dist/core/runtime/kickoff.js +30 -327
  560. package/dist/core/runtime/launch-config-worker.js +1 -12
  561. package/dist/core/runtime/launch-prompt.js +4 -13
  562. package/dist/core/runtime/launch-target.js +1 -55
  563. package/dist/core/runtime/launch.js +1 -483
  564. package/dist/core/runtime/lifecycle.js +2 -213
  565. package/dist/core/runtime/managed-provider-cooling.js +1 -62
  566. package/dist/core/runtime/memory.js +1 -17
  567. package/dist/core/runtime/model-registry.js +1 -13
  568. package/dist/core/runtime/model-selection.js +1 -135
  569. package/dist/core/runtime/model-swap.js +1 -86
  570. package/dist/core/runtime/naming.js +14 -298
  571. package/dist/core/runtime/nerd-font.js +2 -127
  572. package/dist/core/runtime/node-read.js +2 -386
  573. package/dist/core/runtime/nodes.js +1 -331
  574. package/dist/core/runtime/outcome-document.js +1 -97
  575. package/dist/core/runtime/package-health.js +4 -99
  576. package/dist/core/runtime/persona.js +2 -55
  577. package/dist/core/runtime/pi-cli.js +1 -65
  578. package/dist/core/runtime/pi-vendored.js +1 -66
  579. package/dist/core/runtime/placement-tmux.js +1 -81
  580. package/dist/core/runtime/placement.js +1 -386
  581. package/dist/core/runtime/promote.js +1 -174
  582. package/dist/core/runtime/prospective-inventory-cli.js +3 -61
  583. package/dist/core/runtime/prospective-inventory.js +2 -88
  584. package/dist/core/runtime/recap.js +27 -103
  585. package/dist/core/runtime/recycle.js +1 -190
  586. package/dist/core/runtime/reopen.js +1 -138
  587. package/dist/core/runtime/reset.js +1 -245
  588. package/dist/core/runtime/resume-root.js +10 -290
  589. package/dist/core/runtime/revive-all.js +1 -107
  590. package/dist/core/runtime/revive.js +4 -544
  591. package/dist/core/runtime/roadmap.js +4 -38
  592. package/dist/core/runtime/session-branch.js +1 -46
  593. package/dist/core/runtime/session-cycles.js +1 -110
  594. package/dist/core/runtime/session-list-cache.js +1 -406
  595. package/dist/core/runtime/session-visibility.js +1 -99
  596. package/dist/core/runtime/shell-expansion.js +9 -100
  597. package/dist/core/runtime/situational-context.js +2 -67
  598. package/dist/core/runtime/situational-live.js +1 -41
  599. package/dist/core/runtime/spawn-env.js +1 -255
  600. package/dist/core/runtime/spawn.js +3 -577
  601. package/dist/core/runtime/stamp/channel.js +1 -76
  602. package/dist/core/runtime/stamp/protocol.js +1 -113
  603. package/dist/core/runtime/stop-guard.js +7 -116
  604. package/dist/core/runtime/stop-signals.js +1 -46
  605. package/dist/core/runtime/stream-watchdog.js +1 -134
  606. package/dist/core/runtime/structured-output.js +4 -156
  607. package/dist/core/runtime/surface-bg.js +1 -85
  608. package/dist/core/runtime/tmux-bindings.js +4 -730
  609. package/dist/core/runtime/tmux-chrome.js +1 -5
  610. package/dist/core/runtime/tmux-driver.js +7 -637
  611. package/dist/core/runtime/tool-group-summary.js +6 -85
  612. package/dist/core/runtime/turn-visibility.js +1 -31
  613. package/dist/core/runtime/view-socket.js +1 -83
  614. package/dist/core/runtime/warm-pool.js +1 -395
  615. package/dist/core/scope.js +1 -254
  616. package/dist/core/scoped-state/db.js +1 -135
  617. package/dist/core/scoped-state/migrate.js +3 -181
  618. package/dist/core/scoped-state/paths.js +1 -27
  619. package/dist/core/scoped-state/profiles.js +1 -62
  620. package/dist/core/scoped-state/providers.js +1 -8
  621. package/dist/core/scoped-state/schema.js +3 -16
  622. package/dist/core/scoped-state/settings.js +1 -82
  623. package/dist/core/secrets.js +2 -55
  624. package/dist/core/self-update.js +1 -71
  625. package/dist/core/session-model/session-state.js +1 -180
  626. package/dist/core/shell-segments.js +4 -169
  627. package/dist/core/spawn.js +1 -26
  628. package/dist/core/stdout-errors.js +1 -14
  629. package/dist/core/subscription-state.js +3 -193
  630. package/dist/core/substrate/frontmatter-validation.js +1 -105
  631. package/dist/core/substrate/gate-explain.js +1 -424
  632. package/dist/core/substrate/gate.js +1 -26
  633. package/dist/core/substrate/index.js +1 -30
  634. package/dist/core/substrate/injected-store.js +1 -249
  635. package/dist/core/substrate/listings.js +1 -115
  636. package/dist/core/substrate/on-read-node.js +1 -36
  637. package/dist/core/substrate/on-read.js +9 -315
  638. package/dist/core/substrate/plan.js +1 -266
  639. package/dist/core/substrate/render-node.js +1 -30
  640. package/dist/core/substrate/render.js +65 -689
  641. package/dist/core/substrate/schema.js +1 -186
  642. package/dist/core/substrate/session-cache.js +1 -83
  643. package/dist/core/substrate/subject-fields.js +1 -35
  644. package/dist/core/substrate/subject.js +1 -47
  645. package/dist/core/substrate/surface-match.js +1 -242
  646. package/dist/core/termrender/code-doc.js +5 -92
  647. package/dist/core/termrender/display.js +2 -56
  648. package/dist/core/termrender/termrender.js +14 -719
  649. package/dist/core/termrender/version.js +1 -1
  650. package/dist/core/timing.js +2 -94
  651. package/dist/core/tui/draw.js +2 -378
  652. package/dist/core/tui/fuzzy.js +1 -38
  653. package/dist/core/tui/markdown.js +3 -407
  654. package/dist/core/tui/page-host.js +1 -74
  655. package/dist/core/tui/panel.js +1 -137
  656. package/dist/core/tui/terminal.js +2 -100
  657. package/dist/core/user-settings.js +1 -454
  658. package/dist/core/wake.js +1 -296
  659. package/dist/core/worktree-close.js +6 -228
  660. package/dist/core/worktree-containment.js +3 -48
  661. package/dist/core/worktree-landing.js +4 -56
  662. package/dist/core/worktree-mutation-async.js +10 -280
  663. package/dist/core/worktree-quarantine.js +1 -54
  664. package/dist/core/worktree-sweep.js +6 -453
  665. package/dist/core/worktree.js +18 -899
  666. package/dist/daemon/api/bridge.js +8 -418
  667. package/dist/daemon/api/handlers/attach.js +1 -65
  668. package/dist/daemon/api/handlers/bash-jobs.js +2 -91
  669. package/dist/daemon/api/handlers/broker-ops.js +1 -447
  670. package/dist/daemon/api/handlers/broker-recovery.js +1 -251
  671. package/dist/daemon/api/handlers/canvas.js +6 -490
  672. package/dist/daemon/api/handlers/chat-inventory.js +1 -25
  673. package/dist/daemon/api/handlers/crons.js +1 -373
  674. package/dist/daemon/api/handlers/daemon.js +1 -76
  675. package/dist/daemon/api/handlers/feedback-comments.js +3 -199
  676. package/dist/daemon/api/handlers/files.js +1 -63
  677. package/dist/daemon/api/handlers/focus.js +1 -92
  678. package/dist/daemon/api/handlers/health.js +1 -76
  679. package/dist/daemon/api/handlers/human-requests.js +1 -379
  680. package/dist/daemon/api/handlers/human.js +1 -3
  681. package/dist/daemon/api/handlers/inbox-page.js +1 -89
  682. package/dist/daemon/api/handlers/inbox.js +1 -301
  683. package/dist/daemon/api/handlers/memory.js +1 -50
  684. package/dist/daemon/api/handlers/messages.js +2 -506
  685. package/dist/daemon/api/handlers/model-config.js +1 -44
  686. package/dist/daemon/api/handlers/modelauth.js +1 -165
  687. package/dist/daemon/api/handlers/node-outcomes.js +1 -181
  688. package/dist/daemon/api/handlers/nodes.js +1 -939
  689. package/dist/daemon/api/handlers/profiles.js +1 -140
  690. package/dist/daemon/api/handlers/prospective-chat-inventory.js +1 -59
  691. package/dist/daemon/api/handlers/reports.js +16 -332
  692. package/dist/daemon/api/handlers/review-comments.js +1 -465
  693. package/dist/daemon/api/handlers/reviews.js +1 -200
  694. package/dist/daemon/api/handlers/subscriptions.js +1 -53
  695. package/dist/daemon/api/handlers/validate.js +1 -58
  696. package/dist/daemon/api/handlers/worktree.js +1 -39
  697. package/dist/daemon/api/map.js +2 -735
  698. package/dist/daemon/api/router.js +1 -190
  699. package/dist/daemon/api/server.js +11 -408
  700. package/dist/daemon/boot-migrations.js +1 -31
  701. package/dist/daemon/companion-retire.js +1 -34
  702. package/dist/daemon/control.js +1 -22
  703. package/dist/daemon/cron/armed-context.js +1 -100
  704. package/dist/daemon/cron/capture.js +2 -45
  705. package/dist/daemon/cron/disposition.js +1 -55
  706. package/dist/daemon/cron/escalation.js +3 -124
  707. package/dist/daemon/cron/held.js +1 -20
  708. package/dist/daemon/cron/lease-recovery.js +1 -119
  709. package/dist/daemon/cron/live-runs.js +1 -23
  710. package/dist/daemon/cron/passes.js +1 -58
  711. package/dist/daemon/cron/settle.js +1 -61
  712. package/dist/daemon/cron/sinks.js +2 -59
  713. package/dist/daemon/cron-run.js +1 -405
  714. package/dist/daemon/crtrd-cli.js +1 -23
  715. package/dist/daemon/crtrd.js +8 -854
  716. package/dist/daemon/delivery/run-delivery.js +1 -164
  717. package/dist/daemon/fleet.js +17 -475
  718. package/dist/daemon/human/finish.js +10 -179
  719. package/dist/daemon/human/settle.js +1 -89
  720. package/dist/daemon/human/sweep.js +1 -66
  721. package/dist/daemon/manage.js +2 -595
  722. package/dist/daemon/messaging/node-message.js +1 -99
  723. package/dist/daemon/park-activity.js +1 -30
  724. package/dist/daemon/park-pending.js +1 -52
  725. package/dist/daemon/pidfile.js +1 -37
  726. package/dist/daemon/profile-delete.js +1 -306
  727. package/dist/daemon/reconcilers/bash-deadline.js +1 -80
  728. package/dist/daemon/reconcilers/broker-supervision.js +4 -761
  729. package/dist/daemon/reconcilers/controller-death.js +1 -14
  730. package/dist/daemon/reconcilers/cron-lane.js +1 -29
  731. package/dist/daemon/reconcilers/delivery-lane.js +1 -130
  732. package/dist/daemon/reconcilers/live-obligation.js +1 -87
  733. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -202
  734. package/dist/daemon/reconcilers/node-deadline.js +1 -82
  735. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -172
  736. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -59
  737. package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -12
  738. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -146
  739. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -11
  740. package/dist/daemon/reconcilers/pending-review-submit.js +1 -36
  741. package/dist/daemon/reconcilers/storage-maintenance.js +1 -207
  742. package/dist/daemon/review/comment-notify.js +2 -109
  743. package/dist/daemon/review/companion.js +1 -29
  744. package/dist/daemon/review/deliver.js +3 -8
  745. package/dist/daemon/review/finish.js +1 -122
  746. package/dist/daemon/review/sweep.js +1 -18
  747. package/dist/daemon/startup-policy.js +1 -1
  748. package/dist/daemon/supervise-cadence.js +1 -6
  749. package/dist/hook-authoring.js +5 -447
  750. package/dist/hook-process.js +1 -34
  751. package/dist/index.js +1 -52
  752. package/dist/migrations/001-surfaces-frontmatter.js +1 -161
  753. package/dist/migrations/002-profile-project-memory.js +1 -72
  754. package/dist/migrations/003-repository-root-memory-identity/front-door.js +11 -231
  755. package/dist/migrations/003-repository-root-memory-identity/index.js +5 -513
  756. package/dist/migrations/003-repository-root-memory-identity/references.js +5 -469
  757. package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +3 -349
  758. package/dist/migrations/activation.js +2 -89
  759. package/dist/migrations/convergent.js +2 -82
  760. package/dist/migrations/corpus.js +3 -483
  761. package/dist/migrations/frontmatter-splice.js +8 -176
  762. package/dist/migrations/profile-manifests.js +2 -70
  763. package/dist/migrations/registry.js +1 -42
  764. package/dist/migrations/runner.js +1 -85
  765. package/dist/migrations/types.js +0 -24
  766. package/dist/pi-extensions/broker-local.js +2 -106
  767. package/dist/pi-extensions/canvas-bash-valve.js +7 -461
  768. package/dist/pi-extensions/canvas-context-intro.js +2 -113
  769. package/dist/pi-extensions/canvas-doc-substrate.js +9 -178
  770. package/dist/pi-extensions/canvas-goal-capture.js +1 -83
  771. package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1010
  772. package/dist/pi-extensions/canvas-passive-context.js +14 -203
  773. package/dist/pi-extensions/canvas-preview-result.js +2 -72
  774. package/dist/pi-extensions/canvas-prompt-scrub.js +2 -54
  775. package/dist/pi-extensions/canvas-recap.js +11 -405
  776. package/dist/pi-extensions/canvas-review-boundary.js +3 -63
  777. package/dist/pi-extensions/canvas-stamp.js +2 -77
  778. package/dist/pi-extensions/canvas-stophook.js +1 -643
  779. package/dist/pi-extensions/canvas-structured-output.js +13 -35
  780. package/dist/pi-extensions/canvas-tool-guide.js +9 -78
  781. package/dist/pi-extensions/envelope-merge.js +8 -29
  782. package/dist/prompts/review.js +20 -42
  783. package/dist/shared/birth-announcement.js +1 -25
  784. package/dist/shared/crtr-version.js +1 -18
  785. package/dist/shared/env.js +1 -214
  786. package/dist/shared/generated-context.js +11 -226
  787. package/dist/shared/predicates.js +1 -4
  788. package/dist/shared/shell-quote.js +1 -5
  789. package/dist/shared/tool-groups.js +1 -64
  790. package/dist/shared/working-activity.js +1 -27
  791. package/dist/suppress-experimental-warnings.js +1 -15
  792. package/dist/types.js +1 -185
  793. package/docs/public-api.md +10 -9
  794. package/package.json +6 -4
  795. package/runtime.lock.json +5 -5
  796. package/scripts/pack-minify.mjs +108 -0
  797. package/dist/api/__tests__/integration/client.test.d.ts +0 -1
  798. package/dist/api/__tests__/integration/client.test.js +0 -163
  799. package/dist/builtin-pi-packages/pi-crtr-extensions/__tests__/insights-active-init.test.ts +0 -98
  800. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/crtr-commands.test.ts +0 -93
  801. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +0 -2530
  802. package/dist/clients/__tests__/helpers/human-daemon.d.ts +0 -11
  803. package/dist/clients/__tests__/helpers/human-daemon.js +0 -60
  804. package/dist/clients/attach/__tests__/attach-remote-readonly.test.d.ts +0 -1
  805. package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +0 -97
  806. package/dist/clients/attach/__tests__/bash-call-width.test.d.ts +0 -1
  807. package/dist/clients/attach/__tests__/bash-call-width.test.js +0 -38
  808. package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.d.ts +0 -1
  809. package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +0 -175
  810. package/dist/clients/attach/__tests__/completion-frecency.test.d.ts +0 -1
  811. package/dist/clients/attach/__tests__/completion-frecency.test.js +0 -35
  812. package/dist/clients/attach/__tests__/context-message.test.d.ts +0 -1
  813. package/dist/clients/attach/__tests__/context-message.test.js +0 -130
  814. package/dist/clients/attach/__tests__/crtr-output.test.d.ts +0 -1
  815. package/dist/clients/attach/__tests__/crtr-output.test.js +0 -68
  816. package/dist/clients/attach/__tests__/diagram.test.d.ts +0 -1
  817. package/dist/clients/attach/__tests__/diagram.test.js +0 -42
  818. package/dist/clients/attach/__tests__/edit-diff.test.d.ts +0 -1
  819. package/dist/clients/attach/__tests__/edit-diff.test.js +0 -31
  820. package/dist/clients/attach/__tests__/frame-selection.test.d.ts +0 -1
  821. package/dist/clients/attach/__tests__/frame-selection.test.js +0 -84
  822. package/dist/clients/attach/__tests__/group-activity.test.d.ts +0 -1
  823. package/dist/clients/attach/__tests__/group-activity.test.js +0 -165
  824. package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.d.ts +0 -1
  825. package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +0 -83
  826. package/dist/clients/attach/__tests__/pane-tag-successor.test.d.ts +0 -1
  827. package/dist/clients/attach/__tests__/pane-tag-successor.test.js +0 -56
  828. package/dist/clients/attach/__tests__/profile-files.test.d.ts +0 -1
  829. package/dist/clients/attach/__tests__/profile-files.test.js +0 -21
  830. package/dist/clients/attach/__tests__/prompt-preview.test.d.ts +0 -1
  831. package/dist/clients/attach/__tests__/prompt-preview.test.js +0 -21
  832. package/dist/clients/attach/__tests__/ref-autocomplete.test.d.ts +0 -1
  833. package/dist/clients/attach/__tests__/ref-autocomplete.test.js +0 -64
  834. package/dist/clients/attach/__tests__/titled-editor-paste.test.d.ts +0 -1
  835. package/dist/clients/attach/__tests__/titled-editor-paste.test.js +0 -114
  836. package/dist/clients/attach/__tests__/titled-editor-preview.test.d.ts +0 -1
  837. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +0 -83
  838. package/dist/clients/inbox/__tests__/integration/inbox-controller.test.d.ts +0 -1
  839. package/dist/clients/inbox/__tests__/integration/inbox-controller.test.js +0 -81
  840. package/dist/clients/inbox/__tests__/integration/mount-panel.test.d.ts +0 -1
  841. package/dist/clients/inbox/__tests__/integration/mount-panel.test.js +0 -135
  842. package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.d.ts +0 -1
  843. package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.js +0 -66
  844. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.d.ts +0 -1
  845. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +0 -35
  846. package/dist/clients/inbox/review/__tests__/review-core.test.d.ts +0 -1
  847. package/dist/clients/inbox/review/__tests__/review-core.test.js +0 -52
  848. package/dist/clients/inbox/review/__tests__/teardown-notice.test.d.ts +0 -1
  849. package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +0 -100
  850. package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.d.ts +0 -1
  851. package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +0 -69
  852. package/dist/commands/__tests__/human.test.d.ts +0 -1
  853. package/dist/commands/__tests__/human.test.js +0 -172
  854. package/dist/commands/__tests__/integration/dashboard-snapshot.test.d.ts +0 -1
  855. package/dist/commands/__tests__/integration/dashboard-snapshot.test.js +0 -237
  856. package/dist/commands/__tests__/integration/migrate.test.d.ts +0 -1
  857. package/dist/commands/__tests__/integration/migrate.test.js +0 -1330
  858. package/dist/commands/__tests__/node-message.test.d.ts +0 -1
  859. package/dist/commands/__tests__/node-message.test.js +0 -112
  860. package/dist/commands/__tests__/node-new.test.d.ts +0 -1
  861. package/dist/commands/__tests__/node-new.test.js +0 -58
  862. package/dist/commands/__tests__/revive-now-gate.test.d.ts +0 -1
  863. package/dist/commands/__tests__/revive-now-gate.test.js +0 -62
  864. package/dist/commands/__tests__/seam/daemon-status.test.d.ts +0 -1
  865. package/dist/commands/__tests__/seam/daemon-status.test.js +0 -29
  866. package/dist/commands/__tests__/surface-reload-target.test.d.ts +0 -1
  867. package/dist/commands/__tests__/surface-reload-target.test.js +0 -21
  868. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.d.ts +0 -1
  869. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +0 -379
  870. package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.d.ts +0 -1
  871. package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +0 -124
  872. package/dist/commands/memory/__tests__/repository-root-lint.test.d.ts +0 -1
  873. package/dist/commands/memory/__tests__/repository-root-lint.test.js +0 -148
  874. package/dist/commands/sys/__tests__/config-model-ladders.test.d.ts +0 -1
  875. package/dist/commands/sys/__tests__/config-model-ladders.test.js +0 -114
  876. package/dist/commands/sys/__tests__/setup-core.test.d.ts +0 -1
  877. package/dist/commands/sys/__tests__/setup-core.test.js +0 -45
  878. package/dist/commands/sys/__tests__/sync-project-guidance.test.d.ts +0 -1
  879. package/dist/commands/sys/__tests__/sync-project-guidance.test.js +0 -244
  880. package/dist/core/__tests__/bash-guard.test.d.ts +0 -1
  881. package/dist/core/__tests__/bash-guard.test.js +0 -190
  882. package/dist/core/__tests__/boot-fault-attempt.test.d.ts +0 -1
  883. package/dist/core/__tests__/boot-fault-attempt.test.js +0 -105
  884. package/dist/core/__tests__/boot.test.d.ts +0 -1
  885. package/dist/core/__tests__/boot.test.js +0 -274
  886. package/dist/core/__tests__/branded-host-concurrency.test.d.ts +0 -1
  887. package/dist/core/__tests__/branded-host-concurrency.test.js +0 -72
  888. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.d.ts +0 -1
  889. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +0 -75
  890. package/dist/core/__tests__/broker-launch-candidates.test.d.ts +0 -1
  891. package/dist/core/__tests__/broker-launch-candidates.test.js +0 -311
  892. package/dist/core/__tests__/broker-preflight.test.d.ts +0 -1
  893. package/dist/core/__tests__/broker-preflight.test.js +0 -95
  894. package/dist/core/__tests__/broker-stream-watchdog-floor.test.d.ts +0 -1
  895. package/dist/core/__tests__/broker-stream-watchdog-floor.test.js +0 -82
  896. package/dist/core/__tests__/broker-turn-admission.test.d.ts +0 -1
  897. package/dist/core/__tests__/broker-turn-admission.test.js +0 -44
  898. package/dist/core/__tests__/canvas-db-boundary.test.d.ts +0 -1
  899. package/dist/core/__tests__/canvas-db-boundary.test.js +0 -46
  900. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.d.ts +0 -1
  901. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +0 -710
  902. package/dist/core/__tests__/canvas-inbox-watcher-naming.test.d.ts +0 -1
  903. package/dist/core/__tests__/canvas-inbox-watcher-naming.test.js +0 -310
  904. package/dist/core/__tests__/canvas-inbox-watcher.test.d.ts +0 -1
  905. package/dist/core/__tests__/canvas-inbox-watcher.test.js +0 -397
  906. package/dist/core/__tests__/canvas.test.d.ts +0 -1
  907. package/dist/core/__tests__/canvas.test.js +0 -138
  908. package/dist/core/__tests__/child-death-wake.test.d.ts +0 -1
  909. package/dist/core/__tests__/child-death-wake.test.js +0 -153
  910. package/dist/core/__tests__/cli-help-contract.test.d.ts +0 -1
  911. package/dist/core/__tests__/cli-help-contract.test.js +0 -152
  912. package/dist/core/__tests__/close.test.d.ts +0 -1
  913. package/dist/core/__tests__/close.test.js +0 -284
  914. package/dist/core/__tests__/collectible.test.d.ts +0 -1
  915. package/dist/core/__tests__/collectible.test.js +0 -89
  916. package/dist/core/__tests__/config-change-delta.test.d.ts +0 -1
  917. package/dist/core/__tests__/config-change-delta.test.js +0 -108
  918. package/dist/core/__tests__/context-intro.test.d.ts +0 -1
  919. package/dist/core/__tests__/context-intro.test.js +0 -123
  920. package/dist/core/__tests__/cron-armed-context-failure.test.d.ts +0 -1
  921. package/dist/core/__tests__/cron-armed-context-failure.test.js +0 -150
  922. package/dist/core/__tests__/cron-held-settlement.test.d.ts +0 -1
  923. package/dist/core/__tests__/cron-held-settlement.test.js +0 -240
  924. package/dist/core/__tests__/cron-node-sink-parked-root.test.d.ts +0 -1
  925. package/dist/core/__tests__/cron-node-sink-parked-root.test.js +0 -166
  926. package/dist/core/__tests__/cron-self-cancel-delivery.test.d.ts +0 -1
  927. package/dist/core/__tests__/cron-self-cancel-delivery.test.js +0 -84
  928. package/dist/core/__tests__/cron-timeout-descendants.test.d.ts +0 -1
  929. package/dist/core/__tests__/cron-timeout-descendants.test.js +0 -114
  930. package/dist/core/__tests__/daemon-boot.test.d.ts +0 -1
  931. package/dist/core/__tests__/daemon-boot.test.js +0 -422
  932. package/dist/core/__tests__/daemon-wedge.test.d.ts +0 -1
  933. package/dist/core/__tests__/daemon-wedge.test.js +0 -106
  934. package/dist/core/__tests__/dead-node-policy-table.test.d.ts +0 -1
  935. package/dist/core/__tests__/dead-node-policy-table.test.js +0 -77
  936. package/dist/core/__tests__/events-contract.test.d.ts +0 -1
  937. package/dist/core/__tests__/events-contract.test.js +0 -76
  938. package/dist/core/__tests__/extension-abort.test.d.ts +0 -1
  939. package/dist/core/__tests__/extension-abort.test.js +0 -21
  940. package/dist/core/__tests__/fault-classifier.test.d.ts +0 -1
  941. package/dist/core/__tests__/fault-classifier.test.js +0 -138
  942. package/dist/core/__tests__/fixtures/api-server-host.d.ts +0 -1
  943. package/dist/core/__tests__/fixtures/api-server-host.js +0 -47
  944. package/dist/core/__tests__/fixtures/c3-custom-provider-ext.d.ts +0 -2
  945. package/dist/core/__tests__/fixtures/c3-custom-provider-ext.js +0 -34
  946. package/dist/core/__tests__/fixtures/c5-command-boundary-ext.d.ts +0 -2
  947. package/dist/core/__tests__/fixtures/c5-command-boundary-ext.js +0 -32
  948. package/dist/core/__tests__/fixtures/fake-engine.d.ts +0 -347
  949. package/dist/core/__tests__/fixtures/fake-engine.js +0 -1509
  950. package/dist/core/__tests__/fixtures/fake-pi-host.d.ts +0 -2
  951. package/dist/core/__tests__/fixtures/fake-pi-host.js +0 -311
  952. package/dist/core/__tests__/fixtures/memory-slash-live-probe.d.ts +0 -1
  953. package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +0 -75
  954. package/dist/core/__tests__/fixtures/metadata-migration-race.d.ts +0 -1
  955. package/dist/core/__tests__/fixtures/metadata-migration-race.js +0 -49
  956. package/dist/core/__tests__/focuses.test.d.ts +0 -1
  957. package/dist/core/__tests__/focuses.test.js +0 -113
  958. package/dist/core/__tests__/fs-utils.test.d.ts +0 -1
  959. package/dist/core/__tests__/fs-utils.test.js +0 -50
  960. package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -43
  961. package/dist/core/__tests__/helpers/broker-clients.js +0 -174
  962. package/dist/core/__tests__/helpers/fleet.d.ts +0 -12
  963. package/dist/core/__tests__/helpers/fleet.js +0 -50
  964. package/dist/core/__tests__/helpers/harness.d.ts +0 -124
  965. package/dist/core/__tests__/helpers/harness.js +0 -806
  966. package/dist/core/__tests__/helpers/viewer-panes.d.ts +0 -12
  967. package/dist/core/__tests__/helpers/viewer-panes.js +0 -133
  968. package/dist/core/__tests__/history-inbox.test.d.ts +0 -1
  969. package/dist/core/__tests__/history-inbox.test.js +0 -121
  970. package/dist/core/__tests__/human-action-delivery.test.d.ts +0 -1
  971. package/dist/core/__tests__/human-action-delivery.test.js +0 -162
  972. package/dist/core/__tests__/human-actions.test.d.ts +0 -1
  973. package/dist/core/__tests__/human-actions.test.js +0 -120
  974. package/dist/core/__tests__/inline-memory-refs.test.d.ts +0 -1
  975. package/dist/core/__tests__/inline-memory-refs.test.js +0 -225
  976. package/dist/core/__tests__/integration/broker-fork-seam.test.d.ts +0 -1
  977. package/dist/core/__tests__/integration/broker-fork-seam.test.js +0 -193
  978. package/dist/core/__tests__/integration/broker-sdk-wiring.test.d.ts +0 -1
  979. package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +0 -750
  980. package/dist/core/__tests__/integration/broker-snapshot-history.test.d.ts +0 -1
  981. package/dist/core/__tests__/integration/broker-snapshot-history.test.js +0 -288
  982. package/dist/core/__tests__/integration/broker-wedge-supervision.test.d.ts +0 -1
  983. package/dist/core/__tests__/integration/broker-wedge-supervision.test.js +0 -103
  984. package/dist/core/__tests__/integration/command-plugins.test.d.ts +0 -1
  985. package/dist/core/__tests__/integration/command-plugins.test.js +0 -1200
  986. package/dist/core/__tests__/integration/deferred-no-wake.test.d.ts +0 -1
  987. package/dist/core/__tests__/integration/deferred-no-wake.test.js +0 -610
  988. package/dist/core/__tests__/integration/flagship-lifecycle.test.d.ts +0 -1
  989. package/dist/core/__tests__/integration/flagship-lifecycle.test.js +0 -264
  990. package/dist/core/__tests__/integration/fresh-home-commands.test.d.ts +0 -1
  991. package/dist/core/__tests__/integration/fresh-home-commands.test.js +0 -49
  992. package/dist/core/__tests__/integration/git-optional-locks.test.d.ts +0 -1
  993. package/dist/core/__tests__/integration/git-optional-locks.test.js +0 -81
  994. package/dist/core/__tests__/integration/host-teardown-process-group.test.d.ts +0 -1
  995. package/dist/core/__tests__/integration/host-teardown-process-group.test.js +0 -480
  996. package/dist/core/__tests__/integration/lifecycle-hooks.test.d.ts +0 -1
  997. package/dist/core/__tests__/integration/lifecycle-hooks.test.js +0 -498
  998. package/dist/core/__tests__/integration/live-mutation-verbs.test.d.ts +0 -1
  999. package/dist/core/__tests__/integration/live-mutation-verbs.test.js +0 -180
  1000. package/dist/core/__tests__/integration/live-mutation.test.d.ts +0 -1
  1001. package/dist/core/__tests__/integration/live-mutation.test.js +0 -173
  1002. package/dist/core/__tests__/integration/plugin-revalidate.test.d.ts +0 -1
  1003. package/dist/core/__tests__/integration/plugin-revalidate.test.js +0 -359
  1004. package/dist/core/__tests__/integration/profile-pause.test.d.ts +0 -1
  1005. package/dist/core/__tests__/integration/profile-pause.test.js +0 -115
  1006. package/dist/core/__tests__/integration/refresh-stall-recycle.test.d.ts +0 -1
  1007. package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +0 -151
  1008. package/dist/core/__tests__/integration/revive.test.d.ts +0 -1
  1009. package/dist/core/__tests__/integration/revive.test.js +0 -615
  1010. package/dist/core/__tests__/integration/spawn-root.test.d.ts +0 -1
  1011. package/dist/core/__tests__/integration/spawn-root.test.js +0 -536
  1012. package/dist/core/__tests__/integration/subscription-delivery.test.d.ts +0 -1
  1013. package/dist/core/__tests__/integration/subscription-delivery.test.js +0 -132
  1014. package/dist/core/__tests__/integration/tmux-surface.test.d.ts +0 -1
  1015. package/dist/core/__tests__/integration/tmux-surface.test.js +0 -330
  1016. package/dist/core/__tests__/integration/worktree-land.test.d.ts +0 -1
  1017. package/dist/core/__tests__/integration/worktree-land.test.js +0 -607
  1018. package/dist/core/__tests__/integration/worktree-reap.test.d.ts +0 -1
  1019. package/dist/core/__tests__/integration/worktree-reap.test.js +0 -842
  1020. package/dist/core/__tests__/kickoff.test.d.ts +0 -1
  1021. package/dist/core/__tests__/kickoff.test.js +0 -196
  1022. package/dist/core/__tests__/lifecycle-terminal-reasons.test.d.ts +0 -1
  1023. package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +0 -62
  1024. package/dist/core/__tests__/lifecycle.test.d.ts +0 -1
  1025. package/dist/core/__tests__/lifecycle.test.js +0 -176
  1026. package/dist/core/__tests__/live-lifecycle-prompt.test.d.ts +0 -1
  1027. package/dist/core/__tests__/live-lifecycle-prompt.test.js +0 -63
  1028. package/dist/core/__tests__/memory-resolver-precedence.test.d.ts +0 -1
  1029. package/dist/core/__tests__/memory-resolver-precedence.test.js +0 -228
  1030. package/dist/core/__tests__/migration.test.d.ts +0 -1
  1031. package/dist/core/__tests__/migration.test.js +0 -946
  1032. package/dist/core/__tests__/model-pin-durability.test.d.ts +0 -1
  1033. package/dist/core/__tests__/model-pin-durability.test.js +0 -195
  1034. package/dist/core/__tests__/model-routes-config.test.d.ts +0 -1
  1035. package/dist/core/__tests__/model-routes-config.test.js +0 -150
  1036. package/dist/core/__tests__/nested-store-discovery.test.d.ts +0 -1
  1037. package/dist/core/__tests__/nested-store-discovery.test.js +0 -89
  1038. package/dist/core/__tests__/node-outcome.test.d.ts +0 -1
  1039. package/dist/core/__tests__/node-outcome.test.js +0 -246
  1040. package/dist/core/__tests__/on-read-crouter-home-fence.test.d.ts +0 -1
  1041. package/dist/core/__tests__/on-read-crouter-home-fence.test.js +0 -66
  1042. package/dist/core/__tests__/on-read-dedup-resume.test.d.ts +0 -1
  1043. package/dist/core/__tests__/on-read-dedup-resume.test.js +0 -132
  1044. package/dist/core/__tests__/on-read-nested-store.test.d.ts +0 -1
  1045. package/dist/core/__tests__/on-read-nested-store.test.js +0 -135
  1046. package/dist/core/__tests__/parse-argv-stdin-secret.test.d.ts +0 -1
  1047. package/dist/core/__tests__/parse-argv-stdin-secret.test.js +0 -68
  1048. package/dist/core/__tests__/passive-subscription.test.d.ts +0 -1
  1049. package/dist/core/__tests__/passive-subscription.test.js +0 -120
  1050. package/dist/core/__tests__/pid-identity-match.test.d.ts +0 -1
  1051. package/dist/core/__tests__/pid-identity-match.test.js +0 -145
  1052. package/dist/core/__tests__/pid-zombie.test.d.ts +0 -1
  1053. package/dist/core/__tests__/pid-zombie.test.js +0 -42
  1054. package/dist/core/__tests__/plugin-kinds.test.d.ts +0 -1
  1055. package/dist/core/__tests__/plugin-kinds.test.js +0 -182
  1056. package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.d.ts +0 -1
  1057. package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +0 -43
  1058. package/dist/core/__tests__/plugin-page-components.test.d.ts +0 -1
  1059. package/dist/core/__tests__/plugin-page-components.test.js +0 -159
  1060. package/dist/core/__tests__/preview-mirror-cap.test.d.ts +0 -1
  1061. package/dist/core/__tests__/preview-mirror-cap.test.js +0 -53
  1062. package/dist/core/__tests__/preview-registry-sync.test.d.ts +0 -1
  1063. package/dist/core/__tests__/preview-registry-sync.test.js +0 -107
  1064. package/dist/core/__tests__/profile-project-memory-delivery.test.d.ts +0 -1
  1065. package/dist/core/__tests__/profile-project-memory-delivery.test.js +0 -644
  1066. package/dist/core/__tests__/prospective-inventory-capability-parity.test.d.ts +0 -1
  1067. package/dist/core/__tests__/prospective-inventory-capability-parity.test.js +0 -91
  1068. package/dist/core/__tests__/prune.test.d.ts +0 -1
  1069. package/dist/core/__tests__/prune.test.js +0 -243
  1070. package/dist/core/__tests__/push-final-guard.test.d.ts +0 -1
  1071. package/dist/core/__tests__/push-final-guard.test.js +0 -191
  1072. package/dist/core/__tests__/relaunch-root.test.d.ts +0 -1
  1073. package/dist/core/__tests__/relaunch-root.test.js +0 -249
  1074. package/dist/core/__tests__/remote-canvas-target.test.d.ts +0 -1
  1075. package/dist/core/__tests__/remote-canvas-target.test.js +0 -93
  1076. package/dist/core/__tests__/repository-association.test.d.ts +0 -1
  1077. package/dist/core/__tests__/repository-association.test.js +0 -153
  1078. package/dist/core/__tests__/repository-root-identity.test.d.ts +0 -1
  1079. package/dist/core/__tests__/repository-root-identity.test.js +0 -223
  1080. package/dist/core/__tests__/respawn-throttle.test.d.ts +0 -1
  1081. package/dist/core/__tests__/respawn-throttle.test.js +0 -20
  1082. package/dist/core/__tests__/review-model-floor.test.d.ts +0 -1
  1083. package/dist/core/__tests__/review-model-floor.test.js +0 -83
  1084. package/dist/core/__tests__/revive-all.test.d.ts +0 -1
  1085. package/dist/core/__tests__/revive-all.test.js +0 -157
  1086. package/dist/core/__tests__/revive-capacity.test.d.ts +0 -1
  1087. package/dist/core/__tests__/revive-capacity.test.js +0 -184
  1088. package/dist/core/__tests__/revive-parked-fresh.test.d.ts +0 -1
  1089. package/dist/core/__tests__/revive-parked-fresh.test.js +0 -176
  1090. package/dist/core/__tests__/scope-crouter-home-fence.test.d.ts +0 -1
  1091. package/dist/core/__tests__/scope-crouter-home-fence.test.js +0 -55
  1092. package/dist/core/__tests__/seam/broker-attach-multiclient.test.d.ts +0 -1
  1093. package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +0 -262
  1094. package/dist/core/__tests__/seam/broker-attach-stream.test.d.ts +0 -1
  1095. package/dist/core/__tests__/seam/broker-attach-stream.test.js +0 -176
  1096. package/dist/core/__tests__/seam/broker-cap-freeze.test.d.ts +0 -1
  1097. package/dist/core/__tests__/seam/broker-cap-freeze.test.js +0 -155
  1098. package/dist/core/__tests__/seam/broker-crash-teardown.test.d.ts +0 -1
  1099. package/dist/core/__tests__/seam/broker-crash-teardown.test.js +0 -131
  1100. package/dist/core/__tests__/seam/broker-pane-resolution.test.d.ts +0 -1
  1101. package/dist/core/__tests__/seam/broker-pane-resolution.test.js +0 -204
  1102. package/dist/core/__tests__/seam/broker-provider-retry.test.d.ts +0 -1
  1103. package/dist/core/__tests__/seam/broker-provider-retry.test.js +0 -686
  1104. package/dist/core/__tests__/seam/broker-startup-diagnostics.test.d.ts +0 -1
  1105. package/dist/core/__tests__/seam/broker-startup-diagnostics.test.js +0 -82
  1106. package/dist/core/__tests__/seam/broker-whip-interrupt.test.d.ts +0 -1
  1107. package/dist/core/__tests__/seam/broker-whip-interrupt.test.js +0 -50
  1108. package/dist/core/__tests__/seam/deadline-wake-delivery.test.d.ts +0 -1
  1109. package/dist/core/__tests__/seam/deadline-wake-delivery.test.js +0 -138
  1110. package/dist/core/__tests__/seam/dormancy-release.test.d.ts +0 -1
  1111. package/dist/core/__tests__/seam/dormancy-release.test.js +0 -516
  1112. package/dist/core/__tests__/seam/held-deferred-human-prompt.test.d.ts +0 -1
  1113. package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +0 -65
  1114. package/dist/core/__tests__/seam/inbox-reference-guidance.test.d.ts +0 -1
  1115. package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +0 -84
  1116. package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.d.ts +0 -1
  1117. package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +0 -160
  1118. package/dist/core/__tests__/seam/node-outcome-delivery.test.d.ts +0 -1
  1119. package/dist/core/__tests__/seam/node-outcome-delivery.test.js +0 -177
  1120. package/dist/core/__tests__/seam/prospective-inventory-stdout.test.d.ts +0 -1
  1121. package/dist/core/__tests__/seam/prospective-inventory-stdout.test.js +0 -31
  1122. package/dist/core/__tests__/seam/reopen-invalidated-worktree.test.d.ts +0 -1
  1123. package/dist/core/__tests__/seam/reopen-invalidated-worktree.test.js +0 -60
  1124. package/dist/core/__tests__/seam/self-close-teardown.test.d.ts +0 -1
  1125. package/dist/core/__tests__/seam/self-close-teardown.test.js +0 -49
  1126. package/dist/core/__tests__/seam/yield-refresh-transaction.test.d.ts +0 -1
  1127. package/dist/core/__tests__/seam/yield-refresh-transaction.test.js +0 -100
  1128. package/dist/core/__tests__/secrets.test.d.ts +0 -1
  1129. package/dist/core/__tests__/secrets.test.js +0 -49
  1130. package/dist/core/__tests__/self-update.test.d.ts +0 -1
  1131. package/dist/core/__tests__/self-update.test.js +0 -46
  1132. package/dist/core/__tests__/session-branch.test.d.ts +0 -1
  1133. package/dist/core/__tests__/session-branch.test.js +0 -61
  1134. package/dist/core/__tests__/session-cycles.test.d.ts +0 -1
  1135. package/dist/core/__tests__/session-cycles.test.js +0 -133
  1136. package/dist/core/__tests__/session-model.test.d.ts +0 -1
  1137. package/dist/core/__tests__/session-model.test.js +0 -111
  1138. package/dist/core/__tests__/spawn-worktree-id-conflict.test.d.ts +0 -1
  1139. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +0 -71
  1140. package/dist/core/__tests__/stdin-body-no-discard.test.d.ts +0 -1
  1141. package/dist/core/__tests__/stdin-body-no-discard.test.js +0 -33
  1142. package/dist/core/__tests__/stdout-errors.test.d.ts +0 -1
  1143. package/dist/core/__tests__/stdout-errors.test.js +0 -16
  1144. package/dist/core/__tests__/stop-guard.test.d.ts +0 -1
  1145. package/dist/core/__tests__/stop-guard.test.js +0 -237
  1146. package/dist/core/__tests__/stream-watchdog.test.d.ts +0 -1
  1147. package/dist/core/__tests__/stream-watchdog.test.js +0 -154
  1148. package/dist/core/__tests__/subscription-pool-credential-guard.test.d.ts +0 -1
  1149. package/dist/core/__tests__/subscription-pool-credential-guard.test.js +0 -95
  1150. package/dist/core/__tests__/tmux-driver-boundary.test.d.ts +0 -1
  1151. package/dist/core/__tests__/tmux-driver-boundary.test.js +0 -50
  1152. package/dist/core/__tests__/warm-claim-preference-snapshot.test.d.ts +0 -1
  1153. package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +0 -54
  1154. package/dist/core/__tests__/worktree-landing.test.d.ts +0 -1
  1155. package/dist/core/__tests__/worktree-landing.test.js +0 -11
  1156. package/dist/core/__tests__/yield-ensures-daemon.test.d.ts +0 -1
  1157. package/dist/core/__tests__/yield-ensures-daemon.test.js +0 -55
  1158. package/dist/core/broker-client/__tests__/transport-relay.test.d.ts +0 -1
  1159. package/dist/core/broker-client/__tests__/transport-relay.test.js +0 -214
  1160. package/dist/core/broker-client/__tests__/transport-socket.test.d.ts +0 -1
  1161. package/dist/core/broker-client/__tests__/transport-socket.test.js +0 -73
  1162. package/dist/core/canvas/__tests__/attention.test.d.ts +0 -1
  1163. package/dist/core/canvas/__tests__/attention.test.js +0 -83
  1164. package/dist/core/canvas/__tests__/history-transcript.test.d.ts +0 -1
  1165. package/dist/core/canvas/__tests__/history-transcript.test.js +0 -102
  1166. package/dist/core/canvas/__tests__/remote-canvas-source.test.d.ts +0 -1
  1167. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +0 -328
  1168. package/dist/core/canvas/__tests__/remote-transport.test.d.ts +0 -1
  1169. package/dist/core/canvas/__tests__/remote-transport.test.js +0 -97
  1170. package/dist/core/canvas/__tests__/render-remote.test.d.ts +0 -1
  1171. package/dist/core/canvas/__tests__/render-remote.test.js +0 -243
  1172. package/dist/core/canvas/__tests__/session-window.test.d.ts +0 -1
  1173. package/dist/core/canvas/__tests__/session-window.test.js +0 -70
  1174. package/dist/core/feed/__tests__/inbox-migrate.test.d.ts +0 -1
  1175. package/dist/core/feed/__tests__/inbox-migrate.test.js +0 -49
  1176. package/dist/core/human/__tests__/page-catalog.test.d.ts +0 -1
  1177. package/dist/core/human/__tests__/page-catalog.test.js +0 -20
  1178. package/dist/core/human/__tests__/page-html-markdown.test.d.ts +0 -1
  1179. package/dist/core/human/__tests__/page-html-markdown.test.js +0 -48
  1180. package/dist/core/human/__tests__/page.test.d.ts +0 -1
  1181. package/dist/core/human/__tests__/page.test.js +0 -92
  1182. package/dist/core/keybindings/__tests__/resolve.test.d.ts +0 -1
  1183. package/dist/core/keybindings/__tests__/resolve.test.js +0 -171
  1184. package/dist/core/profiles/__tests__/env-store.test.d.ts +0 -1
  1185. package/dist/core/profiles/__tests__/env-store.test.js +0 -99
  1186. package/dist/core/profiles/__tests__/fuzzy-match.test.d.ts +0 -1
  1187. package/dist/core/profiles/__tests__/fuzzy-match.test.js +0 -51
  1188. package/dist/core/profiles/__tests__/root-profile.test.d.ts +0 -1
  1189. package/dist/core/profiles/__tests__/root-profile.test.js +0 -59
  1190. package/dist/core/review/__tests__/capture-origin.test.d.ts +0 -1
  1191. package/dist/core/review/__tests__/capture-origin.test.js +0 -150
  1192. package/dist/core/review/__tests__/comments.test.d.ts +0 -1
  1193. package/dist/core/review/__tests__/comments.test.js +0 -116
  1194. package/dist/core/review/__tests__/remap.test.d.ts +0 -1
  1195. package/dist/core/review/__tests__/remap.test.js +0 -177
  1196. package/dist/core/review/__tests__/stage-identity.test.d.ts +0 -1
  1197. package/dist/core/review/__tests__/stage-identity.test.js +0 -150
  1198. package/dist/core/runtime/__tests__/engine-route.test.d.ts +0 -1
  1199. package/dist/core/runtime/__tests__/engine-route.test.js +0 -36
  1200. package/dist/core/runtime/__tests__/install-id-cache-scoping.test.d.ts +0 -1
  1201. package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +0 -45
  1202. package/dist/core/runtime/__tests__/node-env.test.d.ts +0 -1
  1203. package/dist/core/runtime/__tests__/node-env.test.js +0 -73
  1204. package/dist/core/runtime/__tests__/spawn-env.test.d.ts +0 -1
  1205. package/dist/core/runtime/__tests__/spawn-env.test.js +0 -259
  1206. package/dist/core/substrate/__tests__/surface-match-command.test.d.ts +0 -1
  1207. package/dist/core/substrate/__tests__/surface-match-command.test.js +0 -89
  1208. package/dist/core/substrate/__tests__/surface-match-memory-read.test.d.ts +0 -1
  1209. package/dist/core/substrate/__tests__/surface-match-memory-read.test.js +0 -28
  1210. package/dist/core/substrate/__tests__/surface-match-pre-command.test.d.ts +0 -1
  1211. package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +0 -92
  1212. package/dist/daemon/__tests__/autostart-storm.test.d.ts +0 -1
  1213. package/dist/daemon/__tests__/autostart-storm.test.js +0 -128
  1214. package/dist/daemon/__tests__/broker-ownership.test.d.ts +0 -1
  1215. package/dist/daemon/__tests__/broker-ownership.test.js +0 -25
  1216. package/dist/daemon/__tests__/daemon-ownership.test.d.ts +0 -1
  1217. package/dist/daemon/__tests__/daemon-ownership.test.js +0 -27
  1218. package/dist/daemon/__tests__/helpers/source-daemon.d.ts +0 -30
  1219. package/dist/daemon/__tests__/helpers/source-daemon.js +0 -176
  1220. package/dist/daemon/__tests__/integration/api-startup-readiness.test.d.ts +0 -1
  1221. package/dist/daemon/__tests__/integration/api-startup-readiness.test.js +0 -83
  1222. package/dist/daemon/__tests__/integration/migration-startup.test.d.ts +0 -1
  1223. package/dist/daemon/__tests__/integration/migration-startup.test.js +0 -127
  1224. package/dist/daemon/__tests__/node-deadline-lane.test.d.ts +0 -1
  1225. package/dist/daemon/__tests__/node-deadline-lane.test.js +0 -77
  1226. package/dist/daemon/__tests__/node-outcome-birth-invariants.test.d.ts +0 -1
  1227. package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +0 -146
  1228. package/dist/daemon/__tests__/node-outcome-delivery.test.d.ts +0 -1
  1229. package/dist/daemon/__tests__/node-outcome-delivery.test.js +0 -116
  1230. package/dist/daemon/__tests__/reconciler-signature.test.d.ts +0 -1
  1231. package/dist/daemon/__tests__/reconciler-signature.test.js +0 -37
  1232. package/dist/daemon/__tests__/subtree-filter-freshness.test.d.ts +0 -1
  1233. package/dist/daemon/__tests__/subtree-filter-freshness.test.js +0 -63
  1234. package/dist/daemon/__tests__/thaw-order.test.d.ts +0 -1
  1235. package/dist/daemon/__tests__/thaw-order.test.js +0 -55
  1236. package/dist/daemon/api/__tests__/bridge-heartbeat.test.d.ts +0 -1
  1237. package/dist/daemon/api/__tests__/bridge-heartbeat.test.js +0 -58
  1238. package/dist/daemon/api/__tests__/broker-settle-park.test.d.ts +0 -1
  1239. package/dist/daemon/api/__tests__/broker-settle-park.test.js +0 -175
  1240. package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.d.ts +0 -1
  1241. package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +0 -216
  1242. package/dist/daemon/api/__tests__/error-seam.test.d.ts +0 -1
  1243. package/dist/daemon/api/__tests__/error-seam.test.js +0 -83
  1244. package/dist/daemon/api/__tests__/model-config.test.d.ts +0 -1
  1245. package/dist/daemon/api/__tests__/model-config.test.js +0 -73
  1246. package/dist/daemon/api/__tests__/node-create-description.test.d.ts +0 -1
  1247. package/dist/daemon/api/__tests__/node-create-description.test.js +0 -127
  1248. package/dist/daemon/api/__tests__/node-model-validation.test.d.ts +0 -1
  1249. package/dist/daemon/api/__tests__/node-model-validation.test.js +0 -183
  1250. package/dist/daemon/api/__tests__/nodes-activity-query.test.d.ts +0 -1
  1251. package/dist/daemon/api/__tests__/nodes-activity-query.test.js +0 -99
  1252. package/dist/daemon/api/__tests__/profile-launch-gates.test.d.ts +0 -1
  1253. package/dist/daemon/api/__tests__/profile-launch-gates.test.js +0 -172
  1254. package/dist/daemon/api/__tests__/profile-metadata-route.test.d.ts +0 -1
  1255. package/dist/daemon/api/__tests__/profile-metadata-route.test.js +0 -95
  1256. package/dist/daemon/api/__tests__/reopen-delivery.test.d.ts +0 -1
  1257. package/dist/daemon/api/__tests__/reopen-delivery.test.js +0 -260
  1258. package/dist/daemon/api/__tests__/seam/api-server.test.d.ts +0 -1
  1259. package/dist/daemon/api/__tests__/seam/api-server.test.js +0 -442
  1260. package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.d.ts +0 -1
  1261. package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +0 -310
  1262. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.d.ts +0 -1
  1263. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +0 -351
  1264. package/dist/daemon/api/__tests__/seam/node-outcome-api.test.d.ts +0 -1
  1265. package/dist/daemon/api/__tests__/seam/node-outcome-api.test.js +0 -159
  1266. package/dist/daemon/api/__tests__/seam/profile-delete.test.d.ts +0 -1
  1267. package/dist/daemon/api/__tests__/seam/profile-delete.test.js +0 -372
  1268. package/dist/daemon/api/__tests__/submit-result.test.d.ts +0 -1
  1269. package/dist/daemon/api/__tests__/submit-result.test.js +0 -215
  1270. package/dist/migrations/__tests__/activation-concurrency.test.d.ts +0 -1
  1271. package/dist/migrations/__tests__/activation-concurrency.test.js +0 -146
  1272. package/dist/migrations/__tests__/activation.test.d.ts +0 -1
  1273. package/dist/migrations/__tests__/activation.test.js +0 -152
  1274. package/dist/migrations/__tests__/deletion-and-root-declaration.test.d.ts +0 -1
  1275. package/dist/migrations/__tests__/deletion-and-root-declaration.test.js +0 -149
  1276. package/dist/pi-extensions/__tests__/canvas-bash-valve.test.d.ts +0 -1
  1277. package/dist/pi-extensions/__tests__/canvas-bash-valve.test.js +0 -86
  1278. package/dist/pi-extensions/__tests__/canvas-context-intro.test.d.ts +0 -1
  1279. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +0 -364
  1280. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.d.ts +0 -1
  1281. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +0 -106
  1282. package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +0 -1
  1283. package/dist/pi-extensions/__tests__/canvas-recap.test.js +0 -62
  1284. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.d.ts +0 -1
  1285. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +0 -432
  1286. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.d.ts +0 -1
  1287. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +0 -152
  1288. package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +0 -1
  1289. package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +0 -88
  1290. package/dist/pi-extensions/__tests__/canvas-tool-guide.test.d.ts +0 -1
  1291. package/dist/pi-extensions/__tests__/canvas-tool-guide.test.js +0 -96
  1292. package/dist/pi-extensions/__tests__/integration/canvas-bash-valve.test.d.ts +0 -1
  1293. package/dist/pi-extensions/__tests__/integration/canvas-bash-valve.test.js +0 -133
  1294. package/dist/pi-extensions/__tests__/pre-command-gate.test.d.ts +0 -1
  1295. package/dist/pi-extensions/__tests__/pre-command-gate.test.js +0 -232
  1296. package/dist/shared/__tests__/env-boundary.test.d.ts +0 -1
  1297. package/dist/shared/__tests__/env-boundary.test.js +0 -95
  1298. package/dist/shared/__tests__/generated-context-grammar.test.d.ts +0 -1
  1299. package/dist/shared/__tests__/generated-context-grammar.test.js +0 -80
  1300. package/docs/compat/hearth-crtr-v1.md +0 -179
  1301. package/docs/compat/hearth-crtr-v2.md +0 -177
  1302. package/docs/compat/hearth-crtr-v3.md +0 -176
  1303. package/docs/compat/hearth-crtr-v4.md +0 -182
  1304. package/docs/compat/hearth-crtr-v5.md +0 -169
@@ -1,1055 +1,3 @@
1
- // render.ts — pure frame rendering for the canvas browser.
2
- //
3
- // renderFrame(state, size, caps) → a full-screen string. The app writes it
4
- // verbatim on every keystroke. Redraw is flicker-free: home the cursor (\x1b[H),
5
- // clear each line to EOL (\x1b[K), and clear below the last line (\x1b[J) so a
6
- // shrunk frame leaves no stale rows. A full frame per keypress is fine for a
7
- // picker.
8
- //
9
- // COLOR is browse-only and *reinforces* the status glyphs (`● ○ ✓ ✗ ⊘`) which
10
- // stay the primary, color-free encoding (colorblind / light-bg / NO_COLOR safe).
11
- // Every hue (fg / bg color) is gated on `caps.color`; structural SGR (bold/dim/
12
- // reverse) is allowed always. See detectColorCaps() for the gate, and the
13
- // canvas-browse color spec for the rationale + palette.
14
- import { STATUS_GLYPH, STATUS_COLOR, isFrozenRow, resolveNodeVisual, faultSummary } from '../status-glyph.js';
15
- import { TABS, promptText, previewSnippet } from './model.js';
16
- import { matchIndices } from '../../tui/fuzzy.js';
17
- // Span/color primitives live in core/tui/draw.ts (one copy, shared with the
18
- // `crtr view` host). Re-export the color caps so browse's importers + tests keep
19
- // resolving them from this module.
20
- import { clip, assemble, detectColorCaps } from '../../tui/draw.js';
21
- import { renderMarkdownSpans } from '../../tui/markdown.js';
22
- export { detectColorCaps };
23
- // Fixed chrome heights, shared with app.ts so its viewport math never drifts
24
- // from what renderFrame actually draws.
25
- // header = title + tab bar + status line + separator (+ search input when searching)
26
- // preview = separator + meta line + PREVIEW_BODY lines of node briefing
27
- // The body budget is FIXED and divided between four blocks at paint time (see
28
- // previewPanel): the two optional blocks (recap, report) take two lines each when
29
- // the node has them, and whatever is left over is split between the two blocks that
30
- // always render (the ask and the reply). A node with neither therefore shows twice
31
- // as much literal conversation instead of half a panel of blanks.
32
- export const RECAP_LINES = 2;
33
- export const REPORT_LINES = 2;
34
- export const PREVIEW_BODY = 8;
35
- export const PREVIEW_HEIGHT = PREVIEW_BODY + 2;
36
- // ── Preview placement ─────────────────────────────────────────────────────────
37
- // A wide terminal gets the preview as a full-height RIGHT-HAND COLUMN: the row
38
- // table drops its flush-right metadata cluster (those per-row facts are noise when
39
- // you only care about the hovered node — they come back as a facts block inside the
40
- // panel) and the reclaimed columns become the panel. A narrow terminal cannot spare
41
- // the columns, so it keeps the bottom panel. The choice is width alone, so there is
42
- // one code path per layout and never two hand-maintained copies of the content.
43
- const SIDE_MIN_COLS = 100; // below this the side column would starve the name column
44
- const SIDE_PANEL_MIN = 46;
45
- const SIDE_PANEL_MAX = 110;
46
- const SIDE_PANEL_RATIO = 0.55;
47
- const SIDE_ROWS_MIN = 40; // the row table never shrinks below this
48
- const SIDE_GUTTER = ' │ '; // rows │ panel — the dim rule that separates them
49
- export function previewLayout(cols, previewOn) {
50
- const width = Math.max(20, cols) - 1; // last column is reserved for \x1b[K
51
- if (!previewOn)
52
- return { mode: 'none', panelW: 0, rowsW: width };
53
- if (cols < SIDE_MIN_COLS)
54
- return { mode: 'bottom', panelW: 0, rowsW: width };
55
- const gutter = [...SIDE_GUTTER].length;
56
- let panelW = Math.min(SIDE_PANEL_MAX, Math.max(SIDE_PANEL_MIN, Math.round(width * SIDE_PANEL_RATIO)));
57
- if (width - panelW - gutter < SIDE_ROWS_MIN)
58
- panelW = width - gutter - SIDE_ROWS_MIN;
59
- if (panelW < SIDE_PANEL_MIN)
60
- return { mode: 'bottom', panelW: 0, rowsW: width };
61
- return { mode: 'side', panelW, rowsW: width - panelW - gutter };
62
- }
63
- // header = title + tab bar + status line + column header + separator (+ input line)
64
- // `inputLine` is true whenever a text-input mode is open (search / rename / message)
65
- // — each adds one prompt row above the column header.
66
- export function headerHeight(inputLine) {
67
- return 5 + (inputLine ? 1 : 0);
68
- }
69
- // ── Row table layout ──────────────────────────────────────────────────────────
70
- // A row is three zones: a fixed-width STATUS rail (glyph + word) on the left, the
71
- // flexible tree-indented NAME in the middle, and a flush-right METADATA cluster
72
- // (kind/mode · ctx · age · project) whose fixed-width segments align into clean
73
- // vertical columns down the right edge. Wide terminals widen the name; narrow ones
74
- // clip the name (and drop the cluster) first. The status WORD — not a lone glyph —
75
- // is the legible, NO_COLOR-safe state signal.
76
- const STATUS_W = 10; // glyph + ' ' + longest word ('active'/'cancel') + trailing gap
77
- const KM_W = 22; // kind/mode column
78
- const CTX_W = 6; // ctx tokens column
79
- const AGE_W = 5; // age column
80
- const PROJ_W = 16; // project (~basename) column, only across All dirs
81
- const COL_GAP = ' ';
82
- // ── ANSI ────────────────────────────────────────────────────────────────────
83
- const ESC = '\x1b[';
84
- const RESET = `${ESC}0m`;
85
- const REVERSE = `${ESC}7m`;
86
- const DIM = `${ESC}2m`;
87
- const BOLD = `${ESC}1m`;
88
- const CURSOR_BG = `${ESC}48;5;236m`; // subtle dark-gray cursor-row bg (256-color)
89
- // Basic-16 ANSI fg codes used by the palette.
90
- const FG_YELLOW = '33';
91
- const FG_RED = '31';
92
- const FG_CYAN = '36';
93
- const FG_GRAY = '90'; // bright-black
94
- const FG_BRIGHT_YELLOW = '93';
95
- const FG_BRIGHT_CYAN = '96'; // query-match highlight (ties to the cyan search accent)
96
- const FG_MAGENTA = '35'; // pin star (distinct from the yellow ⚑ asks flag)
97
- function fmtCtx(tokens) {
98
- if (tokens <= 0)
99
- return '0k';
100
- return `${Math.floor(tokens / 1000)}k`;
101
- }
102
- /** Tiered ctx-budget hue: dim under 50k, yellow 50–100k, red ≥100k. `undefined`
103
- * → dim (structural), so low budgets recede. */
104
- function ctxColorCode(tokens) {
105
- if (tokens >= 100_000)
106
- return FG_RED;
107
- if (tokens >= 50_000)
108
- return FG_YELLOW;
109
- return undefined;
110
- }
111
- /** Compact relative age, e.g. `45s` `12m` `3h` `5d` `2w` `4mo`. Empty on a bad
112
- * timestamp. Drives the per-row recency cue + the preview meta line. */
113
- function relAge(created, now) {
114
- const t = Date.parse(created);
115
- if (Number.isNaN(t))
116
- return '';
117
- const s = Math.max(0, Math.floor((now - t) / 1000));
118
- if (s < 60)
119
- return `${s}s`;
120
- const m = Math.floor(s / 60);
121
- if (m < 60)
122
- return `${m}m`;
123
- const h = Math.floor(m / 60);
124
- if (h < 24)
125
- return `${h}h`;
126
- const d = Math.floor(h / 24);
127
- if (d < 7)
128
- return `${d}d`;
129
- const w = Math.floor(d / 7);
130
- if (w < 5)
131
- return `${w}w`;
132
- return `${Math.floor(d / 30)}mo`;
133
- }
134
- /** Last path segment of a cwd — the project name shown as the All-dirs cue. */
135
- function baseDir(cwd) {
136
- const parts = cwd.replace(/\/+$/, '').split('/');
137
- return parts[parts.length - 1] || cwd;
138
- }
139
- // ── Styled spans ──────────────────────────────────────────────────────────────
140
- //
141
- // A row is built from styled spans, then assembled to a width-clipped line. This
142
- // lets each cell carry its own hue (status glyph, ctx tier, asks, match highlight)
143
- // while clipping by VISIBLE width — ANSI bytes don't count toward the column
144
- // budget. `fg` is hue (gated on `color`); `bold`/`dim` are structural (always).
145
- // Span / styleSpan / assemble now live in core/tui/draw.ts (imported above).
146
- /** Status tallies across the whole canvas, for the right-aligned header. Memoized
147
- * per tree — the snapshot is immutable for a browse session, so counting is done
148
- * once, not O(N) on every keystroke (the "massive canvas" target). */
149
- const summaryCache = new WeakMap();
150
- function statusCounts(tree) {
151
- const cached = summaryCache.get(tree);
152
- if (cached !== undefined)
153
- return cached;
154
- const counts = { active: 0, idle: 0, done: 0, dead: 0, canceled: 0 };
155
- for (const node of tree.nodes.values())
156
- counts[node.row.status]++;
157
- const parts = [];
158
- for (const s of ['active', 'idle', 'done', 'dead', 'canceled']) {
159
- if (counts[s] > 0)
160
- parts.push({ status: s, count: counts[s] });
161
- }
162
- summaryCache.set(tree, parts);
163
- return parts;
164
- }
165
- function tabBar(active, color) {
166
- return TABS.map((t) => {
167
- if (t === active) {
168
- // Keep the [ ] brackets in BOTH paths so the active tab reads without color.
169
- return color ? `${BOLD}${ESC}${FG_CYAN}m[ ${t} ]${RESET}` : `${REVERSE}[ ${t} ]${RESET}`;
170
- }
171
- return color ? `${DIM} ${t} ${RESET}` : ` ${t} `;
172
- }).join('');
173
- }
174
- const EMPTY_HI = new Set();
175
- /** Name → spans, splitting out the query-matched chars (bold + bright-cyan) so
176
- * matches are scannable. Non-matched chars carry the row's name style (dim for
177
- * terminal status, bold on the cursor row). */
178
- function nameSpans(name, query, style) {
179
- const hi = query === '' ? EMPTY_HI : matchIndices(query, name);
180
- if (hi.size === 0)
181
- return [{ text: name, style: { dim: style.dim, bold: style.bold } }];
182
- const out = [];
183
- let buf = '';
184
- let bufHi = false;
185
- const flush = () => {
186
- if (buf === '')
187
- return;
188
- if (bufHi)
189
- out.push({ text: buf, style: { fg: FG_BRIGHT_CYAN, bold: true } });
190
- else
191
- out.push({ text: buf, style: { dim: style.dim, bold: style.bold } });
192
- buf = '';
193
- };
194
- for (let i = 0; i < name.length; i++) {
195
- const h = hi.has(i);
196
- if (h !== bufHi) {
197
- flush();
198
- bufHi = h;
199
- }
200
- buf += name[i];
201
- }
202
- flush();
203
- return out;
204
- }
205
- /** Visible (cell) width of a span group — ANSI-free, surrogate-safe. */
206
- function spansWidth(spans) {
207
- let n = 0;
208
- for (const s of spans)
209
- n += [...s.text].length;
210
- return n;
211
- }
212
- /** The status rail: a status WORD next to its glyph, both in the status hue, padded
213
- * to STATUS_W so the rail forms a clean left column. `live` (bright green) when the
214
- * node is genuinely mid-turn; otherwise the lifecycle word. The word is what makes
215
- * state legible at a glance and survives NO_COLOR (the glyph is the second cue). */
216
- function statusRail(r) {
217
- const v = resolveNodeVisual(r.status, {
218
- streaming: r.streaming === true,
219
- frozen: isFrozenRow(r),
220
- hanging: r.hanging ?? null,
221
- });
222
- // Plain status keeps browse's own status WORD; overlays (hanging/⟳)
223
- // carry their own word from resolveNodeVisual. A hanging kind label can exceed
224
- // STATUS_W — acceptable: the rare, attention-demanding row gets a slightly
225
- // wider rail (Math.max(1,…) keeps a gap), which draws the eye.
226
- const word = v.word ?? ({ active: 'active', idle: 'idle', done: 'done', dead: 'dead', canceled: 'cancel' }[r.status] ?? r.status);
227
- const fg = v.color;
228
- const text = `${v.glyph} ${word}`;
229
- const pad = Math.max(1, STATUS_W - [...text].length);
230
- return [
231
- { text, style: { fg, bold: v.bold === true } },
232
- { text: ' '.repeat(pad) },
233
- ];
234
- }
235
- /** The flush-right metadata cluster as fixed-width segments, so kind/mode · ctx ·
236
- * age · project align into vertical columns down the right edge. `showCwd` adds the
237
- * project column (only meaningful across All dirs). */
238
- function metaCluster(r, now, showCwd) {
239
- const ctxFg = ctxColorCode(r.ctx_tokens);
240
- const out = [
241
- { text: clipPad(`${r.kind}/${r.mode}`, KM_W), style: { fg: FG_GRAY } },
242
- { text: COL_GAP },
243
- { text: fmtCtx(r.ctx_tokens).padStart(CTX_W), style: { fg: ctxFg, dim: ctxFg === undefined } },
244
- { text: COL_GAP },
245
- { text: relAge(r.created, now).padStart(AGE_W), style: { dim: true } },
246
- ];
247
- if (showCwd) {
248
- out.push({ text: COL_GAP }, { text: clipPad(`~${baseDir(r.cwd)}`, PROJ_W), style: { fg: FG_GRAY } });
249
- }
250
- return out;
251
- }
252
- /** Left-clip-pad: clip `s` to `w` cells then pad-end with spaces to exactly `w`. */
253
- function clipPad(s, w) {
254
- return clip(s, w).padEnd(w);
255
- }
256
- /** Compose a row from a flexible LEFT zone and a fixed flush-right RIGHT cluster:
257
- * pad fills the gap so RIGHT hugs the edge; when the terminal is too narrow the
258
- * cluster is dropped rather than colliding with the name. The caller has already
259
- * clipped the name to fit. */
260
- function assembleRow(left, right, width, color, lineBase, fill) {
261
- const leftW = spansWidth(left);
262
- const rightW = spansWidth(right);
263
- if (right.length === 0 || leftW + rightW + 1 > width) {
264
- return assemble(left, width, color, lineBase, fill);
265
- }
266
- const pad = width - leftW - rightW;
267
- return assemble([...left, { text: ' '.repeat(pad) }, ...right], width, color, lineBase, fill);
268
- }
269
- /** One table row: `<status rail> <indent><collapse> <name> <flags>` ........ `<meta>`.
270
- * `showCwd` adds the project column (All-dirs view); `now` drives the age. */
271
- function rowLine(row, tree, width, isCursor, query, caps, showCwd, now, isPinned,
272
- /** false in side-preview mode: the metadata cluster is replaced by the panel's
273
- * facts block, so the name gets the whole row. */
274
- showMeta = true,
275
- /** true in side-preview mode: pad every row to exactly `width` so the vertical
276
- * rule and the panel land in the same columns on every line. */
277
- padToWidth = false) {
278
- const node = tree.nodes.get(row.id);
279
- if (node === undefined)
280
- return '';
281
- const r = node.row;
282
- const indent = ' '.repeat(row.depth);
283
- const collapse = !row.hasChildren ? ' ' : row.collapsed ? '▸' : '▾';
284
- const terminal = r.status === 'done' || r.status === 'dead' || r.status === 'canceled';
285
- // Left gutter (fixed slot): an eye when a viewer is ATTACHED — a scannable rail
286
- // down the left edge of "what's on a screen right now". Blank otherwise.
287
- const gutter = r.viewed === true
288
- ? { text: '\uf06e ', style: { fg: FG_BRIGHT_CYAN, bold: true } }
289
- : { text: ' ' };
290
- // Inline attention flag that travels with the name (fault summary lives in the rail,
291
- // attached lives in the gutter).
292
- const flags = [];
293
- if (r.asks > 0)
294
- flags.push({ text: ` ⚑${r.asks}`, style: { fg: FG_BRIGHT_YELLOW, bold: true } }); // pending asks
295
- // Hanging: the fault summary travels with the name (the ⚠ + kind
296
- // label live in the rail). Dim yellow so it reads as secondary detail.
297
- if (r.hanging != null)
298
- flags.push({ text: ` · ${faultSummary(r.hanging, now)}`, style: { fg: FG_YELLOW, dim: true } });
299
- // Pin marker travels just before the name so a starred node is scannable in any
300
- // tab/sort. Magenta keeps it distinct from the yellow ⚑ asks flag.
301
- const pinMark = isPinned ? [{ text: '★ ', style: { fg: FG_MAGENTA, bold: true } }] : [];
302
- const status = statusRail(r);
303
- const right = showMeta ? metaCluster(r, now, showCwd) : [];
304
- const treeLead = `${indent}${collapse} `;
305
- // Clip the NAME (only) so gutter + status + tree + pin + name + flags + meta all
306
- // fit; the cluster is dropped first (assembleRow) when even a 4-col name won't fit.
307
- const fixed = spansWidth([gutter]) + spansWidth(status) + [...treeLead].length + spansWidth(pinMark) + spansWidth(flags);
308
- const rightW = spansWidth(right);
309
- const nameMax = Math.max(4, width - fixed - rightW - 1);
310
- const nameStyle = { dim: !isCursor && terminal, bold: isCursor }; // dim terminal names; bold the cursor row
311
- const left = [
312
- gutter,
313
- ...status,
314
- { text: treeLead, style: { dim: true } },
315
- ...pinMark,
316
- ...nameSpans(clip(r.name, nameMax), query, nameStyle),
317
- ...flags,
318
- ];
319
- // Row base: cursor → subtle bg (256) or reverse fallback (also !color); non-matched
320
- // ancestor → whole-row dim for tree context.
321
- let lineBase = '';
322
- let fill = padToWidth;
323
- if (isCursor) {
324
- lineBase = caps.color256 ? CURSOR_BG : REVERSE;
325
- fill = true;
326
- }
327
- else if (!row.matched) {
328
- lineBase = DIM;
329
- }
330
- return assembleRow(left, right, width, caps.color, lineBase, fill);
331
- }
332
- /** The column-header row — dim labels aligned to the same zones the rows use, so
333
- * the metadata columns read as a table. */
334
- function columnHeaderLine(width, showCwd, caps, showMeta = true, padToWidth = false) {
335
- const left = [
336
- { text: ' ' }, // viewer gutter (no label)
337
- { text: 'STATUS'.padEnd(STATUS_W), style: { dim: true, bold: true } },
338
- { text: 'NAME', style: { dim: true, bold: true } },
339
- ];
340
- if (!showMeta)
341
- return assemble(left, width, caps.color, '', padToWidth);
342
- const right = [
343
- { text: 'KIND/MODE'.padEnd(KM_W), style: { dim: true, bold: true } },
344
- { text: COL_GAP },
345
- { text: 'CTX'.padStart(CTX_W), style: { dim: true, bold: true } },
346
- { text: COL_GAP },
347
- { text: 'AGE'.padStart(AGE_W), style: { dim: true, bold: true } },
348
- ];
349
- if (showCwd)
350
- right.push({ text: COL_GAP }, { text: 'PROJECT'.padEnd(PROJ_W), style: { dim: true, bold: true } });
351
- return assembleRow(left, right, width, caps.color, '', false);
352
- }
353
- /** The status line (always present): active profile/cwd scopes · sort mode ·
354
- * committed filter. The committed-filter indicator lives here now (not its own
355
- * line) so a filtered view always advertises its query without consuming a header row. */
356
- function statusLine(state) {
357
- const dim = (s) => `${DIM}${s}${RESET}`;
358
- const profile = state.profileScope === undefined ? 'all profiles' : 'current';
359
- const scope = state.cwdScope === null ? 'all dirs' : baseDir(state.cwdScope);
360
- const segs = [
361
- `${dim('profile')} ${profile}`,
362
- `${dim('scope')} ${scope}`,
363
- `${dim('sort')} ${state.sort}`,
364
- `${dim('lifecycle')} ${state.residentsOnly ? 'residents' : 'all'}`,
365
- ];
366
- if (!state.search && state.query !== '')
367
- segs.push(`${dim('filter')} ${state.query}`);
368
- return segs.join(dim(' · '));
369
- }
370
- /** One snippet line → a rendered string with the query-matched columns in bold
371
- * bright-cyan (mirrors the row name highlight). Unmatched text stays default. */
372
- function snippetLine(ln, width, caps, base) {
373
- if (ln.hi.size === 0)
374
- return assemble([{ text: ln.text, style: base }], width, caps.color, '', false);
375
- const spans = [];
376
- let buf = '';
377
- let bufHi = false;
378
- const flush = () => {
379
- if (buf === '')
380
- return;
381
- spans.push(bufHi ? { text: buf, style: { fg: FG_BRIGHT_CYAN, bold: true } } : { text: buf, style: base });
382
- buf = '';
383
- };
384
- for (let i = 0; i < ln.text.length; i++) {
385
- const h = ln.hi.has(i);
386
- if (h !== bufHi) {
387
- flush();
388
- bufHi = h;
389
- }
390
- buf += ln.text[i];
391
- }
392
- flush();
393
- return assemble(spans, width, caps.color, '', false);
394
- }
395
- /** How the fixed PREVIEW_BODY budget is divided for one row: the optional blocks
396
- * take their two lines only when the node actually has them, and the remainder is
397
- * split between the ask and the reply (ask keeps the odd line). */
398
- export function previewAllocation(hasRecap, hasReport) {
399
- const recap = hasRecap ? RECAP_LINES : 0;
400
- const report = hasReport ? REPORT_LINES : 0;
401
- const free = Math.max(2, PREVIEW_BODY - recap - report);
402
- const ask = Math.ceil(free / 2);
403
- return { recap, ask, reply: free - ask, report };
404
- }
405
- /** Render one marked block (`marker` on the first line, aligned continuation after)
406
- * into exactly `lines` rows, or the `empty` placeholder when there is no text. */
407
- function markedBlock(marker, text, empty, lines, width, caps, query) {
408
- if (lines <= 0)
409
- return [];
410
- const out = [];
411
- const mark = caps.color ? `${DIM}${marker}${RESET}` : marker;
412
- const inner = Math.max(1, width - 2);
413
- // No query → render the text as markdown (see blockLines for why a live query
414
- // keeps the raw windowed path instead). No spacing: this panel is cramped.
415
- if (query === '') {
416
- const md = renderMarkdownSpans(text, inner, lines, false);
417
- if (md.length === 0)
418
- out.push(`${mark}${DIM}${clip(empty, inner)}${RESET}`);
419
- else
420
- for (const spans of md)
421
- out.push(`${out.length === 0 ? mark : ' '}${assemble(spans, inner, caps.color, '', false)}`);
422
- while (out.length < lines)
423
- out.push('');
424
- return out;
425
- }
426
- const snippet = previewSnippet(query, text, inner, lines);
427
- if (snippet.length === 0) {
428
- out.push(`${mark}${DIM}${clip(empty, inner)}${RESET}`);
429
- }
430
- else {
431
- for (const ln of snippet)
432
- out.push(`${out.length === 0 ? mark : ' '}${snippetLine(ln, inner, caps)}`);
433
- }
434
- while (out.length < lines)
435
- out.push('');
436
- return out;
437
- }
438
- /** One `Goal`/`State` briefing line: a dim fixed-width label then the text. */
439
- function recapLine(label, text, width, caps) {
440
- const lbl = `${label.padEnd(6)}`;
441
- const body = clip(text, Math.max(1, width - lbl.length));
442
- return caps.color ? `${DIM}${lbl}${RESET}${BOLD}${body}${RESET}` : `${lbl}${body}`;
443
- }
444
- /** The bottom preview panel — exactly PREVIEW_HEIGHT lines, ordered by how fast
445
- * each answers "which node was this, and can I pick it back up?":
446
- *
447
- * separator
448
- * meta status · kind/mode · project · age · ctx · asks · fault/viewing
449
- * Goal/State the node's last persisted recap briefing — the one-glance answer
450
- * ❯ ask the spawn prompt in the user's own words (the recognition anchor),
451
- * or, under a live query, the WINDOWED matching prompt from anywhere
452
- * in the conversation with the match highlighted
453
- * ↩ reply the node's last assistant message — where it actually left off
454
- * ▣ report the newest thing it pushed (age · kind · headline), because a
455
- * resident's reports are written to be read, unlike its live tail
456
- *
457
- * The optional blocks yield their lines to the literal ones when absent, so the
458
- * panel is never padded with blanks. Always full height so viewport math holds. */
459
- function previewPanel(r, width, caps, now, query) {
460
- const out = [`${DIM}${'─'.repeat(width)}${RESET}`];
461
- if (r === undefined) {
462
- while (out.length < PREVIEW_HEIGHT)
463
- out.push('');
464
- return out;
465
- }
466
- const v = resolveNodeVisual(r.status, {
467
- streaming: r.streaming === true,
468
- frozen: isFrozenRow(r),
469
- hanging: r.hanging ?? null,
470
- });
471
- const glyph = caps.color
472
- ? `${ESC}${v.color}m${v.glyph}${RESET}`
473
- : v.glyph;
474
- const metaPieces = [`${r.status} ${r.kind}/${r.mode}`, baseDir(r.cwd), relAge(r.created, now), `ctx ${fmtCtx(r.ctx_tokens)}`];
475
- if (r.asks > 0)
476
- metaPieces.push(`⚑${r.asks}`);
477
- if (r.hanging != null)
478
- metaPieces.push(faultSummary(r.hanging, now));
479
- if (r.streaming === true)
480
- metaPieces.push('⟳');
481
- if (r.viewed === true)
482
- metaPieces.push('\uf06e viewing');
483
- const metaText = clip(metaPieces.filter((p) => p !== '').join(' · '), Math.max(0, width - 2));
484
- out.push(caps.color ? `${glyph} ${DIM}${metaText}${RESET}` : `${glyph} ${metaText}`);
485
- const alloc = previewAllocation(r.recap !== undefined, r.report !== undefined);
486
- // Goal / State — the generated briefing, the fastest "what is this and where is
487
- // it" in the panel. Absent for a node that never idled long enough to make one.
488
- if (r.recap !== undefined) {
489
- out.push(recapLine('Goal', r.recap.goal === '' ? '—' : r.recap.goal, width, caps));
490
- out.push(recapLine('State', r.recap.state === '' ? '—' : r.recap.state, width, caps));
491
- }
492
- // The ask, verbatim. Under a live query this becomes the windowed match from the
493
- // WHOLE conversation (the one thing a search result must show), so it keeps the
494
- // query highlight; with no query it is the spawn prompt from the start.
495
- const askText = query !== '' ? promptText(r) : (r.goal ?? '');
496
- out.push(...markedBlock('❯ ', askText, '(no spawn prompt)', alloc.ask, width, caps, query));
497
- // Where it left off.
498
- out.push(...markedBlock('↩ ', r.lastAssistant ?? '', '(no reply yet)', alloc.reply, width, caps, ''));
499
- // What it last delivered. The stamp + kind lead the line because a report's value
500
- // here is "how recently did this node report, and was that its final?".
501
- if (r.report !== undefined) {
502
- const age = relAge(r.report.ts, now);
503
- const stamp = `${age === '' ? '' : `${age} `}${r.report.kind}`;
504
- const headline = r.report.heading === '' ? r.report.body : r.report.heading;
505
- const mark = caps.color ? `${DIM}▣ ${RESET}` : '▣ ';
506
- const inner = Math.max(1, width - 2);
507
- const stampText = caps.color ? `${ESC}${FG_CYAN}m${stamp}${RESET}${DIM} · ${RESET}` : `${stamp} · `;
508
- out.push(`${mark}${stampText}${clip(headline, Math.max(1, inner - stamp.length - 3))}`);
509
- for (let i = 1; i < alloc.report; i++) {
510
- const detail = r.report.heading === '' ? '' : r.report.body;
511
- const ln = previewSnippet('', detail, inner, alloc.report - 1)[i - 1];
512
- out.push(ln === undefined ? '' : ` ${DIM}${clip(ln.text, inner)}${RESET}`);
513
- }
514
- }
515
- return out;
516
- }
517
- // ── The side preview panel ────────────────────────────────────────────────────
518
- //
519
- // Same four zones as the bottom panel (recap · ask · reply · report) with room to
520
- // breathe, drawn as designed chrome instead of a wall of prose:
521
- //
522
- // <title row, drawn on the column-header line> ★ node name 8-char id
523
- // ● active ⚑2 asks viewing ← state, in the status hue
524
- // kind general/base ctx 42k ← facts block: dim right-aligned
525
- // proj ~northlight age 3h labels, values in their own hues
526
- // ── GOAL ───────────────────────────── ← hairline + small-caps label
527
- // ▌ what this conversation is for ← accent bar: the hero quote
528
- // ── ASK ──────────────────────────────
529
- // ❯ the spawn prompt, hanging-indented
530
- //
531
- // Section bodies are allocated from the panel's real height: everyone asks for a
532
- // natural size, the largest gives a line back until it fits, and only then does the
533
- // least-valuable section drop out entirely (report → state → goal → reply; the ask
534
- // is the recognition anchor and never drops).
535
- /** A dim hairline with a small-caps section label — `── GOAL ────────`. The optional
536
- * suffix rides after the label in its own hue (the report's age · kind stamp). */
537
- function sectionRule(label, width, caps, suffix) {
538
- const suf = suffix === undefined ? '' : `${suffix.text} `;
539
- const tail = Math.max(0, width - 4 - label.length - suf.length);
540
- const sufStyled = suffix === undefined
541
- ? ''
542
- : caps.color ? `${ESC}${suffix.fg}m${suffix.text}${RESET}${DIM} ` : `${suffix.text} `;
543
- return `${DIM}── ${BOLD}${label}${RESET}${DIM} ${sufStyled}${'─'.repeat(tail)}${RESET}`;
544
- }
545
- /** A marked body block with a hanging indent: `marker` leads the first line, `cont`
546
- * every wrapped line after it (`▌ ` keeps the accent bar running down a quote).
547
- * Returns the lines it actually filled — never padded, so the panel stacks tight.
548
- * `empty` renders a dim placeholder for a block that must show even when absent. */
549
- function blockLines(marker, cont, markerStyle, text, empty, maxLines, width, caps, query, bodyStyle) {
550
- if (maxLines <= 0)
551
- return [];
552
- const indent = [...marker].length;
553
- const inner = Math.max(1, width - indent);
554
- const mk = (s, st) => assemble([{ text: s, style: st }], indent, caps.color, '', true);
555
- // The ONE case that stays raw: under a live query the ask shows the windowed
556
- // match with the matched columns highlighted, and stripping `**` would shift
557
- // every later column out from under the highlight. Everything else renders
558
- // markdown — headings, lists, and emphasis are how these messages were written.
559
- if (query === '') {
560
- const md = renderMarkdownSpans(text, inner, maxLines, true, bodyStyle);
561
- if (md.length === 0) {
562
- if (empty === undefined)
563
- return [];
564
- return [`${mk(marker, markerStyle)}${DIM}${clip(empty, inner)}${RESET}`];
565
- }
566
- return md.map((spans, i) => `${mk(i === 0 ? marker : cont, markerStyle)}${assemble(spans, inner, caps.color, '', false)}`);
567
- }
568
- const snippet = previewSnippet(query, text, inner, maxLines);
569
- if (snippet.length === 0) {
570
- if (empty === undefined)
571
- return [];
572
- return [`${mk(marker, markerStyle)}${DIM}${clip(empty, inner)}${RESET}`];
573
- }
574
- return snippet.map((ln, i) => `${mk(i === 0 ? marker : cont, markerStyle)}${snippetLine(ln, inner, caps, bodyStyle)}`);
575
- }
576
- // ── The chat transcript ───────────────────────────────────────────────
577
- //
578
- // The panel's centrepiece: the node's conversation painted the way the attach viewer
579
- // paints it — a coloured left bar per turn, a small-caps role label, and the message
580
- // body with its markdown honoured. It serves two jobs from one renderer:
581
- //
582
- // no query — the RECENT tail, newest turn last, so the panel reads as "where did
583
- // this conversation get to".
584
- // a query — only the turns that CONTAIN the query, oldest match first, with every
585
- // occurrence highlighted and the skipped turns counted in a dim elision
586
- // marker. Every visible line is then evidence for the search.
587
- /** Rendered lines a single turn may occupy before it is windowed. Bounded by the
588
- * per-message cap in readTranscript, so this is a ceiling, not a budget. */
589
- const TURN_RENDER_MAX = 400;
590
- /** Rendered lines kept above the first match when a matched turn must be windowed. */
591
- const TURN_MATCH_LEAD = 1;
592
- /** Lines a single turn may take when several turns share the panel. */
593
- const TURN_SOFT_CAP = 14;
594
- /** The matched-run style. `reverse` is structural SGR, so a search match stays
595
- * visible with hue disabled — which the fg-only row highlight cannot manage. */
596
- const MATCH_STYLE = { fg: FG_BRIGHT_CYAN, bold: true, reverse: true };
597
- function spansText(spans) {
598
- let out = '';
599
- for (const s of spans)
600
- out += s.text;
601
- return out;
602
- }
603
- /** Re-style every case-insensitive occurrence of `query` inside already-rendered
604
- * spans, splitting runs at the match edges. Working on the RENDERED text is what
605
- * lets a transcript keep its markdown and still highlight: the markup is already
606
- * gone, so no column can drift out from under a highlight. */
607
- export function highlightSpans(spans, query) {
608
- if (query === '')
609
- return { spans, hits: 0 };
610
- const text = spansText(spans);
611
- const lower = text.toLowerCase();
612
- const q = query.toLowerCase();
613
- if (lower.indexOf(q) < 0)
614
- return { spans, hits: 0 };
615
- const hi = new Uint8Array(text.length);
616
- let hits = 0;
617
- for (let i = lower.indexOf(q); i >= 0; i = lower.indexOf(q, i + q.length)) {
618
- hits++;
619
- for (let j = i; j < i + q.length; j++)
620
- hi[j] = 1;
621
- }
622
- const out = [];
623
- let col = 0;
624
- for (const s of spans) {
625
- let buf = '';
626
- let bufHi = hi[col] === 1;
627
- for (let k = 0; k < s.text.length; k++) {
628
- const h = hi[col] === 1;
629
- if (h !== bufHi) {
630
- if (buf !== '')
631
- out.push({ text: buf, style: bufHi ? MATCH_STYLE : s.style });
632
- buf = '';
633
- bufHi = h;
634
- }
635
- buf += s.text[k];
636
- col++;
637
- }
638
- if (buf !== '')
639
- out.push({ text: buf, style: bufHi ? MATCH_STYLE : s.style });
640
- }
641
- return { spans: out, hits };
642
- }
643
- const TURN_BAR = '▌ ';
644
- /** Paint one turn: `▌ YOU` / `▌ AGENT` then the body, every line carrying the bar so
645
- * a turn stays one contiguous block. The user's bar is the cyan accent and the
646
- * agent's is dim gray — the same weight distinction the row table already uses
647
- * between what you said and what the runtime produced. */
648
- function turnBlock(turn, query, maxLines, width, caps) {
649
- if (maxLines < 2)
650
- return { lines: [], hits: 0, truncated: true };
651
- const user = turn.role === 'user';
652
- const barStyle = user ? { fg: FG_BRIGHT_CYAN, bold: true } : { fg: FG_GRAY };
653
- const inner = Math.max(1, width - TURN_BAR.length);
654
- const bar = () => assemble([{ text: TURN_BAR, style: barStyle }], TURN_BAR.length, caps.color, '', true);
655
- const out = [
656
- assemble([{ text: TURN_BAR, style: barStyle }, { text: user ? 'YOU' : 'AGENT', style: { ...barStyle, bold: true } }], width, caps.color, '', false),
657
- ];
658
- const body = renderMarkdownSpans(turn.text, inner, TURN_RENDER_MAX, false, user ? {} : { dim: true });
659
- const marked = body.map((spans) => highlightSpans(spans, query));
660
- const hits = marked.reduce((n, m) => n + m.hits, 0);
661
- // Window the body when it outgrows its slice of the panel. Searching, the window
662
- // opens on the first match (that is the only line the search has to prove); idle,
663
- // it opens at the top of the message.
664
- const budget = maxLines - 1;
665
- let start = 0;
666
- if (marked.length > budget && hits > 0) {
667
- start = Math.max(0, marked.findIndex((m) => m.hits > 0) - TURN_MATCH_LEAD);
668
- start = Math.min(start, marked.length - budget);
669
- }
670
- const shown = marked.slice(start, start + budget);
671
- for (const m of shown)
672
- out.push(`${bar()}${assemble(m.spans, inner, caps.color, '', false)}`);
673
- // An honest edge: a windowed body must not read as the whole message. The marker
674
- // costs a body line, so it is only worth drawing when a body line survives it.
675
- const cutHead = start > 0;
676
- const cutTail = start + shown.length < marked.length;
677
- if (cutHead && shown.length > 1)
678
- out[1] = `${bar()}${DIM}⋯${RESET}`;
679
- if (cutTail && shown.length > (cutHead ? 2 : 1))
680
- out[out.length - 1] = `${bar()}${DIM}⋯${RESET}`;
681
- return { lines: out, hits, truncated: cutHead || cutTail };
682
- }
683
- /** The dim `⋯ n turns` marker standing in for turns the search skipped over. */
684
- function elisionLine(n, width, caps) {
685
- return assemble([{ text: ` ⋯ ${n} ${n === 1 ? 'turn' : 'turns'}`, style: { dim: true } }], width, caps.color, '', false);
686
- }
687
- /** Does this turn contain the query as a literal, case-insensitive substring?
688
- * Scattered letters are not a transcript hit — the same rule the row preview uses. */
689
- function turnMatches(turn, query) {
690
- return query !== '' && turn.text.toLowerCase().indexOf(query.toLowerCase()) >= 0;
691
- }
692
- /** How many turns contain the query — the count the section rule advertises. */
693
- export function transcriptHitTurns(turns, query) {
694
- return turns.reduce((n, t) => n + (turnMatches(t, query) ? 1 : 0), 0);
695
- }
696
- /** The transcript body, at most `height` lines. With a query it shows the matching
697
- * turns from the oldest match forward; without one it shows the newest turns,
698
- * bottom-anchored so the latest turn is the last line — the chat reading order. */
699
- function transcriptLines(turns, query, width, height, caps) {
700
- if (height <= 0 || turns.length === 0)
701
- return [];
702
- const hitIdx = query === '' ? [] : turns.map((t, i) => (turnMatches(t, query) ? i : -1)).filter((i) => i >= 0);
703
- // Searching with hits: forward from the oldest match, eliding the gaps.
704
- if (hitIdx.length > 0) {
705
- const out = [];
706
- let prev = -1;
707
- for (const i of hitIdx) {
708
- const lead = out.length === 0 ? 0 : 1; // blank separator between turns
709
- const left = height - out.length - lead;
710
- if (left < 3)
711
- break; // a header over one elision marker proves nothing
712
- const { lines } = turnBlock(turns[i], query, Math.min(left, TURN_SOFT_CAP), width, caps);
713
- if (lines.length === 0)
714
- break;
715
- const gap = prev < 0 ? i : i - prev - 1;
716
- const marker = gap > 0 && out.length + lead + lines.length + 1 <= height;
717
- if (lead > 0)
718
- out.push('');
719
- if (marker)
720
- out.push(elisionLine(gap, width, caps));
721
- out.push(...lines);
722
- prev = i;
723
- }
724
- // Slack goes to the turns that FOLLOW the last match, painted in full, so the
725
- // panel reads on as a conversation instead of stopping dead at the evidence.
726
- let last = prev;
727
- for (let i = prev + 1; i < turns.length; i++) {
728
- const left = height - out.length - 1;
729
- if (left < 3)
730
- break;
731
- const { lines, truncated } = turnBlock(turns[i], query, Math.min(left, TURN_SOFT_CAP), width, caps);
732
- if (lines.length === 0 || truncated)
733
- break;
734
- out.push('', ...lines);
735
- last = i;
736
- }
737
- if (last >= 0 && last < turns.length - 1 && out.length < height) {
738
- out.push(elisionLine(turns.length - 1 - last, width, caps));
739
- }
740
- return out.slice(0, height);
741
- }
742
- // No query (or a query that only matched the node's name/kind/id): the tail.
743
- // Built newest-first so the budget is spent on recent turns, then reversed.
744
- const blocks = [];
745
- let used = 0;
746
- for (let i = turns.length - 1; i >= 0; i--) {
747
- const newest = blocks.length === 0;
748
- const lead = newest ? 0 : 1;
749
- const left = height - used - lead;
750
- if (left < 3)
751
- break;
752
- const { lines, truncated } = turnBlock(turns[i], '', Math.min(left, TURN_SOFT_CAP), width, caps);
753
- if (lines.length === 0)
754
- break;
755
- // Only the newest turn may be shown cut — an older one that no longer fits is
756
- // dropped whole rather than left as a header over an elision marker, which
757
- // reads as a message the panel refused to show.
758
- if (truncated && !newest)
759
- break;
760
- if (lead > 0)
761
- blocks.push(['']);
762
- blocks.push(lines);
763
- used += lines.length + lead;
764
- }
765
- return blocks.reverse().flat().slice(-height);
766
- }
767
- /** What an empty panel body MEANS. `(no conversation yet)` is a claim about the
768
- * node; it is only true once the session has actually been read. Until then the
769
- * same blank body means the read is still in flight, and printing the claim made a
770
- * node the panel had simply not gotten to yet look like a node that had never
771
- * spoken. */
772
- function emptyBodyNote(r) {
773
- const read = r.transcriptLoaded === true || r.previewLoaded === true;
774
- return read ? `${DIM}(no conversation yet)${RESET}` : `${DIM}(loading…)${RESET}`;
775
- }
776
- /** The turns the panel paints. A node that was never revived has no session, so its
777
- * spawn prompt and last reply stand in — the panel then still reads as a chat
778
- * rather than going blank, and a remote canvas (no local session file) keeps a body. */
779
- function panelTurns(r) {
780
- const t = r.transcript;
781
- if (t !== undefined && t.length > 0)
782
- return t;
783
- const out = [];
784
- if (r.goal !== undefined && r.goal !== '')
785
- out.push({ role: 'user', text: r.goal });
786
- if (r.lastAssistant !== undefined && r.lastAssistant !== '')
787
- out.push({ role: 'assistant', text: r.lastAssistant });
788
- return out;
789
- }
790
- /** Lines the GOAL and STATE briefings each get. They are one-sentence summaries by
791
- * construction, so a small fixed budget leaves the chat everything else. */
792
- const BRIEFING_LINES = 4;
793
- /** The panel's one metadata line. Deliberately ONE line: the row the cursor sits on
794
- * already carries this node's status word, ask flag, fault and viewer cues, so a
795
- * status line and a four-cell facts grid here would spend six of the panel's rows
796
- * repeating what is on screen a few columns to the left. What is left is what the
797
- * row table gave up in side mode — kind/mode, project, age, ctx. */
798
- function panelFactsLine(r, width, now, caps) {
799
- const ctxFg = ctxColorCode(r.ctx_tokens);
800
- const dot = () => ({ text: ' · ', style: { dim: true } });
801
- const spans = [
802
- { text: `${r.kind}/${r.mode}`, style: { fg: FG_GRAY } },
803
- dot(),
804
- { text: `~${baseDir(r.cwd)}`, style: { fg: FG_GRAY } },
805
- dot(),
806
- { text: relAge(r.created, now), style: { dim: true } },
807
- dot(),
808
- { text: `ctx ${fmtCtx(r.ctx_tokens)}`, style: { fg: ctxFg, dim: ctxFg === undefined } },
809
- ];
810
- return assemble(spans, width, caps.color, '', false);
811
- }
812
- /** The panel's title, drawn on the column-header row so the header rule crosses
813
- * beneath it: the pinned star, the node name in bold, its short id flush right. */
814
- function panelTitleLine(r, width, caps, isPinned) {
815
- if (r === undefined)
816
- return assemble([{ text: 'PREVIEW', style: { dim: true, bold: true } }], width, caps.color, '', false);
817
- const left = [];
818
- if (isPinned)
819
- left.push({ text: '★ ', style: { fg: FG_MAGENTA, bold: true } });
820
- const id = r.node_id.slice(0, 8);
821
- left.push({ text: clip(r.name, Math.max(4, width - id.length - 2 - spansWidth(left))), style: { bold: true } });
822
- return assembleRow(left, [{ text: id, style: { dim: true } }], width, caps.color, '', false);
823
- }
824
- /** The side panel's body, at most `height` lines. Three exclusive shapes:
825
- *
826
- * searching — the panel IS a chat transcript: the turns that literally contain
827
- * the query, oldest match first, every occurrence highlighted.
828
- * report — the node's newest pushed report in full (toggled with `V`).
829
- * default — goal on top, the recent conversation in the middle, state pinned to
830
- * the bottom edge. That is the vertical order the live chat surface
831
- * uses, so the preview reads as a small copy of the conversation it
832
- * is previewing instead of a different presentation of the same node.
833
- */
834
- function sidePanelBody(r, width, height, caps, now, query, showReport) {
835
- if (height <= 0)
836
- return [];
837
- if (r === undefined)
838
- return [`${DIM}(no selection)${RESET}`];
839
- // ── searching ── the transcript takes the whole panel. The goal/state briefing is
840
- // a summary, and a summary cannot show you WHERE your term appears.
841
- if (query !== '') {
842
- const turns = panelTurns(r);
843
- const hits = transcriptHitTurns(turns, query);
844
- const out = [sectionRule('TRANSCRIPT', width, caps, hits > 0
845
- ? { text: `${hits} ${hits === 1 ? 'turn' : 'turns'}`, fg: FG_BRIGHT_CYAN }
846
- : { text: 'matched on name', fg: FG_GRAY })];
847
- const body = transcriptLines(turns, query, width, height - 1, caps);
848
- out.push(...(body.length === 0 ? [emptyBodyNote(r)] : body));
849
- return out.slice(0, height);
850
- }
851
- const rep = r.report;
852
- const accentOf = () => {
853
- const v = resolveNodeVisual(r.status, {
854
- streaming: r.streaming === true, frozen: isFrozenRow(r), hanging: r.hanging ?? null,
855
- });
856
- return { fg: v.color };
857
- };
858
- // ── report ── what the node deliberately DELIVERED, at full length. Reports are
859
- // written to be read, so this one gets the panel rather than a two-line teaser.
860
- if (showReport && rep !== undefined) {
861
- const age = relAge(rep.ts, now);
862
- const out = [sectionRule('REPORT', width, caps, { text: `${age === '' ? '' : `${age} · `}${rep.kind}`, fg: FG_CYAN })];
863
- const headline = rep.heading === '' ? rep.body : rep.heading;
864
- out.push(...blockLines('▣ ', ' ', { fg: FG_CYAN, bold: true }, headline, undefined, 3, width, caps, '', { bold: true }));
865
- if (rep.heading !== '' && rep.body !== '') {
866
- out.push('');
867
- out.push(...blockLines(' ', ' ', undefined, rep.body, undefined, height - out.length, width, caps, ''));
868
- }
869
- return out.slice(0, height);
870
- }
871
- // ── default ── goal, chat, state.
872
- const out = [panelFactsLine(r, width, now, caps), ''];
873
- const accent = accentOf();
874
- const briefing = (label, text) => [
875
- sectionRule(label, width, caps),
876
- ...blockLines('▌ ', '▌ ', accent, text, undefined, BRIEFING_LINES, width, caps, '', { bold: true }),
877
- ];
878
- const goal = r.recap?.goal ?? '';
879
- if (goal !== '')
880
- out.push(...briefing('GOAL', goal), '');
881
- // State is measured before the chat is drawn so the chat can claim exactly the
882
- // slack that is left and state still lands on the panel's bottom edge.
883
- const stateText = r.recap?.state ?? '';
884
- const stateBlock = stateText === '' ? [] : [...briefing('STATE', stateText)];
885
- const reserved = stateBlock.length === 0 ? 0 : stateBlock.length + 1;
886
- const chatH = height - out.length - reserved - 1 /* the CHAT rule */;
887
- if (chatH >= 2) {
888
- out.push(sectionRule('CHAT', width, caps));
889
- const body = transcriptLines(panelTurns(r), '', width, chatH, caps);
890
- out.push(...(body.length === 0 ? [emptyBodyNote(r)] : body));
891
- }
892
- if (stateBlock.length > 0) {
893
- while (out.length < height - stateBlock.length)
894
- out.push('');
895
- out.push(...stateBlock);
896
- }
897
- return out.slice(0, height);
898
- }
899
- /** The keybinding help overlay — a full-screen cheatsheet that replaces the body
900
- * while `?` is held open. Grouped by intent so the whole key surface is legible in
901
- * one glance (the footer only ever advertises the common few). */
902
- const HELP_ROWS = [
903
- ['Move', '↑/↓ j/k', 'up / down'],
904
- ['', 'g / G', 'top / bottom'],
905
- ['', '.', 'jump to this node (recenter)'],
906
- ['Tree', '→/← h/l', 'expand / collapse'],
907
- ['', 'space', 'toggle fold'],
908
- ['Tabs', 'Tab / 1-5', 'All · Live · Dormant · Attention · Pinned'],
909
- ['Find', '/', 'fuzzy search (name · kind · id · prompts)'],
910
- ['Pin', 'p', 'star / unstar — floats to top, Pinned tab'],
911
- ['Open', '⏎ o', 'open conversation (closes navigator)'],
912
- ['', 'O', 'open, keep browsing (background)'],
913
- ['Act', 'y', 'copy the node id to the clipboard'],
914
- ['', 'm', 'message the node (no resume)'],
915
- ['', 'R', 'rename the node'],
916
- ['', 'x', 'close-out node + subtree'],
917
- ['', 'K', 'revive now (a hanging node)'],
918
- ['View', 's', 'cycle sort (attention/tree/relevance/recency)'],
919
- ['', 'c', 'toggle cwd scope'],
920
- ['', 'P', 'toggle profile scope'],
921
- ['', 'r', 'toggle residents-only'],
922
- ['', 'v', 'toggle preview (goal, chat, state)'],
923
- ['', 'V', 'in the preview: swap chat for the newest report'],
924
- ['Quit', 'q / Esc', ''],
925
- ];
926
- function renderHelp(size, caps) {
927
- const cols = Math.max(20, size.cols);
928
- const rows = Math.max(8, size.rows);
929
- const width = cols - 1;
930
- const lines = [];
931
- lines.push(`${BOLD}Canvas navigator — keys${RESET}`);
932
- lines.push('');
933
- const dim = (s) => `${DIM}${s}${RESET}`;
934
- for (const [group, keys, desc] of HELP_ROWS) {
935
- const g = group.padEnd(6);
936
- const k = keys.padEnd(12);
937
- const line = ` ${dim(g)}${BOLD}${k}${RESET}${desc === '' ? '' : ` ${dim(desc)}`}`;
938
- lines.push(clip(line, width));
939
- }
940
- lines.push('');
941
- lines.push(dim(' ? or any key to close'));
942
- while (lines.length < rows - 1)
943
- lines.push('');
944
- const body = lines.map((l) => `${l}${ESC}K`).join('\r\n');
945
- return `${ESC}H${body}${ESC}J`;
946
- }
947
- /**
948
- * Render the whole frame. Returns a single string that, written as-is, repaints
949
- * the screen in place. `caps` gates all hue (defaults to a no-color frame so
950
- * existing callers / non-TTY paths stay color-free).
951
- */
952
- export function renderFrame(state, size, caps = { color: false, color256: false }) {
953
- if (state.help === true)
954
- return renderHelp(size, caps);
955
- const cols = Math.max(20, size.cols);
956
- const rows = Math.max(8, size.rows);
957
- const width = cols - 1; // leave the last column for \x1b[K
958
- const now = Date.now();
959
- const inputMode = state.search || state.rename === true || state.message === true;
960
- const lines = [];
961
- // line 1 — title + right-aligned status summary (each glyph in its status hue).
962
- const title = `${BOLD}Canvas${RESET} — ${state.totalNodes} nodes`;
963
- const titlePlainLen = `Canvas — ${state.totalNodes} nodes`.length;
964
- const parts = statusCounts(state.tree);
965
- const summaryPlain = parts.map((p) => `${STATUS_GLYPH[p.status]}${p.count}`).join(' ');
966
- const summaryColored = caps.color
967
- ? parts.map((p) => `${ESC}${STATUS_COLOR[p.status]}m${STATUS_GLYPH[p.status]}${RESET}${DIM}${p.count}${RESET}`).join(' ')
968
- : `${DIM}${summaryPlain}${RESET}`;
969
- const gap = width - titlePlainLen - summaryPlain.length;
970
- lines.push(gap > 1 ? `${title}${' '.repeat(gap)}${summaryColored}` : title);
971
- // line 2 — tab bar.
972
- lines.push(tabBar(state.tab, caps.color));
973
- // line 3 — status line (scope · sort · filter).
974
- lines.push(statusLine(state));
975
- // line 4 — the text-input prompt, only while a search / rename / message is open.
976
- if (inputMode) {
977
- const prefix = state.rename === true ? 'rename ▸' : state.message === true ? 'msg ▸' : '/';
978
- const buf = state.rename === true ? (state.renameBuf ?? '') : state.message === true ? (state.messageBuf ?? '') : state.query;
979
- const p = caps.color ? `${ESC}${FG_CYAN}m${prefix}${RESET}` : prefix;
980
- lines.push(`${p} ${buf}▎`);
981
- }
982
- // Where the preview goes at this width: a full-height right-hand column when
983
- // there is room for one, else the bottom panel. In side mode the rows give up
984
- // their metadata cluster and the panel takes those columns.
985
- const previewOn = state.preview && state.visible.length > 0;
986
- const layout = previewLayout(cols, previewOn);
987
- const side = layout.mode === 'side';
988
- const rowsW = side ? layout.rowsW : width;
989
- const gutter = `${DIM}${SIDE_GUTTER}${RESET}`;
990
- const sel = state.visible[state.cursor];
991
- const selRow = sel !== undefined ? state.tree.nodes.get(sel.id)?.row : undefined;
992
- // column header (table labels, plus the panel title in side mode) + separator.
993
- const showCwd = state.cwdScope === null && !side; // project column only matters across dirs
994
- const colHeader = columnHeaderLine(rowsW, showCwd, caps, !side, side);
995
- lines.push(side
996
- ? `${colHeader}${gutter}${panelTitleLine(selRow, layout.panelW, caps, sel !== undefined && state.pinned.has(sel.id))}`
997
- : colHeader);
998
- lines.push(side
999
- ? `${DIM}${'─'.repeat(rowsW)}─┼─${'─'.repeat(layout.panelW)}${RESET}`
1000
- : `${DIM}${'─'.repeat(width)}${RESET}`);
1001
- // body — windowed visible rows, leaving room for the (optional) bottom panel.
1002
- const head = lines.length; // === headerHeight(state.search)
1003
- const previewH = layout.mode === 'bottom' ? PREVIEW_HEIGHT : 0;
1004
- const viewport = Math.max(1, rows - head - 1 /* footer */ - previewH);
1005
- const start = state.scrollOffset;
1006
- const end = Math.min(state.visible.length, start + viewport);
1007
- // In side mode each body line is `<row><rule><panel line>`, so the rows are padded
1008
- // to an exact width and the panel body is rendered once for the whole column.
1009
- const panel = side ? sidePanelBody(selRow, layout.panelW, viewport, caps, now, state.query, state.showReport === true) : [];
1010
- const compose = (row, i) => (side ? `${row}${gutter}${panel[i] ?? ''}` : row);
1011
- const blankRow = side ? ' '.repeat(rowsW) : '';
1012
- if (state.visible.length === 0) {
1013
- lines.push(`${DIM} (no nodes match this view)${RESET}`);
1014
- for (let i = 1; i < viewport; i++)
1015
- lines.push('');
1016
- }
1017
- else {
1018
- for (let i = start; i < end; i++) {
1019
- const vr = state.visible[i];
1020
- lines.push(compose(rowLine(vr, state.tree, rowsW, i === state.cursor, state.query, caps, showCwd, now, state.pinned.has(vr.id), !side, side), i - start));
1021
- }
1022
- for (let i = end - start; i < viewport; i++)
1023
- lines.push(compose(blankRow, i));
1024
- }
1025
- // bottom preview panel — the narrow-terminal layout.
1026
- if (layout.mode === 'bottom') {
1027
- for (const l of previewPanel(selRow, width, caps, now, state.query))
1028
- lines.push(l);
1029
- }
1030
- // footer — the y/n close-out confirm takes over when pending; else search / nav.
1031
- if (state.pendingClose !== null && state.pendingClose !== undefined) {
1032
- const node = state.tree.nodes.get(state.pendingClose);
1033
- const who = node !== undefined ? node.row.name : state.pendingClose;
1034
- const warn = `⚠ ${who} is ⟳ — close it (and its subtree) anyway? y / n`;
1035
- lines.push(caps.color ? `${BOLD}${ESC}${FG_BRIGHT_YELLOW}m${clip(warn, width)}${RESET}` : `${REVERSE}${clip(warn, width)}${RESET}`);
1036
- }
1037
- else if (state.flash !== null && state.flash !== undefined && state.flash !== '') {
1038
- lines.push(caps.color ? `${BOLD}${clip(state.flash, width)}${RESET}` : `${REVERSE}${clip(state.flash, width)}${RESET}`);
1039
- }
1040
- else {
1041
- // When the cursor row has an active fault, lead the footer with the on-demand kick
1042
- // hint (K shells `node lifecycle revive <id> --now` — immediate revive instead of
1043
- // waiting for the daemon's retry schedule).
1044
- const hangingHint = selRow?.hanging != null ? 'K revive now ' : '';
1045
- const footer = inputMode
1046
- ? '⏎ commit Esc cancel ⌫ delete'
1047
- : state.readOnly === true
1048
- ? '↑↓ move →/← tree / search p pin v preview Tab tabs ? more q quit — read-only remote canvas'
1049
- : `${hangingHint}${selRow?.report !== undefined && side && state.query === '' ? (state.showReport === true ? 'V chat ' : 'V report ') : ''}↑↓ move ⏎ open O bg / search p pin v preview m msg x close ? more q quit`;
1050
- lines.push(`${DIM}${clip(footer, width)}${RESET}`);
1051
- }
1052
- // Assemble: home, each line cleared to EOL, then clear below.
1053
- const body = lines.map((l) => `${l}${ESC}K`).join('\r\n');
1054
- return `${ESC}H${body}${ESC}J`;
1055
- }
1
+ var Nt=Object.defineProperty;var f=(t,n)=>Nt(t,"name",{value:n,configurable:!0});import{STATUS_GLYPH as rt,STATUS_COLOR as It,isFrozenRow as J,resolveNodeVisual as X,faultSummary as lt}from"../status-glyph.js";import{TABS as Pt,promptText as Ht,previewSnippet as q}from"./model.js";import{matchIndices as Gt}from"../../tui/fuzzy.js";import{clip as _,assemble as w,detectColorCaps as Dt}from"../../tui/draw.js";import{renderMarkdownSpans as Q}from"../../tui/markdown.js";const Bt=2,Ft=2,ct=8,it=ct+2,Ut=100,ut=46,jt=110,Yt=.55,at=40,dt=" \u2502 ";function Vt(t,n){const e=Math.max(20,t)-1;if(!n)return{mode:"none",panelW:0,rowsW:e};if(t<Ut)return{mode:"bottom",panelW:0,rowsW:e};const s=[...dt].length;let r=Math.min(jt,Math.max(ut,Math.round(e*Yt)));return e-r-s<at&&(r=e-s-at),r<ut?{mode:"bottom",panelW:0,rowsW:e}:{mode:"side",panelW:r,rowsW:e-r-s}}f(Vt,"previewLayout");function Me(t){return 5+(t?1:0)}f(Me,"headerHeight");const ft=10,$t=22,ht=6,pt=5,gt=16,W=" ",M="\x1B[",$=`${M}0m`,U=`${M}7m`,y=`${M}2m`,C=`${M}1m`,Kt=`${M}48;5;236m`,mt="33",zt="31",H="36",N="90",xt="93",I="96",bt="35";function Z(t){return t<=0?"0k":`${Math.floor(t/1e3)}k`}f(Z,"fmtCtx");function yt(t){if(t>=1e5)return zt;if(t>=5e4)return mt}f(yt,"ctxColorCode");function G(t,n){const e=Date.parse(t);if(Number.isNaN(e))return"";const s=Math.max(0,Math.floor((n-e)/1e3));if(s<60)return`${s}s`;const r=Math.floor(s/60);if(r<60)return`${r}m`;const o=Math.floor(r/60);if(o<24)return`${o}h`;const u=Math.floor(o/24);if(u<7)return`${u}d`;const i=Math.floor(u/7);return i<5?`${i}w`:`${Math.floor(u/30)}mo`}f(G,"relAge");function j(t){const n=t.replace(/\/+$/,"").split("/");return n[n.length-1]||t}f(j,"baseDir");const vt=new WeakMap;function Jt(t){const n=vt.get(t);if(n!==void 0)return n;const e={active:0,idle:0,done:0,dead:0,canceled:0};for(const r of t.nodes.values())e[r.row.status]++;const s=[];for(const r of["active","idle","done","dead","canceled"])e[r]>0&&s.push({status:r,count:e[r]});return vt.set(t,s),s}f(Jt,"statusCounts");function Xt(t,n){return Pt.map(e=>e===t?n?`${C}${M}${H}m[ ${e} ]${$}`:`${U}[ ${e} ]${$}`:n?`${y} ${e} ${$}`:` ${e} `).join("")}f(Xt,"tabBar");const qt=new Set;function Qt(t,n,e){const s=n===""?qt:Gt(n,t);if(s.size===0)return[{text:t,style:{dim:e.dim,bold:e.bold}}];const r=[];let o="",u=!1;const i=f(()=>{o!==""&&(u?r.push({text:o,style:{fg:I,bold:!0}}):r.push({text:o,style:{dim:e.dim,bold:e.bold}}),o="")},"flush");for(let l=0;l<t.length;l++){const c=s.has(l);c!==u&&(i(),u=c),o+=t[l]}return i(),r}f(Qt,"nameSpans");function L(t){let n=0;for(const e of t)n+=[...e.text].length;return n}f(L,"spansWidth");function Zt(t){const n=X(t.status,{streaming:t.streaming===!0,frozen:J(t),hanging:t.hanging??null}),e=n.word??{active:"active",idle:"idle",done:"done",dead:"dead",canceled:"cancel"}[t.status]??t.status,s=n.color,r=`${n.glyph} ${e}`,o=Math.max(1,ft-[...r].length);return[{text:r,style:{fg:s,bold:n.bold===!0}},{text:" ".repeat(o)}]}f(Zt,"statusRail");function te(t,n,e){const s=yt(t.ctx_tokens),r=[{text:Et(`${t.kind}/${t.mode}`,$t),style:{fg:N}},{text:W},{text:Z(t.ctx_tokens).padStart(ht),style:{fg:s,dim:s===void 0}},{text:W},{text:G(t.created,n).padStart(pt),style:{dim:!0}}];return e&&r.push({text:W},{text:Et(`~${j(t.cwd)}`,gt),style:{fg:N}}),r}f(te,"metaCluster");function Et(t,n){return _(t,n).padEnd(n)}f(Et,"clipPad");function tt(t,n,e,s,r,o){const u=L(t),i=L(n);if(n.length===0||u+i+1>e)return w(t,e,s,r,o);const l=e-u-i;return w([...t,{text:" ".repeat(l)},...n],e,s,r,o)}f(tt,"assembleRow");function ee(t,n,e,s,r,o,u,i,l,c=!0,h=!1){const a=n.nodes.get(t.id);if(a===void 0)return"";const d=a.row,b=" ".repeat(t.depth),m=t.hasChildren?t.collapsed?"\u25B8":"\u25BE":" ",E=d.status==="done"||d.status==="dead"||d.status==="canceled",v=d.viewed===!0?{text:"\uF06E ",style:{fg:I,bold:!0}}:{text:" "},p=[];d.asks>0&&p.push({text:` \u2691${d.asks}`,style:{fg:xt,bold:!0}}),d.hanging!=null&&p.push({text:` \xB7 ${lt(d.hanging,i)}`,style:{fg:mt,dim:!0}});const x=l?[{text:"\u2605 ",style:{fg:bt,bold:!0}}]:[],T=Zt(d),R=c?te(d,i,u):[],A=`${b}${m} `,D=L([v])+L(T)+[...A].length+L(x)+L(p),B=L(R),K=Math.max(4,e-D-B-1),z={dim:!s&&E,bold:s},O=[v,...T,{text:A,style:{dim:!0}},...x,...Qt(_(d.name,K),r,z),...p];let k="",P=h;return s?(k=o.color256?Kt:U,P=!0):t.matched||(k=y),tt(O,R,e,o.color,k,P)}f(ee,"rowLine");function ne(t,n,e,s=!0,r=!1){const o=[{text:" "},{text:"STATUS".padEnd(ft),style:{dim:!0,bold:!0}},{text:"NAME",style:{dim:!0,bold:!0}}];if(!s)return w(o,t,e.color,"",r);const u=[{text:"KIND/MODE".padEnd($t),style:{dim:!0,bold:!0}},{text:W},{text:"CTX".padStart(ht),style:{dim:!0,bold:!0}},{text:W},{text:"AGE".padStart(pt),style:{dim:!0,bold:!0}}];return n&&u.push({text:W},{text:"PROJECT".padEnd(gt),style:{dim:!0,bold:!0}}),tt(o,u,t,e.color,"",!1)}f(ne,"columnHeaderLine");function oe(t){const n=f(o=>`${y}${o}${$}`,"dim"),e=t.profileScope===void 0?"all profiles":"current",s=t.cwdScope===null?"all dirs":j(t.cwdScope),r=[`${n("profile")} ${e}`,`${n("scope")} ${s}`,`${n("sort")} ${t.sort}`,`${n("lifecycle")} ${t.residentsOnly?"residents":"all"}`];return!t.search&&t.query!==""&&r.push(`${n("filter")} ${t.query}`),r.join(n(" \xB7 "))}f(oe,"statusLine");function Mt(t,n,e,s){if(t.hi.size===0)return w([{text:t.text,style:s}],n,e.color,"",!1);const r=[];let o="",u=!1;const i=f(()=>{o!==""&&(r.push(u?{text:o,style:{fg:I,bold:!0}}:{text:o,style:s}),o="")},"flush");for(let l=0;l<t.text.length;l++){const c=t.hi.has(l);c!==u&&(i(),u=c),o+=t.text[l]}return i(),w(r,n,e.color,"",!1)}f(Mt,"snippetLine");function se(t,n){const e=t?Bt:0,s=n?Ft:0,r=Math.max(2,ct-e-s),o=Math.ceil(r/2);return{recap:e,ask:o,reply:r-o,report:s}}f(se,"previewAllocation");function _t(t,n,e,s,r,o,u){if(s<=0)return[];const i=[],l=o.color?`${y}${t}${$}`:t,c=Math.max(1,r-2);if(u===""){const a=Q(n,c,s,!1);if(a.length===0)i.push(`${l}${y}${_(e,c)}${$}`);else for(const d of a)i.push(`${i.length===0?l:" "}${w(d,c,o.color,"",!1)}`);for(;i.length<s;)i.push("");return i}const h=q(u,n,c,s);if(h.length===0)i.push(`${l}${y}${_(e,c)}${$}`);else for(const a of h)i.push(`${i.length===0?l:" "}${Mt(a,c,o)}`);for(;i.length<s;)i.push("");return i}f(_t,"markedBlock");function Tt(t,n,e,s){const r=`${t.padEnd(6)}`,o=_(n,Math.max(1,e-r.length));return s.color?`${y}${r}${$}${C}${o}${$}`:`${r}${o}`}f(Tt,"recapLine");function re(t,n,e,s,r){const o=[`${y}${"\u2500".repeat(n)}${$}`];if(t===void 0){for(;o.length<it;)o.push("");return o}const u=X(t.status,{streaming:t.streaming===!0,frozen:J(t),hanging:t.hanging??null}),i=e.color?`${M}${u.color}m${u.glyph}${$}`:u.glyph,l=[`${t.status} ${t.kind}/${t.mode}`,j(t.cwd),G(t.created,s),`ctx ${Z(t.ctx_tokens)}`];t.asks>0&&l.push(`\u2691${t.asks}`),t.hanging!=null&&l.push(lt(t.hanging,s)),t.streaming===!0&&l.push("\u27F3"),t.viewed===!0&&l.push("\uF06E viewing");const c=_(l.filter(d=>d!=="").join(" \xB7 "),Math.max(0,n-2));o.push(e.color?`${i} ${y}${c}${$}`:`${i} ${c}`);const h=se(t.recap!==void 0,t.report!==void 0);t.recap!==void 0&&(o.push(Tt("Goal",t.recap.goal===""?"\u2014":t.recap.goal,n,e)),o.push(Tt("State",t.recap.state===""?"\u2014":t.recap.state,n,e)));const a=r!==""?Ht(t):t.goal??"";if(o.push(..._t("\u276F ",a,"(no spawn prompt)",h.ask,n,e,r)),o.push(..._t("\u21A9 ",t.lastAssistant??"","(no reply yet)",h.reply,n,e,"")),t.report!==void 0){const d=G(t.report.ts,s),b=`${d===""?"":`${d} `}${t.report.kind}`,m=t.report.heading===""?t.report.body:t.report.heading,E=e.color?`${y}\u25A3 ${$}`:"\u25A3 ",v=Math.max(1,n-2),p=e.color?`${M}${H}m${b}${$}${y} \xB7 ${$}`:`${b} \xB7 `;o.push(`${E}${p}${_(m,Math.max(1,v-b.length-3))}`);for(let x=1;x<h.report;x++){const T=t.report.heading===""?"":t.report.body,R=q("",T,v,h.report-1)[x-1];o.push(R===void 0?"":` ${y}${_(R.text,v)}${$}`)}}return o}f(re,"previewPanel");function Y(t,n,e,s){const r=s===void 0?"":`${s.text} `,o=Math.max(0,n-4-t.length-r.length),u=s===void 0?"":e.color?`${M}${s.fg}m${s.text}${$}${y} `:`${s.text} `;return`${y}\u2500\u2500 ${C}${t}${$}${y} ${u}${"\u2500".repeat(o)}${$}`}f(Y,"sectionRule");function et(t,n,e,s,r,o,u,i,l,c){if(o<=0)return[];const h=[...t].length,a=Math.max(1,u-h),d=f((m,E)=>w([{text:m,style:E}],h,i.color,"",!0),"mk");if(l===""){const m=Q(s,a,o,!0,c);return m.length===0?r===void 0?[]:[`${d(t,e)}${y}${_(r,a)}${$}`]:m.map((E,v)=>`${d(v===0?t:n,e)}${w(E,a,i.color,"",!1)}`)}const b=q(l,s,a,o);return b.length===0?r===void 0?[]:[`${d(t,e)}${y}${_(r,a)}${$}`]:b.map((m,E)=>`${d(E===0?t:n,e)}${Mt(m,a,i,c)}`)}f(et,"blockLines");const le=400,ce=1,nt=14,wt={fg:I,bold:!0,reverse:!0};function ie(t){let n="";for(const e of t)n+=e.text;return n}f(ie,"spansText");function ue(t,n){if(n==="")return{spans:t,hits:0};const e=ie(t),s=e.toLowerCase(),r=n.toLowerCase();if(s.indexOf(r)<0)return{spans:t,hits:0};const o=new Uint8Array(e.length);let u=0;for(let c=s.indexOf(r);c>=0;c=s.indexOf(r,c+r.length)){u++;for(let h=c;h<c+r.length;h++)o[h]=1}const i=[];let l=0;for(const c of t){let h="",a=o[l]===1;for(let d=0;d<c.text.length;d++){const b=o[l]===1;b!==a&&(h!==""&&i.push({text:h,style:a?wt:c.style}),h="",a=b),h+=c.text[d],l++}h!==""&&i.push({text:h,style:a?wt:c.style})}return{spans:i,hits:u}}f(ue,"highlightSpans");const V="\u258C ";function ot(t,n,e,s,r){if(e<2)return{lines:[],hits:0,truncated:!0};const o=t.role==="user",u=o?{fg:I,bold:!0}:{fg:N},i=Math.max(1,s-V.length),l=f(()=>w([{text:V,style:u}],V.length,r.color,"",!0),"bar"),c=[w([{text:V,style:u},{text:o?"YOU":"AGENT",style:{...u,bold:!0}}],s,r.color,"",!1)],a=Q(t.text,i,le,!1,o?{}:{dim:!0}).map(x=>ue(x,n)),d=a.reduce((x,T)=>x+T.hits,0),b=e-1;let m=0;a.length>b&&d>0&&(m=Math.max(0,a.findIndex(x=>x.hits>0)-ce),m=Math.min(m,a.length-b));const E=a.slice(m,m+b);for(const x of E)c.push(`${l()}${w(x.spans,i,r.color,"",!1)}`);const v=m>0,p=m+E.length<a.length;return v&&E.length>1&&(c[1]=`${l()}${y}\u22EF${$}`),p&&E.length>(v?2:1)&&(c[c.length-1]=`${l()}${y}\u22EF${$}`),{lines:c,hits:d,truncated:v||p}}f(ot,"turnBlock");function Rt(t,n,e){return w([{text:` \u22EF ${t} ${t===1?"turn":"turns"}`,style:{dim:!0}}],n,e.color,"",!1)}f(Rt,"elisionLine");function St(t,n){return n!==""&&t.text.toLowerCase().indexOf(n.toLowerCase())>=0}f(St,"turnMatches");function ae(t,n){return t.reduce((e,s)=>e+(St(s,n)?1:0),0)}f(ae,"transcriptHitTurns");function At(t,n,e,s,r){if(s<=0||t.length===0)return[];const o=n===""?[]:t.map((l,c)=>St(l,n)?c:-1).filter(l=>l>=0);if(o.length>0){const l=[];let c=-1;for(const a of o){const d=l.length===0?0:1,b=s-l.length-d;if(b<3)break;const{lines:m}=ot(t[a],n,Math.min(b,nt),e,r);if(m.length===0)break;const E=c<0?a:a-c-1,v=E>0&&l.length+d+m.length+1<=s;d>0&&l.push(""),v&&l.push(Rt(E,e,r)),l.push(...m),c=a}let h=c;for(let a=c+1;a<t.length;a++){const d=s-l.length-1;if(d<3)break;const{lines:b,truncated:m}=ot(t[a],n,Math.min(d,nt),e,r);if(b.length===0||m)break;l.push("",...b),h=a}return h>=0&&h<t.length-1&&l.length<s&&l.push(Rt(t.length-1-h,e,r)),l.slice(0,s)}const u=[];let i=0;for(let l=t.length-1;l>=0;l--){const c=u.length===0,h=c?0:1,a=s-i-h;if(a<3)break;const{lines:d,truncated:b}=ot(t[l],"",Math.min(a,nt),e,r);if(d.length===0||b&&!c)break;h>0&&u.push([""]),u.push(d),i+=d.length+h}return u.reverse().flat().slice(-s)}f(At,"transcriptLines");function kt(t){return t.transcriptLoaded===!0||t.previewLoaded===!0?`${y}(no conversation yet)${$}`:`${y}(loading\u2026)${$}`}f(kt,"emptyBodyNote");function Ct(t){const n=t.transcript;if(n!==void 0&&n.length>0)return n;const e=[];return t.goal!==void 0&&t.goal!==""&&e.push({role:"user",text:t.goal}),t.lastAssistant!==void 0&&t.lastAssistant!==""&&e.push({role:"assistant",text:t.lastAssistant}),e}f(Ct,"panelTurns");const de=4;function fe(t,n,e,s){const r=yt(t.ctx_tokens),o=f(()=>({text:" \xB7 ",style:{dim:!0}}),"dot"),u=[{text:`${t.kind}/${t.mode}`,style:{fg:N}},o(),{text:`~${j(t.cwd)}`,style:{fg:N}},o(),{text:G(t.created,e),style:{dim:!0}},o(),{text:`ctx ${Z(t.ctx_tokens)}`,style:{fg:r,dim:r===void 0}}];return w(u,n,s.color,"",!1)}f(fe,"panelFactsLine");function $e(t,n,e,s){if(t===void 0)return w([{text:"PREVIEW",style:{dim:!0,bold:!0}}],n,e.color,"",!1);const r=[];s&&r.push({text:"\u2605 ",style:{fg:bt,bold:!0}});const o=t.node_id.slice(0,8);return r.push({text:_(t.name,Math.max(4,n-o.length-2-L(r))),style:{bold:!0}}),tt(r,[{text:o,style:{dim:!0}}],n,e.color,"",!1)}f($e,"panelTitleLine");function he(t,n,e,s,r,o,u){if(e<=0)return[];if(t===void 0)return[`${y}(no selection)${$}`];if(o!==""){const p=Ct(t),x=ae(p,o),T=[Y("TRANSCRIPT",n,s,x>0?{text:`${x} ${x===1?"turn":"turns"}`,fg:I}:{text:"matched on name",fg:N})],R=At(p,o,n,e-1,s);return T.push(...R.length===0?[kt(t)]:R),T.slice(0,e)}const i=t.report,l=f(()=>({fg:X(t.status,{streaming:t.streaming===!0,frozen:J(t),hanging:t.hanging??null}).color}),"accentOf");if(u&&i!==void 0){const p=G(i.ts,r),x=[Y("REPORT",n,s,{text:`${p===""?"":`${p} \xB7 `}${i.kind}`,fg:H})],T=i.heading===""?i.body:i.heading;return x.push(...et("\u25A3 "," ",{fg:H,bold:!0},T,void 0,3,n,s,"",{bold:!0})),i.heading!==""&&i.body!==""&&(x.push(""),x.push(...et(" "," ",void 0,i.body,void 0,e-x.length,n,s,""))),x.slice(0,e)}const c=[fe(t,n,r,s),""],h=l(),a=f((p,x)=>[Y(p,n,s),...et("\u258C ","\u258C ",h,x,void 0,de,n,s,"",{bold:!0})],"briefing"),d=t.recap?.goal??"";d!==""&&c.push(...a("GOAL",d),"");const b=t.recap?.state??"",m=b===""?[]:[...a("STATE",b)],E=m.length===0?0:m.length+1,v=e-c.length-E-1;if(v>=2){c.push(Y("CHAT",n,s));const p=At(Ct(t),"",n,v,s);c.push(...p.length===0?[kt(t)]:p)}if(m.length>0){for(;c.length<e-m.length;)c.push("");c.push(...m)}return c.slice(0,e)}f(he,"sidePanelBody");const pe=[["Move","\u2191/\u2193 j/k","up / down"],["","g / G","top / bottom"],["",".","jump to this node (recenter)"],["Tree","\u2192/\u2190 h/l","expand / collapse"],["","space","toggle fold"],["Tabs","Tab / 1-5","All \xB7 Live \xB7 Dormant \xB7 Attention \xB7 Pinned"],["Find","/","fuzzy search (name \xB7 kind \xB7 id \xB7 prompts)"],["Pin","p","star / unstar \u2014 floats to top, Pinned tab"],["Open","\u23CE o","open conversation (closes navigator)"],["","O","open, keep browsing (background)"],["Act","y","copy the node id to the clipboard"],["","m","message the node (no resume)"],["","R","rename the node"],["","x","close-out node + subtree"],["","K","revive now (a hanging node)"],["View","s","cycle sort (attention/tree/relevance/recency)"],["","c","toggle cwd scope"],["","P","toggle profile scope"],["","r","toggle residents-only"],["","v","toggle preview (goal, chat, state)"],["","V","in the preview: swap chat for the newest report"],["Quit","q / Esc",""]];function ge(t,n){const e=Math.max(20,t.cols),s=Math.max(8,t.rows),r=e-1,o=[];o.push(`${C}Canvas navigator \u2014 keys${$}`),o.push("");const u=f(l=>`${y}${l}${$}`,"dim");for(const[l,c,h]of pe){const a=l.padEnd(6),d=c.padEnd(12),b=` ${u(a)}${C}${d}${$}${h===""?"":` ${u(h)}`}`;o.push(_(b,r))}for(o.push(""),o.push(u(" ? or any key to close"));o.length<s-1;)o.push("");const i=o.map(l=>`${l}${M}K`).join(`\r
2
+ `);return`${M}H${i}${M}J`}f(ge,"renderHelp");function _e(t,n,e={color:!1,color256:!1}){if(t.help===!0)return ge(n,e);const s=Math.max(20,n.cols),r=Math.max(8,n.rows),o=s-1,u=Date.now(),i=t.search||t.rename===!0||t.message===!0,l=[],c=`${C}Canvas${$} \u2014 ${t.totalNodes} nodes`,h=`Canvas \u2014 ${t.totalNodes} nodes`.length,a=Jt(t.tree),d=a.map(g=>`${rt[g.status]}${g.count}`).join(" "),b=e.color?a.map(g=>`${M}${It[g.status]}m${rt[g.status]}${$}${y}${g.count}${$}`).join(" "):`${y}${d}${$}`,m=o-h-d.length;if(l.push(m>1?`${c}${" ".repeat(m)}${b}`:c),l.push(Xt(t.tab,e.color)),l.push(oe(t)),i){const g=t.rename===!0?"rename \u25B8":t.message===!0?"msg \u25B8":"/",S=t.rename===!0?t.renameBuf??"":t.message===!0?t.messageBuf??"":t.query,F=e.color?`${M}${H}m${g}${$}`:g;l.push(`${F} ${S}\u258E`)}const E=t.preview&&t.visible.length>0,v=Vt(s,E),p=v.mode==="side",x=p?v.rowsW:o,T=`${y}${dt}${$}`,R=t.visible[t.cursor],A=R!==void 0?t.tree.nodes.get(R.id)?.row:void 0,D=t.cwdScope===null&&!p,B=ne(x,D,e,!p,p);l.push(p?`${B}${T}${$e(A,v.panelW,e,R!==void 0&&t.pinned.has(R.id))}`:B),l.push(p?`${y}${"\u2500".repeat(x)}\u2500\u253C\u2500${"\u2500".repeat(v.panelW)}${$}`:`${y}${"\u2500".repeat(o)}${$}`);const K=l.length,z=v.mode==="bottom"?it:0,O=Math.max(1,r-K-1-z),k=t.scrollOffset,P=Math.min(t.visible.length,k+O),Lt=p?he(A,v.panelW,O,e,u,t.query,t.showReport===!0):[],st=f((g,S)=>p?`${g}${T}${Lt[S]??""}`:g,"compose"),Ot=p?" ".repeat(x):"";if(t.visible.length===0){l.push(`${y} (no nodes match this view)${$}`);for(let g=1;g<O;g++)l.push("")}else{for(let g=k;g<P;g++){const S=t.visible[g];l.push(st(ee(S,t.tree,x,g===t.cursor,t.query,e,D,u,t.pinned.has(S.id),!p,p),g-k))}for(let g=P-k;g<O;g++)l.push(st(Ot,g))}if(v.mode==="bottom")for(const g of re(A,o,e,u,t.query))l.push(g);if(t.pendingClose!==null&&t.pendingClose!==void 0){const g=t.tree.nodes.get(t.pendingClose),F=`\u26A0 ${g!==void 0?g.row.name:t.pendingClose} is \u27F3 \u2014 close it (and its subtree) anyway? y / n`;l.push(e.color?`${C}${M}${xt}m${_(F,o)}${$}`:`${U}${_(F,o)}${$}`)}else if(t.flash!==null&&t.flash!==void 0&&t.flash!=="")l.push(e.color?`${C}${_(t.flash,o)}${$}`:`${U}${_(t.flash,o)}${$}`);else{const g=A?.hanging!=null?"K revive now ":"",S=i?"\u23CE commit Esc cancel \u232B delete":t.readOnly===!0?"\u2191\u2193 move \u2192/\u2190 tree / search p pin v preview Tab tabs ? more q quit \u2014 read-only remote canvas":`${g}${A?.report!==void 0&&p&&t.query===""?t.showReport===!0?"V chat ":"V report ":""}\u2191\u2193 move \u23CE open O bg / search p pin v preview m msg x close ? more q quit`;l.push(`${y}${_(S,o)}${$}`)}const Wt=l.map(g=>`${g}${M}K`).join(`\r
3
+ `);return`${M}H${Wt}${M}J`}f(_e,"renderFrame");export{ct as PREVIEW_BODY,it as PREVIEW_HEIGHT,Bt as RECAP_LINES,Ft as REPORT_LINES,Dt as detectColorCaps,Me as headerHeight,ue as highlightSpans,se as previewAllocation,Vt as previewLayout,_e as renderFrame,ae as transcriptHitTurns};