@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
@@ -0,0 +1 @@
1
+ export declare const TERMRENDER_VERSION = "4.12.6";
@@ -0,0 +1 @@
1
+ export const TERMRENDER_VERSION = '4.12.6';
@@ -1,8 +1,7 @@
1
1
  // terminal.ts — raw-mode helpers shared by every crtr raw-ANSI TUI.
2
2
  //
3
3
  // Moved verbatim from src/core/canvas/browse/terminal.ts (it was already
4
- // generic). Hand-rolled (no deps), mirroring humanloop's src/tui/terminal.ts.
5
- // Extends its key parsing beyond up/down/return/escape/tab/backspace/ctrl +
4
+ // generic). Hand-rolled (no deps). Extends basic key parsing beyond up/down/return/escape/tab/backspace/ctrl +
6
5
  // printable input: adds leftArrow/rightArrow (cursor keys) and shiftTab
7
6
  // (`\x1b[Z`) so callers can drive tree expand/collapse and tab cycling.
8
7
  function emptyKey() {
@@ -92,7 +92,7 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
92
92
  valueConstraint: string;
93
93
  applies: string;
94
94
  order: number;
95
- format: (config: ScopeConfig) => "off" | "on";
95
+ format: (config: ScopeConfig) => "on" | "off";
96
96
  cycle: (config: ScopeConfig) => void;
97
97
  setFromString: (config: ScopeConfig, raw: string) => string | null;
98
98
  };
@@ -110,11 +110,47 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
110
110
  valueConstraint: string;
111
111
  applies: string;
112
112
  order: number;
113
- format: (config: ScopeConfig) => "off" | "on";
113
+ format: (config: ScopeConfig) => "on" | "off";
114
114
  cycle: (config: ScopeConfig) => void;
115
115
  setFromString: (config: ScopeConfig, raw: string) => string | null;
116
116
  };
117
117
  };
118
+ working_gerunds: {
119
+ surface: "specialized";
120
+ owner: string;
121
+ };
122
+ whip_mode: {
123
+ surface: "settings";
124
+ setting: {
125
+ key: "whip_mode";
126
+ label: string;
127
+ description: string;
128
+ valueConstraint: string;
129
+ applies: string;
130
+ order: number;
131
+ format: (config: ScopeConfig) => "on" | "off";
132
+ cycle: (config: ScopeConfig) => void;
133
+ setFromString: (config: ScopeConfig, raw: string) => string | null;
134
+ };
135
+ };
136
+ whip_messages: {
137
+ surface: "specialized";
138
+ owner: string;
139
+ };
140
+ mouse_mode_default: {
141
+ surface: "settings";
142
+ setting: {
143
+ key: "mouse_mode_default";
144
+ label: string;
145
+ description: string;
146
+ valueConstraint: string;
147
+ applies: string;
148
+ order: number;
149
+ format: (config: ScopeConfig) => "on" | "off" | "follow tmux";
150
+ cycle: (config: ScopeConfig, delta: number) => void;
151
+ setFromString: (config: ScopeConfig, raw: string) => string | null;
152
+ };
153
+ };
118
154
  live_cycles: {
119
155
  surface: "settings";
120
156
  setting: {
@@ -152,7 +188,35 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
152
188
  valueConstraint: string;
153
189
  applies: string;
154
190
  order: number;
155
- format: (config: ScopeConfig) => "off" | "on";
191
+ format: (config: ScopeConfig) => "on" | "off";
192
+ cycle: (config: ScopeConfig) => void;
193
+ setFromString: (config: ScopeConfig, raw: string) => string | null;
194
+ };
195
+ };
196
+ summarize_tool_calls: {
197
+ surface: "settings";
198
+ setting: {
199
+ key: "summarize_tool_calls";
200
+ label: string;
201
+ description: string;
202
+ valueConstraint: string;
203
+ applies: string;
204
+ order: number;
205
+ format: (config: ScopeConfig) => "on" | "off";
206
+ cycle: (config: ScopeConfig) => void;
207
+ setFromString: (config: ScopeConfig, raw: string) => string | null;
208
+ };
209
+ };
210
+ detailed_tool_recaps: {
211
+ surface: "settings";
212
+ setting: {
213
+ key: "detailed_tool_recaps";
214
+ label: string;
215
+ description: string;
216
+ valueConstraint: string;
217
+ applies: string;
218
+ order: number;
219
+ format: (config: ScopeConfig) => "on" | "off";
156
220
  cycle: (config: ScopeConfig) => void;
157
221
  setFromString: (config: ScopeConfig, raw: string) => string | null;
158
222
  };
@@ -161,6 +225,10 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
161
225
  surface: "specialized";
162
226
  owner: string;
163
227
  };
228
+ tmux_passthrough: {
229
+ surface: "specialized";
230
+ owner: string;
231
+ };
164
232
  modelLadders: {
165
233
  surface: "specialized";
166
234
  owner: string;
@@ -1,4 +1,4 @@
1
- import { CONDENSED_HISTORY_MODES } from '../types.js';
1
+ import { CONDENSED_HISTORY_MODES, MOUSE_MODE_DEFAULTS } from '../types.js';
2
2
  function cycleChoice(choices, current, delta) {
3
3
  const index = choices.indexOf(current);
4
4
  const start = index >= 0 ? index : 0;
@@ -164,6 +164,47 @@ export const CONFIG_SETTINGS_COVERAGE = {
164
164
  },
165
165
  },
166
166
  },
167
+ working_gerunds: { surface: 'specialized', owner: 'sys config set working_gerunds' },
168
+ whip_mode: {
169
+ surface: 'settings',
170
+ setting: {
171
+ key: 'whip_mode',
172
+ label: 'Whip mode',
173
+ description: 'Play the whip animation when you send a prompt and when an automatically opened child viewer starts.',
174
+ valueConstraint: 'true|false',
175
+ applies: 'Applies on the next attach.',
176
+ order: 39,
177
+ format: (config) => config.whip_mode ? 'on' : 'off',
178
+ cycle: (config) => { config.whip_mode = !config.whip_mode; },
179
+ setFromString: (config, raw) => {
180
+ const value = booleanFromString(raw, 'whip_mode');
181
+ if (typeof value === 'string')
182
+ return value;
183
+ config.whip_mode = value;
184
+ return null;
185
+ },
186
+ },
187
+ },
188
+ whip_messages: { surface: 'specialized', owner: 'sys config set whip_messages' },
189
+ mouse_mode_default: {
190
+ surface: 'settings',
191
+ setting: {
192
+ key: 'mouse_mode_default',
193
+ label: 'Default mouse mode',
194
+ description: 'Initial mouse wheel scrolling for each attached viewer.',
195
+ valueConstraint: MOUSE_MODE_DEFAULTS.join('|'),
196
+ applies: 'Applies on the next attach.',
197
+ order: 38,
198
+ format: (config) => config.mouse_mode_default === 'tmux' ? 'follow tmux' : config.mouse_mode_default,
199
+ cycle: (config, delta) => { config.mouse_mode_default = cycleChoice(MOUSE_MODE_DEFAULTS, config.mouse_mode_default, delta); },
200
+ setFromString: (config, raw) => {
201
+ if (!MOUSE_MODE_DEFAULTS.includes(raw))
202
+ return `mouse_mode_default must be one of: ${MOUSE_MODE_DEFAULTS.join('|')}`;
203
+ config.mouse_mode_default = raw;
204
+ return null;
205
+ },
206
+ },
207
+ },
167
208
  live_cycles: {
168
209
  surface: 'settings',
169
210
  setting: {
@@ -223,7 +264,48 @@ export const CONFIG_SETTINGS_COVERAGE = {
223
264
  },
224
265
  },
225
266
  },
267
+ summarize_tool_calls: {
268
+ surface: 'settings',
269
+ setting: {
270
+ key: 'summarize_tool_calls',
271
+ label: 'Summarize tool calls',
272
+ description: 'Replace completed folded tool-call groups with a one-line broker summary when available.',
273
+ valueConstraint: 'true|false',
274
+ applies: 'Applies when the next visible message closes a tool-call group.',
275
+ order: 35,
276
+ format: (config) => config.summarize_tool_calls ? 'on' : 'off',
277
+ cycle: (config) => { config.summarize_tool_calls = !config.summarize_tool_calls; },
278
+ setFromString: (config, raw) => {
279
+ const value = booleanFromString(raw, 'summarize_tool_calls');
280
+ if (typeof value === 'string')
281
+ return value;
282
+ config.summarize_tool_calls = value;
283
+ return null;
284
+ },
285
+ },
286
+ },
287
+ detailed_tool_recaps: {
288
+ surface: 'settings',
289
+ setting: {
290
+ key: 'detailed_tool_recaps',
291
+ label: 'Detailed tool recaps',
292
+ description: 'Show each memory read and edited file in folded tool recaps. Off shows a compact count line instead.',
293
+ valueConstraint: 'true|false',
294
+ applies: 'Applies on the next attach.',
295
+ order: 36,
296
+ format: (config) => config.detailed_tool_recaps ? 'on' : 'off',
297
+ cycle: (config) => { config.detailed_tool_recaps = !config.detailed_tool_recaps; },
298
+ setFromString: (config, raw) => {
299
+ const value = booleanFromString(raw, 'detailed_tool_recaps');
300
+ if (typeof value === 'string')
301
+ return value;
302
+ config.detailed_tool_recaps = value;
303
+ return null;
304
+ },
305
+ },
306
+ },
226
307
  keybindings: { surface: 'specialized', owner: 'Keybindings tab' },
308
+ tmux_passthrough: { surface: 'specialized', owner: 'Keybindings tab' },
227
309
  modelLadders: { surface: 'specialized', owner: 'Models tab' },
228
310
  modelRoutes: { surface: 'specialized', owner: 'Models route declarations' },
229
311
  modelRouting: { surface: 'specialized', owner: 'Models route declarations' },
@@ -2,43 +2,35 @@
2
2
  //
3
3
  // Integration coverage for crtrd's `/v1/human/inbox` routes
4
4
  // (inbox-contract.md §A, `handlers/inbox.ts`). Exercises the full leaf → typed
5
- // `CrtrClient` → in-process `createApiServer()` → handler → real
6
- // `@crouton-kit/humanloop` boundary — never a mock client, never a
7
- // pre-parsed handler call. Tickets live under a root registered directly
8
- // with humanloop's `registerInboxRoot`, isolated per test via a fresh
9
- // `XDG_STATE_HOME` (humanloop's root registry reads it live, so the SAME
10
- // running server picks up a fresh registry with no restart needed).
11
- //
12
- // Fixture policy: an ordinary pending ticket is created through humanloop's
13
- // public `submitDeck`/`submitReview` — the same surface a real caller uses.
14
- // A raw hand-written `deck.json`/`review.json` is used ONLY where the test's
15
- // whole point is a state `submitDeck`/`submitReview` cannot produce: a
16
- // stored ticket with an unresolved `bodyPath` (submit-time resolution
17
- // already inlines it), a tampered/malformed stored deck (simulating
18
- // mutation after enumeration), an adversarial root-replacement fixture, or a
19
- // deliberately raced foreign claim/resolution. Each such use is commented.
20
- import { test, describe, before, after, beforeEach, afterEach } from 'node:test';
5
+ // `CrtrClient` → in-process `createApiServer()` → handler → ticket store —
6
+ // never a mock client or pre-parsed handler call. Tickets live directly under
7
+ // the derived `ticketsRoot()` and use the same public store APIs as production.
8
+ // A raw hand-written `deck.json` is used only for states that submission cannot
9
+ // produce: an unresolved `bodyPath`, a malformed stored deck, or a raced final.
10
+ import { test, describe, before, after, beforeEach } from 'node:test';
21
11
  import assert from 'node:assert/strict';
22
12
  import { spawn } from 'node:child_process';
23
- import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync, existsSync, symlinkSync, } from 'node:fs';
13
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync, existsSync, realpathSync, } from 'node:fs';
24
14
  import { tmpdir } from 'node:os';
25
15
  import { join } from 'node:path';
26
16
  import { createHash } from 'node:crypto';
27
- import { registerInboxRoot, submitDeck, submitReview, claimTicket, releaseClaim, deckPath, responsePath, notifyDeck, } from '@crouton-kit/humanloop';
17
+ import { claimTicket, releaseClaim } from '../../../core/human/claim.js';
18
+ import { deckPath, responsePath } from '../../../core/human/convention.js';
19
+ import { notifyDeck } from '../../../core/human/deck-factories.js';
20
+ import { ticketsRoot } from '../../../core/human/root.js';
21
+ import { submitDeck, submitReview } from '../../../core/human/tickets.js';
28
22
  import { createApiServer } from '../server.js';
29
23
  import { apiSocketPath } from '../../../core/canvas/paths.js';
30
24
  import { CrtrClient, ApiError } from '../../../api/index.js';
31
25
  const TICKET_ID_PATTERN = /^[a-f0-9]{64}$/;
32
26
  // ---------------------------------------------------------------------------
33
- // Harness — one server for the whole file; a fresh humanloop root registry
34
- // (XDG_STATE_HOME) per test.
27
+ // Harness — one server for the whole file; a fresh derived tickets root per
28
+ // test.
35
29
  // ---------------------------------------------------------------------------
36
30
  let crtrHome;
37
31
  let priorCrtrHome;
38
- let priorXdgStateHome;
39
32
  let server;
40
33
  let client;
41
- let stateHome;
42
34
  async function waitForSocket(path) {
43
35
  for (let i = 0; i < 200; i++) {
44
36
  if (existsSync(path))
@@ -49,7 +41,6 @@ async function waitForSocket(path) {
49
41
  }
50
42
  before(async () => {
51
43
  priorCrtrHome = process.env['CRTR_HOME'];
52
- priorXdgStateHome = process.env['XDG_STATE_HOME'];
53
44
  crtrHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-home-'));
54
45
  process.env['CRTR_HOME'] = crtrHome;
55
46
  server = createApiServer();
@@ -63,29 +54,17 @@ after(async () => {
63
54
  process.env['CRTR_HOME'] = priorCrtrHome;
64
55
  else
65
56
  delete process.env['CRTR_HOME'];
66
- if (priorXdgStateHome !== undefined)
67
- process.env['XDG_STATE_HOME'] = priorXdgStateHome;
68
- else
69
- delete process.env['XDG_STATE_HOME'];
70
57
  });
71
58
  beforeEach(() => {
72
- stateHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-state-'));
73
- process.env['XDG_STATE_HOME'] = stateHome;
74
- });
75
- afterEach(() => {
76
- rmSync(stateHome, { recursive: true, force: true });
59
+ rmSync(ticketsRoot(), { recursive: true, force: true });
60
+ mkdirSync(ticketsRoot(), { recursive: true, mode: 0o700 });
77
61
  });
78
62
  // ---------------------------------------------------------------------------
79
63
  // Fixture helpers
80
64
  // ---------------------------------------------------------------------------
81
- function freshRoot(owner, withHandler = false) {
82
- const dir = mkdtempSync(join(tmpdir(), 'crtr-inbox-root-'));
83
- const reg = registerInboxRoot({
84
- root: dir,
85
- owner,
86
- ...(withHandler ? { handler: { command: process.execPath, args: ['-e', ''] } } : {}),
87
- });
88
- return reg.root; // already canonical (realpathSync'd internally)
65
+ function freshRoot(..._unused) {
66
+ mkdirSync(ticketsRoot(), { recursive: true, mode: 0o700 });
67
+ return realpathSync(ticketsRoot());
89
68
  }
90
69
  function deckJson(blockedSince, extra = {}) {
91
70
  return {
@@ -99,14 +78,14 @@ function deckJson(blockedSince, extra = {}) {
99
78
  * normal fixture path for any test that just needs a valid, answerable
100
79
  * ticket on disk. */
101
80
  function submitTestDeck(root, id, blockedSince, extra = {}) {
102
- return submitDeck({ root, id, deck: deckJson(blockedSince, extra) }).dir;
81
+ return submitDeck({ dir: join(root, id), deck: deckJson(blockedSince, extra) }).dir;
103
82
  }
104
83
  /** Create a real pending review ticket through the public submission API. */
105
84
  function submitTestReview(root, id, blockedSince) {
106
85
  const srcDir = mkdtempSync(join(tmpdir(), 'crtr-inbox-review-src-'));
107
86
  const file = join(srcDir, 'plan.md');
108
87
  writeFileSync(file, '# Plan\n\nDo the thing.\n');
109
- return submitReview({ root, id, review: { title: 'Review the plan', subtitle: 'Review the plan now so implementation can begin with confidence.', source: {}, file, blockedSince } }).dir;
88
+ return submitReview({ dir: join(root, id), review: { title: 'Review the plan', subtitle: 'Review the plan now so implementation can begin with confidence.', source: {}, file, blockedSince } }).dir;
110
89
  }
111
90
  /** RAW fixture writer — bypasses `submitDeck`'s own submit-time validation
112
91
  * and body-path resolution entirely. Used ONLY to construct on-disk states
@@ -144,7 +123,7 @@ function assertKeys(obj, allowed, label) {
144
123
  }
145
124
  function assertSourceShape(source) {
146
125
  assert.equal(typeof source, 'object');
147
- assertKeys(source, ['sessionName', 'askedBy', 'blockedSince', 'nodeId', 'visual'], 'DeckSourceDTO');
126
+ assertKeys(source, ['sessionName', 'askedBy', 'blockedSince', 'nodeId'], 'DeckSourceDTO');
148
127
  }
149
128
  function assertTicketSummaryShape(ticket) {
150
129
  assert.match(ticket.ticket_id, TICKET_ID_PATTERN);
@@ -221,18 +200,23 @@ function assertNoForbiddenContent(value, forbidden, path = '$') {
221
200
  // GET /v1/human/inbox — enumerate
222
201
  // ---------------------------------------------------------------------------
223
202
  describe('GET /v1/human/inbox — enumerate', () => {
224
- test('mixed deck + review tickets sort newest blocked_since first, then ticket_id ascending; closed wire shape, no forbidden content', async () => {
203
+ test('mixed deck + review tickets preserve canonical-root hash ids while sorting newest first', async () => {
225
204
  const root = freshRoot('crouter');
205
+ // This is the pre-cutover opaque-id formula: canonical root + NUL + ticket
206
+ // basename. The single derived root retains that canonical root, so an id
207
+ // a client computed before root registration disappeared still resolves.
208
+ const olderDeckId = ticketIdFor(root, 'older-deck');
226
209
  submitTestDeck(root, 'older-deck', '2026-01-01T00:00:00.000Z');
227
210
  submitTestReview(root, 'newer-review', '2026-01-02T00:00:00.000Z');
228
211
  const list = await client.listHumanInbox();
229
212
  assertInboxListShape(list);
230
- assertNoForbiddenContent(list, [root, stateHome]);
213
+ assertNoForbiddenContent(list, [root]);
231
214
  assert.equal(list.tickets.length, 2);
232
215
  assert.equal(list.tickets[0].kind, 'review', 'newer blocked_since sorts first');
233
216
  assert.equal(list.tickets[1].kind, 'deck');
234
217
  assert.equal(list.tickets[0].ticket_id, ticketIdFor(root, 'newer-review'));
235
- assert.equal(list.tickets[1].ticket_id, ticketIdFor(root, 'older-deck'));
218
+ assert.equal(list.tickets[1].ticket_id, olderDeckId);
219
+ assert.equal((await client.getHumanInboxDeck(olderDeckId)).deck.title, 'Ship it?');
236
220
  });
237
221
  test('sorts by parsed instant across differing UTC offsets, not lexical string order', async () => {
238
222
  const root = freshRoot('crouter');
@@ -302,7 +286,7 @@ describe('GET /v1/human/inbox/:ticket_id', () => {
302
286
  // POST /v1/human/inbox/:ticket_id/respond
303
287
  // ---------------------------------------------------------------------------
304
288
  describe('POST /v1/human/inbox/:ticket_id/respond', () => {
305
- test('persists the canonical humanloop.response/v2 result unchanged, matches stored response.json exactly, and dispatches completion delivery', async () => {
289
+ test('persists the canonical humanloop.response/v2 result unchanged and matches stored response.json exactly', async () => {
306
290
  const root = freshRoot('crouter', true);
307
291
  const dir = submitTestDeck(root, 'ask', '2026-01-01T00:00:00.000Z');
308
292
  const id = ticketIdFor(root, 'ask');
@@ -312,17 +296,12 @@ describe('POST /v1/human/inbox/:ticket_id/respond', () => {
312
296
  assert.deepEqual(result.responses, [{ id: 'q', selectedOptionId: 'yes' }]);
313
297
  const stored = JSON.parse(readFileSync(responsePath(dir), 'utf8'));
314
298
  assert.deepEqual(stored, result, 'the wire result is the stored humanloop response exactly, unreconstructed');
315
- // Completion dispatch is async (spawns the registered handler); poll for
316
- // the delivery marker rather than assuming it lands synchronously.
317
- const deliveryFile = join(dir, 'delivery.json');
318
- for (let i = 0; i < 100 && !existsSync(deliveryFile); i++)
319
- await new Promise((r) => setTimeout(r, 25));
320
- assert.ok(existsSync(deliveryFile), 'completion delivery was dispatched to the registered handler');
299
+ assert.ok(existsSync(responsePath(dir)), 'the canonical response remains the only ticket receipt');
321
300
  });
322
301
  test('ordinary notify acknowledgement — no special endpoint/shape', async () => {
323
302
  const root = freshRoot('crouter');
324
303
  const id_ = 'notify';
325
- submitDeck({ root, id: id_, deck: notifyDeck('Build done', { subtitle: 'The build completed successfully, so the change is ready to review.' }) });
304
+ submitDeck({ dir: join(root, id_), deck: notifyDeck('Build done', { subtitle: 'The build completed successfully, so the change is ready to review.' }) });
326
305
  const id = ticketIdFor(root, 'notify');
327
306
  const result = await client.respondHumanInboxDeck(id, { responses: [{ id: 'notify', selectedOptionId: 'ok' }] });
328
307
  assert.equal(result.kind, 'deck');
@@ -340,20 +319,15 @@ describe('POST /v1/human/inbox/:ticket_id/respond', () => {
340
319
  await client.respondHumanInboxDeck(id, { responses: [{ id: 'q', selectedOptionId: 'yes' }] });
341
320
  await expectApiError(client.respondHumanInboxDeck(id, { responses: [{ id: 'q', selectedOptionId: 'no' }] }), 409, 'ticket_already_resolved');
342
321
  });
343
- test('409 ticket_unavailable when a live foreign claim already holds the ticket', async () => {
322
+ test('a live foreign claim is taken over by the daemon finish path', async () => {
344
323
  const root = freshRoot('crouter');
345
324
  const dir = submitTestDeck(root, 'ask', '2026-01-01T00:00:00.000Z');
346
325
  const id = ticketIdFor(root, 'ask');
347
- // Raw use of the claim API is the legitimate way to simulate a genuine
348
- // live foreign claim.
349
326
  const foreignClaim = claimTicket(dir, { host: 'someone-else' });
350
327
  assert.ok(foreignClaim !== null, 'foreign claim acquired');
351
- try {
352
- await expectApiError(client.respondHumanInboxDeck(id, { responses: [{ id: 'q', selectedOptionId: 'yes' }] }), 409, 'ticket_unavailable');
353
- }
354
- finally {
355
- releaseClaim(dir, foreignClaim.token);
356
- }
328
+ const result = await client.respondHumanInboxDeck(id, { responses: [{ id: 'q', selectedOptionId: 'yes' }] });
329
+ assertDeckResultShape(result);
330
+ assert.equal(releaseClaim(dir, foreignClaim.token), false, 'the takeover released the replaced claim');
357
331
  });
358
332
  test('external cancel/resolve race: a resolution that lands between the precheck and claimTicket() reports ticket_already_resolved, never ticket_unavailable', async () => {
359
333
  const root = freshRoot('crouter');
@@ -458,7 +432,7 @@ describe('POST /v1/human/inbox/:ticket_id/respond', () => {
458
432
  // POST /v1/human/inbox/:ticket_id/cancel
459
433
  // ---------------------------------------------------------------------------
460
434
  describe('POST /v1/human/inbox/:ticket_id/cancel', () => {
461
- test('default reason, actor is hardcoded human, matches stored response.json, dispatches completion delivery', async () => {
435
+ test('default reason and hardcoded human actor match stored response.json', async () => {
462
436
  const root = freshRoot('crouter', true);
463
437
  const dir = submitTestDeck(root, 'ask', '2026-01-01T00:00:00.000Z');
464
438
  const id = ticketIdFor(root, 'ask');
@@ -469,10 +443,7 @@ describe('POST /v1/human/inbox/:ticket_id/cancel', () => {
469
443
  assert.equal(result.actor, 'human');
470
444
  const stored = JSON.parse(readFileSync(responsePath(dir), 'utf8'));
471
445
  assert.deepEqual(stored, result, 'the wire result is the stored humanloop cancellation exactly, unreconstructed');
472
- const deliveryFile = join(dir, 'delivery.json');
473
- for (let i = 0; i < 100 && !existsSync(deliveryFile); i++)
474
- await new Promise((r) => setTimeout(r, 25));
475
- assert.ok(existsSync(deliveryFile), 'completion delivery was dispatched to the registered handler');
446
+ assert.ok(existsSync(responsePath(dir)), 'the canonical cancellation remains the only ticket receipt');
476
447
  });
477
448
  test('custom reason is honored; actor is always human regardless of any client-supplied field', async () => {
478
449
  const root = freshRoot('crouter');
@@ -482,10 +453,12 @@ describe('POST /v1/human/inbox/:ticket_id/cancel', () => {
482
453
  assert.equal(result.reason, 'changed my mind');
483
454
  assert.equal(result.actor, 'human');
484
455
  });
485
- test('409 ticket_kind_unsupported for a review ticket', async () => {
456
+ test('recordless review cancellation returns the stored humanloop.cancel/v1 result', async () => {
486
457
  const root = freshRoot('crouter');
487
- submitTestReview(root, 'rev', '2026-01-01T00:00:00.000Z');
488
- await expectApiError(client.cancelHumanInboxTicket(ticketIdFor(root, 'rev')), 409, 'ticket_kind_unsupported');
458
+ const dir = submitTestReview(root, 'rev', '2026-01-01T00:00:00.000Z');
459
+ const result = await client.cancelHumanInboxTicket(ticketIdFor(root, 'rev'));
460
+ assertCanceledResultShape(result);
461
+ assert.deepEqual(JSON.parse(readFileSync(responsePath(dir), 'utf8')), result);
489
462
  });
490
463
  test('409 ticket_already_resolved after the ticket was already resolved via respond', async () => {
491
464
  const root = freshRoot('crouter');
@@ -514,65 +487,3 @@ describe('malformed ticket id syntax', () => {
514
487
  }
515
488
  });
516
489
  });
517
- // ---------------------------------------------------------------------------
518
- // Root filtering
519
- // ---------------------------------------------------------------------------
520
- describe('root filtering', () => {
521
- test('a non-crouter-owned root never appears in enumeration and its ticket 404s on GET', async () => {
522
- const root = freshRoot('humanloop');
523
- submitTestDeck(root, 'ask', '2026-01-01T00:00:00.000Z');
524
- const id = ticketIdFor(root, 'ask');
525
- const list = await client.listHumanInbox();
526
- assert.equal(list.tickets.length, 0);
527
- await expectApiError(client.getHumanInboxDeck(id), 404, 'ticket_not_found');
528
- });
529
- test('a root that becomes unavailable disappears from enumeration and resolution', async () => {
530
- const root = freshRoot('crouter');
531
- submitTestDeck(root, 'ask', '2026-01-01T00:00:00.000Z');
532
- const id = ticketIdFor(root, 'ask');
533
- let list = await client.listHumanInbox();
534
- assert.equal(list.tickets.length, 1);
535
- rmSync(root, { recursive: true, force: true });
536
- list = await client.listHumanInbox();
537
- assert.equal(list.tickets.length, 0);
538
- await expectApiError(client.getHumanInboxDeck(id), 404, 'ticket_not_found');
539
- });
540
- test('a registered root replaced by a symlink to an unrelated directory confers no authority (enumeration and resolution)', async () => {
541
- const root = freshRoot('crouter');
542
- submitTestDeck(root, 'legit', '2026-01-01T00:00:00.000Z');
543
- // Adversarial fixture: after registration, the registered pathname is
544
- // removed and replaced with a symlink to an unrelated directory that
545
- // was never registered as a crouter-owned root. Only a raw fixture can
546
- // construct this — no submission API models a compromised root.
547
- const attackerDir = mkdtempSync(join(tmpdir(), 'crtr-inbox-attacker-'));
548
- writeRawDeckTicket(attackerDir, 'attacker', deckJson('2026-01-01T00:00:00.000Z', { title: 'Attacker deck' }));
549
- rmSync(root, { recursive: true, force: true });
550
- symlinkSync(attackerDir, root);
551
- const list = await client.listHumanInbox();
552
- assert.equal(list.tickets.length, 0, 'the attacker-controlled target must not be exposed through the replaced pathname');
553
- const attackerId = ticketIdFor(attackerDir, 'attacker');
554
- await expectApiError(client.getHumanInboxDeck(attackerId), 404, 'ticket_not_found');
555
- });
556
- });
557
- // ---------------------------------------------------------------------------
558
- // Opaque-id collision safety
559
- // ---------------------------------------------------------------------------
560
- describe('opaque-id collision safety', () => {
561
- test('two crouter roots with tickets sharing the same basename resolve to distinct ids and correct decks', async () => {
562
- const rootA = freshRoot('crouter');
563
- const rootB = freshRoot('crouter');
564
- submitTestDeck(rootA, 'dup', '2026-01-01T00:00:00.000Z', { title: 'From root A' });
565
- submitTestDeck(rootB, 'dup', '2026-01-01T00:00:00.000Z', { title: 'From root B' });
566
- const idA = ticketIdFor(rootA, 'dup');
567
- const idB = ticketIdFor(rootB, 'dup');
568
- assert.notEqual(idA, idB);
569
- const list = await client.listHumanInbox();
570
- assert.equal(list.tickets.length, 2);
571
- const ids = list.tickets.map((t) => t.ticket_id).sort();
572
- assert.deepEqual(ids, [idA, idB].sort());
573
- const deckA = await client.getHumanInboxDeck(idA);
574
- const deckB = await client.getHumanInboxDeck(idB);
575
- assert.equal(deckA.deck.title, 'From root A');
576
- assert.equal(deckB.deck.title, 'From root B');
577
- });
578
- });
@@ -1,12 +1,2 @@
1
- import type { CompletionHandler } from '@crouton-kit/humanloop';
2
1
  import type { RouteTable } from '../router.js';
3
- /** A broker retains its sealed runtime generation across installs. Humanloop
4
- * freezes that generation's `_visual` argv into the request, while crtrd may
5
- * already run a newer sibling generation when the human opens the ticket.
6
- * Accept only a Node invocation of the same leaf from an immutable 64-hex
7
- * generation beneath the current handler's exact generations directory. The
8
- * command differs legitimately: CLI registrations use the system Node path,
9
- * while the daemon runs through crouter's stable copied-Node host. */
10
- export declare function trustedCrouterHandler(candidate: CompletionHandler | undefined, current: CompletionHandler, leaf: '_visual' | '_consult'): boolean;
11
- export declare function trustedCrouterVisualHandler(candidate: CompletionHandler | undefined, current?: CompletionHandler): boolean;
12
2
  export declare const humanRoutes: RouteTable;