@crouton-kit/crouter 0.3.32 → 0.3.33

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 (440) hide show
  1. package/README.md +8 -0
  2. package/dist/build-root.js +1 -0
  3. package/dist/builtin-memory/crouter-development/marketplaces.md +2 -2
  4. package/dist/builtin-memory/crouter-development/personas/base-prompt.md +2 -2
  5. package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +5 -5
  6. package/dist/builtin-memory/crouter-development/personas.md +3 -4
  7. package/dist/builtin-memory/crouter-development/plugins.md +18 -18
  8. package/dist/builtin-memory/design.md +4 -1
  9. package/dist/builtin-memory/development.md +4 -1
  10. package/dist/builtin-memory/internal/INDEX.md +1 -1
  11. package/dist/builtin-memory/internal/nodes-and-canvas.md +6 -6
  12. package/dist/builtin-memory/internal/storage-tiers.md +5 -5
  13. package/dist/builtin-memory/planning.md +4 -1
  14. package/dist/builtin-memory/product.md +80 -0
  15. package/dist/builtin-memory/spec.md +4 -1
  16. package/dist/builtin-personas/advisor/PERSONA.md +10 -0
  17. package/dist/builtin-personas/design/PERSONA.md +2 -2
  18. package/dist/builtin-personas/design/orchestrator.md +3 -3
  19. package/dist/builtin-personas/developer/PERSONA.md +1 -1
  20. package/dist/builtin-personas/developer/orchestrator.md +2 -2
  21. package/dist/builtin-personas/explore/PERSONA.md +3 -3
  22. package/dist/builtin-personas/explore/orchestrator.md +4 -2
  23. package/dist/builtin-personas/general/PERSONA.md +1 -1
  24. package/dist/builtin-personas/general/orchestrator.md +1 -1
  25. package/dist/builtin-personas/orchestration-kernel.md +7 -14
  26. package/dist/builtin-personas/plan/PERSONA.md +1 -1
  27. package/dist/builtin-personas/plan/orchestrator.md +2 -2
  28. package/dist/builtin-personas/plan/reviewers/architecture-fit/PERSONA.md +1 -1
  29. package/dist/builtin-personas/plan/reviewers/code-smells/PERSONA.md +1 -1
  30. package/dist/builtin-personas/plan/reviewers/pattern-consistency/PERSONA.md +1 -1
  31. package/dist/builtin-personas/plan/reviewers/requirements-coverage/PERSONA.md +1 -1
  32. package/dist/builtin-personas/plan/reviewers/security/PERSONA.md +1 -1
  33. package/dist/builtin-personas/product/PERSONA.md +18 -0
  34. package/dist/builtin-personas/product/orchestrator.md +14 -0
  35. package/dist/builtin-personas/product/teardown/PERSONA.md +13 -0
  36. package/dist/builtin-personas/review/PERSONA.md +1 -1
  37. package/dist/builtin-personas/review/orchestrator.md +1 -1
  38. package/dist/builtin-personas/runtime-base.md +5 -0
  39. package/dist/builtin-personas/spec/PERSONA.md +1 -1
  40. package/dist/builtin-personas/spec/orchestrator.md +2 -2
  41. package/dist/builtin-personas/spec/requirements/PERSONA.md +1 -1
  42. package/dist/builtin-views/canvas/core.mjs +82 -1
  43. package/dist/builtin-views/canvas/tui.mjs +9 -5
  44. package/dist/builtin-views/canvas/web.jsx +3 -2
  45. package/dist/builtin-views/chat/core.mjs +725 -0
  46. package/dist/builtin-views/chat/text.mjs +101 -0
  47. package/dist/builtin-views/chat/tui.mjs +368 -0
  48. package/dist/builtin-views/chat/web.jsx +367 -0
  49. package/dist/builtin-views/prompt-review/core.mjs +863 -0
  50. package/dist/builtin-views/prompt-review/text.mjs +15 -0
  51. package/dist/builtin-views/prompt-review/tui.mjs +196 -0
  52. package/dist/builtin-views/prompt-review/web.jsx +484 -0
  53. package/dist/builtin-views/settings/core.mjs +397 -0
  54. package/dist/builtin-views/settings/text.mjs +40 -0
  55. package/dist/builtin-views/settings/tui.mjs +95 -0
  56. package/dist/builtin-views/settings/web.jsx +167 -0
  57. package/dist/cli.js +16 -3
  58. package/dist/clients/attach/__tests__/autocomplete-and-bash-mode.test.js +96 -0
  59. package/dist/clients/attach/__tests__/bash-bang-routing.test.js +58 -0
  60. package/dist/clients/attach/__tests__/bundle-pi-tui-dedup.test.d.ts +1 -0
  61. package/dist/clients/attach/__tests__/bundle-pi-tui-dedup.test.js +56 -0
  62. package/dist/clients/attach/__tests__/titled-editor.test.js +22 -1
  63. package/dist/clients/attach/attach-cmd.d.ts +18 -0
  64. package/dist/clients/attach/attach-cmd.js +1723 -795
  65. package/dist/clients/attach/canvas-panels.js +2 -2
  66. package/dist/clients/attach/chat-view.d.ts +10 -0
  67. package/dist/clients/attach/chat-view.js +23 -0
  68. package/dist/clients/attach/config-load.d.ts +8 -4
  69. package/dist/clients/attach/config-load.js +2 -0
  70. package/dist/clients/attach/extension-dialogs.d.ts +2 -3
  71. package/dist/clients/attach/extension-dialogs.js +7 -9
  72. package/dist/clients/attach/graph-overlay.js +3 -2
  73. package/dist/clients/attach/input-controller.d.ts +4 -3
  74. package/dist/clients/attach/input-controller.js +24 -3
  75. package/dist/clients/attach/slash-commands.d.ts +7 -7
  76. package/dist/clients/attach/slash-commands.js +38 -14
  77. package/dist/clients/attach/titled-editor.js +18 -14
  78. package/dist/clients/attach/view-socket.d.ts +2 -1
  79. package/dist/clients/attach/view-socket.js +27 -8
  80. package/dist/clients/web/__tests__/source-cache.test.d.ts +1 -0
  81. package/dist/clients/web/__tests__/source-cache.test.js +32 -0
  82. package/dist/clients/web/dev-server.js +1 -0
  83. package/dist/clients/web/events.js +9 -11
  84. package/dist/clients/web/server.d.ts +4 -3
  85. package/dist/clients/web/server.js +138 -31
  86. package/dist/clients/web/source-cache.d.ts +10 -0
  87. package/dist/clients/web/source-cache.js +57 -0
  88. package/dist/clients/web/web-cmd.js +28 -9
  89. package/dist/commands/__tests__/human.test.js +30 -28
  90. package/dist/commands/canvas-history/search.js +1 -1
  91. package/dist/commands/canvas-history.js +5 -8
  92. package/dist/commands/canvas-issue.d.ts +2 -0
  93. package/dist/commands/canvas-issue.js +148 -0
  94. package/dist/commands/canvas-prune.js +19 -0
  95. package/dist/commands/canvas-rebuild-index.d.ts +2 -0
  96. package/dist/commands/canvas-rebuild-index.js +57 -0
  97. package/dist/commands/canvas-snapshot.d.ts +2 -0
  98. package/dist/commands/canvas-snapshot.js +48 -0
  99. package/dist/commands/canvas-tmux-spread.d.ts +2 -0
  100. package/dist/commands/canvas-tmux-spread.js +188 -0
  101. package/dist/commands/canvas.d.ts +1 -0
  102. package/dist/commands/canvas.js +16 -1
  103. package/dist/commands/chord.js +143 -48
  104. package/dist/commands/daemon.js +3 -3
  105. package/dist/commands/human/prompts.d.ts +0 -1
  106. package/dist/commands/human/prompts.js +39 -54
  107. package/dist/commands/human/queue.d.ts +12 -1
  108. package/dist/commands/human/queue.js +468 -73
  109. package/dist/commands/human/shared.d.ts +3 -4
  110. package/dist/commands/human/shared.js +3 -3
  111. package/dist/commands/human.js +11 -10
  112. package/dist/commands/memory/find.js +3 -2
  113. package/dist/commands/memory/list.js +4 -3
  114. package/dist/commands/memory/read.js +3 -3
  115. package/dist/commands/memory/shared.d.ts +1 -4
  116. package/dist/commands/memory/shared.js +6 -9
  117. package/dist/commands/memory/write.js +3 -3
  118. package/dist/commands/memory.js +4 -7
  119. package/dist/commands/node-context.d.ts +2 -0
  120. package/dist/commands/node-context.js +172 -0
  121. package/dist/commands/node-snapshot.d.ts +2 -0
  122. package/dist/commands/node-snapshot.js +123 -0
  123. package/dist/commands/node.js +228 -52
  124. package/dist/commands/pkg/plugin-inspect.js +6 -6
  125. package/dist/commands/pkg/plugin-manage.js +1 -1
  126. package/dist/commands/pkg/plugin.js +2 -2
  127. package/dist/commands/pkg.js +2 -2
  128. package/dist/commands/push.d.ts +2 -0
  129. package/dist/commands/push.js +79 -11
  130. package/dist/commands/revive.js +74 -1
  131. package/dist/commands/search/answer.d.ts +1 -0
  132. package/dist/commands/search/answer.js +50 -0
  133. package/dist/commands/search/contents.d.ts +1 -0
  134. package/dist/commands/search/contents.js +96 -0
  135. package/dist/commands/search/exa.d.ts +53 -0
  136. package/dist/commands/search/exa.js +155 -0
  137. package/dist/commands/search/puremd.d.ts +11 -0
  138. package/dist/commands/search/puremd.js +53 -0
  139. package/dist/commands/search/web.d.ts +1 -0
  140. package/dist/commands/search/web.js +65 -0
  141. package/dist/commands/search.d.ts +2 -0
  142. package/dist/commands/search.js +24 -0
  143. package/dist/commands/sys/__tests__/sync-import.test.d.ts +1 -0
  144. package/dist/commands/sys/__tests__/sync-import.test.js +72 -0
  145. package/dist/commands/sys/config.js +59 -10
  146. package/dist/commands/sys/doctor.js +56 -4
  147. package/dist/commands/sys/prompt-review.d.ts +1 -0
  148. package/dist/commands/sys/prompt-review.js +178 -0
  149. package/dist/commands/sys/promptstudio.d.ts +2 -0
  150. package/dist/commands/sys/promptstudio.js +65 -0
  151. package/dist/commands/sys/settings.d.ts +2 -0
  152. package/dist/commands/sys/settings.js +16 -0
  153. package/dist/commands/sys/sync.js +311 -159
  154. package/dist/commands/sys/sysprompt.d.ts +1 -0
  155. package/dist/commands/sys/sysprompt.js +86 -0
  156. package/dist/commands/sys.js +9 -5
  157. package/dist/commands/view-new.js +2 -2
  158. package/dist/core/__tests__/artifact-paths.test.d.ts +1 -0
  159. package/dist/core/__tests__/artifact-paths.test.js +44 -0
  160. package/dist/core/__tests__/broker-preflight.test.d.ts +1 -0
  161. package/dist/core/__tests__/broker-preflight.test.js +85 -0
  162. package/dist/core/__tests__/broker-sdk-wiring.test.js +15 -0
  163. package/dist/core/__tests__/canvas.test.js +37 -1
  164. package/dist/core/__tests__/chat-view-reconnect.test.d.ts +1 -0
  165. package/dist/core/__tests__/chat-view-reconnect.test.js +70 -0
  166. package/dist/core/__tests__/child-death-wake.test.js +11 -2
  167. package/dist/core/__tests__/close.test.js +39 -1
  168. package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +1 -0
  169. package/dist/core/__tests__/connection-reconnect-resume.test.js +37 -0
  170. package/dist/core/__tests__/context-intro.test.js +48 -14
  171. package/dist/core/__tests__/daemon-boot.test.js +182 -9
  172. package/dist/core/__tests__/editor-label.test.d.ts +1 -0
  173. package/dist/core/__tests__/editor-label.test.js +26 -0
  174. package/dist/core/__tests__/fault-marker.test.d.ts +1 -0
  175. package/dist/core/__tests__/fault-marker.test.js +112 -0
  176. package/dist/core/__tests__/fault-retry-rewind.test.d.ts +1 -0
  177. package/dist/core/__tests__/fault-retry-rewind.test.js +123 -0
  178. package/dist/core/__tests__/fixtures/fake-engine.d.ts +30 -4
  179. package/dist/core/__tests__/fixtures/fake-engine.js +156 -17
  180. package/dist/core/__tests__/fixtures/fake-pi-host.js +10 -1
  181. package/dist/core/__tests__/full/human-new-window-regression.test.js +1 -1
  182. package/dist/core/__tests__/helpers/harness.d.ts +1 -1
  183. package/dist/core/__tests__/helpers/harness.js +2 -2
  184. package/dist/core/__tests__/human-stranded-deliver.test.js +38 -1
  185. package/dist/core/__tests__/human-surface-target.test.js +1 -1
  186. package/dist/core/__tests__/kickoff.test.js +18 -19
  187. package/dist/core/__tests__/memory-resolver.test.js +12 -1
  188. package/dist/core/__tests__/migration.test.js +49 -14
  189. package/dist/core/__tests__/model-ladders.test.d.ts +1 -0
  190. package/dist/core/__tests__/model-ladders.test.js +160 -0
  191. package/dist/core/__tests__/node-env.test.d.ts +1 -0
  192. package/dist/core/__tests__/node-env.test.js +26 -0
  193. package/dist/core/__tests__/push-final-guard.test.js +7 -1
  194. package/dist/core/__tests__/relaunch-root.test.js +9 -9
  195. package/dist/core/__tests__/revive.test.js +36 -6
  196. package/dist/core/__tests__/spawn-root.test.js +24 -1
  197. package/dist/core/__tests__/stop-guard.test.js +10 -0
  198. package/dist/core/__tests__/stranded-relaunch.test.d.ts +1 -0
  199. package/dist/core/__tests__/stranded-relaunch.test.js +72 -0
  200. package/dist/core/__tests__/tmux-surface.test.js +5 -1
  201. package/dist/core/__tests__/unknown-path.test.js +19 -19
  202. package/dist/core/__tests__/yield-ensures-daemon.test.d.ts +1 -0
  203. package/dist/core/__tests__/yield-ensures-daemon.test.js +54 -0
  204. package/dist/core/artifact.d.ts +2 -33
  205. package/dist/core/artifact.js +27 -87
  206. package/dist/core/bootstrap.js +2 -0
  207. package/dist/core/canvas/browse/__tests__/model.test.js +35 -1
  208. package/dist/core/canvas/browse/app.js +87 -17
  209. package/dist/core/canvas/browse/model.d.ts +10 -1
  210. package/dist/core/canvas/browse/model.js +37 -1
  211. package/dist/core/canvas/browse/render.js +35 -33
  212. package/dist/core/canvas/canvas.d.ts +7 -0
  213. package/dist/core/canvas/canvas.js +54 -5
  214. package/dist/core/canvas/db.js +35 -8
  215. package/dist/core/canvas/labels.d.ts +6 -8
  216. package/dist/core/canvas/labels.js +8 -11
  217. package/dist/core/canvas/nav-model.d.ts +5 -4
  218. package/dist/core/canvas/nav-model.js +31 -17
  219. package/dist/core/canvas/paths.d.ts +18 -1
  220. package/dist/core/canvas/paths.js +31 -2
  221. package/dist/core/canvas/render.d.ts +25 -0
  222. package/dist/core/canvas/render.js +96 -13
  223. package/dist/core/canvas/status-glyph.d.ts +35 -0
  224. package/dist/core/canvas/status-glyph.js +104 -0
  225. package/dist/core/canvas/types.d.ts +2 -2
  226. package/dist/core/config.js +114 -16
  227. package/dist/core/fault-classifier.d.ts +41 -0
  228. package/dist/core/fault-classifier.js +110 -0
  229. package/dist/core/feed/inbox.d.ts +15 -0
  230. package/dist/core/feed/inbox.js +40 -14
  231. package/dist/core/frontmatter.d.ts +1 -11
  232. package/dist/core/frontmatter.js +1 -55
  233. package/dist/core/hearth/config.d.ts +2 -0
  234. package/dist/core/hearth/config.js +75 -0
  235. package/dist/core/hearth/guest-env.d.ts +2 -0
  236. package/dist/core/hearth/guest-env.js +11 -0
  237. package/dist/core/hearth/index.d.ts +5 -0
  238. package/dist/core/hearth/index.js +5 -0
  239. package/dist/core/hearth/provider.d.ts +21 -0
  240. package/dist/core/hearth/provider.js +10 -0
  241. package/dist/core/hearth/providers/blaxel-bootstrap.d.ts +10 -0
  242. package/dist/core/hearth/providers/blaxel-bootstrap.js +39 -0
  243. package/dist/core/hearth/providers/blaxel-home.d.ts +11 -0
  244. package/dist/core/hearth/providers/blaxel-home.js +126 -0
  245. package/dist/core/hearth/providers/blaxel.d.ts +26 -0
  246. package/dist/core/hearth/providers/blaxel.js +208 -0
  247. package/dist/core/hearth/providers/types.d.ts +72 -0
  248. package/dist/core/hearth/providers/types.js +1 -0
  249. package/dist/core/hearth/registry.d.ts +15 -0
  250. package/dist/core/hearth/registry.js +179 -0
  251. package/dist/core/hearth/types.d.ts +121 -0
  252. package/dist/core/hearth/types.js +1 -0
  253. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +1 -0
  254. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +79 -0
  255. package/dist/core/{skill-sync → host-exports}/builtins.d.ts +21 -13
  256. package/dist/core/host-exports/builtins.js +68 -0
  257. package/dist/core/{skill-sync → host-exports}/export.d.ts +9 -6
  258. package/dist/core/{skill-sync → host-exports}/export.js +37 -14
  259. package/dist/core/io.js +1 -1
  260. package/dist/core/log.d.ts +9 -0
  261. package/dist/core/log.js +113 -0
  262. package/dist/core/memory-resolver.d.ts +8 -8
  263. package/dist/core/memory-resolver.js +15 -28
  264. package/dist/core/personas/index.d.ts +4 -4
  265. package/dist/core/personas/index.js +2 -2
  266. package/dist/core/personas/loader.d.ts +51 -0
  267. package/dist/core/personas/loader.js +54 -50
  268. package/dist/core/personas/resolve.d.ts +43 -27
  269. package/dist/core/personas/resolve.js +336 -94
  270. package/dist/core/runtime/auth-reload.d.ts +7 -0
  271. package/dist/core/runtime/auth-reload.js +69 -0
  272. package/dist/core/runtime/bearings.d.ts +35 -15
  273. package/dist/core/runtime/bearings.js +305 -44
  274. package/dist/core/runtime/branded-host.d.ts +4 -2
  275. package/dist/core/runtime/branded-host.js +66 -4
  276. package/dist/core/runtime/broker-protocol.d.ts +38 -3
  277. package/dist/core/runtime/broker.js +343 -18
  278. package/dist/core/runtime/close.js +37 -29
  279. package/dist/core/runtime/connectivity.d.ts +12 -0
  280. package/dist/core/runtime/connectivity.js +73 -0
  281. package/dist/core/runtime/fault-recovery-nudge.d.ts +2 -0
  282. package/dist/core/runtime/fault-recovery-nudge.js +2 -0
  283. package/dist/core/runtime/fault-recovery.d.ts +23 -0
  284. package/dist/core/runtime/fault-recovery.js +74 -0
  285. package/dist/core/runtime/fault.d.ts +25 -0
  286. package/dist/core/runtime/fault.js +176 -0
  287. package/dist/core/runtime/front-door.d.ts +1 -1
  288. package/dist/core/runtime/front-door.js +2 -2
  289. package/dist/core/runtime/host.d.ts +10 -0
  290. package/dist/core/runtime/host.js +71 -9
  291. package/dist/core/runtime/kickoff.js +31 -45
  292. package/dist/core/runtime/launch.d.ts +32 -18
  293. package/dist/core/runtime/launch.js +148 -43
  294. package/dist/core/runtime/model-swap.d.ts +18 -0
  295. package/dist/core/runtime/model-swap.js +95 -0
  296. package/dist/core/runtime/naming.d.ts +7 -0
  297. package/dist/core/runtime/naming.js +61 -9
  298. package/dist/core/runtime/nodes.js +6 -1
  299. package/dist/core/runtime/persona.js +16 -17
  300. package/dist/core/runtime/placement.d.ts +36 -31
  301. package/dist/core/runtime/placement.js +149 -64
  302. package/dist/core/runtime/promote.d.ts +2 -0
  303. package/dist/core/runtime/promote.js +23 -3
  304. package/dist/core/runtime/recycle.js +6 -4
  305. package/dist/core/runtime/reset.d.ts +5 -2
  306. package/dist/core/runtime/reset.js +2 -2
  307. package/dist/core/runtime/revive.d.ts +4 -0
  308. package/dist/core/runtime/revive.js +27 -9
  309. package/dist/core/runtime/roadmap.d.ts +1 -1
  310. package/dist/core/runtime/roadmap.js +1 -1
  311. package/dist/core/runtime/spawn.d.ts +2 -2
  312. package/dist/core/runtime/spawn.js +30 -6
  313. package/dist/core/runtime/stop-guard.js +6 -1
  314. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  315. package/dist/core/runtime/tmux-chrome.js +1 -1
  316. package/dist/core/runtime/tmux.d.ts +29 -6
  317. package/dist/core/runtime/tmux.js +134 -80
  318. package/dist/core/runtime/view-socket-client.d.ts +46 -0
  319. package/dist/core/runtime/view-socket-client.js +203 -0
  320. package/dist/core/substrate/index.d.ts +1 -1
  321. package/dist/core/substrate/index.js +1 -1
  322. package/dist/core/substrate/on-read.js +16 -4
  323. package/dist/core/substrate/render.d.ts +10 -13
  324. package/dist/core/substrate/render.js +56 -51
  325. package/dist/core/tui/host.js +83 -18
  326. package/dist/core/view/__tests__/transport-cache.test.d.ts +1 -0
  327. package/dist/core/view/__tests__/transport-cache.test.js +62 -0
  328. package/dist/core/view/contract.d.ts +20 -0
  329. package/dist/core/view/stream-local.d.ts +3 -0
  330. package/dist/core/view/stream-local.js +184 -0
  331. package/dist/core/view/transport-cache.d.ts +8 -0
  332. package/dist/core/view/transport-cache.js +38 -0
  333. package/dist/core/view/transport-local.js +4 -0
  334. package/dist/core/view/transport.d.ts +7 -1
  335. package/dist/daemon/crtrd.d.ts +3 -19
  336. package/dist/daemon/crtrd.js +139 -178
  337. package/dist/daemon/manage.d.ts +18 -1
  338. package/dist/daemon/manage.js +54 -9
  339. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.d.ts +1 -0
  340. package/dist/hearth/wake-proxy/__tests__/anthropic-oauth.test.js +289 -0
  341. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.d.ts +1 -0
  342. package/dist/hearth/wake-proxy/__tests__/config-timeout.test.js +34 -0
  343. package/dist/hearth/wake-proxy/__tests__/guest-source.test.d.ts +1 -0
  344. package/dist/hearth/wake-proxy/__tests__/guest-source.test.js +203 -0
  345. package/dist/hearth/wake-proxy/__tests__/hardening.test.d.ts +1 -0
  346. package/dist/hearth/wake-proxy/__tests__/hardening.test.js +59 -0
  347. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.d.ts +1 -0
  348. package/dist/hearth/wake-proxy/__tests__/hearth-status-route.test.js +372 -0
  349. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.d.ts +1 -0
  350. package/dist/hearth/wake-proxy/__tests__/http-running-route-fast-path.test.js +258 -0
  351. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.d.ts +1 -0
  352. package/dist/hearth/wake-proxy/__tests__/model-auth-routes.test.js +437 -0
  353. package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.d.ts +1 -0
  354. package/dist/hearth/wake-proxy/__tests__/source-bridge-gate.test.js +455 -0
  355. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.d.ts +1 -0
  356. package/dist/hearth/wake-proxy/__tests__/static-asset-allowlist.test.js +15 -0
  357. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.d.ts +1 -0
  358. package/dist/hearth/wake-proxy/__tests__/warm-path-concurrency.test.js +141 -0
  359. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.d.ts +1 -0
  360. package/dist/hearth/wake-proxy/__tests__/ws-teardown-accounting.test.js +143 -0
  361. package/dist/hearth/wake-proxy/anthropic-oauth.d.ts +58 -0
  362. package/dist/hearth/wake-proxy/anthropic-oauth.js +189 -0
  363. package/dist/hearth/wake-proxy/auth.d.ts +22 -0
  364. package/dist/hearth/wake-proxy/auth.js +128 -0
  365. package/dist/hearth/wake-proxy/config.d.ts +2 -0
  366. package/dist/hearth/wake-proxy/config.js +151 -0
  367. package/dist/hearth/wake-proxy/guest-source.d.ts +14 -0
  368. package/dist/hearth/wake-proxy/guest-source.js +130 -0
  369. package/dist/hearth/wake-proxy/hearth-status.d.ts +44 -0
  370. package/dist/hearth/wake-proxy/hearth-status.js +267 -0
  371. package/dist/hearth/wake-proxy/home.d.ts +67 -0
  372. package/dist/hearth/wake-proxy/home.js +297 -0
  373. package/dist/hearth/wake-proxy/main.d.ts +1 -0
  374. package/dist/hearth/wake-proxy/main.js +134 -0
  375. package/dist/hearth/wake-proxy/model-auth.d.ts +13 -0
  376. package/dist/hearth/wake-proxy/model-auth.js +345 -0
  377. package/dist/hearth/wake-proxy/proxy.d.ts +35 -0
  378. package/dist/hearth/wake-proxy/proxy.js +716 -0
  379. package/dist/hearth/wake-proxy/public-source-gate.d.ts +9 -0
  380. package/dist/hearth/wake-proxy/public-source-gate.js +409 -0
  381. package/dist/hearth/wake-proxy/redact.d.ts +1 -0
  382. package/dist/hearth/wake-proxy/redact.js +17 -0
  383. package/dist/hearth/wake-proxy/server.d.ts +11 -0
  384. package/dist/hearth/wake-proxy/server.js +142 -0
  385. package/dist/hearth/wake-proxy/state.d.ts +18 -0
  386. package/dist/hearth/wake-proxy/state.js +342 -0
  387. package/dist/hearth/wake-proxy/types.d.ts +76 -0
  388. package/dist/hearth/wake-proxy/types.js +1 -0
  389. package/dist/index.js +3 -2
  390. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +6 -5
  391. package/dist/pi-extensions/canvas-context-intro.js +7 -7
  392. package/dist/pi-extensions/canvas-doc-substrate.js +19 -22
  393. package/dist/pi-extensions/canvas-nav.js +15 -8
  394. package/dist/pi-extensions/canvas-stophook.d.ts +1 -1
  395. package/dist/pi-extensions/canvas-stophook.js +78 -11
  396. package/dist/types.d.ts +39 -20
  397. package/dist/types.js +38 -13
  398. package/dist/web/runtime.js +141 -42
  399. package/dist/web/transport-http.js +7 -5
  400. package/dist/web/transport-stream.d.ts +3 -0
  401. package/dist/web/transport-stream.js +204 -0
  402. package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  403. package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  404. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  405. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  406. package/dist/web-client/assets/fraunces-latin-ext-wght-normal-Ca2vKHc0.woff2 +0 -0
  407. package/dist/web-client/assets/fraunces-latin-wght-normal-ukD16Tqj.woff2 +0 -0
  408. package/dist/web-client/assets/fraunces-vietnamese-wght-normal-CnvboYUG.woff2 +0 -0
  409. package/dist/web-client/assets/index-BZUxTkv5.css +2 -0
  410. package/dist/web-client/assets/index-D36PNBj4.js +80 -0
  411. package/dist/web-client/assets/instrument-sans-latin-ext-wght-normal-B5bTHO_g.woff2 +0 -0
  412. package/dist/web-client/assets/instrument-sans-latin-wght-normal-BbzFLZTg.woff2 +0 -0
  413. package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
  414. package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
  415. package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
  416. package/dist/web-client/index.html +3 -2
  417. package/package.json +32 -10
  418. package/dist/core/__tests__/error-stall-recycle.test.js +0 -141
  419. package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.js +0 -57
  420. package/dist/core/skill-sync/builtins.js +0 -112
  421. package/dist/core/skill-sync/claude-plugins.d.ts +0 -23
  422. package/dist/core/skill-sync/claude-plugins.js +0 -71
  423. package/dist/core/skill-sync/engine.d.ts +0 -42
  424. package/dist/core/skill-sync/engine.js +0 -633
  425. package/dist/core/skill-sync/manifest.d.ts +0 -64
  426. package/dist/core/skill-sync/manifest.js +0 -181
  427. package/dist/core/skill-sync/profile.d.ts +0 -76
  428. package/dist/core/skill-sync/profile.js +0 -173
  429. package/dist/core/skill-sync/snapshot.d.ts +0 -57
  430. package/dist/core/skill-sync/snapshot.js +0 -120
  431. package/dist/pi-extensions/canvas-commands.d.ts +0 -37
  432. package/dist/pi-extensions/canvas-commands.js +0 -113
  433. package/dist/pi-extensions/canvas-resume.d.ts +0 -21
  434. package/dist/pi-extensions/canvas-resume.js +0 -83
  435. package/dist/pi-extensions/canvas-view.d.ts +0 -21
  436. package/dist/pi-extensions/canvas-view.js +0 -76
  437. package/dist/web-client/assets/index-BUvQb4hR.css +0 -2
  438. package/dist/web-client/assets/index-ClLQXYAE.js +0 -10
  439. /package/dist/{core/__tests__/error-stall-recycle.test.d.ts → clients/attach/__tests__/autocomplete-and-bash-mode.test.d.ts} +0 -0
  440. /package/dist/{core/skill-sync/__tests__/dry-run-wrote-count.test.d.ts → clients/attach/__tests__/bash-bang-routing.test.d.ts} +0 -0
@@ -1,51 +1,123 @@
1
1
  // `crtr canvas chord` — the tmux prefix-menu dispatcher.
2
2
  //
3
3
  // The alt+c display-menu can't see the cursor node or read config at popup time
4
- // — it only knows the active pane. So every config-driven prefix chord routes
5
- // through this one leaf: tmux passes `--pane '#{pane_id}'` + `--key <k>`, and
6
- // the dispatcher resolves the node in that pane, reads
7
- // `canvasNav.prefixBinds[key]`, interpolates the template vars, and execs
8
- // `crtr <argv>`. This keeps the menu static while the behaviour stays fully
9
- // config-driven (no per-node menu rebuild).
4
+ // — it only knows the active pane. So the menu hands this leaf a resolved `--run`
5
+ // string plus the originating pane id; this dispatcher resolves the node in that
6
+ // pane, interpolates the node vars, and execs `crtr <argv>` with no shell.
10
7
  //
11
- // One special case bypasses the bind table:
12
- // a bind whose `run` is the sentinel `__graph__` → send-keys `/graph` into
13
- // the pane (toggles the in-pi GRAPH modal); the menu emits this directly so
14
- // the dispatcher only handles it defensively.
15
- //
16
- // execFile (never `sh -c`) runs the interpolated argv, so a node name with
17
- // shell metacharacters can never inject — each argv element is literal.
8
+ // execFile/spawn (never `sh -c`) keeps the argv literal, so shell metacharacters
9
+ // in config data cannot inject.
10
+ import { spawn, execFile } from 'node:child_process';
18
11
  import { promisify } from 'node:util';
19
- import { execFile } from 'node:child_process';
20
12
  import { defineLeaf } from '../core/command.js';
21
13
  import { InputError } from '../core/io.js';
22
- import { readConfig } from '../core/config.js';
23
- import { sendKeysEnter } from '../core/runtime/tmux-chrome.js';
24
14
  import { nodeInPane } from './node.js';
25
15
  import { getNode, subscribersOf, view, fullName, } from '../core/canvas/index.js';
26
16
  const pexec = promisify(execFile);
27
17
  /** Template vars available to a `run` string. Single-valued vars interpolate
28
- * in place (preserving spaces, e.g. a node name); `{subtree}` is multi-valued
29
- * and a bare `{subtree}` token expands to several argv elements. */
30
- function buildVars(selfId) {
18
+ * in place (preserving spaces, e.g. a node name); `{pane}` is the active tmux
19
+ * pane id; `{subtree}` is multi-valued and a bare `{subtree}` token expands to
20
+ * several argv elements. */
21
+ function buildVars(selfId, pane) {
31
22
  const node = getNode(selfId);
32
23
  const manager = subscribersOf(selfId)[0]?.node_id ?? '';
33
24
  return {
34
25
  id: selfId,
35
26
  self: selfId,
27
+ pane,
36
28
  lane: selfId,
37
29
  name: node !== null ? fullName(node) : selfId,
38
30
  manager,
39
31
  subtree: view(selfId).join(' '),
40
32
  };
41
33
  }
34
+ function parseRun(run) {
35
+ const out = [];
36
+ let cur = '';
37
+ let quoted = null;
38
+ let escaped = false;
39
+ let inToken = false;
40
+ const push = () => {
41
+ if (!inToken)
42
+ return;
43
+ out.push(cur);
44
+ cur = '';
45
+ inToken = false;
46
+ };
47
+ for (let i = 0; i < run.length; i++) {
48
+ const ch = run[i];
49
+ if (escaped) {
50
+ cur += ch;
51
+ inToken = true;
52
+ escaped = false;
53
+ continue;
54
+ }
55
+ if (quoted === 'single') {
56
+ if (ch === "'") {
57
+ quoted = null;
58
+ }
59
+ else {
60
+ cur += ch;
61
+ inToken = true;
62
+ }
63
+ continue;
64
+ }
65
+ if (quoted === 'double') {
66
+ if (ch === '"') {
67
+ quoted = null;
68
+ }
69
+ else if (ch === '\\') {
70
+ escaped = true;
71
+ }
72
+ else {
73
+ cur += ch;
74
+ inToken = true;
75
+ }
76
+ continue;
77
+ }
78
+ if (/\s/.test(ch)) {
79
+ push();
80
+ continue;
81
+ }
82
+ if (ch === "'") {
83
+ quoted = 'single';
84
+ inToken = true;
85
+ continue;
86
+ }
87
+ if (ch === '"') {
88
+ quoted = 'double';
89
+ inToken = true;
90
+ continue;
91
+ }
92
+ if (ch === '\\') {
93
+ escaped = true;
94
+ inToken = true;
95
+ continue;
96
+ }
97
+ cur += ch;
98
+ inToken = true;
99
+ }
100
+ if (escaped) {
101
+ cur += '\\';
102
+ inToken = true;
103
+ }
104
+ if (quoted !== null) {
105
+ throw new InputError({
106
+ error: 'bad_run',
107
+ message: 'invalid canvas run string: unterminated quote',
108
+ next: 'Fix the bind in config.json and try again.',
109
+ });
110
+ }
111
+ push();
112
+ return out;
113
+ }
42
114
  /** Split a `run` string argv-style and interpolate the template vars. A bare
43
115
  * `{subtree}` token expands to several argv elements; every other placeholder
44
116
  * is substituted in place (kept as one element so a multi-word name survives
45
117
  * as a single argument under execFile). */
46
118
  function interpolateArgv(run, vars) {
47
119
  const out = [];
48
- for (const tok of run.split(/\s+/).filter((t) => t !== '')) {
120
+ for (const tok of parseRun(run)) {
49
121
  if (tok === '{subtree}') {
50
122
  for (const part of (vars['subtree'] ?? '').split(/\s+/).filter((p) => p !== ''))
51
123
  out.push(part);
@@ -55,13 +127,36 @@ function interpolateArgv(run, vars) {
55
127
  }
56
128
  return out;
57
129
  }
130
+ async function dispatch(argv, interactive) {
131
+ if (argv.length === 0)
132
+ return;
133
+ if (interactive) {
134
+ await new Promise((resolve) => {
135
+ try {
136
+ const child = spawn('crtr', argv, { stdio: 'inherit' });
137
+ child.once('error', () => resolve());
138
+ child.once('close', () => resolve());
139
+ }
140
+ catch {
141
+ resolve();
142
+ }
143
+ });
144
+ return;
145
+ }
146
+ try {
147
+ await pexec('crtr', argv, { timeout: 15_000 });
148
+ }
149
+ catch {
150
+ /* best-effort: the keystroke just acts; errors are surfaced by the inner cmd */
151
+ }
152
+ }
58
153
  export const chordLeaf = defineLeaf({
59
154
  name: 'chord',
60
155
  description: 'tmux prefix-menu dispatcher (bound by alt+c; not run by hand)',
61
- whenToUse: 'never directly — the alt+c menu routes config-driven chords through it',
156
+ whenToUse: 'never directly — the alt+c menu routes node-relative actions through it',
62
157
  help: {
63
158
  name: 'canvas chord',
64
- summary: 'tmux prefix-menu dispatcher — resolve the node in --pane, look up canvasNav.prefixBinds[--key], interpolate, and exec `crtr <argv>`. Bound by the alt+c menu; not meant to be run by hand.',
159
+ summary: 'tmux prefix-menu dispatcher — resolve the node in --pane, interpolate --run against it, and exec `crtr <argv>`. Bound by the alt+c menu; not meant to be run by hand.',
65
160
  params: [
66
161
  {
67
162
  kind: 'flag',
@@ -72,24 +167,39 @@ export const chordLeaf = defineLeaf({
72
167
  },
73
168
  {
74
169
  kind: 'flag',
75
- name: 'key',
170
+ name: 'run',
76
171
  type: 'string',
77
172
  required: true,
78
- constraint: 'The chord key pressed after alt+c (e.g. g or m).',
173
+ constraint: 'The argv string to run as crtr, after node vars resolve.',
174
+ },
175
+ {
176
+ kind: 'flag',
177
+ name: 'interactive',
178
+ type: 'bool',
179
+ required: false,
180
+ constraint: 'When true, inherit stdio so popup forms can read from the popup tty.',
79
181
  },
80
182
  ],
81
183
  output: [
82
184
  { name: 'ran', type: 'boolean', required: true, constraint: 'True when an action was dispatched.' },
83
- { name: 'key', type: 'string', required: true, constraint: 'Echo of the chord key.' },
84
185
  { name: 'node_id', type: 'string', required: false, constraint: 'The node the chord resolved against.' },
85
- { name: 'action', type: 'string', required: false, constraint: 'What ran: a crtr argv string, "graph-toggle", or "noop".' },
186
+ { name: 'action', type: 'string', required: false, constraint: 'What ran: a crtr argv string or "noop".' },
86
187
  ],
87
188
  outputKind: 'object',
88
- effects: ['Runs a `crtr` subcommand (focus/close/…) or sends `/graph` into the pane, per the matched bind.'],
189
+ effects: ['Runs a `crtr` subcommand per the resolved bind.'],
89
190
  },
90
191
  run: async (input) => {
91
- const pane = input['pane'] ?? process.env['TMUX_PANE'];
92
- const key = input['key'].trim();
192
+ const rawPane = input['pane'];
193
+ const pane = rawPane !== undefined && rawPane !== '' ? rawPane : process.env['TMUX_PANE'];
194
+ const run = input['run']?.trim();
195
+ const interactive = input['interactive'] === true;
196
+ if (run === undefined || run === '') {
197
+ throw new InputError({
198
+ error: 'missing_run',
199
+ message: 'no run string provided',
200
+ next: 'Pass --run <argv-string> from the menu renderer.',
201
+ });
202
+ }
93
203
  const selfId = nodeInPane(pane);
94
204
  if (selfId === undefined) {
95
205
  throw new InputError({
@@ -98,25 +208,10 @@ export const chordLeaf = defineLeaf({
98
208
  next: 'Run from inside an agent\'s pane, or pass --pane <pane-id>.',
99
209
  });
100
210
  }
101
- const bind = readConfig('user').canvasNav.prefixBinds[key];
102
- if (bind === undefined)
103
- return { ran: false, key, node_id: selfId, action: 'noop' };
104
- // The GRAPH-toggle sentinel: type /graph into the pane (the menu normally
105
- // emits this directly; handle it here too so a manual chord still works).
106
- if (bind.run === '__graph__') {
107
- if (pane !== undefined && pane !== '')
108
- sendKeysEnter(pane, '/graph');
109
- return { ran: true, key, node_id: selfId, action: 'graph-toggle' };
110
- }
111
- const argv = interpolateArgv(bind.run, buildVars(selfId));
211
+ const argv = interpolateArgv(run, buildVars(selfId, pane ?? ''));
112
212
  if (argv.length === 0)
113
- return { ran: false, key, node_id: selfId, action: 'noop' };
114
- try {
115
- await pexec('crtr', argv, { timeout: 15_000 });
116
- }
117
- catch {
118
- /* best-effort: the keystroke just acts; errors are surfaced by the inner cmd */
119
- }
120
- return { ran: true, key, node_id: selfId, action: `crtr ${argv.join(' ')}` };
213
+ return { ran: false, node_id: selfId, action: 'noop' };
214
+ await dispatch(argv, interactive);
215
+ return { ran: true, node_id: selfId, action: `crtr ${argv.join(' ')}` };
121
216
  },
122
217
  });
@@ -29,11 +29,11 @@ const daemonStart = defineLeaf({
29
29
  outputKind: 'object',
30
30
  effects: [
31
31
  'Spawns dist/daemon/crtrd-cli.js detached + unref\'d; it outlives this process.',
32
- 'Writes a pidfile at crtrHome()/crtrd.pid.',
32
+ 'Writes a pidfile at CRTR_PIDFILE if set, otherwise crtrHome()/crtrd.pid.'
33
33
  ],
34
34
  },
35
35
  run: async (_input) => {
36
- const result = spawnDaemon();
36
+ const result = await spawnDaemon();
37
37
  return result;
38
38
  },
39
39
  });
@@ -94,7 +94,7 @@ const daemonStop = defineLeaf({
94
94
  throw new InputError({
95
95
  error: 'kill_failed',
96
96
  message: `failed to signal pid ${pid}: ${err.message}`,
97
- next: 'The pidfile may be stale; remove ~/.crouter/canvas/crtrd.pid manually.',
97
+ next: 'The pidfile may be stale; remove the recorded pidfile manually.',
98
98
  });
99
99
  }
100
100
  },
@@ -1,5 +1,4 @@
1
1
  export declare const humanAsk: import("../../core/command.js").LeafDef;
2
- export declare const humanApprove: import("../../core/command.js").LeafDef;
3
2
  export declare const humanReview: import("../../core/command.js").LeafDef;
4
3
  export declare const humanNotify: import("../../core/command.js").LeafDef;
5
4
  export declare const humanShow: import("../../core/command.js").LeafDef;
@@ -6,25 +6,40 @@ import { tmuxServerReachable } from '../../core/spawn.js';
6
6
  import { mkdirSync, existsSync } from 'node:fs';
7
7
  import { join, resolve } from 'node:path';
8
8
  import { randomBytes } from 'node:crypto';
9
- import { validateDeck, approveDeck, notifyDeck, atomicWriteJson, deckPath, display, } from '@crouton-kit/humanloop';
9
+ import { validateDeck, notifyDeck, atomicWriteJson, deckPath, display, } from '@crouton-kit/humanloop';
10
10
  import { DECK_SCHEMA_HINT, followUpReview, spawnHumanJob, detachHumanTui, resolveMaxPanes, } from './shared.js';
11
11
  /** The asking node's id, or null when run from a bare shell (no parent to route to). */
12
12
  function askingNode() {
13
13
  return process.env['CRTR_NODE_ID'] ?? null;
14
14
  }
15
+ function buildHumanAskDeck(question) {
16
+ return validateDeck({
17
+ title: question,
18
+ interactions: [
19
+ {
20
+ id: 'question',
21
+ title: question,
22
+ options: [],
23
+ allowFreetext: true,
24
+ freetextLabel: 'Your answer',
25
+ },
26
+ ],
27
+ });
28
+ }
15
29
  // ---------------------------------------------------------------------------
16
30
  // ask
17
31
  // ---------------------------------------------------------------------------
18
32
  export const humanAsk = defineLeaf({
19
33
  name: 'ask',
20
34
  description: 'put a structured choice or open question to a person',
21
- whenToUse: 'you would otherwise lay a decision, a set of options, or a question out for the user as prose — reach for this instead, for anything from a quick yes/no to a judgment-heavy call: reviewing all the requirements before building, choosing among implementation patterns, walking a list of risks and deciding what to do about each, settling a naming or scope question, picking which of several findings to act on. Works for open-ended asks too (set `allowFreetext`, offer a few `options` as starting points). The kickoff never blocks, so the human answering on their own time is never a reason to skip the ask and guess instead',
35
+ whenToUse: 'you would otherwise lay a decision, a set of options, or a question out for the user as prose — reach for this instead, for anything from a quick yes/no to a judgment-heavy call: gating a handoff, merge, deploy, destructive/irreversible operation, or real budget on an explicit human sign-off (offer Yes/No options), reviewing all the requirements before building, choosing among implementation patterns, walking a list of risks and deciding what to do about each, settling a naming or scope question, picking which of several findings to act on. Works for open-ended asks too (set `allowFreetext`, offer a few `options` as starting points). The kickoff never blocks, so the human answering on their own time is never a reason to skip the ask and guess instead',
22
36
  help: {
23
37
  name: 'human ask',
24
38
  summary: 'put a humanloop decision deck in front of a person; returns a job handle immediately. This is the default, expected channel for posing ANY question or decision to the user — reach for it instead of writing the question as prose in your reply.',
25
- guide: 'Use this for quick, open-ended, and nuanced asks alike not just "formal" multiple-choice. Set `allowFreetext: true` (with `freetextLabel`) when the answer is open-ended; offer a few `options` as starting points even for judgment calls. The kickoff is instant and NEVER blocks — "never block on the result" refers only to not busy-waiting on the job; the human answering on their own time is not a reason to avoid asking or to fall back to inline prose. The deck body is directive-flavored markdown rendered by termrender (panels, columns, trees, callouts, mermaid) — see `termrender doc -h` for the directive set before authoring one.',
39
+ guide: 'Use exactly one of these forms: `crtr human ask "<question>"` for a simple open-text prompt (the CLI builds a one-item humanloop deck internally), or `crtr human ask --context-file deck.json` for a fully structured deck. The kickoff is instant and NEVER blocks — "never block on the result" refers only to not busy-waiting on the job; the human answering on their own time is not a reason to avoid asking or to fall back to inline prose. The deck body is directive-flavored markdown rendered by termrender (panels, columns, trees, callouts, mermaid) — see `termrender doc -h` for the directive set before authoring one.',
26
40
  params: [
27
- { kind: 'context-file', name: 'deck', required: true, constraint: 'Contains a humanloop deck. Validated before any job is created.', shape: DECK_SCHEMA_HINT },
41
+ { kind: 'positional', name: 'question', type: 'string', required: false, constraint: 'Bare-question shorthand for a simple open-text ask. Mutually exclusive with `--context-file`.' },
42
+ { kind: 'context-file', name: 'deck', required: false, constraint: 'Strict complex-ask deck JSON. Use this when you need multiple interactions, options, or other deck structure. Mutually exclusive with the question shorthand.', shape: DECK_SCHEMA_HINT },
28
43
  { kind: 'flag', name: 'wait', type: 'bool', required: false, constraint: 'Accepted for symmetry with the job contract; the kickoff never blocks.' },
29
44
  ],
30
45
  output: [
@@ -39,9 +54,25 @@ export const humanAsk = defineLeaf({
39
54
  ],
40
55
  },
41
56
  run: async (input) => {
57
+ const question = input['question'];
58
+ const deckInput = input['deck'];
59
+ if (question !== undefined && deckInput !== undefined) {
60
+ throw new InputError({
61
+ error: 'bad_invocation',
62
+ message: 'use either a bare question or --context-file, not both',
63
+ next: 'Run `crtr human ask "<question>"` for a simple open-text prompt, or `crtr human ask --context-file deck.json` for a structured deck.',
64
+ });
65
+ }
66
+ if (question === undefined && deckInput === undefined) {
67
+ throw new InputError({
68
+ error: 'missing_parameter',
69
+ message: 'human ask needs either a question or --context-file deck.json',
70
+ next: 'Run `crtr human ask "<question>"` or `crtr human ask --context-file deck.json`.',
71
+ });
72
+ }
42
73
  let deck;
43
74
  try {
44
- deck = validateDeck(input['deck']);
75
+ deck = validateDeck(question !== undefined ? buildHumanAskDeck(question) : deckInput);
45
76
  }
46
77
  catch (e) {
47
78
  throw new InputError({
@@ -63,61 +94,15 @@ export const humanAsk = defineLeaf({
63
94
  },
64
95
  });
65
96
  // ---------------------------------------------------------------------------
66
- // approve
67
- // ---------------------------------------------------------------------------
68
- export const humanApprove = defineLeaf({
69
- name: 'approve',
70
- description: 'a Yes/No sign-off gate',
71
- whenToUse: 'a step needs an explicit human yes before it proceeds and a plain answer (not anchored comments) is enough: before a handoff, a merge or deploy, a destructive or irreversible operation, spending real budget, or acting on a risky plan. Reach for `ask` instead when you need them to choose among options or answer something open-ended; reach for `review` when the feedback belongs inline on a document',
72
- help: {
73
- name: 'human approve',
74
- summary: 'a Yes/No approval gate; returns a job handle immediately. The standard way to gate a handoff on human sign-off. Kickoff never blocks — peek at the result later rather than busy-waiting; the human answering on their own time is not a reason to skip the gate.',
75
- guide: 'The body is directive-flavored markdown rendered by termrender (panels, columns, trees, callouts, mermaid) — see `termrender doc -h` for the directive set before authoring one.',
76
- params: [
77
- { kind: 'positional', name: 'title', type: 'string', required: true, constraint: 'The question shown to the human.' },
78
- { kind: 'flag', name: 'subtitle', type: 'string', required: false, constraint: 'Optional one-line context.' },
79
- { kind: 'flag', name: 'body', type: 'string', required: false, constraint: 'Optional markdown body.' },
80
- ],
81
- output: [
82
- { name: 'job_id', type: 'string', required: true, constraint: 'Node id of this approval; the {approved, …envelope} result is pushed to your inbox when answered.' },
83
- { name: 'dir', type: 'string', required: true, constraint: 'Interaction directory.' },
84
- { name: 'follow_up', type: 'string', required: true, constraint: 'A non-blocking status peek. The human may take minutes to hours — never block waiting on this.' },
85
- ],
86
- outputKind: 'object',
87
- effects: [
88
- 'Creates a kind:"human" node under you and writes a Yes/No validation deck.',
89
- 'Spawns the approval TUI in a detached tmux pane (when in tmux).',
90
- ],
91
- },
92
- run: async (input) => {
93
- const title = input['title'];
94
- const subtitle = input['subtitle'];
95
- const body = input['body'];
96
- const deck = approveDeck(title, {
97
- ...(subtitle !== undefined ? { subtitle } : {}),
98
- ...(body !== undefined ? { body } : {}),
99
- });
100
- const cwd = process.cwd();
101
- const jobId = spawnNode({ kind: 'human', parent: askingNode(), cwd, name: 'human-approve', lifecycle: 'terminal' }).node_id;
102
- const idir = interactionDir(jobId, cwd);
103
- mkdirSync(idir, { recursive: true });
104
- atomicWriteJson(deckPath(idir), deck);
105
- const rc = { mode: 'approve', job_id: jobId, approve_iid: 'approve' };
106
- atomicWriteJson(join(idir, 'run.json'), rc);
107
- const { follow_up } = spawnHumanJob(jobId, idir, cwd);
108
- return { job_id: jobId, dir: idir, follow_up };
109
- },
110
- });
111
- // ---------------------------------------------------------------------------
112
97
  // review
113
98
  // ---------------------------------------------------------------------------
114
99
  export const humanReview = defineLeaf({
115
100
  name: 'review',
116
101
  description: 'collect anchored comments on a .md (plan or spec)',
117
- whenToUse: 'a human should comment line-by-line on a document rather than give one overall answer: reviewing a plan or spec before you build it, marking up a draft, flagging specific sections to change. The comments come back anchored to the lines they touch. Use `approve` instead for a single yes/no on the whole thing, or `ask` to pose a discrete choice',
102
+ whenToUse: 'a human should comment line-by-line on a document rather than give one overall answer: reviewing a plan or spec before you build it, marking up a draft, flagging specific sections to change. The comments come back anchored to the lines they touch. Use `ask` instead for a single yes/no sign-off on the whole thing, or to pose a discrete choice',
118
103
  help: {
119
104
  name: 'human review',
120
- summary: "put a .md live on the human's screen for anchored, line-by-line comments; returns a job handle instantly (a non-blocking kickoff, like ask/approve). The pane tracks the file and re-renders on every save, so edit in place rather than re-presenting.",
105
+ summary: "put a .md live on the human's screen for anchored, line-by-line comments; returns a job handle instantly (a non-blocking kickoff, like ask). The pane tracks the file and re-renders on every save, so edit in place rather than re-presenting.",
121
106
  guide: "A kickoff, not a blocking call: it returns at once and the human reviews on their own time. When they submit, the FeedbackResult (anchored comments, plus any line edits they made) is pushed to your inbox — waking you — and autosaved to `output`; you never poll, verify it opened, or background it. The pane is a LIVE view of the file: keep editing the .md in place and it updates, so do not cancel and re-present to show a change. The .md is directive-flavored markdown rendered by termrender (panels, columns, trees, callouts, mermaid) — see `termrender doc -h` for the directive set before authoring one.",
122
107
  params: [
123
108
  { kind: 'positional', name: 'file', type: 'path', required: true, constraint: 'Absolute path to an existing .md file.' },
@@ -163,7 +148,7 @@ export const humanReview = defineLeaf({
163
148
  const output = outputArg !== undefined ? outputArg : join(idir, 'feedback.json');
164
149
  const rc = { mode: 'review', job_id: jobId, file: abs, output };
165
150
  atomicWriteJson(join(idir, 'run.json'), rc);
166
- // review is a non-blocking kickoff, exactly like ask/approve: the detached
151
+ // review is a non-blocking kickoff, exactly like ask: the detached
167
152
  // `_run` worker pushes the FeedbackResult as this node's final report when
168
153
  // the human submits, which fans into our inbox and wakes us (and is also
169
154
  // autosaved to `output`). There is nothing to block on — the doc is live on
@@ -10,12 +10,23 @@
10
10
  * flips status=done). Reconstructs the same pushFinal body `_run` would have
11
11
  * emitted, per mode; a canceled-on-disk response reaps the node without
12
12
  * delivering a result (mirrors `human cancel`). Returns true iff it acted. */
13
- export declare function finalizeResolvedInteraction(jobId: string): Promise<boolean>;
13
+ export declare function finalizeResolvedInteraction(jobId: string, claim?: InteractionClaim): Promise<boolean>;
14
14
  /** Sweep every interaction under the cwd's interactions root and deliver-back +
15
15
  * reap any that are answered-but-undelivered (see finalizeResolvedInteraction).
16
16
  * Interaction dir names ARE the bridge node ids. Returns how many it healed. */
17
17
  export declare function healStrandedInteractions(cwd: string): Promise<number>;
18
18
  export declare const humanInbox: import("../../core/command.js").LeafDef;
19
19
  export declare const humanList: import("../../core/command.js").LeafDef;
20
+ export declare const humanDeck: import("../../core/command.js").LeafDef;
21
+ interface InteractionClaim {
22
+ release: () => void;
23
+ }
24
+ export declare function acquireInteractionClaim(dir: string, jobId: string, opts?: {
25
+ allowResolved?: boolean;
26
+ markProgress?: boolean;
27
+ respectProgress?: boolean;
28
+ }): InteractionClaim | 'already_resolved' | 'claimed';
29
+ export declare const humanResolve: import("../../core/command.js").LeafDef;
20
30
  export declare const humanCancel: import("../../core/command.js").LeafDef;
21
31
  export declare const humanRun: import("../../core/command.js").LeafDef;
32
+ export {};