@north-light/crouter 0.3.233 → 0.3.235

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 (411) hide show
  1. package/dist/api/client.js +16 -15
  2. package/dist/api/dto/nodes.d.ts +11 -0
  3. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +1 -1
  4. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +14 -17
  5. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/index.ts +7 -11
  6. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +8 -8
  7. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +10 -11
  8. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/pi-shell-runner.ts +2 -2
  9. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +3 -3
  10. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +7 -7
  11. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +8 -8
  12. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +6 -6
  13. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +3 -3
  14. package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +1 -1
  15. package/dist/clients/attach/chrome/ticket-panel.js +15 -2
  16. package/dist/clients/attach/overlays/graph.js +0 -3
  17. package/dist/clients/attach/overlays/mcp.js +1 -2
  18. package/dist/clients/attach/render/chat-view.js +0 -12
  19. package/dist/clients/attach/render/crtr-output.js +0 -2
  20. package/dist/clients/attach/render/tool-calls.js +0 -6
  21. package/dist/clients/attach/slash/dispatch.js +8 -11
  22. package/dist/clients/attach/viewer.js +535 -537
  23. package/dist/clients/conversation/projection.js +0 -2
  24. package/dist/clients/inbox/controller.js +22 -3
  25. package/dist/clients/inbox/review/companion-pane.js +0 -4
  26. package/dist/clients/inbox/review-adapter.js +0 -7
  27. package/dist/clients/inbox/tui/slots.d.ts +3 -3
  28. package/dist/clients/inbox/tui/types.d.ts +2 -2
  29. package/dist/commands/api-client.js +0 -8
  30. package/dist/commands/attention.js +1 -9
  31. package/dist/commands/canvas-browse.js +2 -1
  32. package/dist/commands/canvas-config.js +0 -10
  33. package/dist/commands/canvas-history.js +2 -1
  34. package/dist/commands/cron.js +10 -23
  35. package/dist/commands/dashboard.js +0 -2
  36. package/dist/commands/human/feedback.js +2 -1
  37. package/dist/commands/human/prompts.js +2 -5
  38. package/dist/commands/human/queue.js +2 -7
  39. package/dist/commands/human/request.js +0 -14
  40. package/dist/commands/human/review.js +2 -1
  41. package/dist/commands/human.js +1 -1
  42. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +4 -4
  43. package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.d.ts +1 -0
  44. package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +96 -0
  45. package/dist/commands/memory/delete.js +1 -1
  46. package/dist/commands/memory/edit.js +6 -3
  47. package/dist/commands/memory/find.js +2 -2
  48. package/dist/commands/memory/lint.js +2 -1
  49. package/dist/commands/memory/list.d.ts +4 -0
  50. package/dist/commands/memory/list.js +20 -14
  51. package/dist/commands/memory/move.js +1 -1
  52. package/dist/commands/memory/read.d.ts +2 -7
  53. package/dist/commands/memory/read.js +5 -16
  54. package/dist/commands/memory/shared.d.ts +1 -0
  55. package/dist/commands/memory/shared.js +17 -8
  56. package/dist/commands/memory/write.js +8 -4
  57. package/dist/commands/node/bash.js +2 -1
  58. package/dist/commands/node/create.js +2 -1
  59. package/dist/commands/node/inspect.js +11 -10
  60. package/dist/commands/node/lifecycle.js +5 -13
  61. package/dist/commands/node/message.js +11 -6
  62. package/dist/commands/node/subscription.js +7 -2
  63. package/dist/commands/node/wait.js +9 -4
  64. package/dist/commands/node-context.js +2 -1
  65. package/dist/commands/node-lifecycle-revive.js +0 -2
  66. package/dist/commands/node-worktree.js +2 -1
  67. package/dist/commands/pkg/browse/actions.d.ts +1 -1
  68. package/dist/commands/pkg/browse/actions.js +4 -4
  69. package/dist/commands/pkg/browse/catalog.d.ts +1 -1
  70. package/dist/commands/pkg/browse/catalog.js +15 -15
  71. package/dist/commands/pkg/browse/command-view.d.ts +1 -1
  72. package/dist/commands/pkg/browse/command-view.js +3 -3
  73. package/dist/commands/pkg/browse/detail-panel.d.ts +1 -1
  74. package/dist/commands/pkg/browse/detail-panel.js +8 -8
  75. package/dist/commands/pkg/browse/doc-view.d.ts +1 -1
  76. package/dist/commands/pkg/browse/doc-view.js +3 -3
  77. package/dist/commands/pkg/browse/list-panel.d.ts +1 -1
  78. package/dist/commands/pkg/browse/list-panel.js +3 -3
  79. package/dist/commands/pkg/browse/model.d.ts +3 -3
  80. package/dist/commands/pkg/browse/shell.d.ts +2 -2
  81. package/dist/commands/pkg/browse/shell.js +13 -13
  82. package/dist/commands/pkg/plugin-manage.js +3 -2
  83. package/dist/commands/pkg/shared.js +0 -2
  84. package/dist/commands/pkg.js +1 -0
  85. package/dist/commands/profile/delete.js +2 -1
  86. package/dist/commands/profile/rename.js +1 -1
  87. package/dist/commands/push.js +2 -3
  88. package/dist/commands/revive.js +0 -2
  89. package/dist/commands/surface/node/placement.js +2 -1
  90. package/dist/commands/surface-edit.js +2 -1
  91. package/dist/commands/sys/config.js +1 -4
  92. package/dist/commands/sys/daemon.js +0 -10
  93. package/dist/commands/sys/doctor.js +3 -2
  94. package/dist/commands/sys/panels/broker-limits-panel.d.ts +2 -2
  95. package/dist/commands/sys/panels/broker-limits-panel.js +4 -4
  96. package/dist/commands/sys/panels/dependencies-panel.d.ts +2 -2
  97. package/dist/commands/sys/panels/dependencies-panel.js +2 -2
  98. package/dist/commands/sys/panels/keybindings-panel.d.ts +1 -1
  99. package/dist/commands/sys/panels/keybindings-panel.js +5 -5
  100. package/dist/commands/sys/panels/models-panel.d.ts +4 -4
  101. package/dist/commands/sys/panels/models-panel.js +11 -10
  102. package/dist/commands/sys/panels/plugins-panel.d.ts +2 -2
  103. package/dist/commands/sys/panels/plugins-panel.js +2 -2
  104. package/dist/commands/sys/panels/prefs-panel.d.ts +2 -2
  105. package/dist/commands/sys/panels/prefs-panel.js +4 -4
  106. package/dist/commands/sys/panels/profiles-panel.d.ts +1 -1
  107. package/dist/commands/sys/panels/profiles-panel.js +14 -13
  108. package/dist/commands/sys/panels/provider-panel.d.ts +3 -3
  109. package/dist/commands/sys/panels/provider-panel.js +8 -8
  110. package/dist/commands/sys/settings-shell.d.ts +3 -3
  111. package/dist/commands/sys/settings-shell.js +15 -15
  112. package/dist/commands/sys/setup-settings-runner.d.ts +3 -3
  113. package/dist/commands/sys/setup-settings-runner.js +5 -5
  114. package/dist/commands/sys/setup-wizard.d.ts +4 -4
  115. package/dist/commands/sys/setup-wizard.js +8 -8
  116. package/dist/commands/sys/support/prepare.js +4 -4
  117. package/dist/commands/sys/support/submit.js +2 -2
  118. package/dist/commands/sys/sync-deps.js +0 -2
  119. package/dist/commands/sys/sync-project-guidance.js +2 -1
  120. package/dist/commands/sys/sysprompt.js +2 -1
  121. package/dist/commands/sys.js +1 -0
  122. package/dist/core/__tests__/boot.test.js +0 -8
  123. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +23 -1
  124. package/dist/core/__tests__/canvas-db-boundary.test.d.ts +1 -0
  125. package/dist/core/__tests__/canvas-db-boundary.test.js +46 -0
  126. package/dist/core/__tests__/canvas.test.js +1 -1
  127. package/dist/core/__tests__/child-death-wake.test.js +0 -2
  128. package/dist/core/__tests__/cli-help-contract.test.d.ts +1 -0
  129. package/dist/core/__tests__/cli-help-contract.test.js +150 -0
  130. package/dist/core/__tests__/cron-armed-context-failure.test.d.ts +1 -0
  131. package/dist/core/__tests__/cron-armed-context-failure.test.js +145 -0
  132. package/dist/core/__tests__/daemon-wedge.test.js +0 -4
  133. package/dist/core/__tests__/dead-node-policy-table.test.js +0 -4
  134. package/dist/core/__tests__/fixtures/fake-engine.js +4 -14
  135. package/dist/core/__tests__/fixtures/fake-pi-host.js +5 -5
  136. package/dist/core/__tests__/focuses.test.js +0 -6
  137. package/dist/core/__tests__/fs-utils.test.d.ts +1 -0
  138. package/dist/core/__tests__/fs-utils.test.js +50 -0
  139. package/dist/core/__tests__/helpers/harness.js +1 -1
  140. package/dist/core/__tests__/inline-memory-refs.test.js +0 -2
  141. package/dist/core/__tests__/integration/broker-fork-seam.test.js +0 -2
  142. package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +3 -16
  143. package/dist/core/__tests__/integration/command-plugins.test.js +21 -24
  144. package/dist/core/__tests__/integration/deferred-no-wake.test.js +0 -6
  145. package/dist/core/__tests__/integration/flagship-lifecycle.test.js +0 -26
  146. package/dist/core/__tests__/integration/live-mutation-verbs.test.js +0 -4
  147. package/dist/core/__tests__/integration/live-mutation.test.js +1 -5
  148. package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +1 -5
  149. package/dist/core/__tests__/integration/revive.test.js +0 -12
  150. package/dist/core/__tests__/integration/subscription-delivery.test.js +0 -6
  151. package/dist/core/__tests__/integration/tmux-surface.test.js +24 -8
  152. package/dist/core/__tests__/integration/worktree-reap.test.js +0 -6
  153. package/dist/core/__tests__/lifecycle.test.js +0 -18
  154. package/dist/core/__tests__/memory-resolver-precedence.test.js +1 -1
  155. package/dist/core/__tests__/migration.test.js +2 -2
  156. package/dist/core/__tests__/on-read-dedup-resume.test.js +3 -3
  157. package/dist/core/__tests__/pid-identity-match.test.js +1 -1
  158. package/dist/core/__tests__/plugin-kinds.test.js +1 -1
  159. package/dist/core/__tests__/plugin-page-components.test.js +1 -1
  160. package/dist/core/__tests__/preview-registry-sync.test.js +42 -1
  161. package/dist/core/__tests__/respawn-throttle.test.js +0 -4
  162. package/dist/core/__tests__/revive-all.test.js +5 -5
  163. package/dist/core/__tests__/revive-parked-fresh.test.js +62 -11
  164. package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +0 -8
  165. package/dist/core/__tests__/seam/broker-attach-stream.test.js +0 -8
  166. package/dist/core/__tests__/seam/broker-crash-teardown.test.js +0 -2
  167. package/dist/core/__tests__/tmux-driver-boundary.test.d.ts +1 -0
  168. package/dist/core/__tests__/tmux-driver-boundary.test.js +50 -0
  169. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +11 -6
  170. package/dist/core/activity-signal.d.ts +7 -0
  171. package/dist/core/activity-signal.js +38 -0
  172. package/dist/core/auto-update.js +2 -1
  173. package/dist/core/bootstrap.js +2 -1
  174. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
  175. package/dist/core/canvas/__tests__/remote-transport.test.js +1 -1
  176. package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
  177. package/dist/core/canvas/browse/app.js +3 -2
  178. package/dist/core/canvas/browse/model.d.ts +1 -1
  179. package/dist/core/canvas/browse/model.js +0 -4
  180. package/dist/core/canvas/canvas.d.ts +22 -0
  181. package/dist/core/canvas/canvas.js +61 -19
  182. package/dist/core/canvas/crons.js +0 -6
  183. package/dist/core/canvas/db.d.ts +14 -20
  184. package/dist/core/canvas/db.js +30 -1332
  185. package/dist/core/canvas/focuses.js +0 -4
  186. package/dist/core/canvas/history.js +2 -1
  187. package/dist/core/canvas/meta-file.js +18 -27
  188. package/dist/core/canvas/migrations.d.ts +20 -0
  189. package/dist/core/canvas/migrations.js +1339 -0
  190. package/dist/core/canvas/nav-model.js +1 -11
  191. package/dist/core/canvas/nav-render.js +0 -8
  192. package/dist/core/canvas/remote-canvas-source.d.ts +8 -0
  193. package/dist/core/canvas/remote-canvas-source.js +9 -3
  194. package/dist/core/canvas/render-source.js +31 -13
  195. package/dist/core/command-manifests/manifest.js +0 -10
  196. package/dist/core/command-manifests/registry.d.ts +2 -0
  197. package/dist/core/command-manifests/schema.js +0 -4
  198. package/dist/core/command-plugins/compose.js +4 -2
  199. package/dist/core/command-plugins/discovery.d.ts +1 -0
  200. package/dist/core/command-plugins/discovery.js +1 -1
  201. package/dist/core/command-plugins/transport/http-invoke.js +0 -14
  202. package/dist/core/command.js +2 -6
  203. package/dist/core/config.js +2 -1
  204. package/dist/core/fault-classifier.js +8 -0
  205. package/dist/core/feed/inbox.d.ts +10 -0
  206. package/dist/core/feed/inbox.js +18 -12
  207. package/dist/core/fs-utils.d.ts +9 -2
  208. package/dist/core/fs-utils.js +7 -15
  209. package/dist/core/help.js +0 -8
  210. package/dist/core/host-exports/export.d.ts +2 -2
  211. package/dist/core/host-exports/export.js +9 -12
  212. package/dist/core/human/answer.d.ts +2 -2
  213. package/dist/core/human/convention.d.ts +2 -5
  214. package/dist/core/human/convention.js +3 -13
  215. package/dist/core/human/page-schema.d.ts +2 -2
  216. package/dist/core/human/page-schema.js +2 -2
  217. package/dist/core/human/root.js +6 -23
  218. package/dist/core/human/scan.js +24 -7
  219. package/dist/core/human/tickets.d.ts +4 -1
  220. package/dist/core/human/tickets.js +20 -6
  221. package/dist/core/io.js +0 -12
  222. package/dist/core/memory/identity.js +0 -4
  223. package/dist/core/memory/inline-ref-inventory.js +3 -2
  224. package/dist/core/memory/lint.js +3 -6
  225. package/dist/core/memory-resolver.d.ts +5 -0
  226. package/dist/core/memory-resolver.js +14 -12
  227. package/dist/core/pagination.d.ts +2 -0
  228. package/dist/core/pagination.js +2 -3
  229. package/dist/core/preview-registry.d.ts +14 -0
  230. package/dist/core/preview-registry.js +2 -4
  231. package/dist/core/preview-result-path.js +2 -1
  232. package/dist/core/profiles/manifest.d.ts +37 -5
  233. package/dist/core/profiles/manifest.js +44 -24
  234. package/dist/core/profiles/select.js +0 -4
  235. package/dist/core/review/signal.js +4 -23
  236. package/dist/core/review/ticket-filter.d.ts +3 -3
  237. package/dist/core/review/ticket-filter.js +4 -9
  238. package/dist/core/runtime/__tests__/engine-route.test.js +1 -1
  239. package/dist/core/runtime/__tests__/spawn-env.test.js +0 -8
  240. package/dist/core/runtime/bearings-render.d.ts +56 -0
  241. package/dist/core/runtime/bearings-render.js +241 -0
  242. package/dist/core/runtime/bearings.d.ts +2 -17
  243. package/dist/core/runtime/bearings.js +12 -198
  244. package/dist/core/runtime/broker/auth-reload.d.ts +39 -0
  245. package/dist/core/runtime/broker/auth-reload.js +149 -0
  246. package/dist/core/runtime/broker/engine-drive.d.ts +26 -0
  247. package/dist/core/runtime/broker/engine-drive.js +257 -0
  248. package/dist/core/runtime/broker/engine-routing.d.ts +143 -0
  249. package/dist/core/runtime/broker/engine-routing.js +211 -0
  250. package/dist/core/runtime/broker/event-projection.js +3 -2
  251. package/dist/core/runtime/broker/fault-retry.js +11 -4
  252. package/dist/core/runtime/broker/frame-client.d.ts +38 -0
  253. package/dist/core/runtime/broker/frame-client.js +129 -0
  254. package/dist/core/runtime/broker/frame-dispatch.d.ts +12 -189
  255. package/dist/core/runtime/broker/frame-dispatch.js +89 -1476
  256. package/dist/core/runtime/broker/frame-engine-control.d.ts +20 -0
  257. package/dist/core/runtime/broker/frame-engine-control.js +231 -0
  258. package/dist/core/runtime/broker/frame-memory-refs.d.ts +19 -0
  259. package/dist/core/runtime/broker/frame-memory-refs.js +41 -0
  260. package/dist/core/runtime/broker/frame-model-query.d.ts +13 -0
  261. package/dist/core/runtime/broker/frame-model-query.js +69 -0
  262. package/dist/core/runtime/broker/frame-read.d.ts +19 -0
  263. package/dist/core/runtime/broker/frame-read.js +116 -0
  264. package/dist/core/runtime/broker/frame-replies.d.ts +24 -0
  265. package/dist/core/runtime/broker/frame-replies.js +64 -0
  266. package/dist/core/runtime/broker/frame-session.d.ts +34 -0
  267. package/dist/core/runtime/broker/frame-session.js +203 -0
  268. package/dist/core/runtime/broker/rebind.js +50 -0
  269. package/dist/core/runtime/broker/turn-ignition.d.ts +42 -0
  270. package/dist/core/runtime/broker/turn-ignition.js +74 -0
  271. package/dist/core/runtime/broker-extension-render.js +9 -85
  272. package/dist/core/runtime/broker-protocol.js +0 -4
  273. package/dist/core/runtime/broker-sdk.js +2 -1
  274. package/dist/core/runtime/broker.d.ts +1 -1
  275. package/dist/core/runtime/broker.js +5 -23
  276. package/dist/core/runtime/fault.js +3 -2
  277. package/dist/core/runtime/headless-pi.js +3 -2
  278. package/dist/core/runtime/host.js +2 -3
  279. package/dist/core/runtime/kickoff.js +0 -4
  280. package/dist/core/runtime/launch-target.js +2 -1
  281. package/dist/core/runtime/launch.d.ts +2 -2
  282. package/dist/core/runtime/launch.js +20 -10
  283. package/dist/core/runtime/lifecycle.js +17 -26
  284. package/dist/core/runtime/managed-provider-cooling.d.ts +1 -1
  285. package/dist/core/runtime/naming.js +0 -2
  286. package/dist/core/runtime/nodes.js +2 -1
  287. package/dist/core/runtime/persona.js +0 -6
  288. package/dist/core/runtime/placement-tmux.js +2 -5
  289. package/dist/core/runtime/placement.js +4 -11
  290. package/dist/core/runtime/recap.js +4 -3
  291. package/dist/core/runtime/reopen.js +4 -7
  292. package/dist/core/runtime/reset.js +0 -4
  293. package/dist/core/runtime/resume-root.js +0 -2
  294. package/dist/core/runtime/revive.js +17 -13
  295. package/dist/core/runtime/session-list-cache.js +2 -2
  296. package/dist/core/runtime/shell-expansion.js +0 -2
  297. package/dist/core/runtime/spawn.js +0 -2
  298. package/dist/core/runtime/stop-guard.js +28 -16
  299. package/dist/core/runtime/stream-watchdog.d.ts +0 -1
  300. package/dist/core/runtime/stream-watchdog.js +13 -18
  301. package/dist/core/runtime/tmux-bindings.js +0 -2
  302. package/dist/core/runtime/tmux-driver.d.ts +12 -0
  303. package/dist/core/runtime/tmux-driver.js +18 -13
  304. package/dist/core/runtime/warm-pool.js +0 -4
  305. package/dist/core/scope.js +4 -3
  306. package/dist/core/spawn.js +2 -3
  307. package/dist/core/subscription-state.js +10 -17
  308. package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +3 -3
  309. package/dist/core/substrate/frontmatter-validation.d.ts +1 -0
  310. package/dist/core/substrate/frontmatter-validation.js +1 -1
  311. package/dist/core/substrate/render.js +0 -12
  312. package/dist/core/substrate/schema.js +0 -12
  313. package/dist/core/substrate/surface-match.js +0 -2
  314. package/dist/core/termrender/display.js +2 -1
  315. package/dist/core/tui/page-host.d.ts +3 -3
  316. package/dist/core/tui/page-host.js +4 -4
  317. package/dist/core/tui/panel.js +3 -3
  318. package/dist/core/wake.js +0 -12
  319. package/dist/core/worktree.js +0 -2
  320. package/dist/daemon/__tests__/reconciler-signature.test.d.ts +1 -0
  321. package/dist/daemon/__tests__/reconciler-signature.test.js +36 -0
  322. package/dist/daemon/api/__tests__/error-seam.test.js +27 -0
  323. package/dist/daemon/api/__tests__/seam/api-server.test.js +2 -16
  324. package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +3 -11
  325. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +0 -6
  326. package/dist/daemon/api/handlers/attach.js +2 -1
  327. package/dist/daemon/api/handlers/broker-ops.js +3 -6
  328. package/dist/daemon/api/handlers/canvas.js +12 -18
  329. package/dist/daemon/api/handlers/feedback-comments.js +0 -8
  330. package/dist/daemon/api/handlers/health.js +3 -2
  331. package/dist/daemon/api/handlers/human-requests.js +0 -10
  332. package/dist/daemon/api/handlers/human.js +1 -5
  333. package/dist/daemon/api/handlers/inbox.js +0 -18
  334. package/dist/daemon/api/handlers/memory.js +1 -1
  335. package/dist/daemon/api/handlers/messages.js +16 -20
  336. package/dist/daemon/api/handlers/nodes.js +23 -22
  337. package/dist/daemon/api/handlers/reports.js +1 -1
  338. package/dist/daemon/api/handlers/reviews.js +1 -6
  339. package/dist/daemon/api/handlers/worktree.js +6 -22
  340. package/dist/daemon/api/map.d.ts +4 -2
  341. package/dist/daemon/api/map.js +22 -8
  342. package/dist/daemon/api/router.js +0 -4
  343. package/dist/daemon/api/server.js +2 -5
  344. package/dist/daemon/boot-migrations.d.ts +14 -0
  345. package/dist/daemon/boot-migrations.js +31 -0
  346. package/dist/daemon/cron/armed-context.d.ts +21 -0
  347. package/dist/daemon/cron/armed-context.js +100 -0
  348. package/dist/daemon/cron/capture.d.ts +20 -0
  349. package/dist/daemon/cron/capture.js +45 -0
  350. package/dist/daemon/cron/disposition.d.ts +19 -0
  351. package/dist/daemon/cron/disposition.js +52 -0
  352. package/dist/daemon/cron/escalation.d.ts +12 -0
  353. package/dist/daemon/cron/escalation.js +124 -0
  354. package/dist/daemon/cron/held.d.ts +4 -0
  355. package/dist/daemon/cron/held.js +20 -0
  356. package/dist/daemon/cron/lease-recovery.d.ts +3 -0
  357. package/dist/daemon/cron/lease-recovery.js +119 -0
  358. package/dist/daemon/cron/live-runs.d.ts +11 -0
  359. package/dist/daemon/cron/live-runs.js +23 -0
  360. package/dist/daemon/cron/passes.d.ts +11 -0
  361. package/dist/daemon/cron/passes.js +78 -0
  362. package/dist/daemon/cron/settle.d.ts +28 -0
  363. package/dist/daemon/cron/settle.js +37 -0
  364. package/dist/daemon/cron/sinks.d.ts +2 -0
  365. package/dist/daemon/cron/sinks.js +100 -0
  366. package/dist/daemon/cron-run.d.ts +5 -41
  367. package/dist/daemon/cron-run.js +193 -882
  368. package/dist/daemon/crtrd-cli.js +2 -1
  369. package/dist/daemon/crtrd.js +22 -22
  370. package/dist/daemon/fleet.js +0 -4
  371. package/dist/daemon/human/deliver-action.js +2 -1
  372. package/dist/daemon/human/sweep.js +15 -4
  373. package/dist/daemon/manage.d.ts +2 -2
  374. package/dist/daemon/manage.js +4 -13
  375. package/dist/daemon/pidfile.js +2 -2
  376. package/dist/daemon/reconcilers/broker-supervision.js +27 -30
  377. package/dist/daemon/reconcilers/dormant-inbox.d.ts +1 -1
  378. package/dist/daemon/reconcilers/dormant-inbox.js +2 -1
  379. package/dist/daemon/reconcilers/live-obligation.js +2 -2
  380. package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
  381. package/dist/daemon/reconcilers/pending-review-submit.js +2 -1
  382. package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -1
  383. package/dist/daemon/reconcilers/storage-maintenance.js +2 -1
  384. package/dist/daemon/review/companion.js +2 -2
  385. package/dist/daemon/review/sweep.js +8 -3
  386. package/dist/migrations/001-surfaces-frontmatter.js +0 -6
  387. package/dist/migrations/corpus.js +2 -5
  388. package/dist/migrations/registry.js +15 -2
  389. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +0 -4
  390. package/dist/pi-extensions/broker-local.js +2 -1
  391. package/dist/pi-extensions/canvas-bash-valve.js +7 -20
  392. package/dist/pi-extensions/canvas-context-intro.js +2 -7
  393. package/dist/pi-extensions/canvas-doc-substrate.js +2 -3
  394. package/dist/pi-extensions/canvas-goal-capture.js +2 -1
  395. package/dist/pi-extensions/canvas-inbox-watcher.js +5 -12
  396. package/dist/pi-extensions/canvas-passive-context.js +2 -5
  397. package/dist/pi-extensions/canvas-preview-result.js +2 -1
  398. package/dist/pi-extensions/canvas-prompt-scrub.js +2 -1
  399. package/dist/pi-extensions/canvas-recap.js +3 -16
  400. package/dist/pi-extensions/canvas-review-boundary.js +2 -5
  401. package/dist/pi-extensions/canvas-stophook.js +2 -26
  402. package/dist/pi-extensions/canvas-structured-output.js +2 -1
  403. package/dist/pi-extensions/canvas-tool-guide.js +2 -1
  404. package/dist/shared/__tests__/env-boundary.test.d.ts +1 -0
  405. package/dist/shared/__tests__/env-boundary.test.js +93 -0
  406. package/dist/shared/env.d.ts +68 -0
  407. package/dist/shared/env.js +171 -0
  408. package/package.json +3 -1
  409. package/runtime.lock.json +2 -2
  410. package/dist/core/canvas/render.d.ts +0 -47
  411. package/dist/core/canvas/render.js +0 -245
@@ -119,9 +119,7 @@ export function pruneNode(tree, id) {
119
119
  }
120
120
  tree.nodes.delete(id);
121
121
  }
122
- // ---------------------------------------------------------------------------
123
122
  // Fuzzy match
124
- // ---------------------------------------------------------------------------
125
123
  /** Case-insensitive subsequence match: every char of `query` appears in `text`
126
124
  * in order (gaps allowed). Empty query matches everything. Substrings are a
127
125
  * subsequence, so this subsumes substring matching too. */
@@ -322,9 +320,7 @@ export function scoreRow(query, row) {
322
320
  const strength = matches.reduce((sum, { match, weight }) => sum + (match.tier === tier ? match.quality * weight : 0), 0);
323
321
  return { tier, strength };
324
322
  }
325
- // ---------------------------------------------------------------------------
326
323
  // Attention tiering (default sort)
327
- // ---------------------------------------------------------------------------
328
324
  /** The "most recent message" signal for the attention sort: the pi session-file
329
325
  * mtime (ms) the snapshot stamps on each row, falling back to the `created`
330
326
  * birth timestamp when no session file exists. Larger = more recent.
@@ -24,6 +24,28 @@ export declare function updateNode(nodeId: string, patch: Partial<NodeIdentity>)
24
24
  export declare function setStatus(nodeId: string, status: NodeStatus): void;
25
25
  /** Set a node's exit intent. Atomic single-column write. */
26
26
  export declare function setIntent(nodeId: string, intent: ExitIntent): void;
27
+ /** Atomically write status and/or intent, gated on an optional from-status set
28
+ * and/or on the row carrying no committed final_report. The lifecycle state
29
+ * machine (runtime/lifecycle.ts) is the one caller: it owns the legality
30
+ * table and the unknown-node/illegal-move/already-finalized-cancel branching,
31
+ * this only performs the single conditional UPDATE it needs. A PRESENT key in
32
+ * `fields` (even `intent: null`) writes that column; an ABSENT key leaves it
33
+ * unchanged. Returns the row-changed count so the caller can distinguish "no
34
+ * such node", "gate failed", and "already applied" without a second query. */
35
+ export declare function transitionStatusIntent(nodeId: string, fields: {
36
+ status?: NodeStatus;
37
+ intent?: ExitIntent;
38
+ }, opts?: {
39
+ fromStatuses?: readonly NodeStatus[];
40
+ requireNoFinalReport?: boolean;
41
+ }): number;
42
+ /** Read a node's committed-final latch pointer. Pure read, no side effect. */
43
+ export declare function getFinalReport(nodeId: string): string | null;
44
+ /** CAS-clear a node's finalization latch (final_report + finalized_at) —
45
+ * retract-pointer-only. Gated on the exact final_report value the caller
46
+ * observed via getFinalReport, so a concurrent clear/refinalize can never be
47
+ * clobbered. Returns true iff the CAS matched and cleared. */
48
+ export declare function clearFinalReportIfMatches(nodeId: string, expectedFinalReport: string): boolean;
27
49
  /** Set a node's tmux presence in one atomic write: the durable LOCATION anchor
28
50
  * `pane` (the `%pane_id`) plus its derived cache (`tmux_session` + `window`).
29
51
  * All three move together — `pane` joins the others inside the single UPDATE so
@@ -4,20 +4,19 @@
4
4
  // Source-of-truth split: a node's meta.json is canonical for its own fields;
5
5
  // the db row is a queryable index re-derivable from it. The subscribes_to edges
6
6
  // are db-authoritative (mutable, many-writers — what WAL is for).
7
+ import { envNodeId } from '../../shared/env.js';
7
8
  import { existsSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from 'node:fs';
8
9
  import { join, resolve } from 'node:path';
9
10
  import { openDb, withCanvasWrite } from './db.js';
10
11
  import { withMetaLock, readMetaObject, writeMetaObjectLocked, writeJsonFileDurably } from './meta-file.js';
11
12
  import { isPidAlive, recordedPidLiveness, capturePidIdentities, identitiesMatch, isLegacyTicksIdentity, isBootScopedIdentity, } from './pid.js';
12
13
  import { ensureHome, ensureNodeDirs, nodeMetaPath, nodeDir, nodesRoot, jobDir, } from './paths.js';
13
- // ---------------------------------------------------------------------------
14
14
  // meta.json (durable identity — the source of truth for what PERSISTS)
15
15
  //
16
16
  // One authoritative store per fact: meta.json holds NodeIdentity only; the six
17
17
  // runtime fields (status, intent, pi_pid, window, tmux_session, pane) are
18
18
  // authoritative in the WAL'd `nodes` row, each mutated by one atomic setter
19
19
  // below. getNode() hydrates the two back into the historical NodeMeta view.
20
- // ---------------------------------------------------------------------------
21
20
  /** The identity keys meta.json persists. Listed explicitly so no runtime field
22
21
  * can ever leak onto disk even when a fully-hydrated NodeMeta is handed in. */
23
22
  const IDENTITY_KEYS = [
@@ -75,12 +74,10 @@ function readMeta(nodeId) {
75
74
  function writeMeta(meta) {
76
75
  writeJsonFileDurably(nodeMetaPath(meta.node_id), toIdentity(meta));
77
76
  }
78
- // ---------------------------------------------------------------------------
79
77
  // row index — identity columns are a derived projection of meta; runtime
80
78
  // columns are authoritative. The two have DIFFERENT writers: upsertRow only
81
79
  // ever touches identity (so a re-index never clobbers live runtime), while
82
80
  // createNode seeds runtime once and the atomic setters own it thereafter.
83
- // ---------------------------------------------------------------------------
84
81
  /** Upsert the IDENTITY columns of a node's row. ON CONFLICT updates identity
85
82
  * ONLY — runtime columns (status/intent/pi_pid/window/tmux_session/pane) are left
86
83
  * exactly as they are, so re-indexing or an identity edit never disturbs live
@@ -162,15 +159,23 @@ function runtimeFromRow(nodeId) {
162
159
  pane: r['pane'] ?? null,
163
160
  };
164
161
  }
165
- // ---------------------------------------------------------------------------
166
162
  // Nodes
167
- // ---------------------------------------------------------------------------
168
163
  /** Create a node: scaffold its dirs, persist identity to meta.json, and seed the
169
164
  * row (identity + runtime from the incoming meta). Returns the hydrated view. */
170
165
  export function createNode(meta) {
171
166
  ensureHome();
167
+ const scaffolded = !existsSync(nodeDir(meta.node_id));
172
168
  ensureNodeDirs(meta.node_id);
173
- writeMeta(meta);
169
+ try {
170
+ writeMeta(meta);
171
+ }
172
+ catch (error) {
173
+ // No row exists yet, so a dir left here is invisible to every surface and to
174
+ // ghost-row reaping. Only unwind a dir this call created.
175
+ if (scaffolded)
176
+ rmSync(nodeDir(meta.node_id), { recursive: true, force: true });
177
+ throw error;
178
+ }
174
179
  seedRow(meta);
175
180
  return getNode(meta.node_id);
176
181
  }
@@ -236,13 +241,11 @@ export function updateNode(nodeId, patch) {
236
241
  upsertRow(next);
237
242
  return getNode(nodeId);
238
243
  }
239
- // ---------------------------------------------------------------------------
240
244
  // Atomic runtime setters — each one a single-statement UPDATE on the WAL'd row,
241
245
  // the authoritative store for live state. No read-modify-write, so concurrent
242
246
  // writers of DIFFERENT fields (the daemon stamping pi_pid while a node flips
243
247
  // status) can never clobber each other: WAL serializes the two statements.
244
248
  // `"window"` is quoted defensively — it is a SQLite keyword.
245
- // ---------------------------------------------------------------------------
246
249
  /** Set a node's status. Atomic single-column write. */
247
250
  export function setStatus(nodeId, status) {
248
251
  openDb().prepare('UPDATE nodes SET status = ? WHERE node_id = ?').run(status, nodeId);
@@ -251,6 +254,53 @@ export function setStatus(nodeId, status) {
251
254
  export function setIntent(nodeId, intent) {
252
255
  openDb().prepare('UPDATE nodes SET intent = ? WHERE node_id = ?').run(intent ?? null, nodeId);
253
256
  }
257
+ /** Atomically write status and/or intent, gated on an optional from-status set
258
+ * and/or on the row carrying no committed final_report. The lifecycle state
259
+ * machine (runtime/lifecycle.ts) is the one caller: it owns the legality
260
+ * table and the unknown-node/illegal-move/already-finalized-cancel branching,
261
+ * this only performs the single conditional UPDATE it needs. A PRESENT key in
262
+ * `fields` (even `intent: null`) writes that column; an ABSENT key leaves it
263
+ * unchanged. Returns the row-changed count so the caller can distinguish "no
264
+ * such node", "gate failed", and "already applied" without a second query. */
265
+ export function transitionStatusIntent(nodeId, fields, opts = {}) {
266
+ const assignments = [];
267
+ const values = [];
268
+ if (Object.prototype.hasOwnProperty.call(fields, 'status')) {
269
+ assignments.push('status = ?');
270
+ values.push(fields.status ?? null);
271
+ }
272
+ if (Object.prototype.hasOwnProperty.call(fields, 'intent')) {
273
+ assignments.push('intent = ?');
274
+ values.push(fields.intent ?? null);
275
+ }
276
+ const predicates = ['node_id = ?'];
277
+ values.push(nodeId);
278
+ if (opts.fromStatuses !== undefined) {
279
+ predicates.push(`status IN (${opts.fromStatuses.map(() => '?').join(', ')})`);
280
+ values.push(...opts.fromStatuses);
281
+ }
282
+ if (opts.requireNoFinalReport === true)
283
+ predicates.push('final_report IS NULL');
284
+ const result = openDb()
285
+ .prepare(`UPDATE nodes SET ${assignments.join(', ')} WHERE ${predicates.join(' AND ')}`)
286
+ .run(...values);
287
+ return Number(result.changes);
288
+ }
289
+ /** Read a node's committed-final latch pointer. Pure read, no side effect. */
290
+ export function getFinalReport(nodeId) {
291
+ const row = openDb().prepare('SELECT final_report FROM nodes WHERE node_id = ?').get(nodeId);
292
+ return row?.final_report ?? null;
293
+ }
294
+ /** CAS-clear a node's finalization latch (final_report + finalized_at) —
295
+ * retract-pointer-only. Gated on the exact final_report value the caller
296
+ * observed via getFinalReport, so a concurrent clear/refinalize can never be
297
+ * clobbered. Returns true iff the CAS matched and cleared. */
298
+ export function clearFinalReportIfMatches(nodeId, expectedFinalReport) {
299
+ const result = openDb()
300
+ .prepare('UPDATE nodes SET final_report = NULL, finalized_at = NULL WHERE node_id = ? AND final_report = ?')
301
+ .run(nodeId, expectedFinalReport);
302
+ return result.changes > 0;
303
+ }
254
304
  /** Set a node's tmux presence in one atomic write: the durable LOCATION anchor
255
305
  * `pane` (the `%pane_id`) plus its derived cache (`tmux_session` + `window`).
256
306
  * All three move together — `pane` joins the others inside the single UPDATE so
@@ -387,10 +437,8 @@ export function listNodes(filter) {
387
437
  }
388
438
  return rows.map(rowFrom);
389
439
  }
390
- // ---------------------------------------------------------------------------
391
440
  // Warm pool — spare booted roots awaiting a `prefer_warm` claim (see
392
441
  // `runtime/warm-pool.ts` for the recipe key and the mint/refill policy).
393
- // ---------------------------------------------------------------------------
394
442
  /** Mark an already-spawned node as an unclaimed spare for `recipeKey`. Hides it
395
443
  * from every listing until it is claimed. */
396
444
  export function registerWarmSpare(nodeId, recipeKey) {
@@ -539,9 +587,7 @@ export function listResumableRoots(cwd) {
539
587
  .all(cwd);
540
588
  return rows.map(rowFrom);
541
589
  }
542
- // ---------------------------------------------------------------------------
543
590
  // Edges
544
- // ---------------------------------------------------------------------------
545
591
  function addEdge(type, from, to, active) {
546
592
  openDb()
547
593
  .prepare(`INSERT INTO edges (type, from_id, to_id, active, created)
@@ -592,9 +638,7 @@ export function subscriptionsOf(subscriber) {
592
638
  created: r['created'],
593
639
  }));
594
640
  }
595
- // ---------------------------------------------------------------------------
596
641
  // Graph queries
597
- // ---------------------------------------------------------------------------
598
642
  /** A "view": every node whose output cascades up to `root` via subscriptions —
599
643
  * the subscription sub-DAG reachable downward (root → its reports → theirs …).
600
644
  * Returns ids excluding root, in BFS order. Cycle-safe. */
@@ -714,9 +758,7 @@ export function withFreshTerminalGuard(nodeId, isTerminal, body) {
714
758
  return { kind: 'ran', result: body() };
715
759
  });
716
760
  }
717
- // ---------------------------------------------------------------------------
718
761
  // Index rebuild
719
- // ---------------------------------------------------------------------------
720
762
  /** Rebuild node rows from on-disk metas (the db node table is a derived index).
721
763
  * Only the IDENTITY columns are rebuilt — they are a projection of meta. The
722
764
  * runtime columns (status/intent/pi_pid/window/tmux_session/pane) are NOT in meta
@@ -823,7 +865,7 @@ export function pruneNodes(opts) {
823
865
  const dryRun = opts.dryRun ?? false;
824
866
  const includeStale = opts.includeStale ?? false;
825
867
  const cutoff = new Date(Date.now() - opts.ttlDays * 86_400_000).toISOString();
826
- const selfId = process.env['CRTR_NODE_ID'] ?? '';
868
+ const selfId = envNodeId() ?? '';
827
869
  const db = openDb();
828
870
  const terminal = db
829
871
  .prepare(`SELECT node_id, status, created FROM nodes
@@ -960,7 +1002,7 @@ function recencyMs(nodeId, created) {
960
1002
  * reports the candidate set and deletes NOTHING. */
961
1003
  export function pruneToLimit(opts) {
962
1004
  const dryRun = opts.dryRun ?? false;
963
- const selfId = process.env['CRTR_NODE_ID'] ?? '';
1005
+ const selfId = envNodeId() ?? '';
964
1006
  const rows = listNodes();
965
1007
  // Rank ALL nodes by recency DESC, tagging protection as we go. Protection is
966
1008
  // status-only (active|idle) — NOT gated on pi_pid liveness — so a node whose
@@ -59,9 +59,7 @@ function cronFrom(r) {
59
59
  updated: r['updated'],
60
60
  };
61
61
  }
62
- // ---------------------------------------------------------------------------
63
62
  // Signal safety
64
- // ---------------------------------------------------------------------------
65
63
  /** The ONLY sanctioned way to signal a cron run's process group from a stored
66
64
  * row. Re-captures the CURRENT identity of `run_pid` and signals only when it
67
65
  * MATCHES the fingerprint recorded at lease acquisition. Returns whether the
@@ -101,9 +99,7 @@ export function verifyLeasedCronRun(c) {
101
99
  return false; // pid genuinely gone
102
100
  return identitiesMatch(current, c.run_pid_identity);
103
101
  }
104
- // ---------------------------------------------------------------------------
105
102
  // Writes
106
- // ---------------------------------------------------------------------------
107
103
  /** INSERT one cron row from the pinned arm spec, returning its (caller-
108
104
  * supplied) `cron_id` plus the ids of any deadline it displaced. Stamps
109
105
  * `created`/`updated`; lease fields start idle.
@@ -301,9 +297,7 @@ export function advanceCron(cron_id, nextFireIso) {
301
297
  .prepare('UPDATE crons SET fire_at = ?, updated = ? WHERE cron_id = ?')
302
298
  .run(nextFireIso, new Date().toISOString(), cron_id);
303
299
  }
304
- // ---------------------------------------------------------------------------
305
300
  // Daemon run-executor primitives (src/daemon/cron-run.ts)
306
- // ---------------------------------------------------------------------------
307
301
  /** The daemon's per-tick due query: active, idle, fire_at arrived, in
308
302
  * deterministic order. The idle-only filter IS the default `overlap='skip'`
309
303
  * behavior — a row whose previous run is still leased is simply not due.
@@ -1,26 +1,20 @@
1
1
  import { DatabaseSync } from 'node:sqlite';
2
- /** The ordered migration list. Index `i` is migration version `i + 1`; the db's
3
- * `user_version` tracks how many have been applied. Append only. Journaled
4
- * entries from `src/migrations/registry.ts` follow the local steps, so a new
5
- * registry migration lands as the next version. */
6
- export declare const MIGRATIONS: ReadonlyArray<(db: DatabaseSync) => void>;
7
- /** Bring `db` up to the latest schema version. Reads `user_version`, runs each
8
- * pending migration in order, and bumps `user_version` after each so the work
9
- * is gated and idempotent: re-running is a no-op once `user_version` reaches
10
- * `MIGRATIONS.length`. Forward-only.
11
- *
12
- * ATOMIC AND RESTARTABLE: each step AND its `user_version` bump run inside one
13
- * `BEGIN IMMEDIATE`/`COMMIT` (SQLite journals `user_version` with the
14
- * transaction, so a rollback restores it too). An interrupted or failing step
15
- * therefore leaves the db exactly at the previous version with none of its
16
- * writes committed — a half-applied step can never wedge every later open. The
17
- * write lock also serializes concurrent openers; the version is re-read after
18
- * acquiring it so a step another process just applied is skipped rather than
19
- * re-run. */
20
- export declare function migrate(db: DatabaseSync): void;
2
+ export { migrate, MIGRATIONS } from './migrations.js';
21
3
  /** Open (or reuse) the canvas db at the current `CRTR_HOME`, initializing the
22
4
  * schema and WAL on first open. Keyed by path so tests with distinct homes get
23
- * independent handles. */
5
+ * independent handles.
6
+ *
7
+ * A cache hit trusts the cached handle outright: `crtrd` is this process's
8
+ * sole canvas-db owner (see `crtrd-sole-state-owner`), and nothing outside
9
+ * `openDb`/`closeDb` ever touches `handles` — there is no other actor in this
10
+ * process that could invalidate a live handle out from under it. (A
11
+ * 2026-06-25 revision added a `PRAGMA database_list` liveness probe here that
12
+ * silently closed and reopened the handle on any throw; it shipped alongside
13
+ * an unrelated guest-relay `PATH` fix for the now-removed `hearth` guest
14
+ * bootstrap, named no concrete failure mode in its commit or a test, and that
15
+ * guest-relay path no longer exists. Removed rather than kept-and-logged: a
16
+ * silent boot-path reopen is worse than trusting a handle this process
17
+ * already owns.) */
24
18
  export declare function openDb(): DatabaseSync;
25
19
  /** Run `body` under the canvas SQLite write lock, joining an outer transaction
26
20
  * when the shared connection already owns one. This is the common boundary for