@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
@@ -14,10 +14,10 @@ import { readConfig, readRawConfigAtRoot, readRawScopeConfig, updateConfig, upda
14
14
  import { findProjectScopeRoots, userScopeRoot } from '../../core/scope.js';
15
15
  import { loadProfileManifest, profileRoot } from '../../core/profiles/manifest.js';
16
16
  import { USER_SETTINGS } from '../../core/user-settings.js';
17
- import { BINDING_CATALOG, formatBinding, formatGesture, matchesPiTuiInput, persistUserKeybindings, resolveKeybindings, KeybindingConcurrentEditError, KeybindingValidationError, } from '../../core/keybindings/index.js';
17
+ import { BINDING_CATALOG, formatBinding, formatGesture, isAttachPaneBinding, matchesPiTuiInput, persistUserKeybindings, resolveKeybindings, KeybindingConcurrentEditError, KeybindingValidationError, } from '../../core/keybindings/index.js';
18
18
  import { configuredLadderProviders, inferPortableModelSelection } from '../../core/runtime/model-selection.js';
19
19
  import { cliClient } from '../api-client.js';
20
- import { installTmuxBindings } from '../../core/runtime/tmux-chrome.js';
20
+ import { installTmuxBindings, occupiedTmuxRootGestures } from '../../core/runtime/tmux-chrome.js';
21
21
  const ANSI_GREEN = (s) => `\x1b[32m${s}\x1b[39m`;
22
22
  const ANSI_YELLOW = (s) => `\x1b[33m${s}\x1b[39m`;
23
23
  const theme = {
@@ -1316,6 +1316,7 @@ export class SetupWizard {
1316
1316
  keyDiagnostics = [];
1317
1317
  keyConfirm = null;
1318
1318
  keyNotice;
1319
+ keyTmuxOccupancy;
1319
1320
  brokerLimitIndex = 0;
1320
1321
  brokerLimitNotice;
1321
1322
  settingsIndex = 0;
@@ -1326,7 +1327,7 @@ export class SetupWizard {
1326
1327
  _focused = false;
1327
1328
  onSubmit;
1328
1329
  onCancel;
1329
- constructor(manifest, installedPackageIds, systemTools, tui, agentDir, runtime, registry, openingBindings, rawKeybindings, terminalRows) {
1330
+ constructor(manifest, installedPackageIds, systemTools, tui, agentDir, runtime, registry, openingBindings, rawKeybindings, terminalRows, rawTmuxPassthrough = undefined) {
1330
1331
  this.manifest = manifest;
1331
1332
  this.providers = new ProviderPanel(tui, agentDir, runtime, registry);
1332
1333
  // The panel drives OAuth async; bust our line cache when it transitions so the panel's
@@ -1338,7 +1339,7 @@ export class SetupWizard {
1338
1339
  this.systemTools = systemTools;
1339
1340
  this.terminalRows = terminalRows;
1340
1341
  this.openingBindings = openingBindings;
1341
- this.keyDraft = new SetupKeybindingsDraft(rawKeybindings);
1342
+ this.keyDraft = new SetupKeybindingsDraft(rawKeybindings, rawTmuxPassthrough);
1342
1343
  this.keyDiagnostics = this.keyDraft.resolution().diagnostics;
1343
1344
  for (const entry of this.manifest)
1344
1345
  this.selectedPackageIds.add(entry.id);
@@ -1570,6 +1571,32 @@ export class SetupWizard {
1570
1571
  selectedKeybinding() {
1571
1572
  return this.selectedKeyRow()?.fields[this.keyFieldIndex]?.definition;
1572
1573
  }
1574
+ tmuxPassthroughOffer() {
1575
+ const definition = this.selectedKeybinding();
1576
+ if (definition === undefined || !isAttachPaneBinding(definition))
1577
+ return undefined;
1578
+ const gestures = this.keyDraft.resolution().gestures(definition.id);
1579
+ const expression = gestures.join('\u0000');
1580
+ if (this.keyTmuxOccupancy?.id !== definition.id || this.keyTmuxOccupancy.expression !== expression) {
1581
+ this.keyTmuxOccupancy = {
1582
+ id: definition.id,
1583
+ expression,
1584
+ gestures: occupiedTmuxRootGestures(gestures),
1585
+ };
1586
+ }
1587
+ const gesture = this.keyTmuxOccupancy.gestures[0];
1588
+ return gesture === undefined ? undefined : { id: definition.id, gesture };
1589
+ }
1590
+ toggleTmuxPassthrough() {
1591
+ const offer = this.tmuxPassthroughOffer();
1592
+ if (offer === undefined)
1593
+ return false;
1594
+ this.keyDraft.toggleTmuxPassthrough(offer.id);
1595
+ this.keyTmuxOccupancy = undefined;
1596
+ this.keyNotice = undefined;
1597
+ this.invalidate();
1598
+ return true;
1599
+ }
1573
1600
  moveKey(delta) {
1574
1601
  const rows = this.filteredKeybindings();
1575
1602
  if (rows.length === 0)
@@ -1662,8 +1689,10 @@ export class SetupWizard {
1662
1689
  try {
1663
1690
  const saved = persistUserKeybindings(this.keyDraft.overrides(), {
1664
1691
  expectedKeybindings: this.keyDraft.expectedKeybindings(),
1692
+ tmuxPassthrough: this.keyDraft.tmuxPassthrough(),
1693
+ expectedTmuxPassthrough: this.keyDraft.expectedTmuxPassthrough(),
1665
1694
  });
1666
- this.keyDraft.markSaved(saved.overrides);
1695
+ this.keyDraft.markSaved(saved.overrides, saved.tmuxPassthrough);
1667
1696
  this.keyNotice = 'Saved. Reload attach and reopen active views to apply changes; refreshing tmux…';
1668
1697
  // The config is already persisted; a tmux-refresh failure (installer throw)
1669
1698
  // must land in the notice, never as an unhandled rejection that tears down
@@ -1863,6 +1892,10 @@ export class SetupWizard {
1863
1892
  this.moveKey(this.keyPageSize());
1864
1893
  return;
1865
1894
  }
1895
+ else if (this.matches('crtr.setup.toggle', data)) {
1896
+ if (this.toggleTmuxPassthrough())
1897
+ return;
1898
+ }
1866
1899
  else if (this.matches('crtr.setup.keybindings.edit', data)) {
1867
1900
  this.beginKeyEdit();
1868
1901
  return;
@@ -2061,7 +2094,7 @@ export class SetupWizard {
2061
2094
  ? `type gestures separated by commas · ${this.label('crtr.setup.keybindings.commit-edit')} commit · ${this.label('crtr.setup.keybindings.cancel-edit')} cancel · ${this.label('crtr.setup.keybindings.page-up')}/${this.label('crtr.setup.keybindings.page-down')} scroll`
2062
2095
  : this.filteringKeys
2063
2096
  ? `filter: ${this.keyFilter || 'type to search'} · ${this.label('crtr.setup.keybindings.edit')} keep · ${this.label('crtr.setup.keybindings.filter-delete')} delete · ${this.label('crtr.setup.keybindings.filter-clear')} clear`
2064
- : `${this.label('crtr.setup.list-down')}/${this.label('crtr.setup.list-up')} move · ${this.label('crtr.setup.cell-previous')}/${this.label('crtr.setup.cell-next')} field · ${this.label('crtr.setup.keybindings.edit')} edit · ${this.label('crtr.setup.keybindings.unbind')} disable · ${this.label('crtr.setup.keybindings.reset-row')} reset · ${this.label('crtr.setup.keybindings.reset-all')} reset all · ${this.label('crtr.setup.keybindings.filter')} filter · ${this.label('crtr.setup.keybindings.save')} save · ${this.label('crtr.setup.keybindings.discard')} ${this.keyFilter !== '' ? 'clear filter' : 'discard'}`;
2097
+ : `${this.label('crtr.setup.list-down')}/${this.label('crtr.setup.list-up')} move · ${this.label('crtr.setup.cell-previous')}/${this.label('crtr.setup.cell-next')} field · ${this.label('crtr.setup.keybindings.edit')} edit · ${this.tmuxPassthroughOffer() === undefined ? '' : `${this.label('crtr.setup.toggle')} tmux · `}${this.label('crtr.setup.keybindings.unbind')} disable · ${this.label('crtr.setup.keybindings.reset-row')} reset · ${this.label('crtr.setup.keybindings.reset-all')} reset all · ${this.label('crtr.setup.keybindings.filter')} filter · ${this.label('crtr.setup.keybindings.save')} save · ${this.label('crtr.setup.keybindings.discard')} ${this.keyFilter !== '' ? 'clear filter' : 'discard'}`;
2065
2098
  return [truncateToWidth(theme.fg('dim', line), width)];
2066
2099
  }
2067
2100
  renderProviders(width) {
@@ -2189,7 +2222,8 @@ export class SetupWizard {
2189
2222
  const row = rows[index];
2190
2223
  lines += (row.group !== previousGroup ? 1 : 0)
2191
2224
  + this.keyRowBodyLineCount(row, index, resolution, width)
2192
- + (this.keyRowMessage(rows, index) ? 1 : 0);
2225
+ + (this.keyRowMessage(rows, index) ? 1 : 0)
2226
+ + (index === this.keyIndex && this.tmuxPassthroughOffer() !== undefined ? 1 : 0);
2193
2227
  previousGroup = row.group;
2194
2228
  }
2195
2229
  return lines;
@@ -2246,10 +2280,11 @@ export class SetupWizard {
2246
2280
  ? editingFieldIndex
2247
2281
  : selected ? Math.min(this.keyFieldIndex, row.fields.length - 1) : 0;
2248
2282
  const message = this.keyRowMessage(rows, index);
2283
+ const tmuxOffer = selected ? this.tmuxPassthroughOffer() : undefined;
2249
2284
  const bodyLines = this.keyRowBodyLineCount(row, index, resolution, width);
2250
2285
  // Budget output lines (heading + responsive row + optional diagnostic) so
2251
2286
  // the list never clips the confirm prompt / notice / footer below it.
2252
- const cost = (row.group !== previousGroup ? 1 : 0) + bodyLines + (message ? 1 : 0);
2287
+ const cost = (row.group !== previousGroup ? 1 : 0) + bodyLines + (message ? 1 : 0) + (tmuxOffer ? 1 : 0);
2253
2288
  if (emitted > 0 && emitted + cost > viewport)
2254
2289
  break;
2255
2290
  if (row.group !== previousGroup) {
@@ -2320,6 +2355,12 @@ export class SetupWizard {
2320
2355
  : '';
2321
2356
  out.push(truncateToWidth(`${marker}${sourceMark} ${name} ${fieldsText}${description}`, width));
2322
2357
  }
2358
+ if (tmuxOffer) {
2359
+ const checked = this.keyDraft.usesTmuxPassthrough(tmuxOffer.id)
2360
+ ? theme.fg('success', '[x]')
2361
+ : theme.fg('dim', '[ ]');
2362
+ out.push(truncateToWidth(` ${checked} ${theme.fg('accent', `Use tmux's ${formatGesture(tmuxOffer.gesture)} here`)}`, width));
2363
+ }
2323
2364
  if (message) {
2324
2365
  const fieldPrefix = message.label === undefined ? '' : `${message.label}: `;
2325
2366
  out.push(truncateToWidth(theme.fg('warning', ` ${fieldPrefix}${message.message}`), width));
@@ -2458,7 +2499,7 @@ export async function runSetup() {
2458
2499
  const openingBindings = resolveKeybindings(rawKeybindings);
2459
2500
  const terminal = new ProcessTerminal();
2460
2501
  const tui = new TUI(terminal, true);
2461
- const wizard = new SetupWizard(state.manifest, state.installedPackageIds, state.systemTools, tui, agentDir, runtime, registry, openingBindings, rawKeybindings, () => terminal.rows);
2502
+ const wizard = new SetupWizard(state.manifest, state.installedPackageIds, state.systemTools, tui, agentDir, runtime, registry, openingBindings, rawKeybindings, () => terminal.rows, rawUserConfig?.tmux_passthrough);
2462
2503
  tui.addChild(wizard);
2463
2504
  tui.setFocus(wizard);
2464
2505
  await new Promise((resolve, reject) => {
@@ -4,7 +4,7 @@
4
4
  // convention) into the owning project's OWN `.crouter/memory/deps/` as
5
5
  // substrate docs. This is the same one-way conversion door as the rest of
6
6
  // `sys sync` — SKILL.md never becomes an active runtime surface (see
7
- // `crtr memory read taste/document-substrate`). The lane's contract:
7
+ // `crtr memory read insights/agent-memory/document-substrate`). The lane's contract:
8
8
  //
9
9
  // • `deps/` is WHOLLY DERIVED state — wiped and regenerated from
10
10
  // node_modules on every run (like node_modules itself), guarded by a
@@ -1,5 +1,4 @@
1
- // `crtr sys` subtree: config {get,set,path}, doctor, sync, update, version.
2
- // Replaces old config.ts + doctor.ts + update.ts command files.
1
+ // `crtr sys` subtree: configuration, diagnostics, and self-management.
3
2
  import { defineBranch } from '../core/command.js';
4
3
  import { configBranch } from './sys/config.js';
5
4
  import { daemonBranch } from './sys/daemon.js';
@@ -10,7 +9,6 @@ import { sysSetupLeaf } from './sys/setup.js';
10
9
  import { supportBranch } from './sys/support.js';
11
10
  import { sysSyspromptLeaf } from './sys/sysprompt.js';
12
11
  import { promptReviewLeaf } from './sys/prompt-review.js';
13
- import { sysPromptStudioLeaf } from './sys/promptstudio.js';
14
12
  import { sysSyncBranch } from './sys/sync.js';
15
13
  import { sysUpdateLeaf, sysVersionLeaf } from './sys/update.js';
16
14
  export function registerSys() {
@@ -18,13 +16,13 @@ export function registerSys() {
18
16
  name: 'sys',
19
17
  rootEntry: {
20
18
  concept: 'crtr configuration, diagnostics, and self-management',
21
- desc: 'config, setup, doctor, sysprompt, prompt-review, promptstudio, sync, update, version, feedback, logs, support, daemon',
22
- useWhen: 'managing the crtr installation, the crtrd supervisor process, or opening built-in system views',
19
+ desc: 'config, setup, doctor, sysprompt, prompt-review, sync, update, version, feedback, logs, support, daemon',
20
+ useWhen: 'managing the crtr installation, inspecting diagnostics, or operating the crtrd supervisor process',
23
21
  },
24
22
  help: {
25
23
  name: 'sys',
26
24
  summary: 'crtr system configuration, settings, diagnostics, and self-management',
27
25
  },
28
- children: [configBranch, sysSetupLeaf, sysDoctorLeaf, sysSyspromptLeaf, promptReviewLeaf, sysPromptStudioLeaf, sysFeedbackLeaf, sysLogsLeaf, supportBranch, sysUpdateLeaf, sysVersionLeaf, sysSyncBranch, daemonBranch],
26
+ children: [configBranch, sysSetupLeaf, sysDoctorLeaf, sysSyspromptLeaf, promptReviewLeaf, sysFeedbackLeaf, sysLogsLeaf, supportBranch, sysUpdateLeaf, sysVersionLeaf, sysSyncBranch, daemonBranch],
29
27
  });
30
28
  }
@@ -26,7 +26,7 @@ import { tmpdir } from 'node:os';
26
26
  import { join, dirname } from 'node:path';
27
27
  import { fileURLToPath } from 'node:url';
28
28
  import { createAgentSessionServices, createAgentSessionFromServices, SessionManager, VERSION, } from '../runtime/broker-sdk.js';
29
- import { buildBrokerSession, makeBrokerUiContext, isLeadingEngineCommand, chooseGuidanceDeliveryMode, promptWithNextTurnGuidance, isHiddenJsonlBranchEntry, stripHiddenEntriesFromJsonlExport, engineLeadingCommandTokens, } from '../runtime/broker.js';
29
+ import { buildBrokerSession, makeBrokerUiContext, isLeadingEngineCommand, resolveSteerCall, chooseGuidanceDeliveryMode, promptWithNextTurnGuidance, isHiddenJsonlBranchEntry, stripHiddenEntriesFromJsonlExport, engineLeadingCommandTokens, } from '../runtime/broker.js';
30
30
  import { CANVAS_EXTENSIONS } from '../runtime/launch.js';
31
31
  import { buildRefInventory } from '../memory/inline-ref-inventory.js';
32
32
  import { buildGuidance } from '../memory/inline-ref-guidance.js';
@@ -409,6 +409,11 @@ test('C5 — isLeadingEngineCommand truth table against structural stubs (pure,
409
409
  };
410
410
  assert.equal(isLeadingEngineCommand('/mytemplate', throwingExtButRealTemplate), true, 'a throwing extensionRunner check degrades to false for ITSELF but does not abort the template check');
411
411
  });
412
+ test('a streaming extension command uses prompt preflight instead of the rejecting steer queue', () => {
413
+ const session = { extensionRunner: { getCommand: (name) => (name === 'recap' ? { name: 'recap' } : undefined) } };
414
+ assert.equal(resolveSteerCall('/recap', session), 'prompt');
415
+ assert.equal(resolveSteerCall('new information', session), 'steer');
416
+ });
412
417
  test('C5 — isLeadingEngineCommand against a REAL session (registered extension command)', async () => {
413
418
  // Only the extension-command branch is driven against a REAL session here.
414
419
  // Skill/prompt-template discovery requires `session.bindExtensions(...)`
@@ -66,7 +66,15 @@ function assistantMsg(text, stopReason = 'stop') {
66
66
  timestamp: Date.now(),
67
67
  };
68
68
  }
69
- test('broker welcome snapshot serves the persisted history, not pi\u2019s sliced live array (omit-on-revive regression)', async () => {
69
+ // 30s (approved in scripts/test-runner.mjs): this boot loads the REAL mandatory
70
+ // canvas extension set from TypeScript sources, and those extensions pull the
71
+ // crouter module graph through tsx for the first time in the process — ~6s of
72
+ // the ~9s local runtime, and 12.6s total on a hosted runner, which blew the
73
+ // ordinary 10s cap. The extension set is not decoration: booting the same
74
+ // composition production boots is what makes `session.messages.length === 5` at
75
+ // boot a real check that no canvas hook injects a message the persisted tree
76
+ // lacks. Loading `[C3_EXT]` alone runs in ~2.3s but drops that coverage.
77
+ test('broker welcome snapshot serves the persisted history, not pi\u2019s sliced live array (omit-on-revive regression)', { timeout: 30_000 }, async () => {
70
78
  const cwd = mkdtempSync(join(tmpdir(), 'crtr-snaphist-'));
71
79
  try {
72
80
  // 1. Build a real persisted session whose tail mimics an auto-retried turn:
@@ -19,7 +19,7 @@ function row(over = {}) {
19
19
  intent: null,
20
20
  pi_session_id: null,
21
21
  cycle_pending: null,
22
- private_fork_phase: null,
22
+ fork_from: null,
23
23
  ...over,
24
24
  };
25
25
  }
@@ -59,12 +59,11 @@ test('row 7: a saved session with no crash markers resumes strictly; a pending c
59
59
  assert.equal(classifyDeadNode(row({ pi_session_id: 'sess', cycle_pending: true }), false), 'respawn-cycle');
60
60
  assert.equal(classifyDeadNode(row({ pi_session_id: 'sess', cycle_pending: false }), false), 'respawn-resume');
61
61
  });
62
- test('row 8: a private fork dead before binding its child session retries the immutable fork birth', () => {
63
- assert.equal(classifyDeadNode(row({ private_fork_phase: 'fork_pending' }), false), 'respawn-fresh');
62
+ test('row 8: an ordinary fork dead before binding its child session retries the immutable fork birth', () => {
63
+ assert.equal(classifyDeadNode(row({ fork_from: '/reviews/branch-point.jsonl' }), false), 'respawn-fresh');
64
64
  });
65
65
  test('row 9: sessionless with no fork claim — a fresh launch died before session_start — is a boot failure', () => {
66
66
  assert.equal(classifyDeadNode(row(), false), 'boot-failure');
67
- assert.equal(classifyDeadNode(row({ private_fork_phase: 'session_started' }), false), 'boot-failure', 'a bound fork whose session identity was cleared for a fresh launch classifies like any fresh launch');
68
67
  });
69
68
  // ===========================================================================
70
69
  // retryResumeMode (pure) — ported verbatim from the deleted grace-clock suite.
@@ -1,4 +1,4 @@
1
- import type { AgentMessage } from '@earendil-works/pi-agent-core';
1
+ import type { AgentMessage, ThinkingLevel } from '@earendil-works/pi-agent-core';
2
2
  /** Test seams for prompt-scoped failures before session_start. The one-shot
3
3
  * variant records its first failure per node so the next cycling retry can
4
4
  * reach boot confirmation. */
@@ -165,8 +165,9 @@ declare class FakeSession {
165
165
  get model(): FakeModel | undefined;
166
166
  private currentModel;
167
167
  private currentThinkingLevel;
168
- get thinkingLevel(): string | undefined;
169
- setThinkingLevel(level: string): void;
168
+ get thinkingLevel(): ThinkingLevel | undefined;
169
+ setThinkingLevel(level: ThinkingLevel): void;
170
+ cycleThinkingLevel(): ThinkingLevel;
170
171
  private recordModel;
171
172
  setModel(model: FakeModel): Promise<void>;
172
173
  /** The broker's read-op picker data (buildListModelsData → registryOf(session))
@@ -256,7 +257,9 @@ interface FakeModelRuntime {
256
257
  getAvailable: () => Promise<FakeModel[]>;
257
258
  hasConfiguredAuth: (provider: string) => boolean;
258
259
  getError: () => string | undefined;
259
- refresh: () => Promise<void>;
260
+ refresh: (options?: {
261
+ allowNetwork?: boolean;
262
+ }) => Promise<void>;
260
263
  }
261
264
  interface FakeServices {
262
265
  resourceLoader: ResourceLoader;
@@ -275,7 +278,7 @@ export declare function createAgentSessionFromServices(options: {
275
278
  services: FakeServices;
276
279
  sessionManager: SessionManager;
277
280
  model?: FakeModel;
278
- thinkingLevel?: string;
281
+ thinkingLevel?: ThinkingLevel;
279
282
  }): Promise<{
280
283
  session: FakeSession;
281
284
  }>;
@@ -356,7 +356,17 @@ class FakeSession {
356
356
  return this.currentThinkingLevel;
357
357
  }
358
358
  setThinkingLevel(level) {
359
+ if (this.currentThinkingLevel === level)
360
+ return;
359
361
  this.currentThinkingLevel = level;
362
+ this.emit({ type: 'thinking_level_changed', level });
363
+ }
364
+ cycleThinkingLevel() {
365
+ const levels = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh'];
366
+ const current = this.currentThinkingLevel === undefined ? -1 : levels.indexOf(this.currentThinkingLevel);
367
+ const next = levels[(current + 1) % levels.length];
368
+ this.setThinkingLevel(next);
369
+ return next;
360
370
  }
361
371
  recordModel() {
362
372
  // Treat the unknown-stub as "no model" on the recorded surface (parity with
@@ -1110,7 +1120,20 @@ export async function createAgentSessionServices(options) {
1110
1120
  // Absent (the common case) → unchanged always-authenticated behavior.
1111
1121
  const home = (process.env['CRTR_HOME'] ?? '').trim();
1112
1122
  const noAuthSentinel = join(home, 'fake-pi.no-auth');
1123
+ const unauthenticatedProviderSentinel = join(home, 'fake-pi.unauthenticated-provider');
1113
1124
  const zeroAuth = () => home !== '' && existsSync(noAuthSentinel);
1125
+ const readUnauthenticatedProvider = () => {
1126
+ try {
1127
+ return readFileSync(unauthenticatedProviderSentinel, 'utf8').trim() || undefined;
1128
+ }
1129
+ catch {
1130
+ return undefined;
1131
+ }
1132
+ };
1133
+ // Unlike the all-or-nothing no-auth seam, this mirrors ModelRuntime's cached
1134
+ // configuredProviders snapshot: a provider-specific auth change becomes
1135
+ // visible only after refresh() completes.
1136
+ let unauthenticatedProvider = readUnauthenticatedProvider();
1114
1137
  return {
1115
1138
  resourceLoader: loader,
1116
1139
  modelRuntime: {
@@ -1124,9 +1147,12 @@ export async function createAgentSessionServices(options) {
1124
1147
  getAvailableSnapshot: () => (zeroAuth() ? [] : [FAKE_AVAILABLE_MODEL]),
1125
1148
  getAvailable: async () => (zeroAuth() ? [] : [FAKE_AVAILABLE_MODEL]),
1126
1149
  getModels: () => (zeroAuth() ? [] : FAKE_REGISTERED_MODELS),
1127
- hasConfiguredAuth: () => !zeroAuth(),
1150
+ hasConfiguredAuth: (provider) => !zeroAuth() && provider !== unauthenticatedProvider,
1128
1151
  getError: () => undefined,
1129
- refresh: async () => { },
1152
+ refresh: async () => {
1153
+ await new Promise((resolve) => setImmediate(resolve));
1154
+ unauthenticatedProvider = readUnauthenticatedProvider();
1155
+ },
1130
1156
  },
1131
1157
  };
1132
1158
  }
@@ -5,13 +5,14 @@
5
5
  // exercises runBroker's live retry handler rather than its helpers in isolation.
6
6
  import { test, before, after, afterEach } from 'node:test';
7
7
  import assert from 'node:assert/strict';
8
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
8
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
9
9
  import { join } from 'node:path';
10
10
  import { createHeadlessHarness } from '../helpers/harness.js';
11
11
  import { createAttachKit } from '../helpers/broker-clients.js';
12
12
  import { defaultModelLaddersConfig } from '../../../types.js';
13
13
  import { readFault } from '../../runtime/fault.js';
14
- import { normalizeModel } from '../../runtime/launch.js';
14
+ import { buildPiArgv, normalizeModel } from '../../runtime/launch.js';
15
+ import { encodeFrame } from '../../runtime/broker-protocol.js';
15
16
  const MODEL_LADDERS = defaultModelLaddersConfig();
16
17
  function resolvedModel(spec) {
17
18
  const normalized = normalizeModel(spec, MODEL_LADDERS);
@@ -269,3 +270,87 @@ test('an explicit picker choice pins and clears prior logical routing; an intern
269
270
  assert.equal(after.launch?.modelProviderPinned, true, 'an internal no-raw-token change (cycle_ladder) preserves the existing pin verbatim');
270
271
  ctrl.close();
271
272
  });
273
+ test("a user's Alt+M and Shift+Tab choices replace stale launch intent for restart replay", { timeout: 30_000 }, async () => {
274
+ const parent = h.spawnRoot('session choice durability parent');
275
+ seedPool('anthropic', false);
276
+ seedPool('openai-codex', false);
277
+ const child = await h.spawnHeadlessChild(parent, 'session choice durability child', { model: 'openai/strong' });
278
+ const before = h.node(child);
279
+ assert.deepEqual(before.launch?.modelIntent, { family: 'openai', strength: 'strong' }, 'fixture starts from a logical launch preference');
280
+ assert.equal(before.launch?.env.CRTR_MODEL_INTENT, 'openai/strong');
281
+ const ctrl = await kit.attach(child, 'controller', 'session-choice-durability');
282
+ ctrl.send({ type: 'cycle_ladder', direction: 'forward' });
283
+ await ctrl.waitFrame((f) => f.type === 'ack' && f.for === 'cycle_ladder', 'Alt+M cycle acked');
284
+ let after = h.node(child);
285
+ assert.equal(after.launch?.modelIntent, undefined, 'Alt+M replaces the old logical route intent');
286
+ assert.equal(after.launch?.env.CRTR_MODEL_INTENT, undefined, 'a restarted broker cannot resolve the old route over the selected rung');
287
+ assert.equal(after.launch?.model, after.model_override, 'the selected model and thinking rung is the durable revive recipe');
288
+ const rung = after.launch?.model;
289
+ assert.ok(rung, 'Alt+M persisted a concrete model rung');
290
+ const thinkingFrameOffset = ctrl.frames.length;
291
+ ctrl.send({ type: 'cycle_thinking' });
292
+ const thinkingChanged = await h.waitFor(() => ctrl.frames.slice(thinkingFrameOffset).find((f) => f.type === 'thinking_level_changed') ?? null, { label: 'Shift+Tab thinking change relayed' });
293
+ await ctrl.waitFrame((f) => f.type === 'ack' && f.for === 'cycle_thinking', 'Shift+Tab cycle acked');
294
+ after = h.node(child);
295
+ const level = thinkingChanged.type === 'thinking_level_changed' ? thinkingChanged.level : 'off';
296
+ const bareRung = rung.replace(/:(?:off|minimal|low|medium|high|xhigh|max)$/, '');
297
+ const expected = `${bareRung}${level === 'off' ? '' : `:${level}`}`;
298
+ assert.equal(after.launch?.model, expected, 'Shift+Tab persists the new thinking level with the selected model');
299
+ assert.equal(after.model_override, expected, 'polymorphs preserve the same user-selected model and thinking level');
300
+ const replay = buildPiArgv(after, { resumeSessionPath: after.pi_session_file ?? undefined });
301
+ const modelArg = replay.argv.indexOf('--model');
302
+ assert.notEqual(modelArg, -1, 'a daemon revive replays a model argument');
303
+ assert.equal(replay.argv[modelArg + 1], expected, 'the replayed model argument carries both choices');
304
+ assert.equal(replay.env.CRTR_MODEL_INTENT, undefined, 'the stale logical intent is absent from the restarted broker environment');
305
+ ctrl.close();
306
+ });
307
+ test('reload_auth restores a newly authenticated personal route before the next idle prompt', { timeout: 30_000 }, async () => {
308
+ const personal = { provider: 'personal-anthropic', id: 'claude-personal' };
309
+ const funded = { provider: 'northlight-openai', id: 'gpt-funded' };
310
+ const personalSpec = `${personal.provider}/${personal.id}:xhigh`;
311
+ const userConfigDir = join(h.agentHome, '.crouter');
312
+ const userConfigPath = join(userConfigDir, 'config.json');
313
+ const unauthenticatedProvider = join(h.home, 'fake-pi.unauthenticated-provider');
314
+ mkdirSync(userConfigDir, { recursive: true });
315
+ writeFileSync(userConfigPath, JSON.stringify({
316
+ modelRoutes: {
317
+ personal: { family: 'anthropic', credentialSource: 'user', providerId: personal.provider, models: { medium: personalSpec } },
318
+ funded: { family: 'anthropic', credentialSource: 'northlight', providerId: funded.provider, models: { medium: `${funded.provider}/${funded.id}:medium` } },
319
+ },
320
+ modelRouting: { credentialSourceOrder: ['user', 'northlight'], familyOrder: ['anthropic'], strengthFallback: ['medium'] },
321
+ }));
322
+ writeFileSync(unauthenticatedProvider, personal.provider);
323
+ try {
324
+ const parent = h.spawnRoot('auth route reconciliation parent');
325
+ const child = await h.spawnHeadlessChild(parent, 'auth route reconciliation child', { model: 'anthropic/medium' });
326
+ assert.deepEqual(model(child), funded, 'the logical request starts on the funded route while personal auth is absent');
327
+ const controller = await kit.connectRaw(child, { read: true });
328
+ controller.send({ type: 'hello', role: 'controller', client_id: 'auth-route-reconciliation' });
329
+ await h.waitFor(() => controller.frames.some((frame) => frame.type === 'welcome') ? true : null, { label: 'route reconciliation controller welcomed' });
330
+ rmSync(unauthenticatedProvider, { force: true });
331
+ const frameStart = controller.frames.length;
332
+ controller.writeRaw(encodeFrame({ type: 'reload_auth' })
333
+ + encodeFrame({ type: 'prompt', text: 'continue after login' }));
334
+ await h.waitFor(() => {
335
+ const frames = controller.frames.slice(frameStart);
336
+ const changed = frames.some((frame) => frame.type === 'model_changed' && frame.spec === personalSpec);
337
+ const started = frames.some((frame) => frame.type === 'agent_start');
338
+ return changed && started ? true : null;
339
+ }, { label: 'personal route adopted before queued prompt starts' });
340
+ const frames = controller.frames.slice(frameStart);
341
+ const modelChangedIndex = frames.findIndex((frame) => frame.type === 'model_changed' && frame.spec === personalSpec);
342
+ const agentStartIndex = frames.findIndex((frame) => frame.type === 'agent_start');
343
+ assert.ok(modelChangedIndex >= 0 && modelChangedIndex < agentStartIndex, 'route reconciliation completes before the next idle prompt starts');
344
+ assert.deepEqual(model(child), personal, 'the live session adopts the newly authenticated personal route');
345
+ const persisted = await h.waitFor(() => {
346
+ const node = h.node(child);
347
+ return node?.launch?.model === personalSpec ? node : null;
348
+ }, { label: 'personal route persisted without clearing logical intent' });
349
+ assert.deepEqual(persisted.launch?.modelIntent, { family: 'anthropic', strength: 'medium' });
350
+ assert.equal(persisted.launch?.env.CRTR_MODEL_INTENT, 'anthropic/medium', 'algorithmic reconciliation preserves the durable logical intent');
351
+ }
352
+ finally {
353
+ rmSync(unauthenticatedProvider, { force: true });
354
+ rmSync(userConfigPath, { force: true });
355
+ }
356
+ });
@@ -0,0 +1,39 @@
1
+ // Run with: node --import tsx/esm --test src/core/__tests__/full/broker-whip-interrupt.test.ts
2
+ //
3
+ // A whip is a transport-level abort-then-prompt, not an ordinary steering queue
4
+ // entry. This needs a real broker because the guarantee crosses the socket frame,
5
+ // broker dispatch, and pi session abort boundary.
6
+ import { test, before, after, afterEach } from 'node:test';
7
+ import assert from 'node:assert/strict';
8
+ import { createHeadlessHarness } from '../helpers/harness.js';
9
+ import { createAttachKit } from '../helpers/broker-clients.js';
10
+ let h;
11
+ let heldTurnBefore;
12
+ const kit = createAttachKit(() => h);
13
+ before(async () => {
14
+ heldTurnBefore = process.env['PI_FAKE_ENGINE_HOLD_TURN'];
15
+ process.env['PI_FAKE_ENGINE_HOLD_TURN'] = '1';
16
+ h = await createHeadlessHarness({ sessionPrefix: 'crtr-whip' });
17
+ });
18
+ after(async () => {
19
+ if (h !== undefined)
20
+ await h.dispose();
21
+ if (heldTurnBefore === undefined)
22
+ delete process.env['PI_FAKE_ENGINE_HOLD_TURN'];
23
+ else
24
+ process.env['PI_FAKE_ENGINE_HOLD_TURN'] = heldTurnBefore;
25
+ });
26
+ afterEach(() => {
27
+ kit.closeAll();
28
+ });
29
+ test('a whip aborts the active turn before starting its prompt', { timeout: 20_000 }, async () => {
30
+ const root = h.spawnRoot('broker-whip suite root');
31
+ const id = await h.spawnHeadlessChild(root, 'headless worker — held turn');
32
+ const controller = await kit.attach(id, 'controller', 'whip-controller');
33
+ assert.equal(controller.welcome.snapshot.state.isStreaming, true, 'the original turn is held active');
34
+ const startsBeforeWhip = controller.frames.filter((frame) => frame.type === 'agent_start').length;
35
+ const message = 'Whip command must start after the active turn is interrupted';
36
+ controller.send({ type: 'prompt', text: message, interrupt: true });
37
+ await h.waitFor(() => controller.frames.filter((frame) => frame.type === 'agent_start').length > startsBeforeWhip || null, { label: 'whip prompt started a new turn after the abort' });
38
+ assert.ok(controller.frames.some((frame) => frame.type === 'message_start' && JSON.stringify(frame).includes(message)), 'the whip message starts a fresh prompt rather than entering the steering queue');
39
+ });
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // `crtr node demote --detach` on a node with a live viewer (Alt+C → D).
4
4
  //
5
- // BROKER-CUT ADAPTATION (taste/broker-is-the-host, 2026-06-10): every node is a
5
+ // BROKER-CUT ADAPTATION (insights/runtime/broker-is-the-host, 2026-06-10): every node is a
6
6
  // detached headless broker. After a09b71f a managed child opens NO viewer on
7
7
  // spawn — a viewer is opened on demand via `surface node focus`, registering
8
8
  // its `crtr surface attach` VIEWER pane in the focuses table. The engine is NOT in a pane, so the