@north-light/crouter 0.3.170 → 0.3.172

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (670) hide show
  1. package/dist/api/client.d.ts +37 -11
  2. package/dist/api/client.js +84 -15
  3. package/dist/api/dto/human.d.ts +53 -39
  4. package/dist/api/dto/human.js +2 -3
  5. package/dist/api/dto/inbox.d.ts +0 -1
  6. package/dist/api/dto/nodes.d.ts +12 -0
  7. package/dist/api/dto/review-comments.d.ts +137 -0
  8. package/dist/api/dto/review-comments.js +5 -0
  9. package/dist/api/dto/reviews.d.ts +109 -0
  10. package/dist/api/dto/reviews.js +5 -0
  11. package/dist/api/index.d.ts +2 -0
  12. package/dist/api/index.js +2 -0
  13. package/dist/api/routes.d.ts +17 -4
  14. package/dist/api/routes.js +21 -5
  15. package/dist/build-root.d.ts +1 -16
  16. package/dist/build-root.js +1 -25
  17. package/dist/builtin-memory/00-runtime-base.md +7 -5
  18. package/dist/builtin-memory/04-base-worker.md +1 -1
  19. package/dist/builtin-memory/04-orchestration-kernel.md +7 -7
  20. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
  21. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +1 -1
  22. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -1
  23. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -1
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -1
  25. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -1
  26. package/dist/builtin-memory/05-kinds/review/00-base.md +1 -1
  27. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +20 -0
  28. package/dist/builtin-memory/05-kinds/spec/00-base.md +3 -7
  29. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +3 -3
  30. package/dist/builtin-memory/05-kinds/spec/requirements.md +3 -3
  31. package/dist/builtin-memory/design.md +2 -2
  32. package/dist/builtin-memory/insights/capture.md +50 -0
  33. package/dist/builtin-memory/insights/init.md +45 -0
  34. package/dist/builtin-memory/insights/listen.md +9 -0
  35. package/dist/builtin-memory/internal/agent-shaping.md +2 -2
  36. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  37. package/dist/builtin-memory/internal/plugins.md +12 -11
  38. package/dist/builtin-memory/internal/storage-tiers.md +2 -2
  39. package/dist/builtin-memory/{planning.md → plan/roadmap.md} +3 -3
  40. package/dist/builtin-memory/plan.md +19 -0
  41. package/dist/builtin-memory/spec/guide.md +38 -0
  42. package/dist/builtin-memory/spec/requirements.md +31 -0
  43. package/dist/builtin-memory/spec/roadmap.md +35 -0
  44. package/dist/builtin-memory/spec.md +10 -86
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +3 -4
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +49 -5
  47. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +56 -0
  48. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +920 -0
  49. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +221 -156
  50. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +4 -5
  51. package/dist/cli.js +2 -6
  52. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +7 -35
  53. package/dist/clients/attach/__tests__/attach-keybindings.test.js +32 -16
  54. package/dist/clients/attach/__tests__/context-message.test.js +142 -6
  55. package/dist/clients/attach/__tests__/crtr-output.test.js +29 -45
  56. package/dist/clients/attach/__tests__/diagram.test.js +1 -1
  57. package/dist/clients/attach/__tests__/file-review-focus.test.js +48 -0
  58. package/dist/clients/attach/__tests__/group-activity.test.js +266 -0
  59. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +32 -0
  60. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +32 -0
  61. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -2
  62. package/dist/clients/attach/chrome/header.d.ts +10 -0
  63. package/dist/clients/attach/chrome/header.js +30 -0
  64. package/dist/clients/attach/chrome/recap.d.ts +7 -0
  65. package/dist/clients/attach/chrome/recap.js +19 -0
  66. package/dist/clients/attach/chrome/status-line.d.ts +3 -0
  67. package/dist/clients/attach/chrome/status-line.js +5 -0
  68. package/dist/clients/attach/chrome/widgets.js +11 -21
  69. package/dist/clients/attach/command.js +11 -7
  70. package/dist/clients/attach/config.d.ts +4 -0
  71. package/dist/clients/attach/config.js +3 -0
  72. package/dist/clients/attach/input/controller.d.ts +19 -0
  73. package/dist/clients/attach/input/controller.js +62 -28
  74. package/dist/clients/attach/input/titled-editor.d.ts +0 -4
  75. package/dist/clients/attach/input/titled-editor.js +2 -10
  76. package/dist/clients/attach/overlays/file-review.d.ts +9 -5
  77. package/dist/clients/attach/overlays/file-review.js +9 -70
  78. package/dist/clients/attach/overlays/help.d.ts +33 -0
  79. package/dist/clients/attach/overlays/help.js +204 -0
  80. package/dist/clients/attach/render/activity-slot.d.ts +4 -0
  81. package/dist/clients/attach/render/activity-slot.js +13 -0
  82. package/dist/clients/attach/render/chat-view.d.ts +117 -12
  83. package/dist/clients/attach/render/chat-view.js +604 -135
  84. package/dist/clients/attach/render/context-message.d.ts +2 -1
  85. package/dist/clients/attach/render/context-message.js +17 -13
  86. package/dist/clients/attach/render/crtr-output.js +1 -3
  87. package/dist/clients/attach/render/diagram.js +2 -2
  88. package/dist/clients/attach/render/edit-diff.d.ts +4 -1
  89. package/dist/clients/attach/render/edit-diff.js +7 -11
  90. package/dist/clients/attach/render/group-activity.d.ts +32 -0
  91. package/dist/clients/attach/render/group-activity.js +206 -0
  92. package/dist/clients/attach/render/group-recap.d.ts +10 -0
  93. package/dist/clients/attach/render/group-recap.js +93 -0
  94. package/dist/clients/attach/render/html-markdown.d.ts +17 -0
  95. package/dist/clients/attach/render/html-markdown.js +228 -0
  96. package/dist/clients/attach/render/measured-container.d.ts +96 -0
  97. package/dist/clients/attach/render/measured-container.js +322 -0
  98. package/dist/clients/attach/render/scroll-animation.d.ts +8 -0
  99. package/dist/clients/attach/render/scroll-animation.js +80 -0
  100. package/dist/clients/attach/render/tool-calls.js +6 -6
  101. package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
  102. package/dist/clients/attach/render/transcript-copy.js +81 -0
  103. package/dist/clients/attach/render/viewport.d.ts +29 -0
  104. package/dist/clients/attach/render/viewport.js +159 -0
  105. package/dist/clients/attach/session/bindings.d.ts +10 -7
  106. package/dist/clients/attach/session/bindings.js +23 -8
  107. package/dist/clients/attach/session/connection.js +4 -5
  108. package/dist/clients/attach/session/context.d.ts +6 -4
  109. package/dist/clients/attach/session/frame.d.ts +34 -0
  110. package/dist/clients/attach/session/frame.js +176 -0
  111. package/dist/clients/attach/session/frames.d.ts +4 -1
  112. package/dist/clients/attach/session/frames.js +14 -1
  113. package/dist/clients/attach/session/identity.js +4 -3
  114. package/dist/clients/attach/session/input-wiring.d.ts +14 -4
  115. package/dist/clients/attach/session/input-wiring.js +15 -13
  116. package/dist/clients/attach/session/invariant.d.ts +9 -0
  117. package/dist/clients/attach/session/invariant.js +15 -0
  118. package/dist/clients/attach/session/keys.d.ts +10 -2
  119. package/dist/clients/attach/session/keys.js +13 -5
  120. package/dist/clients/attach/session/layout.d.ts +10 -8
  121. package/dist/clients/attach/session/layout.js +33 -34
  122. package/dist/clients/attach/session/mouse.d.ts +18 -0
  123. package/dist/clients/attach/session/mouse.js +64 -0
  124. package/dist/clients/attach/session/pane-tag.d.ts +3 -0
  125. package/dist/clients/attach/session/pane-tag.js +51 -8
  126. package/dist/clients/attach/session/reconnect.d.ts +3 -0
  127. package/dist/clients/attach/session/reconnect.js +42 -5
  128. package/dist/clients/attach/session/surface-frame.d.ts +20 -0
  129. package/dist/clients/attach/session/surface-frame.js +73 -0
  130. package/dist/clients/attach/session/surface-host.d.ts +64 -0
  131. package/dist/clients/attach/session/surface-host.js +255 -0
  132. package/dist/clients/attach/session/whip.d.ts +17 -0
  133. package/dist/clients/attach/session/whip.js +334 -0
  134. package/dist/clients/attach/slash/dispatch.d.ts +13 -1
  135. package/dist/clients/attach/slash/dispatch.js +51 -29
  136. package/dist/clients/attach/viewer.js +907 -819
  137. package/dist/clients/conversation/conversation.d.ts +65 -0
  138. package/dist/clients/conversation/conversation.js +318 -0
  139. package/dist/clients/conversation/frames.d.ts +30 -0
  140. package/dist/clients/conversation/frames.js +52 -0
  141. package/dist/clients/conversation/region.d.ts +51 -0
  142. package/dist/clients/conversation/region.js +265 -0
  143. package/dist/clients/conversation/submit.d.ts +38 -0
  144. package/dist/clients/conversation/submit.js +51 -0
  145. package/dist/clients/inbox/__tests__/inbox-controller.test.js +247 -0
  146. package/dist/clients/inbox/__tests__/mount-panel.test.js +776 -0
  147. package/dist/clients/inbox/controller.d.ts +79 -0
  148. package/dist/clients/inbox/controller.js +448 -0
  149. package/dist/clients/inbox/deck-adapter.d.ts +29 -0
  150. package/dist/clients/inbox/deck-adapter.js +62 -0
  151. package/dist/clients/inbox/layout.d.ts +8 -0
  152. package/dist/clients/inbox/layout.js +9 -0
  153. package/dist/clients/inbox/resolve.d.ts +10 -0
  154. package/dist/clients/inbox/resolve.js +34 -0
  155. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +29 -0
  156. package/dist/clients/inbox/review/__tests__/remap.test.js +196 -0
  157. package/dist/clients/inbox/review/__tests__/review-core.test.js +341 -0
  158. package/dist/clients/inbox/review/anchors.d.ts +41 -0
  159. package/dist/clients/inbox/review/anchors.js +89 -0
  160. package/dist/clients/inbox/review/columns.d.ts +22 -0
  161. package/dist/clients/inbox/review/columns.js +40 -0
  162. package/dist/clients/inbox/review/comments-client.d.ts +66 -0
  163. package/dist/clients/inbox/review/comments-client.js +98 -0
  164. package/dist/clients/inbox/review/composition.d.ts +60 -0
  165. package/dist/clients/inbox/review/composition.js +278 -0
  166. package/dist/clients/inbox/review/document-region.d.ts +120 -0
  167. package/dist/clients/inbox/review/document-region.js +902 -0
  168. package/dist/clients/inbox/review/frame.d.ts +45 -0
  169. package/dist/clients/inbox/review/frame.js +215 -0
  170. package/dist/clients/inbox/review/keys.d.ts +67 -0
  171. package/dist/clients/inbox/review/keys.js +130 -0
  172. package/dist/clients/inbox/review/launch.d.ts +10 -0
  173. package/dist/clients/inbox/review/launch.js +129 -0
  174. package/dist/clients/inbox/review/live-source.d.ts +24 -0
  175. package/dist/clients/inbox/review/live-source.js +160 -0
  176. package/dist/clients/inbox/review/nvim.d.ts +13 -0
  177. package/dist/clients/inbox/review/nvim.js +42 -0
  178. package/dist/clients/inbox/review/remap.d.ts +51 -0
  179. package/dist/clients/inbox/review/remap.js +157 -0
  180. package/dist/clients/inbox/review/review-client.d.ts +30 -0
  181. package/dist/clients/inbox/review/review-client.js +107 -0
  182. package/dist/clients/inbox/review/roundtrip.d.ts +5 -0
  183. package/dist/clients/inbox/review/roundtrip.js +36 -0
  184. package/dist/clients/inbox/review/state.d.ts +143 -0
  185. package/dist/clients/inbox/review/state.js +282 -0
  186. package/dist/clients/inbox/review-adapter.d.ts +29 -0
  187. package/dist/clients/inbox/review-adapter.js +92 -0
  188. package/dist/clients/inbox/review-visibility.d.ts +5 -0
  189. package/dist/clients/inbox/review-visibility.js +19 -0
  190. package/dist/clients/inbox/surface.d.ts +19 -0
  191. package/dist/clients/inbox/surface.js +128 -0
  192. package/dist/clients/inbox/tui/ansi.d.ts +66 -0
  193. package/dist/clients/inbox/tui/ansi.js +317 -0
  194. package/dist/clients/inbox/tui/clipboard.d.ts +2 -0
  195. package/dist/clients/inbox/tui/clipboard.js +26 -0
  196. package/dist/clients/inbox/tui/input.d.ts +7 -0
  197. package/dist/clients/inbox/tui/input.js +653 -0
  198. package/dist/clients/inbox/tui/keys.d.ts +28 -0
  199. package/dist/clients/inbox/tui/keys.js +111 -0
  200. package/dist/clients/inbox/tui/panel.d.ts +2 -0
  201. package/dist/clients/inbox/tui/panel.js +217 -0
  202. package/dist/clients/inbox/tui/render.d.ts +37 -0
  203. package/dist/clients/inbox/tui/render.js +476 -0
  204. package/dist/clients/inbox/tui/types.d.ts +57 -0
  205. package/dist/clients/inbox/tui/types.js +1 -0
  206. package/dist/clients/inbox/tui.d.ts +6 -0
  207. package/dist/clients/inbox/tui.js +74 -0
  208. package/dist/clients/surfaces/host.d.ts +66 -0
  209. package/dist/clients/surfaces/host.js +1 -0
  210. package/dist/clients/surfaces/region.d.ts +16 -0
  211. package/dist/clients/surfaces/region.js +1 -0
  212. package/dist/clients/web/__tests__/push-engine.test.js +14 -158
  213. package/dist/clients/web/dev-server.d.ts +3 -3
  214. package/dist/clients/web/dev-server.js +9 -23
  215. package/dist/clients/web/events.js +4 -6
  216. package/dist/clients/web/push-engine.d.ts +2 -66
  217. package/dist/clients/web/push-engine.js +30 -161
  218. package/dist/clients/web/push-registry.d.ts +0 -4
  219. package/dist/clients/web/push-registry.js +2 -7
  220. package/dist/clients/web/server.js +3 -35
  221. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -108
  222. package/dist/clients/web/web-cmd.js +2 -2
  223. package/dist/commands/__tests__/human.test.js +27 -15
  224. package/dist/commands/api-client.js +3 -3
  225. package/dist/commands/canvas-browse.js +1 -1
  226. package/dist/commands/canvas-issue.js +1 -1
  227. package/dist/commands/canvas-use.js +1 -1
  228. package/dist/commands/human/doc.d.ts +2 -0
  229. package/dist/commands/human/doc.js +98 -0
  230. package/dist/commands/human/inbox.d.ts +2 -0
  231. package/dist/commands/human/inbox.js +101 -0
  232. package/dist/commands/human/prompts.d.ts +2 -3
  233. package/dist/commands/human/prompts.js +27 -180
  234. package/dist/commands/human/queue.d.ts +1 -5
  235. package/dist/commands/human/queue.js +54 -216
  236. package/dist/commands/human/review.d.ts +2 -0
  237. package/dist/commands/human/review.js +298 -0
  238. package/dist/commands/human/shared.d.ts +2 -69
  239. package/dist/commands/human/shared.js +1 -181
  240. package/dist/commands/human.js +15 -20
  241. package/dist/commands/memory/__tests__/lint.test.d.ts +1 -0
  242. package/dist/commands/memory/__tests__/lint.test.js +15 -0
  243. package/dist/commands/memory/delete.js +2 -2
  244. package/dist/commands/memory/lint.d.ts +1 -0
  245. package/dist/commands/memory/lint.js +21 -3
  246. package/dist/commands/memory/read.js +4 -4
  247. package/dist/commands/node.js +8 -7
  248. package/dist/commands/pkg/plugin-manage.js +143 -68
  249. package/dist/commands/surface-inspect.js +2 -2
  250. package/dist/commands/surface.js +6 -12
  251. package/dist/commands/sys/__tests__/setup-core.test.js +9 -5
  252. package/dist/commands/sys/__tests__/setup-front-door.test.js +7 -42
  253. package/dist/commands/sys/config.js +29 -3
  254. package/dist/commands/sys/feedback.js +1 -1
  255. package/dist/commands/sys/setup-core.d.ts +12 -11
  256. package/dist/commands/sys/setup-core.js +55 -46
  257. package/dist/commands/sys/setup-wizard.d.ts +4 -1
  258. package/dist/commands/sys/setup-wizard.js +50 -9
  259. package/dist/commands/sys/sync-deps.js +1 -1
  260. package/dist/commands/sys.js +4 -6
  261. package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -1
  262. package/dist/core/__tests__/broker-snapshot-history.test.js +9 -1
  263. package/dist/core/__tests__/dead-node-policy-table.test.js +3 -4
  264. package/dist/core/__tests__/fixtures/fake-engine.d.ts +8 -5
  265. package/dist/core/__tests__/fixtures/fake-engine.js +28 -2
  266. package/dist/core/__tests__/full/broker-provider-retry.test.js +87 -2
  267. package/dist/core/__tests__/full/broker-whip-interrupt.test.d.ts +1 -0
  268. package/dist/core/__tests__/full/broker-whip-interrupt.test.js +39 -0
  269. package/dist/core/__tests__/full/detach-focus.test.js +1 -1
  270. package/dist/core/__tests__/human-deliver-e2e.test.js +64 -64
  271. package/dist/core/__tests__/human-deliver.test.js +71 -345
  272. package/dist/core/__tests__/inline-memory-refs.test.js +2 -12
  273. package/dist/core/__tests__/memory-resolver-precedence.test.js +12 -15
  274. package/dist/core/__tests__/migration.test.js +10 -0
  275. package/dist/core/__tests__/model-pin-durability.test.js +14 -0
  276. package/dist/core/__tests__/phase4-review-migration.test.d.ts +1 -0
  277. package/dist/core/__tests__/phase4-review-migration.test.js +100 -0
  278. package/dist/core/__tests__/phase4-review-store.test.d.ts +1 -0
  279. package/dist/core/__tests__/phase4-review-store.test.js +143 -0
  280. package/dist/core/__tests__/remote-canvas-target.test.js +2 -2
  281. package/dist/core/__tests__/revive.test.js +22 -53
  282. package/dist/core/__tests__/session-cycles.test.js +48 -18
  283. package/dist/core/__tests__/spawn-no-kickoff.test.js +8 -12
  284. package/dist/core/__tests__/stop-guard.test.js +16 -1
  285. package/dist/core/__tests__/tmux-surface.test.js +21 -25
  286. package/dist/core/asset-root.d.ts +7 -0
  287. package/dist/core/asset-root.js +18 -0
  288. package/dist/core/broker-client/client.d.ts +0 -7
  289. package/dist/core/broker-client/client.js +4 -10
  290. package/dist/core/broker-client/transport-relay.d.ts +3 -4
  291. package/dist/core/broker-client/transport-relay.js +3 -4
  292. package/dist/core/canvas/__tests__/attention.test.js +1 -1
  293. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
  294. package/dist/core/canvas/__tests__/remote-transport.test.d.ts +1 -0
  295. package/dist/core/{view/__tests__/transport-remote.test.js → canvas/__tests__/remote-transport.test.js} +2 -2
  296. package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
  297. package/dist/core/canvas/attention.js +4 -4
  298. package/dist/core/canvas/canvas.d.ts +6 -11
  299. package/dist/core/canvas/canvas.js +11 -33
  300. package/dist/core/canvas/db.js +207 -38
  301. package/dist/core/canvas/extensions.d.ts +1 -1
  302. package/dist/core/canvas/extensions.js +8 -1
  303. package/dist/core/canvas/index.d.ts +0 -1
  304. package/dist/core/canvas/index.js +0 -1
  305. package/dist/core/canvas/nav-model.d.ts +1 -1
  306. package/dist/core/canvas/nav-model.js +1 -1
  307. package/dist/core/canvas/paths.d.ts +5 -0
  308. package/dist/core/canvas/paths.js +16 -0
  309. package/dist/core/canvas/remote-canvas-source.js +2 -2
  310. package/dist/core/canvas/remote-transport.d.ts +7 -0
  311. package/dist/core/{view/transport-remote.js → canvas/remote-transport.js} +3 -4
  312. package/dist/core/canvas/source.js +1 -1
  313. package/dist/core/canvas/status-glyph.js +4 -12
  314. package/dist/core/canvas/types.d.ts +10 -35
  315. package/dist/core/clipboard-text.d.ts +8 -0
  316. package/dist/core/clipboard-text.js +18 -0
  317. package/dist/core/command-manifests/registry.d.ts +1 -3
  318. package/dist/core/command-plugins/bundle.d.ts +29 -0
  319. package/dist/core/command-plugins/bundle.js +198 -0
  320. package/dist/core/command-plugins/discovery.d.ts +0 -8
  321. package/dist/core/command-plugins/discovery.js +2 -39
  322. package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
  323. package/dist/core/command-plugins/transport/http-fetch.js +17 -95
  324. package/dist/core/command.d.ts +1 -13
  325. package/dist/core/command.js +1 -16
  326. package/dist/core/config.d.ts +4 -0
  327. package/dist/core/config.js +28 -3
  328. package/dist/core/document-lines.d.ts +4 -0
  329. package/dist/core/document-lines.js +6 -0
  330. package/dist/core/feed/feed.d.ts +2 -0
  331. package/dist/core/feed/feed.js +11 -7
  332. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +1 -0
  333. package/dist/core/human/__tests__/inbox-cancel-worker.js +7 -0
  334. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +1 -0
  335. package/dist/core/human/__tests__/inbox-claim-worker.js +17 -0
  336. package/dist/core/human/__tests__/inbox-core.test.d.ts +1 -0
  337. package/dist/core/human/__tests__/inbox-core.test.js +144 -0
  338. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +1 -0
  339. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +8 -0
  340. package/dist/core/human/__tests__/visible-paths.test.d.ts +1 -0
  341. package/dist/{clients/attach → core/human}/__tests__/visible-paths.test.js +9 -0
  342. package/dist/core/human/claim.d.ts +23 -0
  343. package/dist/core/human/claim.js +67 -0
  344. package/dist/core/human/convention.d.ts +30 -0
  345. package/dist/core/human/convention.js +202 -0
  346. package/dist/core/human/deck-factories.d.ts +8 -0
  347. package/dist/core/human/deck-factories.js +15 -0
  348. package/dist/core/human/deck-schema.d.ts +70 -0
  349. package/dist/core/human/deck-schema.js +92 -0
  350. package/dist/core/human/root.d.ts +7 -0
  351. package/dist/core/human/root.js +37 -0
  352. package/dist/core/human/scan.d.ts +3 -0
  353. package/dist/core/human/scan.js +76 -0
  354. package/dist/core/human/summary.d.ts +8 -0
  355. package/dist/core/human/summary.js +44 -0
  356. package/dist/core/human/tickets.d.ts +49 -0
  357. package/dist/core/human/tickets.js +190 -0
  358. package/dist/core/human/types.d.ts +136 -0
  359. package/dist/core/human/types.js +5 -0
  360. package/dist/{clients/attach → core/human}/visible-paths.d.ts +1 -1
  361. package/dist/{clients/attach → core/human}/visible-paths.js +3 -2
  362. package/dist/core/inspector/chrome.d.ts +6 -0
  363. package/dist/core/inspector/chrome.js +14 -0
  364. package/dist/core/inspector/contract.d.ts +105 -0
  365. package/dist/core/inspector/contract.js +1 -0
  366. package/dist/core/inspector/core.d.ts +4 -5
  367. package/dist/core/inspector/core.js +3 -5
  368. package/dist/core/inspector/host.d.ts +46 -0
  369. package/dist/core/{tui → inspector}/host.js +42 -208
  370. package/dist/core/inspector/text.d.ts +2 -2
  371. package/dist/core/inspector/transport.d.ts +6 -0
  372. package/dist/core/inspector/transport.js +36 -0
  373. package/dist/core/inspector/tui.d.ts +2 -2
  374. package/dist/core/inspector/tui.js +15 -15
  375. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +11 -11
  376. package/dist/core/keybindings/__tests__/resolve.test.js +10 -19
  377. package/dist/core/keybindings/attach-control.d.ts +9 -3
  378. package/dist/core/keybindings/attach-control.js +3 -1
  379. package/dist/core/keybindings/catalog.d.ts +6 -5
  380. package/dist/core/keybindings/catalog.js +61 -133
  381. package/dist/core/keybindings/inbox.d.ts +5 -6
  382. package/dist/core/keybindings/inbox.js +9 -10
  383. package/dist/core/keybindings/index.d.ts +3 -3
  384. package/dist/core/keybindings/index.js +3 -3
  385. package/dist/core/keybindings/persistence.d.ts +5 -1
  386. package/dist/core/keybindings/persistence.js +24 -6
  387. package/dist/core/keybindings/resolve.d.ts +6 -0
  388. package/dist/core/keybindings/resolve.js +10 -3
  389. package/dist/core/memory/inline-ref-grammar.js +2 -3
  390. package/dist/core/memory-resolver.d.ts +27 -29
  391. package/dist/core/memory-resolver.js +45 -39
  392. package/dist/core/model-routes.d.ts +33 -0
  393. package/dist/core/model-routes.js +42 -3
  394. package/dist/core/preview-registry.js +17 -55
  395. package/dist/core/profiles/select.js +3 -3
  396. package/dist/core/{view/remote-canvas-target.d.ts → remote-canvas-target.d.ts} +2 -2
  397. package/dist/core/{view/remote-canvas-target.js → remote-canvas-target.js} +4 -4
  398. package/dist/core/review/__tests__/capture-origin.test.d.ts +1 -0
  399. package/dist/core/review/__tests__/capture-origin.test.js +139 -0
  400. package/dist/core/review/__tests__/comments.test.d.ts +1 -0
  401. package/dist/core/review/__tests__/comments.test.js +98 -0
  402. package/dist/core/review/__tests__/project.test.d.ts +1 -0
  403. package/dist/core/review/__tests__/project.test.js +71 -0
  404. package/dist/core/review/__tests__/remap.test.d.ts +1 -0
  405. package/dist/core/review/__tests__/remap.test.js +159 -0
  406. package/dist/core/review/__tests__/stage-identity.test.d.ts +1 -0
  407. package/dist/core/review/__tests__/stage-identity.test.js +140 -0
  408. package/dist/core/review/birth.d.ts +7 -0
  409. package/dist/core/review/birth.js +23 -0
  410. package/dist/core/review/comments.d.ts +69 -0
  411. package/dist/core/review/comments.js +295 -0
  412. package/dist/core/review/companion.d.ts +35 -0
  413. package/dist/core/review/companion.js +205 -0
  414. package/dist/core/review/document.d.ts +27 -0
  415. package/dist/core/review/document.js +138 -0
  416. package/dist/core/review/project.d.ts +13 -0
  417. package/dist/core/review/project.js +58 -0
  418. package/dist/core/review/realize.d.ts +19 -0
  419. package/dist/core/review/realize.js +217 -0
  420. package/dist/core/review/remap.d.ts +24 -0
  421. package/dist/core/review/remap.js +156 -0
  422. package/dist/core/review/signal.d.ts +5 -0
  423. package/dist/core/review/signal.js +31 -0
  424. package/dist/core/review/stage.d.ts +26 -0
  425. package/dist/core/review/stage.js +184 -0
  426. package/dist/core/review/store.d.ts +46 -0
  427. package/dist/core/review/store.js +163 -0
  428. package/dist/core/review/ticket-filter.d.ts +17 -0
  429. package/dist/core/review/ticket-filter.js +32 -0
  430. package/dist/core/review/types.d.ts +130 -0
  431. package/dist/core/review/types.js +23 -0
  432. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +1 -0
  433. package/dist/core/runtime/__tests__/session-visibility.test.js +119 -0
  434. package/dist/core/runtime/bearings.d.ts +5 -17
  435. package/dist/core/runtime/bearings.js +88 -71
  436. package/dist/core/runtime/broker-protocol.d.ts +31 -8
  437. package/dist/core/runtime/broker.d.ts +15 -1
  438. package/dist/core/runtime/broker.js +573 -141
  439. package/dist/core/runtime/canvas-extensions.d.ts +4 -5
  440. package/dist/core/runtime/canvas-extensions.js +5 -5
  441. package/dist/core/runtime/front-door.js +4 -4
  442. package/dist/core/runtime/headless-pi.d.ts +24 -0
  443. package/dist/core/runtime/headless-pi.js +152 -0
  444. package/dist/core/runtime/kickoff.d.ts +1 -5
  445. package/dist/core/runtime/kickoff.js +1 -5
  446. package/dist/core/runtime/model-registry.d.ts +3 -0
  447. package/dist/core/runtime/model-registry.js +13 -0
  448. package/dist/core/runtime/naming-persist.d.ts +4 -0
  449. package/dist/core/runtime/naming-persist.js +27 -1
  450. package/dist/core/runtime/naming.d.ts +17 -12
  451. package/dist/core/runtime/naming.js +91 -140
  452. package/dist/core/runtime/node-read.js +19 -10
  453. package/dist/core/runtime/nodes.d.ts +9 -14
  454. package/dist/core/runtime/nodes.js +3 -53
  455. package/dist/core/runtime/package-health.d.ts +6 -21
  456. package/dist/core/runtime/package-health.js +12 -123
  457. package/dist/core/runtime/placement-tmux.d.ts +2 -1
  458. package/dist/core/runtime/placement-tmux.js +6 -4
  459. package/dist/core/runtime/placement.d.ts +1 -0
  460. package/dist/core/runtime/placement.js +4 -8
  461. package/dist/core/runtime/promote.js +3 -0
  462. package/dist/core/runtime/recap.d.ts +2 -7
  463. package/dist/core/runtime/recap.js +35 -69
  464. package/dist/core/runtime/revive.js +34 -77
  465. package/dist/core/runtime/session-cycles.d.ts +4 -0
  466. package/dist/core/runtime/session-cycles.js +14 -1
  467. package/dist/core/runtime/session-visibility.d.ts +37 -0
  468. package/dist/core/runtime/session-visibility.js +83 -0
  469. package/dist/core/runtime/spawn.js +10 -22
  470. package/dist/core/runtime/stop-guard.d.ts +1 -1
  471. package/dist/core/runtime/stop-guard.js +18 -13
  472. package/dist/core/runtime/surface-bg.js +1 -1
  473. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  474. package/dist/core/runtime/tmux-chrome.js +1 -1
  475. package/dist/core/runtime/tmux.d.ts +35 -7
  476. package/dist/core/runtime/tmux.js +439 -62
  477. package/dist/core/runtime/tool-group-summary.d.ts +19 -0
  478. package/dist/core/runtime/tool-group-summary.js +88 -0
  479. package/dist/core/scope.d.ts +2 -7
  480. package/dist/core/scope.js +9 -35
  481. package/dist/core/substrate/schema.d.ts +2 -2
  482. package/dist/core/termrender/code-doc.d.ts +12 -0
  483. package/dist/core/termrender/code-doc.js +92 -0
  484. package/dist/core/termrender/display.d.ts +12 -0
  485. package/dist/core/termrender/display.js +19 -0
  486. package/dist/core/termrender/termrender.d.ts +73 -0
  487. package/dist/core/termrender/termrender.js +795 -0
  488. package/dist/core/termrender/version.d.ts +1 -0
  489. package/dist/core/termrender/version.js +1 -0
  490. package/dist/core/tui/terminal.js +1 -2
  491. package/dist/core/user-settings.d.ts +71 -3
  492. package/dist/core/user-settings.js +83 -1
  493. package/dist/daemon/api/__tests__/inbox.test.js +44 -133
  494. package/dist/daemon/api/handlers/human.d.ts +0 -10
  495. package/dist/daemon/api/handlers/human.js +104 -702
  496. package/dist/daemon/api/handlers/inbox.js +113 -142
  497. package/dist/daemon/api/handlers/review-comments.d.ts +2 -0
  498. package/dist/daemon/api/handlers/review-comments.js +500 -0
  499. package/dist/daemon/api/handlers/reviews.d.ts +2 -0
  500. package/dist/daemon/api/handlers/reviews.js +287 -0
  501. package/dist/daemon/api/map.d.ts +22 -7
  502. package/dist/daemon/api/map.js +159 -11
  503. package/dist/daemon/api/server.js +4 -0
  504. package/dist/daemon/cron-run.js +6 -9
  505. package/dist/daemon/crtrd.js +17 -33
  506. package/dist/daemon/fleet.d.ts +1 -8
  507. package/dist/daemon/fleet.js +4 -30
  508. package/dist/daemon/human/finish.d.ts +14 -0
  509. package/dist/daemon/human/finish.js +115 -0
  510. package/dist/daemon/human/sweep.d.ts +6 -0
  511. package/dist/daemon/human/sweep.js +49 -0
  512. package/dist/daemon/messaging/node-message.d.ts +18 -0
  513. package/dist/daemon/messaging/node-message.js +70 -0
  514. package/dist/daemon/review/comment-notify.d.ts +26 -0
  515. package/dist/daemon/review/comment-notify.js +107 -0
  516. package/dist/daemon/review/deliver.d.ts +7 -0
  517. package/dist/daemon/review/deliver.js +56 -0
  518. package/dist/daemon/review/finish.d.ts +22 -0
  519. package/dist/daemon/review/finish.js +254 -0
  520. package/dist/daemon/review/sweep.d.ts +11 -0
  521. package/dist/daemon/review/sweep.js +120 -0
  522. package/dist/index.d.ts +2 -0
  523. package/dist/index.js +2 -2
  524. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +42 -64
  525. package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +1 -0
  526. package/dist/pi-extensions/__tests__/canvas-recap.test.js +159 -0
  527. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +16 -38
  528. package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
  529. package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
  530. package/dist/pi-extensions/canvas-context-intro.d.ts +8 -11
  531. package/dist/pi-extensions/canvas-context-intro.js +50 -104
  532. package/dist/pi-extensions/canvas-recap.d.ts +15 -2
  533. package/dist/pi-extensions/canvas-recap.js +192 -69
  534. package/dist/pi-extensions/canvas-review-boundary.d.ts +59 -0
  535. package/dist/pi-extensions/canvas-review-boundary.js +81 -0
  536. package/dist/pi-extensions/canvas-stophook.d.ts +3 -3
  537. package/dist/pi-extensions/canvas-stophook.js +78 -128
  538. package/dist/pi-extensions/canvas-structured-output.js +52 -8
  539. package/dist/shared/generated-context.d.ts +29 -4
  540. package/dist/shared/generated-context.js +122 -7
  541. package/dist/shared/tool-groups.d.ts +23 -0
  542. package/dist/shared/tool-groups.js +60 -0
  543. package/dist/shared/working-activity.d.ts +8 -0
  544. package/dist/shared/working-activity.js +26 -0
  545. package/dist/types.d.ts +36 -2
  546. package/dist/types.js +51 -0
  547. package/dist/web-client/assets/index-CCPaLeW7.css +2 -0
  548. package/dist/web-client/assets/index-kyOWsnZK.js +86 -0
  549. package/dist/web-client/index.html +2 -2
  550. package/dist/web-client/sw.js +1 -1
  551. package/docs/compat/hearth-crtr-v4.md +2 -2
  552. package/docs/compat/hearth-crtr-v5.md +4 -2
  553. package/docs/public-api.md +3 -3
  554. package/package.json +21 -14
  555. package/runtime.lock.json +4661 -1453
  556. package/scripts/postinstall.mjs +15 -2
  557. package/dist/builtin-pi-packages/pi-mode-switch/README.md +0 -36
  558. package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +0 -36
  559. package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +0 -449
  560. package/dist/builtin-pi-packages/pi-mode-switch/package.json +0 -14
  561. package/dist/builtin-pi-packages/pi-mode-switch/tsconfig.json +0 -9
  562. package/dist/builtin-views/_lib/states.mjs +0 -161
  563. package/dist/builtin-views/canvas/core.mjs +0 -657
  564. package/dist/builtin-views/canvas/text.mjs +0 -58
  565. package/dist/builtin-views/canvas/tui.mjs +0 -168
  566. package/dist/builtin-views/canvas/web.jsx +0 -121
  567. package/dist/builtin-views/chat/core.mjs +0 -684
  568. package/dist/builtin-views/chat/text.mjs +0 -101
  569. package/dist/builtin-views/chat/tui.mjs +0 -360
  570. package/dist/builtin-views/chat/web.jsx +0 -362
  571. package/dist/builtin-views/git-pr/core.mjs +0 -673
  572. package/dist/builtin-views/git-pr/text.mjs +0 -84
  573. package/dist/builtin-views/git-pr/tui.mjs +0 -301
  574. package/dist/builtin-views/git-pr/web.jsx +0 -216
  575. package/dist/builtin-views/inbox/_lib/render.mjs +0 -175
  576. package/dist/builtin-views/inbox/core.mjs +0 -1273
  577. package/dist/builtin-views/inbox/text.mjs +0 -73
  578. package/dist/builtin-views/inbox/tui.mjs +0 -314
  579. package/dist/builtin-views/inbox/web.jsx +0 -188
  580. package/dist/builtin-views/linkedin/core.mjs +0 -906
  581. package/dist/builtin-views/linkedin/text.mjs +0 -69
  582. package/dist/builtin-views/linkedin/tui.mjs +0 -413
  583. package/dist/builtin-views/linkedin/web.jsx +0 -206
  584. package/dist/builtin-views/prompt-review/core.mjs +0 -735
  585. package/dist/builtin-views/prompt-review/text.mjs +0 -15
  586. package/dist/builtin-views/prompt-review/tui.mjs +0 -196
  587. package/dist/builtin-views/prompt-review/web.jsx +0 -484
  588. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.js +0 -50
  589. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.ts +0 -53
  590. package/dist/builtin-views/workspace-sidebar/core.mjs +0 -670
  591. package/dist/builtin-views/workspace-sidebar/text.mjs +0 -53
  592. package/dist/builtin-views/workspace-sidebar/tui.mjs +0 -141
  593. package/dist/builtin-views/workspace-sidebar/web.jsx +0 -109
  594. package/dist/clients/attach/session/mode.d.ts +0 -25
  595. package/dist/clients/attach/session/mode.js +0 -97
  596. package/dist/commands/sys/promptstudio.d.ts +0 -2
  597. package/dist/commands/sys/promptstudio.js +0 -65
  598. package/dist/commands/view-cycle.d.ts +0 -2
  599. package/dist/commands/view-cycle.js +0 -130
  600. package/dist/commands/view-list.d.ts +0 -2
  601. package/dist/commands/view-list.js +0 -66
  602. package/dist/commands/view-new.d.ts +0 -2
  603. package/dist/commands/view-new.js +0 -74
  604. package/dist/commands/view-pick.d.ts +0 -6
  605. package/dist/commands/view-pick.js +0 -129
  606. package/dist/commands/view-run.d.ts +0 -2
  607. package/dist/commands/view-run.js +0 -214
  608. package/dist/commands/view.d.ts +0 -2
  609. package/dist/commands/view.js +0 -31
  610. package/dist/commands/workspace.d.ts +0 -2
  611. package/dist/commands/workspace.js +0 -165
  612. package/dist/core/__tests__/chat-view-reconnect.test.js +0 -105
  613. package/dist/core/__tests__/full/consult-startup-failure.test.js +0 -124
  614. package/dist/core/canvas/__tests__/human-work-outbox.test.js +0 -123
  615. package/dist/core/canvas/human-work-outbox.d.ts +0 -73
  616. package/dist/core/canvas/human-work-outbox.js +0 -261
  617. package/dist/core/command-plugins/store.d.ts +0 -16
  618. package/dist/core/command-plugins/store.js +0 -64
  619. package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +0 -40
  620. package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
  621. package/dist/core/runtime/fault-recovery-nudge.js +0 -3
  622. package/dist/core/tui/__tests__/host-keybindings.test.js +0 -113
  623. package/dist/core/tui/host.d.ts +0 -66
  624. package/dist/core/view/__tests__/transport-cache.test.js +0 -62
  625. package/dist/core/view/bridge.d.ts +0 -10
  626. package/dist/core/view/bridge.js +0 -31
  627. package/dist/core/view/chrome.d.ts +0 -9
  628. package/dist/core/view/chrome.js +0 -22
  629. package/dist/core/view/contract.d.ts +0 -205
  630. package/dist/core/view/contract.js +0 -23
  631. package/dist/core/view/loader.d.ts +0 -31
  632. package/dist/core/view/loader.js +0 -188
  633. package/dist/core/view/stream-local.d.ts +0 -3
  634. package/dist/core/view/stream-local.js +0 -231
  635. package/dist/core/view/transport-cache.d.ts +0 -8
  636. package/dist/core/view/transport-cache.js +0 -38
  637. package/dist/core/view/transport-local.d.ts +0 -7
  638. package/dist/core/view/transport-local.js +0 -83
  639. package/dist/core/view/transport-remote.d.ts +0 -2
  640. package/dist/core/view/transport.d.ts +0 -10
  641. package/dist/core/view/transport.js +0 -15
  642. package/dist/pi-extensions/naming-tool.d.ts +0 -24
  643. package/dist/pi-extensions/naming-tool.js +0 -67
  644. package/dist/prompts/view.d.ts +0 -7
  645. package/dist/prompts/view.js +0 -172
  646. package/dist/web/ViewChrome.d.ts +0 -7
  647. package/dist/web/ViewChrome.js +0 -28
  648. package/dist/web/ViewPane.d.ts +0 -39
  649. package/dist/web/ViewPane.js +0 -48
  650. package/dist/web/index.d.ts +0 -8
  651. package/dist/web/index.js +0 -22
  652. package/dist/web/runtime.d.ts +0 -39
  653. package/dist/web/runtime.js +0 -232
  654. package/dist/web/states.d.ts +0 -24
  655. package/dist/web/states.js +0 -24
  656. package/dist/web/transport-http.d.ts +0 -5
  657. package/dist/web/transport-http.js +0 -34
  658. package/dist/web/transport-stream.d.ts +0 -3
  659. package/dist/web/transport-stream.js +0 -204
  660. package/dist/web-client/assets/index-U_NZ66VE.js +0 -79
  661. package/dist/web-client/assets/index-aaeu4adv.css +0 -2
  662. /package/dist/{builtin-views/workspace-sidebar/__tests__/core.test.d.ts → clients/attach/__tests__/file-review-focus.test.d.ts} +0 -0
  663. /package/dist/clients/attach/__tests__/{visible-paths.test.d.ts → group-activity.test.d.ts} +0 -0
  664. /package/dist/{core/__tests__/chat-view-reconnect.test.d.ts → clients/attach/__tests__/input-controller-extension-command.test.d.ts} +0 -0
  665. /package/dist/{core/__tests__/full/consult-startup-failure.test.d.ts → clients/attach/__tests__/session-identity-refresh.test.d.ts} +0 -0
  666. /package/dist/{core/canvas/__tests__/human-work-outbox.test.d.ts → clients/inbox/__tests__/inbox-controller.test.d.ts} +0 -0
  667. /package/dist/{core/keybindings/__tests__/bespoke-consumers.test.d.ts → clients/inbox/__tests__/mount-panel.test.d.ts} +0 -0
  668. /package/dist/{core/tui/__tests__/host-keybindings.test.d.ts → clients/inbox/review/__tests__/editor-roundtrip.test.d.ts} +0 -0
  669. /package/dist/{core/view/__tests__/transport-cache.test.d.ts → clients/inbox/review/__tests__/remap.test.d.ts} +0 -0
  670. /package/dist/{core/view/__tests__/transport-remote.test.d.ts → clients/inbox/review/__tests__/review-core.test.d.ts} +0 -0
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import { openSync } from 'node:fs';
4
4
  import { enableCompileCache } from 'node:module';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { runCli } from './core/command.js';
7
- import { resolveRoot, hydrateAbsentStoresAndRebuild } from './build-root.js';
7
+ import { resolveRoot } from './build-root.js';
8
8
  import { maybeBootRoot } from './core/runtime/front-door.js';
9
9
  import { maybeAutoUpdate } from './core/auto-update.js';
10
10
  import { ensureOfficialMarketplace, ensureProjectScope } from './core/bootstrap.js';
@@ -57,12 +57,8 @@ async function main() {
57
57
  ensureOfficialMarketplace(process.argv);
58
58
  ensureProjectScope(process.argv);
59
59
  maybeAutoUpdate(process.argv);
60
- // Pass the one-shot unknown-first-token retry seam: on a first-token miss with
61
- // absent HTTP-plugin stores, hydrate them once, rebuild, and re-walk.
62
- // A recognized core first token resolves in `resolveRoot`'s fast path and never
63
- // reaches a first-token miss, so the seam stays off the core fast path.
64
60
  mark('cli.dispatch_start');
65
- await runCli(root, process.argv, { onUnknownFirstTokenMiss: hydrateAbsentStoresAndRebuild });
61
+ await runCli(root, process.argv);
66
62
  mark('cli.dispatch_done');
67
63
  }
68
64
  main().catch((err) => {
@@ -31,7 +31,6 @@ import { recordFault } from '../../../core/runtime/fault.js';
31
31
  import { BG_ATTACHED } from '../../../core/canvas/nav-model.js';
32
32
  import { resolveKeybindings } from '../../../core/keybindings/index.js';
33
33
  import { dispatchSlashCommand, slashCommandList } from '../slash/dispatch.js';
34
- import { resolveInitialMode, requestModeSwitch } from '../session/mode.js';
35
34
  import { tagAttachPane, untagAttachPane } from '../session/pane-tag.js';
36
35
  import { createMemoryRefRefreshCoordinator } from '../session/editor-inventory.js';
37
36
  import { InputController } from '../input/controller.js';
@@ -94,6 +93,8 @@ const IDENTITY_PALETTE = {
94
93
  bold: (s) => s,
95
94
  error: (s) => s,
96
95
  warning: (s) => s,
96
+ diffAdded: (s) => s,
97
+ diffRemoved: (s) => s,
97
98
  bashMode: (s) => s,
98
99
  bashModeAlt: (s) => s,
99
100
  surface: (s) => s,
@@ -244,7 +245,7 @@ test('GraphOverlay suppresses every local-read adornment for a RemoteCanvasSourc
244
245
  });
245
246
  // ---------------------------------------------------------------------------
246
247
  // Phase 3 review 2 — the ENCLOSING attach viewer (slash commands, pane tag,
247
- // detach-reap, Alt+Shift+P mode-switch), not just the GraphOverlay/panel rendering
248
+ // detach-reap), not just the GraphOverlay/panel rendering
248
249
  // the fix above already covers. Same adversarial shape: seed colliding LOCAL
249
250
  // state for the remote node id `a`, then assert the remote path never touches
250
251
  // it — and, symmetrically, that the LOCAL path is byte-for-byte unchanged
@@ -269,17 +270,14 @@ function fakeSlashContext(remote, nodeId) {
269
270
  };
270
271
  return { ctx, notices, sent };
271
272
  }
272
- test('slash autocomplete structurally omits the local-only native canvas commands (/promote, /resume-node, /context) in remote mode, and keeps them in local mode', () => {
273
+ test('slash autocomplete structurally omits local-only native canvas commands in remote mode and keeps them in local mode', () => {
273
274
  const remoteNames = slashCommandList(undefined, true).map((c) => c.name);
274
275
  assert.ok(!remoteNames.includes('promote'), `remote autocomplete must not offer /promote: ${remoteNames.join(',')}`);
275
276
  assert.ok(!remoteNames.includes('resume-node'), `remote autocomplete must not offer /resume-node: ${remoteNames.join(',')}`);
276
277
  assert.ok(!remoteNames.includes('context'), `remote autocomplete must not offer /context: ${remoteNames.join(',')}`);
277
- // Remote-safe canvas commands stay offered.
278
- assert.ok(remoteNames.includes('graph'), 'remote autocomplete must still offer /graph (already remote-safe)');
279
- assert.ok(remoteNames.includes('view'), 'remote autocomplete must still offer /view (self-contained popup)');
280
- // Local (remote=false, the default) is unchanged — all five canvas commands.
278
+ assert.ok(remoteNames.includes('graph'), 'remote autocomplete must still offer /graph');
281
279
  const localNames = slashCommandList().map((c) => c.name);
282
- for (const name of ['graph', 'promote', 'resume-node', 'view', 'context']) {
280
+ for (const name of ['graph', 'promote', 'resume-node', 'context']) {
283
281
  assert.ok(localNames.includes(name), `local autocomplete must still offer /${name}: ${localNames.join(',')}`);
284
282
  }
285
283
  });
@@ -293,9 +291,7 @@ test('dispatchSlashCommand no-ops /promote, /resume-node, /context in remote mod
293
291
  assert.match(notices[0], /not available for a remote attach/, `${cmd} must notify the remote-unsafe message, not proceed into its local handler: ${notices[0]}`);
294
292
  }
295
293
  assert.equal(sent.length, 0, 'no command frame must ever be sent for a gated remote canvas command');
296
- // /graph and /view are UNaffected by the remote gate (graph is already
297
- // remote-safe via GraphOverlay's own `remote` handling; view is self-
298
- // contained). Neither reaches the remote-unsafe notice.
294
+ // /graph is remote-safe via GraphOverlay's own `remote` handling.
299
295
  notices.length = 0;
300
296
  ctx.onGraph = () => notices.push('graph-toggled');
301
297
  dispatchSlashCommand('/graph', ctx);
@@ -332,30 +328,6 @@ test('dispatchSlashCommand leaves the LOCAL (non-remote) path for /promote, /res
332
328
  delete process.env['TMUX_PANE'];
333
329
  }
334
330
  });
335
- test('resolveInitialMode/requestModeSwitch never touch the local mode-switch read/write for a remote attach, and are unchanged for local', () => {
336
- let reads = 0;
337
- const readMode = (_cwd, _nodeId) => {
338
- reads++;
339
- return 'plan'; // poisoned value — must never surface for remote
340
- };
341
- assert.equal(resolveInitialMode('/tmp/cwd', 'a', true, readMode), 'normal', 'remote must always start normal');
342
- assert.equal(reads, 0, 'remote must never read the local mode-switch current file');
343
- assert.equal(resolveInitialMode('/tmp/cwd', 'a', false, readMode), 'plan', 'local must read through unchanged');
344
- assert.equal(reads, 1, 'local must call the injected local reader exactly once');
345
- let writes = 0;
346
- let lastWrite;
347
- const writeRequest = (cwd, nodeId, mode) => {
348
- writes++;
349
- lastWrite = { cwd, nodeId, mode };
350
- };
351
- const remoteOk = requestModeSwitch('/tmp/cwd', 'a', true, 'spec', writeRequest);
352
- assert.equal(remoteOk, false, 'remote Alt+Shift+P must no-op (return false)');
353
- assert.equal(writes, 0, 'remote must never write the local mode-switch request file');
354
- const localOk = requestModeSwitch('/tmp/cwd', 'a', false, 'spec', writeRequest);
355
- assert.equal(localOk, true, 'local Alt+Shift+P must still write through');
356
- assert.equal(writes, 1, 'local must call the injected local writer exactly once');
357
- assert.deepEqual(lastWrite, { cwd: '/tmp/cwd', nodeId: 'a', mode: 'spec' });
358
- });
359
331
  test('tagAttachPane/untagAttachPane never tag/untag the pane for a remote attach, and are unchanged for local', () => {
360
332
  let calls = [];
361
333
  const setOpt = (pane, name, value) => {
@@ -13,6 +13,8 @@ const PALETTE = {
13
13
  bold: (s) => s,
14
14
  error: (s) => s,
15
15
  warning: (s) => s,
16
+ diffAdded: (s) => s,
17
+ diffRemoved: (s) => s,
16
18
  bashMode: (s) => s,
17
19
  bashModeAlt: (s) => s,
18
20
  surface: (s) => s,
@@ -28,41 +30,49 @@ test('attach direct and private control input dispatch through the same action m
28
30
  'crtr.attach.detach': ['ctrl+x'],
29
31
  'crtr.attach.clear-or-detach': [],
30
32
  'crtr.attach.graph.toggle': [],
31
- 'crtr.mode.cycle': ['alt+x'],
33
+ 'crtr.attach.help.toggle': ['alt+shift+k'],
34
+ 'crtr.attach.inbox.toggle': [],
32
35
  'crtr.attach.model-ladder.next': ['alt+z'],
33
36
  'crtr.attach.model-ladder.previous': ['alt+y'],
34
37
  'crtr.attach.command.inspect': ['alt+shift+h'],
35
38
  'crtr.attach.file-review': [],
36
39
  'crtr.attach.profile-files': [],
40
+ 'crtr.attach.whip': [],
37
41
  });
38
42
  const calls = [];
39
43
  const actions = {
40
44
  'crtr.attach.detach': () => calls.push('detach'),
41
45
  'crtr.attach.clear-or-detach': () => calls.push('clear'),
42
46
  'crtr.attach.graph.toggle': () => calls.push('graph'),
43
- 'crtr.mode.cycle': () => calls.push('mode'),
47
+ 'crtr.attach.help.toggle': () => calls.push('help'),
48
+ 'crtr.attach.inbox.toggle': () => calls.push('inbox'),
44
49
  'crtr.attach.model-ladder.next': () => calls.push('ladder'),
45
50
  'crtr.attach.model-ladder.previous': () => calls.push('ladder-back'),
46
51
  'crtr.attach.command.inspect': () => calls.push('inspect'),
47
52
  'crtr.attach.file-review': () => calls.push('review'),
48
53
  'crtr.attach.profile-files': () => calls.push('profile-files'),
54
+ 'crtr.attach.whip': () => calls.push('whip'),
49
55
  };
50
56
  assert.equal(dispatchAttachBinding(bindings, '\x18', actions), true);
51
57
  assert.equal(dispatchAttachBinding(bindings, '\x04', actions), false, 'old detach must not reach the listener action');
52
58
  assert.equal(dispatchAttachBinding(bindings, '\x1bg', actions), false, 'disabled graph must not reach the listener action');
53
- assert.equal(dispatchAttachBinding(bindings, '\x1bx', actions), true);
54
- assert.equal(dispatchAttachBinding(bindings, '\x1bP', actions), false, 'old mode key must not reach the listener action');
59
+ assert.equal(dispatchAttachBinding(bindings, '\x1bx', actions), false, 'removed mode key must stay ordinary input');
60
+ assert.equal(dispatchAttachBinding(bindings, '\x1bP', actions), false, 'removed mode key must stay ordinary input');
55
61
  assert.equal(dispatchAttachBinding(bindings, '\x1bz', actions), true);
56
62
  assert.equal(dispatchAttachBinding(bindings, '\x1bm', actions), false, 'old ladder key must not reach the listener action');
57
63
  assert.equal(dispatchAttachBinding(bindings, '\x1by', actions), true);
58
64
  assert.equal(dispatchAttachBinding(bindings, '\x1bM', actions), false, 'old ladder-back key must not reach the listener action');
59
65
  assert.equal(dispatchAttachBinding(bindings, '\x1b[72;4u', actions), true);
66
+ assert.equal(dispatchAttachBinding(bindings, '\x1b[75;4u', actions), true);
60
67
  assert.equal(dispatchAttachBinding(bindings, '\x06', actions), false, 'disabled direct binding must stay disabled');
61
68
  const privateInput = encodeAttachControlInput('crtr.attach.profile-files');
62
69
  const privateAction = decodeAttachControlInput(privateInput);
63
70
  assert.equal(privateAction, 'crtr.attach.profile-files');
64
71
  dispatchAttachAction(privateAction, actions);
65
- assert.deepEqual(calls, ['detach', 'mode', 'ladder', 'ladder-back', 'inspect', 'profile-files']);
72
+ const helpPrivateInput = encodeAttachControlInput('crtr.attach.help.toggle');
73
+ assert.equal(decodeAttachControlInput(helpPrivateInput), 'crtr.attach.help.toggle');
74
+ dispatchAttachAction('crtr.attach.help.toggle', actions);
75
+ assert.deepEqual(calls, ['detach', 'ladder', 'ladder-back', 'inspect', 'help', 'profile-files', 'help']);
66
76
  assert.equal(decodeAttachControlInput(`${privateInput}x`), undefined, 'whole-input decoding must be exact');
67
77
  assert.equal(decodeAttachControlInput('\x1b_crtr;crtr.attach.not-real\x1b\\'), undefined, 'unknown actions must stay ordinary input');
68
78
  assert.deepEqual(extractAttachControlInput(`before${privateInput}after`), {
@@ -83,28 +93,34 @@ test('closed-inbox footer hint resolves the configured inbox shortcut(s)', () =>
83
93
  // Disabled: omit the shortcut clause and fall back to the CLI affordance,
84
94
  // never render the word "Disabled".
85
95
  const disabled = inboxOpenHint(resolveKeybindings({ 'crtr.tmux.inbox.toggle': [] }));
86
- assert.equal(disabled, 'hl inbox open');
96
+ assert.equal(disabled, 'crtr human list');
87
97
  assert.doesNotMatch(disabled, /Disabled/);
88
98
  });
89
- test('attach startup and reload replace the dispatch/GRAPH snapshots and install each tmux snapshot', () => {
99
+ test('attach startup and reload replace the dispatch/GRAPH snapshots and install each complete tmux snapshot', () => {
90
100
  const first = resolveKeybindings({ 'crtr.attach.detach': ['ctrl+x'], 'crtr.graph.focus': ['f'] });
91
101
  const second = resolveKeybindings({
92
102
  'crtr.attach.detach': ['ctrl+z'],
93
103
  'crtr.graph.focus': ['r'],
94
104
  'crtr.graph.revive': [],
95
105
  });
96
- const snapshots = [first, second];
106
+ const settings = [
107
+ { bindings: first, tmuxPassthrough: ['crtr.attach.detach'] },
108
+ { bindings: second, tmuxPassthrough: ['crtr.attach.copy.message'] },
109
+ ];
97
110
  const graphSnapshots = [];
98
111
  const installed = [];
99
- let active = refreshAttachBindingSnapshot(() => snapshots.shift(), (bindings) => graphSnapshots.push(bindings), () => true, (bindings) => installed.push(bindings));
100
- assert.equal(matchesAttachBinding(active, 'crtr.attach.detach', '\x18'), true, 'startup snapshot drives attach dispatch');
101
- assert.equal(active.gestures('crtr.graph.focus')[0], 'f', 'startup snapshot reaches GRAPH');
102
- active = refreshAttachBindingSnapshot(() => snapshots.shift(), (bindings) => graphSnapshots.push(bindings), () => true, (bindings) => installed.push(bindings));
103
- assert.equal(matchesAttachBinding(active, 'crtr.attach.detach', '\x18'), false, 'reload replaces the old attach snapshot');
104
- assert.equal(matchesAttachBinding(active, 'crtr.attach.detach', '\x1a'), true, 'reload dispatches through the new attach snapshot');
105
- assert.equal(active.gestures('crtr.graph.focus')[0], 'r', 'reload replaces GRAPH bindings too');
112
+ let active = refreshAttachBindingSnapshot(() => settings.shift(), (bindings) => graphSnapshots.push(bindings), () => true, (bindings, tmuxPassthrough) => installed.push({ bindings, tmuxPassthrough }));
113
+ assert.equal(matchesAttachBinding(active.bindings, 'crtr.attach.detach', '\x18'), true, 'startup snapshot drives attach dispatch');
114
+ assert.equal(active.bindings.gestures('crtr.graph.focus')[0], 'f', 'startup snapshot reaches GRAPH');
115
+ active = refreshAttachBindingSnapshot(() => settings.shift(), (bindings) => graphSnapshots.push(bindings), () => true, (bindings, tmuxPassthrough) => installed.push({ bindings, tmuxPassthrough }));
116
+ assert.equal(matchesAttachBinding(active.bindings, 'crtr.attach.detach', '\x18'), false, 'reload replaces the old attach snapshot');
117
+ assert.equal(matchesAttachBinding(active.bindings, 'crtr.attach.detach', '\x1a'), true, 'reload dispatches through the new attach snapshot');
118
+ assert.equal(active.bindings.gestures('crtr.graph.focus')[0], 'r', 'reload replaces GRAPH bindings too');
106
119
  assert.deepEqual(graphSnapshots, [first, second]);
107
- assert.deepEqual(installed, [first, second], 'the unified tmux installer receives startup and reload snapshots');
120
+ assert.deepEqual(installed, [
121
+ { bindings: first, tmuxPassthrough: ['crtr.attach.detach'] },
122
+ { bindings: second, tmuxPassthrough: ['crtr.attach.copy.message'] },
123
+ ], 'the unified tmux installer receives startup and reload settings snapshots');
108
124
  });
109
125
  test('GRAPH navigation and hints use effective bindings rather than default literals', () => {
110
126
  const bindings = resolveKeybindings({
@@ -1,7 +1,7 @@
1
1
  // Regression coverage for the attach viewer's display-only folding of
2
2
  // crouter-generated context. The body must stay agent-visible and expandable,
3
- // while bearings, situational updates, fresh-revive kickoffs, context nudges,
4
- // and node inbox digests share one compact renderer by default.
3
+ // while bearings, situational updates, fresh-revive kickoffs, runtime steering,
4
+ // recovery prompts, and node inbox digests share one compact renderer by default.
5
5
  import assert from 'node:assert/strict';
6
6
  import { readFileSync } from 'node:fs';
7
7
  import { dirname, join } from 'node:path';
@@ -13,7 +13,7 @@ import { applyTheme, attachMarkdownTheme } from '../config.js';
13
13
  import { ChatView } from '../render/chat-view.js';
14
14
  import { ContextMessageComponent } from '../render/context-message.js';
15
15
  import { styleAttachMarkdownHeadings } from '../render/markdown-headings.js';
16
- import { CONTEXT_NUDGE_CUSTOM_TYPE, REVIVE_KICKOFF_SENTINEL, generatedContextPresentation, } from '../../../shared/generated-context.js';
16
+ import { AUTH_FAULT_RECOVERY_BODY, CONNECTION_FAULT_RECOVERY_BODY, CONTEXT_INTRO_CUSTOM_TYPE, CONTEXT_NUDGE_CUSTOM_TYPE, PROVIDER_FAULT_RECOVERY_BODY, REVIVE_KICKOFF_SENTINEL, RUNTIME_RESTART_CONTINUATION, STALL_REPROMPT, formatModelFallbackRecovery, formatPersonaTransition, formatStructuredOutputReprompt, generatedContextExpandedBody, generatedContextPresentation, } from '../../../shared/generated-context.js';
17
17
  const HERE = dirname(fileURLToPath(import.meta.url));
18
18
  const CHAT_VIEW = readFileSync(join(HERE, '..', 'render/chat-view.ts'), 'utf8');
19
19
  const identity = (s) => s;
@@ -23,7 +23,9 @@ test('collapsed by default: body text is not rendered until expanded', () => {
23
23
  const collapsed = new ContextMessageComponent(body, false, identity, identity, 'situational context', ' hint');
24
24
  const collapsedRender = collapsed.render(80);
25
25
  const collapsedLines = collapsedRender.join('\n');
26
- assert.equal(collapsedRender.length, 1, 'a collapsed row has no surrounding blank line');
26
+ assert.equal(collapsedRender.length, 3, 'a collapsed row has one blank line above and below');
27
+ assert.equal(collapsedRender[0], '');
28
+ assert.equal(collapsedRender.at(-1), '');
27
29
  assert.match(collapsedLines, /\[situational context\]/);
28
30
  assert.doesNotMatch(collapsedLines, /mid-checkout/, 'collapsed state must never leak the body');
29
31
  collapsed.setExpanded(true);
@@ -34,7 +36,7 @@ test('collapsed by default: body text is not rendered until expanded', () => {
34
36
  assert.deepEqual(expandedRender.slice(0, -1), normalUserRender, 'expanded generated context uses the ordinary user-message surface');
35
37
  assert.equal(expandedRender.at(-1), '', 'an expanded block leaves one blank line below its body');
36
38
  });
37
- test('generated rows add no leading spacer after prior transcript content', async () => {
39
+ test('generated rows have a leading spacer after prior transcript content', async () => {
38
40
  const container = new Container();
39
41
  const tui = { requestRender() { }, terminal: { rows: 40 } };
40
42
  const view = new ChatView(tui, container, { toolOutputExpanded: false });
@@ -49,7 +51,74 @@ test('generated rows add no leading spacer after prior transcript content', asyn
49
51
  const lines = container.render(80).map((line) => line.replace(/\x1b\[[0-9;]*m/g, ''));
50
52
  const generatedIndex = lines.findIndex((line) => line.includes('[crtr revive]'));
51
53
  assert.notEqual(generatedIndex, -1);
52
- assert.match(lines[generatedIndex - 1] ?? '', /before/, 'the collapsed row follows prior content directly');
54
+ assert.equal(lines[generatedIndex - 1], '', 'the collapsed row has one blank line above it');
55
+ assert.equal(lines[generatedIndex + 1], '', 'the collapsed row has one blank line below it');
56
+ });
57
+ test('adjacent padded transcript blocks share one blank boundary row', async () => {
58
+ const container = new Container();
59
+ const tui = { requestRender() { }, terminal: { rows: 40 } };
60
+ const view = new ChatView(tui, container, { toolOutputExpanded: false });
61
+ await view.applySnapshot({
62
+ messages: [
63
+ { role: 'assistant', content: [{ type: 'text', text: 'before' }], stopReason: 'stop' },
64
+ {
65
+ role: 'custom',
66
+ customType: CONTEXT_INTRO_CUSTOM_TYPE,
67
+ display: true,
68
+ content: 'bearings body',
69
+ },
70
+ { role: 'user', content: `${REVIVE_KICKOFF_SENTINEL} — full disk bearings` },
71
+ ],
72
+ stats: {},
73
+ state: { isStreaming: false },
74
+ });
75
+ const lines = container.render(80).map((line) => line.replace(/\x1b\[[0-9;]*m/g, ''));
76
+ const bearingsIndex = lines.findIndex((line) => line.includes('[crtr context]'));
77
+ const reviveIndex = lines.findIndex((line) => line.includes('[crtr revive]'));
78
+ assert.notEqual(bearingsIndex, -1);
79
+ assert.equal(reviveIndex, bearingsIndex + 2, 'the two padded blocks share exactly one blank row');
80
+ assert.equal(lines[bearingsIndex + 1], '');
81
+ });
82
+ test('Ctrl+O expands context, revive, and inbox details without unfolding continuations', async () => {
83
+ const container = new Container();
84
+ const tui = { requestRender() { }, terminal: { rows: 40 } };
85
+ const view = new ChatView(tui, container, { toolOutputExpanded: false });
86
+ const internals = view;
87
+ internals.summarizeToolCalls = true;
88
+ internals.foldSettledTools = true;
89
+ internals.showGroupSummaries = true;
90
+ await view.applySnapshot({
91
+ messages: [
92
+ {
93
+ role: 'custom',
94
+ customType: CONTEXT_INTRO_CUSTOM_TYPE,
95
+ display: true,
96
+ content: '<auto-loaded-context>\nloaded INDEX.md content\n</auto-loaded-context>',
97
+ },
98
+ { role: 'user', content: `${REVIVE_KICKOFF_SENTINEL}\n<yield-message>resume from this note</yield-message>` },
99
+ { role: 'user', content: RUNTIME_RESTART_CONTINUATION },
100
+ {
101
+ role: 'custom',
102
+ customType: CONTEXT_NUDGE_CUSTOM_TYPE,
103
+ display: true,
104
+ content: '[crtr] Context ~150k. private context reminder',
105
+ },
106
+ { role: 'user', content: 'From child-node-123 — 1 update:\n [update] private inbox detail' },
107
+ ],
108
+ stats: {},
109
+ state: { isStreaming: false },
110
+ });
111
+ assert.doesNotMatch(container.render(80).join('\n'), /loaded INDEX\.md content|resume from this note|runtime-restart-continuation|private context reminder|private inbox detail/);
112
+ assert.deepEqual(view.toggleToolsExpanded(), { kind: 'summaries', shown: false });
113
+ assert.equal(internals.toolOutputExpanded, true);
114
+ const expanded = container.render(80).join('\n');
115
+ assert.match(expanded, /loaded INDEX\.md content/);
116
+ assert.match(expanded, /resume from this note/);
117
+ assert.doesNotMatch(expanded, /runtime-restart-continuation|private context reminder/);
118
+ assert.match(expanded, /private inbox detail/, 'an expanded inbox card shows the actual delivered update');
119
+ assert.deepEqual(view.toggleToolsExpanded(), { kind: 'summaries', shown: true });
120
+ assert.equal(internals.toolOutputExpanded, false);
121
+ assert.doesNotMatch(container.render(80).join('\n'), /loaded INDEX\.md content|resume from this note|runtime-restart-continuation|private context reminder|private inbox detail/);
53
122
  });
54
123
  test('the crtr-context label/hint keep their defaults when callers omit the new params', () => {
55
124
  const bearings = new ContextMessageComponent('some bearings body', false, identity, identity);
@@ -57,6 +126,45 @@ test('the crtr-context label/hint keep their defaults when callers omit the new
57
126
  assert.match(line, /\[crtr context\]/);
58
127
  assert.match(line, /orienting bearings/);
59
128
  });
129
+ test('expanded crtr context and revive cards disclose memory and the yield note only', () => {
130
+ const contextBody = [
131
+ '<crtr-bearings>',
132
+ 'node and project details that stay folded',
133
+ '</crtr-bearings>',
134
+ '<memory kind="knowledge">',
135
+ 'memory catalog that stays folded',
136
+ '</memory>',
137
+ '<auto-loaded-context>',
138
+ '<memory kind="knowledge" name="project">',
139
+ 'loaded INDEX.md content',
140
+ '</memory>',
141
+ '</auto-loaded-context>',
142
+ '<project_context>',
143
+ 'environment details that stay folded',
144
+ '</project_context>',
145
+ ].join('\n');
146
+ const context = generatedContextPresentation({
147
+ role: 'custom',
148
+ customType: CONTEXT_INTRO_CUSTOM_TYPE,
149
+ content: contextBody,
150
+ });
151
+ assert.equal(generatedContextExpandedBody(context), '<memory kind="knowledge" name="project">\nloaded INDEX.md content\n</memory>');
152
+ const reviveBody = [
153
+ `${REVIVE_KICKOFF_SENTINEL} — full disk bearings`,
154
+ '<roadmap>roadmap details that stay folded</roadmap>',
155
+ '<yield-message>',
156
+ 'Resume the migration from the recorded checkpoint.',
157
+ '</yield-message>',
158
+ '<context-dir>context listing that stays folded</context-dir>',
159
+ ].join('\n');
160
+ const revive = generatedContextPresentation({ role: 'user', content: reviveBody });
161
+ assert.equal(generatedContextExpandedBody(revive), 'Resume the migration from the recorded checkpoint.');
162
+ const noYield = generatedContextPresentation({
163
+ role: 'user',
164
+ content: `${REVIVE_KICKOFF_SENTINEL}\n<yield-message/>`,
165
+ });
166
+ assert.equal(generatedContextExpandedBody(noYield), '');
167
+ });
60
168
  test('fresh-revive kickoff and both context-nudge roles classify as generated context', () => {
61
169
  const revive = generatedContextPresentation({
62
170
  role: 'user',
@@ -80,7 +188,35 @@ test('fresh-revive kickoff and both context-nudge roles classify as generated co
80
188
  assert.equal(inbox?.label, 'crtr inbox');
81
189
  assert.equal(inbox?.summary, '2 updates from child-node-123');
82
190
  });
191
+ test('runtime steering and recovery prompts classify without hiding their full bodies', () => {
192
+ const personaBody = formatPersonaTransition('You are now an orchestrator.');
193
+ const persona = generatedContextPresentation({ role: 'user', content: personaBody });
194
+ assert.equal(persona?.kind, 'persona-transition');
195
+ assert.equal(persona?.body, personaBody);
196
+ const structuredBody = formatStructuredOutputReprompt(JSON.stringify({ type: 'object' }, null, 2));
197
+ assert.equal(generatedContextPresentation({ role: 'user', content: STALL_REPROMPT })?.summary, 'completion required');
198
+ assert.equal(generatedContextPresentation({ role: 'user', content: structuredBody })?.summary, 'structured output required');
199
+ const recoveries = [
200
+ [AUTH_FAULT_RECOVERY_BODY, 'provider credentials updated'],
201
+ [CONNECTION_FAULT_RECOVERY_BODY, 'network connection restored'],
202
+ [PROVIDER_FAULT_RECOVERY_BODY, 'provider retry'],
203
+ [formatModelFallbackRecovery('old/model', 'new/model:high', 'credential'), 'model route changed'],
204
+ [formatModelFallbackRecovery('custom(provider)/model', 'new/model:high', 'not-found'), 'model route changed'],
205
+ [RUNTIME_RESTART_CONTINUATION, 'continuing from where it left off'],
206
+ ];
207
+ for (const [body, summary] of recoveries) {
208
+ const presentation = generatedContextPresentation({ role: 'user', content: body });
209
+ assert.equal(presentation?.kind, 'recovery');
210
+ assert.equal(presentation?.label, 'crouter continuation');
211
+ assert.equal(presentation?.summary, summary);
212
+ assert.equal(presentation?.body, body);
213
+ }
214
+ assert.equal(generatedContextPresentation({ role: 'user', content: 'continue' }), null, 'a human one-word continue is not mistaken for runtime recovery');
215
+ const unmarkedModelRecovery = formatModelFallbackRecovery('custom(provider)/model', 'new/model:high', 'not-found').split('\n').slice(1, -1).join('\n');
216
+ assert.equal(generatedContextPresentation({ role: 'user', content: unmarkedModelRecovery }), null, 'a human message matching the recovery prose lacks the producer marker');
217
+ });
83
218
  test('render/chat-view.ts routes the shared generated-context classification through the foldable component', () => {
84
219
  assert.match(CHAT_VIEW, /generatedContextPresentation\(message\)/);
220
+ assert.match(CHAT_VIEW, /generatedContextExpandedBody\(generated\)/);
85
221
  assert.match(CHAT_VIEW, /new ContextMessageComponent\(/);
86
222
  });
@@ -28,7 +28,7 @@ test('detects crtr in bash command position, not heredoc body prose', () => {
28
28
  assert.equal(isCrtrBashCommand('crtr node new -h'), true);
29
29
  assert.equal(isCrtrBashCommand('crtr node inspect snapshot --node abc'), true);
30
30
  assert.equal(isCrtrBashCommand('crtr sys daemon status'), true);
31
- assert.equal(isCrtrBashCommand('npm test && /usr/local/bin/crouter surface view run inbox'), true);
31
+ assert.equal(isCrtrBashCommand('npm test && /usr/local/bin/crouter surface web serve'), true);
32
32
  assert.equal(isCrtrBashCommand("cat <<'EOF'\nask about crtr node new\nEOF\necho done"), false);
33
33
  assert.equal(isCrtrBashCommand('echo crtr node new'), false);
34
34
  });
@@ -51,6 +51,13 @@ test('styles crtr structural output and status glyphs', () => {
51
51
  assert.match(rendered, /<success>● active/);
52
52
  assert.match(rendered, /<error>Command exited/);
53
53
  });
54
+ test('crtr results do not invalidate their owning tool component', () => {
55
+ let ownerInvalidations = 0;
56
+ const def = createCrtrBashToolDefinition({ command: 'crtr canvas dashboard' });
57
+ const component = def.renderResult({ content: [{ type: 'text', text: 'dashboard' }] }, { expanded: false }, theme, { invalidate: () => { ownerInvalidations++; } });
58
+ component.invalidate?.();
59
+ assert.equal(ownerInvalidations, 0);
60
+ });
54
61
  // Help output is structural schema text, never a command result, so the
55
62
  // viewer detects it from the invocation itself and gives it help-specific
56
63
  // collapsed chrome rather than treating it as a normal result preview.
@@ -442,7 +449,7 @@ test('renderCall uses a mapped Nerd Font glyph and one line for every mapped roo
442
449
  { command: 'crtr pkg plugin list', iconTokens: ['pkg', 'plugin', 'list'], path: 'pkg plugin list' },
443
450
  { command: 'crtr push update', iconTokens: ['push', 'update'], path: 'push update' },
444
451
  { command: 'crtr search web', iconTokens: ['search', 'web'], path: 'search web' },
445
- { command: 'crtr surface view list', iconTokens: ['surface', 'view', 'list'], path: 'surface view list' },
452
+ { command: 'crtr surface attach to demo', iconTokens: ['surface', 'attach', 'to'], path: 'surface attach to demo' },
446
453
  { command: 'crtr sys doctor', iconTokens: ['sys', 'doctor'], path: 'sys doctor' },
447
454
  ];
448
455
  for (const { command, iconTokens, path } of cases) {
@@ -506,7 +513,7 @@ const WIDE_GENERIC_TABLE_OUTPUT = [
506
513
  ...Array.from({ length: 24 }, (_, i) => `| plugin-${String(i).padStart(2, '0')} | 1.0.${i} | This is a deliberately over-wide description cell that used to wrap the collapsed card mid-cell for row ${i} | ${i % 2 === 0 ? 'enabled' : 'disabled'} |`),
507
514
  ].join('\n');
508
515
  test('generic collapsed fallback renders wide GFM tables aligned, clipped, and row-capped instead of raw pipe rows', () => {
509
- const def = createCrtrBashToolDefinition({ command: 'crtr surface view run catalog' });
516
+ const def = createCrtrBashToolDefinition({ command: 'crtr surface web serve' });
510
517
  const rendered = def
511
518
  .renderResult({ content: [{ type: 'text', text: WIDE_GENERIC_TABLE_OUTPUT }] }, { expanded: false }, plainTheme, {})
512
519
  .render(58)
@@ -531,7 +538,7 @@ const HEADERLESS_TABLE_TAIL_OUTPUT = [
531
538
  '| mr2ejzaw-6f70e858 | preview-roadmap | /Users/silasrhyneer/Code/cli/crouter | done |',
532
539
  ].join('\n');
533
540
  test('generic collapsed fallback aligns a header-less truncated table tail by column count', () => {
534
- const def = createCrtrBashToolDefinition({ command: 'crtr surface view run catalog' });
541
+ const def = createCrtrBashToolDefinition({ command: 'crtr surface web serve' });
535
542
  const rendered = def
536
543
  .renderResult({ content: [{ type: 'text', text: HEADERLESS_TABLE_TAIL_OUTPUT }] }, { expanded: false }, plainTheme, {})
537
544
  .render(64)
@@ -544,7 +551,7 @@ test('generic collapsed fallback aligns a header-less truncated table tail by co
544
551
  assert.equal(rows[1].indexOf('/Users'), rows[2].indexOf('/Users'));
545
552
  });
546
553
  test('generic collapsed fallback renders the pi truncation marker as one muted line', () => {
547
- const def = createCrtrBashToolDefinition({ command: 'crtr surface view run catalog' });
554
+ const def = createCrtrBashToolDefinition({ command: 'crtr surface web serve' });
548
555
  const marker = '[Showing lines 951-1000 of 1000 (50.0KB limit). Full output: /tmp/pi-bash-output.log]';
549
556
  const rendered = def
550
557
  .renderResult({ content: [{ type: 'text', text: `last retained line\n${marker}` }] }, { expanded: false }, theme, {})
@@ -560,7 +567,7 @@ const NO_EDGE_PIPE_TABLE_OUTPUT = [
560
567
  'beta | 2.1.0 | disabled',
561
568
  ].join('\n');
562
569
  test('generic collapsed fallback aligns a GFM table whose rows omit both outer pipes', () => {
563
- const def = createCrtrBashToolDefinition({ command: 'crtr surface view run catalog' });
570
+ const def = createCrtrBashToolDefinition({ command: 'crtr surface web serve' });
564
571
  const rendered = def
565
572
  .renderResult({ content: [{ type: 'text', text: NO_EDGE_PIPE_TABLE_OUTPUT }] }, { expanded: false }, plainTheme, {})
566
573
  .render(60)
@@ -575,7 +582,7 @@ test('generic collapsed fallback aligns a GFM table whose rows omit both outer p
575
582
  assert.equal(alphaRow.indexOf('1.0.0'), betaRow.indexOf('2.1.0'));
576
583
  });
577
584
  test('a stray line containing a single literal pipe is not mistaken for a table row', () => {
578
- const def = createCrtrBashToolDefinition({ command: 'crtr surface view run catalog' });
585
+ const def = createCrtrBashToolDefinition({ command: 'crtr surface web serve' });
579
586
  const rendered = def
580
587
  .renderResult({ content: [{ type: 'text', text: 'warning: use x | y instead' }] }, { expanded: false }, plainTheme, {})
581
588
  .render(60)
@@ -1213,7 +1220,7 @@ test('crtr push urgent/final cards collapse to a one-line outcome + report basen
1213
1220
  // always just durable queue state, so the card collapses to one posted line.
1214
1221
  // The summarizer keys on the stable `Queued for the human` prefix; the inbox-
1215
1222
  // affordance tail resolves per call, so this fixture pins one resolved form.
1216
- const QUEUED_FOLLOW_UP = 'Queued for the human. Their answer is pushed to your inbox and wakes you when they respond — never poll, verify it opened, or block. To see the queue, press ⌥I (or run `hl inbox open` at a terminal).';
1223
+ const QUEUED_FOLLOW_UP = 'Queued for the human. Their answer is pushed to your inbox and wakes you when they respond — never poll, verify it opened, or block. To see the queue, press ⌥I in a node viewer (or run `crtr human list` for the queue).';
1217
1224
  const HUMAN_ASK_QUEUED_OUTPUT = [
1218
1225
  '- job_id: mrASK0001',
1219
1226
  '',
@@ -1237,29 +1244,32 @@ test('a crtr human ask card collapses to a posted status + question teaser, not
1237
1244
  assert.match(expanded, /job_id: mrASK0001/);
1238
1245
  assert.match(expanded, /wakes you when they respond/);
1239
1246
  });
1240
- const HUMAN_REVIEW_QUEUED_OUTPUT = [
1247
+ const HUMAN_REVIEW_NEW_OUTPUT = [
1241
1248
  '- job_id: mrREV0001',
1242
1249
  '',
1243
1250
  '**dir:** /Users/silas/Code/cli/crouter',
1244
1251
  '',
1245
- '**output:** /Users/silas/Code/cli/crouter/spec.review.md',
1252
+ '**output:** /Users/silas/Code/cli/crouter/feedback.json',
1246
1253
  '',
1247
- `**follow_up:** ${QUEUED_FOLLOW_UP}`,
1254
+ '- review_id: review-0001',
1255
+ '',
1256
+ '**follow_up:** The review is live for the person in the attach viewer with its companion agent. Approval is pushed to the origin inbox when submitted.',
1248
1257
  ].join('\n');
1249
- test('a crtr human review card collapses to a posted status + file basename, not the raw fields', () => {
1250
- const def = createCrtrBashToolDefinition({ command: 'crtr human review /Users/silas/Code/cli/crouter/spec.md' });
1258
+ test('a crtr human review new card collapses to its live companion status + file basename, not the raw fields', () => {
1259
+ const def = createCrtrBashToolDefinition({ command: 'crtr human review new /Users/silas/Code/cli/crouter/spec.md --subtitle "Review the implementation."' });
1251
1260
  const collapsed = def
1252
- .renderResult({ content: [{ type: 'text', text: HUMAN_REVIEW_QUEUED_OUTPUT }] }, { expanded: false }, theme, {})
1261
+ .renderResult({ content: [{ type: 'text', text: HUMAN_REVIEW_NEW_OUTPUT }] }, { expanded: false }, theme, {})
1253
1262
  .render(140)
1254
1263
  .join('\n');
1255
- assert.match(collapsed, /<accent>review posted: spec\.md → waiting on human<\/accent>/);
1264
+ assert.match(collapsed, /<accent>review posted: spec\.md → live with companion<\/accent>/);
1256
1265
  assert.doesNotMatch(collapsed, /- job_id:/);
1257
1266
  const expanded = def
1258
- .renderResult({ content: [{ type: 'text', text: HUMAN_REVIEW_QUEUED_OUTPUT }] }, { expanded: true }, theme, {})
1267
+ .renderResult({ content: [{ type: 'text', text: HUMAN_REVIEW_NEW_OUTPUT }] }, { expanded: true }, theme, {})
1259
1268
  .render(140)
1260
1269
  .join('\n');
1261
1270
  assert.match(expanded, /job_id: mrREV0001/);
1262
- assert.match(expanded, /wakes you when they respond/);
1271
+ assert.match(expanded, /review_id: review-0001/);
1272
+ assert.match(expanded, /Approval is pushed to the origin inbox when\s+submitted/);
1263
1273
  });
1264
1274
  const HUMAN_LIST_OUTPUT = [
1265
1275
  '- total: 2',
@@ -1955,7 +1965,6 @@ const SYS_SETUP_OUTPUT = [
1955
1965
  '',
1956
1966
  'Packages:',
1957
1967
  '- pi-crtr-extensions — crtr companion extensions. (installed)',
1958
- '- pi-mode-switch — Alt+Shift+P mode cycling. (installed)',
1959
1968
  '- pi-claude-oauth-adapter — OAuth adapter. (not installed)',
1960
1969
  '',
1961
1970
  'System deps:',
@@ -1971,7 +1980,7 @@ test('a crtr sys setup card collapses to an ok/pending step digest, not the raw
1971
1980
  .renderResult({ content: [{ type: 'text', text: SYS_SETUP_OUTPUT }] }, { expanded: false }, theme, {})
1972
1981
  .render(140)
1973
1982
  .join('\n');
1974
- assert.match(collapsed, /<warning>3 ok · 2 pending<\/warning>/);
1983
+ assert.match(collapsed, /<warning>2 ok · 2 pending<\/warning>/);
1975
1984
  assert.match(collapsed, /<muted>pi-claude-oauth-adapter, nvim<\/muted>/);
1976
1985
  assert.doesNotMatch(collapsed, /Packages:/);
1977
1986
  const expanded = def
@@ -1984,7 +1993,7 @@ test('a crtr sys setup card collapses to an ok/pending step digest, not the raw
1984
1993
  .renderResult({ content: [{ type: 'text', text: SYS_SETUP_OUTPUT.replace('(not installed)', '(installed)').replace('brew install neovim', '✓ installed') }] }, { expanded: false }, theme, {})
1985
1994
  .render(140)
1986
1995
  .join('\n');
1987
- assert.match(allOk, /<success>5 steps ok<\/success>/);
1996
+ assert.match(allOk, /<success>4 steps ok<\/success>/);
1988
1997
  });
1989
1998
  const SYS_DOCTOR_PASS_OUTPUT = [
1990
1999
  '- ok: true',
@@ -2090,28 +2099,3 @@ test('a crtr sys feedback card collapses to a filed/saved-locally pointer, not t
2090
2099
  .join('\n');
2091
2100
  assert.match(expanded, /gh not available: not found/);
2092
2101
  });
2093
- const SURFACE_VIEW_LIST_OUTPUT = [
2094
- 'canvas Canvas [builtin] Live agent graph — who is working, who is blocked',
2095
- 'chat Chat [builtin] Portable chat-as-a-view core',
2096
- 'workspace-sidebar Workspace [builtin] Left rail for `crtr workspace` — this graph + other agents in this cwd',
2097
- ].join('\n');
2098
- test('a crtr surface view list card collapses to a view count + id digest, not the raw rows', () => {
2099
- const def = createCrtrBashToolDefinition({ command: 'crtr surface view list' });
2100
- const collapsed = def
2101
- .renderResult({ content: [{ type: 'text', text: SURFACE_VIEW_LIST_OUTPUT }] }, { expanded: false }, theme, {})
2102
- .render(140)
2103
- .join('\n');
2104
- assert.match(collapsed, /3 views/);
2105
- assert.match(collapsed, /<muted>canvas, chat, workspace-sidebar<\/muted>/);
2106
- assert.doesNotMatch(collapsed, /Live agent graph/);
2107
- const expanded = def
2108
- .renderResult({ content: [{ type: 'text', text: SURFACE_VIEW_LIST_OUTPUT }] }, { expanded: true }, theme, {})
2109
- .render(140)
2110
- .join('\n');
2111
- assert.match(expanded, /Live agent graph/);
2112
- const empty = def
2113
- .renderResult({ content: [{ type: 'text', text: 'No views found. Scaffold one with the view new leaf.' }] }, { expanded: false }, theme, {})
2114
- .render(140)
2115
- .join('\n');
2116
- assert.match(empty, /No views found/);
2117
- });
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import test from 'node:test';
3
- import { ensureRenderer, isRendererReady } from '@crouton-kit/humanloop';
3
+ import { ensureRenderer, isRendererReady } from '../../../core/termrender/termrender.js';
4
4
  import { transformDiagramFences } from '../render/diagram.js';
5
5
  // This asserts a REAL termrender render (box-drawing glyphs), so it only holds
6
6
  // once the managed renderer is provisioned — true in the full tier and on a dev