@north-light/crouter 0.3.312 → 0.3.313

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 (495) hide show
  1. package/dist/api/client.d.ts +27 -30
  2. package/dist/api/client.js +80 -67
  3. package/dist/api/dto/broker-ops.d.ts +10 -20
  4. package/dist/api/dto/canvas.d.ts +1 -10
  5. package/dist/api/dto/health.d.ts +113 -0
  6. package/dist/api/dto/human-requests.d.ts +14 -3
  7. package/dist/api/dto/human.d.ts +2 -48
  8. package/dist/api/dto/human.js +3 -2
  9. package/dist/api/dto/inbox.d.ts +14 -0
  10. package/dist/api/dto/mail.d.ts +43 -0
  11. package/dist/api/dto/nodes.d.ts +11 -8
  12. package/dist/api/dto/recovery.d.ts +96 -0
  13. package/dist/api/dto/reviews.d.ts +2 -2
  14. package/dist/api/routes.d.ts +9 -6
  15. package/dist/api/routes.js +11 -11
  16. package/dist/build-root.d.ts +4 -0
  17. package/dist/build-root.js +11 -1
  18. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +35 -47
  19. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +1 -1
  20. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +12 -5
  21. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +12 -5
  22. package/dist/cli.js +10 -1
  23. package/dist/clients/__tests__/helpers/human-daemon.d.ts +11 -0
  24. package/dist/clients/__tests__/helpers/human-daemon.js +60 -0
  25. package/dist/clients/attach/chrome/canvas-panels.js +1 -1
  26. package/dist/clients/attach/chrome/inbox-strip.d.ts +3 -3
  27. package/dist/clients/attach/chrome/inbox-strip.js +17 -9
  28. package/dist/clients/attach/chrome/ticket-panel.d.ts +2 -2
  29. package/dist/clients/attach/chrome/ticket-panel.js +77 -46
  30. package/dist/clients/attach/overlays/graph.js +6 -9
  31. package/dist/clients/attach/render/chat-view.d.ts +5 -4
  32. package/dist/clients/attach/render/chat-view.js +22 -13
  33. package/dist/clients/attach/render/page-block.d.ts +11 -7
  34. package/dist/clients/attach/render/page-block.js +64 -55
  35. package/dist/clients/attach/viewer.js +746 -735
  36. package/dist/clients/inbox/__tests__/integration/inbox-controller.test.js +56 -56
  37. package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.js +45 -32
  38. package/dist/clients/inbox/controller.d.ts +42 -14
  39. package/dist/clients/inbox/controller.js +240 -124
  40. package/dist/clients/inbox/dto-adapt.d.ts +28 -0
  41. package/dist/clients/inbox/dto-adapt.js +93 -0
  42. package/dist/clients/inbox/page-adapter.d.ts +5 -4
  43. package/dist/clients/inbox/page-adapter.js +12 -12
  44. package/dist/clients/inbox/resolve.d.ts +10 -5
  45. package/dist/clients/inbox/resolve.js +13 -12
  46. package/dist/clients/inbox/review/review-client.d.ts +0 -1
  47. package/dist/clients/inbox/review/review-client.js +0 -4
  48. package/dist/clients/inbox/review-adapter.d.ts +2 -1
  49. package/dist/clients/inbox/review-adapter.js +3 -5
  50. package/dist/clients/inbox/surface.d.ts +2 -2
  51. package/dist/clients/inbox/surface.js +19 -8
  52. package/dist/clients/inbox/tui.d.ts +3 -3
  53. package/dist/commands/__tests__/human.test.js +31 -15
  54. package/dist/commands/__tests__/integration/dashboard-snapshot.test.js +36 -11
  55. package/dist/commands/{sys/__tests__ → __tests__/integration}/migrate.test.js +142 -36
  56. package/dist/commands/__tests__/revive-now-gate.test.js +2 -0
  57. package/dist/commands/api-client.d.ts +5 -4
  58. package/dist/commands/api-client.js +13 -7
  59. package/dist/commands/canvas-history/shared.js +1 -1
  60. package/dist/commands/canvas-history.js +1 -1
  61. package/dist/commands/canvas-roster.js +1 -1
  62. package/dist/commands/canvas.js +1 -2
  63. package/dist/commands/human/feedback.js +20 -17
  64. package/dist/commands/human/prompts.js +45 -36
  65. package/dist/commands/human/queue.js +73 -123
  66. package/dist/commands/human/review.js +6 -16
  67. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +2 -0
  68. package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +2 -0
  69. package/dist/commands/memory/__tests__/repository-root-lint.test.js +2 -0
  70. package/dist/commands/node-inspect-artifacts.js +1 -1
  71. package/dist/commands/node-lifecycle-revive.d.ts +2 -2
  72. package/dist/commands/node-lifecycle-revive.js +9 -19
  73. package/dist/commands/pkg/plugin-manage.js +0 -1
  74. package/dist/commands/profile/show.js +4 -12
  75. package/dist/commands/surface-tmux-spread.js +1 -5
  76. package/dist/commands/sys/__tests__/config-model-ladders.test.js +23 -30
  77. package/dist/commands/sys/__tests__/sync-project-guidance.test.js +37 -11
  78. package/dist/commands/sys/branch.d.ts +2 -0
  79. package/dist/commands/sys/branch.js +19 -0
  80. package/dist/commands/sys/config.js +106 -33
  81. package/dist/commands/sys/daemon.d.ts +2 -0
  82. package/dist/commands/sys/daemon.js +130 -7
  83. package/dist/commands/sys/doctor.js +5 -15
  84. package/dist/commands/sys/migrate.js +21 -92
  85. package/dist/commands/sys/setup-settings-runner.js +4 -2
  86. package/dist/commands/sys.js +2 -15
  87. package/dist/core/__tests__/boot-fault-attempt.test.js +23 -1
  88. package/dist/core/__tests__/boot.test.js +32 -25
  89. package/dist/core/__tests__/broker-launch-candidates.test.js +49 -0
  90. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +149 -176
  91. package/dist/core/__tests__/canvas-inbox-watcher-naming.test.js +59 -10
  92. package/dist/core/__tests__/canvas-inbox-watcher.test.js +76 -20
  93. package/dist/core/__tests__/canvas.test.js +18 -47
  94. package/dist/core/__tests__/child-death-wake.test.js +29 -7
  95. package/dist/core/__tests__/cli-help-contract.test.js +2 -0
  96. package/dist/core/__tests__/close.test.js +29 -10
  97. package/dist/core/__tests__/collectible.test.js +2 -1
  98. package/dist/core/__tests__/config-change-delta.test.js +2 -0
  99. package/dist/core/__tests__/context-intro.test.js +13 -1
  100. package/dist/core/__tests__/cron-armed-context-failure.test.js +17 -12
  101. package/dist/core/__tests__/cron-held-settlement.test.js +21 -3
  102. package/dist/core/__tests__/cron-node-sink-parked-root.test.js +29 -10
  103. package/dist/core/__tests__/cron-self-cancel-delivery.test.js +14 -2
  104. package/dist/core/__tests__/cron-timeout-descendants.test.js +13 -1
  105. package/dist/core/__tests__/daemon-boot.test.js +51 -14
  106. package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
  107. package/dist/core/__tests__/fixtures/fake-engine.js +8 -3
  108. package/dist/core/__tests__/focuses.test.js +10 -5
  109. package/dist/core/__tests__/helpers/harness.js +50 -18
  110. package/dist/core/__tests__/history-inbox.test.js +12 -16
  111. package/dist/core/__tests__/human-action-delivery.test.js +48 -28
  112. package/dist/core/__tests__/human-actions.test.js +7 -3
  113. package/dist/core/__tests__/inline-memory-refs.test.js +7 -2
  114. package/dist/core/__tests__/integration/broker-fork-seam.test.js +37 -10
  115. package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +42 -0
  116. package/dist/core/__tests__/integration/broker-snapshot-history.test.js +42 -29
  117. package/dist/core/__tests__/integration/broker-wedge-supervision.test.js +36 -35
  118. package/dist/core/__tests__/integration/command-plugins.test.js +15 -6
  119. package/dist/core/__tests__/integration/deferred-no-wake.test.js +113 -92
  120. package/dist/core/__tests__/integration/host-teardown-process-group.test.js +9 -5
  121. package/dist/core/__tests__/integration/lifecycle-hooks.test.js +16 -3
  122. package/dist/core/__tests__/integration/plugin-revalidate.test.js +4 -0
  123. package/dist/core/__tests__/integration/profile-pause.test.js +4 -4
  124. package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +9 -12
  125. package/dist/core/__tests__/integration/revive.test.js +67 -21
  126. package/dist/core/__tests__/integration/spawn-root.test.js +51 -8
  127. package/dist/core/__tests__/integration/subscription-delivery.test.js +33 -21
  128. package/dist/core/__tests__/integration/worktree-land.test.js +5 -2
  129. package/dist/core/__tests__/integration/worktree-reap.test.js +15 -1
  130. package/dist/core/__tests__/kickoff.test.js +36 -39
  131. package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +2 -1
  132. package/dist/core/__tests__/lifecycle.test.js +2 -1
  133. package/dist/core/__tests__/live-lifecycle-prompt.test.js +13 -1
  134. package/dist/core/__tests__/memory-resolver-precedence.test.js +2 -0
  135. package/dist/core/__tests__/migration.test.js +145 -31
  136. package/dist/core/__tests__/model-pin-durability.test.js +4 -1
  137. package/dist/core/__tests__/model-routes-config.test.js +13 -5
  138. package/dist/core/__tests__/node-outcome.test.js +93 -26
  139. package/dist/core/__tests__/on-read-crouter-home-fence.test.js +2 -1
  140. package/dist/core/__tests__/on-read-dedup-resume.test.js +2 -1
  141. package/dist/core/__tests__/on-read-nested-store.test.js +2 -1
  142. package/dist/core/__tests__/passive-subscription.test.js +50 -157
  143. package/dist/core/__tests__/plugin-kinds.test.js +6 -4
  144. package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +6 -1
  145. package/dist/core/__tests__/plugin-page-components.test.js +6 -4
  146. package/dist/core/__tests__/preview-registry-sync.test.js +2 -0
  147. package/dist/core/__tests__/profile-project-memory-delivery.test.js +4 -1
  148. package/dist/core/__tests__/prune.test.js +11 -5
  149. package/dist/core/__tests__/push-final-guard.test.js +14 -7
  150. package/dist/core/__tests__/relaunch-root.test.js +30 -2
  151. package/dist/core/__tests__/remote-canvas-target.test.js +7 -1
  152. package/dist/core/__tests__/repository-root-identity.test.js +4 -0
  153. package/dist/core/__tests__/review-model-floor.test.js +6 -3
  154. package/dist/core/__tests__/revive-all.test.js +13 -3
  155. package/dist/core/__tests__/revive-capacity.test.js +26 -4
  156. package/dist/core/__tests__/revive-parked-fresh.test.js +31 -8
  157. package/dist/core/__tests__/seam/broker-attach-stream.test.js +1 -1
  158. package/dist/core/__tests__/seam/broker-cap-freeze.test.js +4 -3
  159. package/dist/core/__tests__/seam/broker-crash-teardown.test.js +11 -14
  160. package/dist/core/__tests__/seam/broker-provider-retry.test.js +85 -71
  161. package/dist/core/__tests__/seam/dormancy-release.test.js +33 -19
  162. package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +7 -5
  163. package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +20 -6
  164. package/dist/core/__tests__/seam/node-outcome-delivery.test.js +27 -3
  165. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +2 -1
  166. package/dist/core/__tests__/stop-guard.test.js +2 -1
  167. package/dist/core/__tests__/subscription-pool-credential-guard.test.js +4 -3
  168. package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +18 -4
  169. package/dist/core/__tests__/yield-ensures-daemon.test.js +2 -1
  170. package/dist/core/bootstrap.js +2 -0
  171. package/dist/core/broker-client/__tests__/transport-socket.test.js +51 -6
  172. package/dist/core/broker-client/transport-socket.d.ts +1 -0
  173. package/dist/core/broker-client/transport-socket.js +13 -5
  174. package/dist/core/canvas/__tests__/attention.test.js +29 -35
  175. package/dist/core/canvas/__tests__/history-transcript.test.js +6 -6
  176. package/dist/core/canvas/__tests__/render-remote.test.js +25 -9
  177. package/dist/core/canvas/attention.d.ts +2 -5
  178. package/dist/core/canvas/attention.js +15 -64
  179. package/dist/core/canvas/boot.d.ts +6 -7
  180. package/dist/core/canvas/boot.js +5 -9
  181. package/dist/core/canvas/canvas.d.ts +13 -109
  182. package/dist/core/canvas/canvas.js +140 -401
  183. package/dist/core/canvas/crons.d.ts +2 -0
  184. package/dist/core/canvas/crons.js +16 -15
  185. package/dist/core/canvas/daemon-owner.js +10 -0
  186. package/dist/core/canvas/db.d.ts +2 -2
  187. package/dist/core/canvas/db.js +2 -18
  188. package/dist/core/canvas/deliveries.d.ts +104 -0
  189. package/dist/core/canvas/deliveries.js +354 -0
  190. package/dist/core/canvas/executions.d.ts +29 -0
  191. package/dist/core/canvas/executions.js +68 -0
  192. package/dist/core/canvas/history.js +35 -35
  193. package/dist/core/canvas/index.d.ts +3 -1
  194. package/dist/core/canvas/index.js +3 -1
  195. package/dist/core/canvas/migrations.js +20 -12
  196. package/dist/core/canvas/nav-model.js +1 -3
  197. package/dist/core/canvas/nav-render.d.ts +4 -4
  198. package/dist/core/canvas/nav-render.js +11 -21
  199. package/dist/core/canvas/node-sql-migration.d.ts +3 -0
  200. package/dist/core/canvas/node-sql-migration.js +261 -0
  201. package/dist/core/canvas/paths.d.ts +2 -16
  202. package/dist/core/canvas/paths.js +2 -31
  203. package/dist/core/canvas/recovery.d.ts +76 -0
  204. package/dist/core/canvas/recovery.js +588 -0
  205. package/dist/core/canvas/remote-canvas-source.js +4 -0
  206. package/dist/core/canvas/render-source.d.ts +16 -27
  207. package/dist/core/canvas/render-source.js +16 -45
  208. package/dist/core/canvas/sessions.d.ts +33 -0
  209. package/dist/core/canvas/sessions.js +78 -0
  210. package/dist/core/canvas/types.d.ts +33 -33
  211. package/dist/core/canvas/types.js +2 -5
  212. package/dist/core/canvas/waits.d.ts +18 -0
  213. package/dist/core/canvas/waits.js +70 -0
  214. package/dist/core/canvas/worktrees.d.ts +40 -0
  215. package/dist/core/canvas/worktrees.js +93 -0
  216. package/dist/core/config.d.ts +17 -12
  217. package/dist/core/config.js +106 -155
  218. package/dist/core/feed/__tests__/inbox-migrate.test.js +27 -31
  219. package/dist/core/feed/feed.d.ts +0 -6
  220. package/dist/core/feed/feed.js +68 -56
  221. package/dist/core/feed/inbox.d.ts +7 -81
  222. package/dist/core/feed/inbox.js +46 -378
  223. package/dist/core/feed/messages.d.ts +58 -0
  224. package/dist/core/feed/messages.js +217 -0
  225. package/dist/core/fs-utils.d.ts +4 -0
  226. package/dist/core/fs-utils.js +21 -1
  227. package/dist/core/human/answer.d.ts +1 -1
  228. package/dist/core/human/answer.js +1 -1
  229. package/dist/core/human/claim.d.ts +1 -1
  230. package/dist/core/human/claim.js +2 -4
  231. package/dist/core/human/component-docs.js +1 -1
  232. package/dist/core/human/feedback-companion.js +3 -2
  233. package/dist/core/human/feedback.d.ts +5 -8
  234. package/dist/core/human/feedback.js +57 -85
  235. package/dist/core/human/page-authoring.d.ts +30 -0
  236. package/dist/core/human/page-authoring.js +19 -0
  237. package/dist/core/human/requests.d.ts +136 -0
  238. package/dist/core/human/requests.js +515 -0
  239. package/dist/core/human/root.d.ts +0 -7
  240. package/dist/core/human/root.js +0 -17
  241. package/dist/core/human/scan.d.ts +2 -7
  242. package/dist/core/human/scan.js +48 -132
  243. package/dist/core/human/summary.d.ts +1 -1
  244. package/dist/core/human/summary.js +1 -1
  245. package/dist/core/human/tickets.d.ts +23 -83
  246. package/dist/core/human/tickets.js +92 -243
  247. package/dist/core/human/types.d.ts +5 -1
  248. package/dist/core/installed-plugins.js +8 -3
  249. package/dist/core/keybindings/__tests__/resolve.test.js +19 -17
  250. package/dist/core/locked-file.d.ts +6 -3
  251. package/dist/core/locked-file.js +36 -9
  252. package/dist/core/memory/extensions.js +2 -0
  253. package/dist/core/preview-registry.js +0 -1
  254. package/dist/core/profiles/__tests__/env-store.test.js +2 -0
  255. package/dist/core/profiles/default-binding.d.ts +0 -4
  256. package/dist/core/profiles/default-binding.js +12 -58
  257. package/dist/core/profiles/env-store.js +8 -3
  258. package/dist/core/profiles/manifest.d.ts +2 -37
  259. package/dist/core/profiles/manifest.js +35 -161
  260. package/dist/core/profiles/select.js +3 -0
  261. package/dist/core/review/__tests__/capture-origin.test.js +13 -2
  262. package/dist/core/review/__tests__/comments.test.js +28 -10
  263. package/dist/core/review/__tests__/remap.test.js +28 -10
  264. package/dist/core/review/__tests__/stage-identity.test.js +17 -7
  265. package/dist/core/review/birth.d.ts +1 -1
  266. package/dist/core/review/birth.js +34 -5
  267. package/dist/core/review/comments.js +1 -1
  268. package/dist/core/review/document.js +1 -1
  269. package/dist/core/review/project.d.ts +5 -1
  270. package/dist/core/review/project.js +14 -36
  271. package/dist/core/review/realize.d.ts +3 -6
  272. package/dist/core/review/realize.js +51 -168
  273. package/dist/core/review/remap.js +1 -1
  274. package/dist/core/review/stage.d.ts +3 -2
  275. package/dist/core/review/stage.js +2 -3
  276. package/dist/core/review/store.d.ts +3 -21
  277. package/dist/core/review/store.js +140 -186
  278. package/dist/core/review/types.d.ts +0 -1
  279. package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +9 -5
  280. package/dist/core/runtime/__tests__/spawn-env.test.js +8 -9
  281. package/dist/core/runtime/broker/auth-reload.js +9 -10
  282. package/dist/core/runtime/broker/daemon-ops.d.ts +25 -8
  283. package/dist/core/runtime/broker/daemon-ops.js +42 -9
  284. package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
  285. package/dist/core/runtime/broker/extension-abort.js +11 -0
  286. package/dist/core/runtime/broker/fault-retry.d.ts +15 -6
  287. package/dist/core/runtime/broker/fault-retry.js +142 -95
  288. package/dist/core/runtime/broker/inbox.d.ts +4 -32
  289. package/dist/core/runtime/broker/inbox.js +4 -92
  290. package/dist/core/runtime/broker/rebind.d.ts +1 -0
  291. package/dist/core/runtime/broker/rebind.js +21 -12
  292. package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
  293. package/dist/core/runtime/broker-persona-guidance.js +2 -13
  294. package/dist/core/runtime/broker.js +28 -22
  295. package/dist/core/runtime/close.d.ts +3 -9
  296. package/dist/core/runtime/close.js +16 -27
  297. package/dist/core/runtime/fault.d.ts +3 -93
  298. package/dist/core/runtime/fault.js +9 -419
  299. package/dist/core/runtime/kickoff.d.ts +3 -6
  300. package/dist/core/runtime/kickoff.js +12 -18
  301. package/dist/core/runtime/launch.js +1 -1
  302. package/dist/core/runtime/lifecycle.js +40 -7
  303. package/dist/core/runtime/placement.js +2 -2
  304. package/dist/core/runtime/recycle.js +8 -2
  305. package/dist/core/runtime/reset.js +22 -6
  306. package/dist/core/runtime/revive.js +226 -218
  307. package/dist/core/runtime/spawn.js +14 -3
  308. package/dist/core/scoped-state/db.d.ts +7 -0
  309. package/dist/core/scoped-state/db.js +92 -0
  310. package/dist/core/scoped-state/migrate.d.ts +11 -0
  311. package/dist/core/scoped-state/migrate.js +198 -0
  312. package/dist/core/scoped-state/paths.d.ts +9 -0
  313. package/dist/core/scoped-state/paths.js +27 -0
  314. package/dist/core/scoped-state/profiles.d.ts +12 -0
  315. package/dist/core/scoped-state/profiles.js +62 -0
  316. package/dist/core/scoped-state/providers.d.ts +16 -0
  317. package/dist/core/scoped-state/providers.js +8 -0
  318. package/dist/core/scoped-state/schema.d.ts +3 -0
  319. package/dist/core/scoped-state/schema.js +26 -0
  320. package/dist/core/scoped-state/settings.d.ts +28 -0
  321. package/dist/core/scoped-state/settings.js +82 -0
  322. package/dist/core/subscription-state.d.ts +29 -48
  323. package/dist/core/subscription-state.js +176 -712
  324. package/dist/core/worktree-close.js +4 -4
  325. package/dist/core/worktree-mutation-async.js +2 -2
  326. package/dist/core/worktree-sweep.js +11 -16
  327. package/dist/core/worktree.js +6 -12
  328. package/dist/daemon/__tests__/autostart-storm.test.js +1 -39
  329. package/dist/daemon/__tests__/helpers/source-daemon.d.ts +2 -2
  330. package/dist/daemon/__tests__/helpers/source-daemon.js +7 -6
  331. package/dist/daemon/__tests__/integration/migration-startup.test.js +59 -26
  332. package/dist/daemon/__tests__/node-deadline-lane.test.js +2 -1
  333. package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +39 -15
  334. package/dist/daemon/__tests__/node-outcome-delivery.test.js +39 -10
  335. package/dist/daemon/__tests__/reconciler-signature.test.js +2 -2
  336. package/dist/daemon/__tests__/subtree-filter-freshness.test.js +2 -2
  337. package/dist/daemon/api/__tests__/broker-settle-park.test.js +17 -12
  338. package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +27 -5
  339. package/dist/daemon/api/__tests__/model-config.test.js +8 -8
  340. package/dist/daemon/api/__tests__/node-create-description.test.js +22 -5
  341. package/dist/daemon/api/__tests__/node-model-validation.test.js +21 -1
  342. package/dist/daemon/api/__tests__/nodes-activity-query.test.js +10 -12
  343. package/dist/daemon/api/__tests__/profile-launch-gates.test.js +4 -1
  344. package/dist/daemon/api/__tests__/profile-metadata-route.test.js +4 -1
  345. package/dist/daemon/api/__tests__/reopen-delivery.test.js +26 -8
  346. package/dist/daemon/api/__tests__/seam/api-server.test.js +24 -32
  347. package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +4 -1
  348. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +5 -4
  349. package/dist/daemon/api/__tests__/seam/profile-delete.test.js +27 -41
  350. package/dist/daemon/api/__tests__/submit-result.test.js +3 -2
  351. package/dist/daemon/api/bridge.js +1 -1
  352. package/dist/daemon/api/handlers/bash-jobs.js +6 -7
  353. package/dist/daemon/api/handlers/broker-ops.js +47 -84
  354. package/dist/daemon/api/handlers/broker-recovery.d.ts +4 -0
  355. package/dist/daemon/api/handlers/broker-recovery.js +251 -0
  356. package/dist/daemon/api/handlers/canvas.js +2 -44
  357. package/dist/daemon/api/handlers/daemon.js +41 -0
  358. package/dist/daemon/api/handlers/feedback-comments.js +2 -2
  359. package/dist/daemon/api/handlers/health.js +10 -5
  360. package/dist/daemon/api/handlers/human-requests.js +168 -188
  361. package/dist/daemon/api/handlers/human.js +3 -151
  362. package/dist/daemon/api/handlers/inbox-page.d.ts +4 -0
  363. package/dist/daemon/api/handlers/inbox-page.js +89 -0
  364. package/dist/daemon/api/handlers/inbox.js +21 -120
  365. package/dist/daemon/api/handlers/messages.d.ts +1 -0
  366. package/dist/daemon/api/handlers/messages.js +73 -15
  367. package/dist/daemon/api/handlers/node-outcomes.js +58 -13
  368. package/dist/daemon/api/handlers/nodes.js +7 -13
  369. package/dist/daemon/api/handlers/reviews.js +4 -29
  370. package/dist/daemon/api/map.d.ts +25 -3
  371. package/dist/daemon/api/map.js +84 -14
  372. package/dist/daemon/api/server.js +68 -9
  373. package/dist/daemon/control.d.ts +18 -0
  374. package/dist/daemon/cron/disposition.d.ts +2 -0
  375. package/dist/daemon/cron/disposition.js +8 -5
  376. package/dist/daemon/cron/settle.js +37 -13
  377. package/dist/daemon/cron/sinks.d.ts +18 -1
  378. package/dist/daemon/cron/sinks.js +47 -93
  379. package/dist/daemon/crtrd-cli.js +4 -19
  380. package/dist/daemon/crtrd.d.ts +2 -0
  381. package/dist/daemon/crtrd.js +206 -81
  382. package/dist/daemon/fleet.js +5 -6
  383. package/dist/daemon/human/finish.d.ts +12 -24
  384. package/dist/daemon/human/finish.js +88 -285
  385. package/dist/daemon/human/settle.d.ts +40 -0
  386. package/dist/daemon/human/settle.js +89 -0
  387. package/dist/daemon/human/sweep.d.ts +20 -5
  388. package/dist/daemon/human/sweep.js +56 -60
  389. package/dist/daemon/manage.d.ts +21 -16
  390. package/dist/daemon/manage.js +85 -51
  391. package/dist/daemon/messaging/node-message.d.ts +1 -1
  392. package/dist/daemon/messaging/node-message.js +9 -12
  393. package/dist/daemon/park-activity.js +3 -3
  394. package/dist/daemon/reconcilers/bash-deadline.js +6 -7
  395. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  396. package/dist/daemon/reconcilers/broker-supervision.js +41 -19
  397. package/dist/daemon/reconcilers/controller-death.js +6 -18
  398. package/dist/daemon/reconcilers/delivery-lane.d.ts +9 -0
  399. package/dist/daemon/reconcilers/delivery-lane.js +130 -0
  400. package/dist/daemon/reconcilers/live-obligation.js +3 -3
  401. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  402. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -1
  403. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +10 -12
  404. package/dist/daemon/reconcilers/node-lifecycle/tick.js +5 -5
  405. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  406. package/dist/daemon/reconcilers/pending-review-submit.js +3 -3
  407. package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -8
  408. package/dist/daemon/reconcilers/storage-maintenance.js +13 -43
  409. package/dist/daemon/review/companion.js +5 -11
  410. package/dist/daemon/review/deliver.d.ts +1 -5
  411. package/dist/daemon/review/deliver.js +3 -52
  412. package/dist/daemon/review/finish.d.ts +2 -27
  413. package/dist/daemon/review/finish.js +79 -263
  414. package/dist/daemon/review/sweep.d.ts +3 -10
  415. package/dist/daemon/review/sweep.js +13 -131
  416. package/dist/daemon/startup-policy.d.ts +0 -5
  417. package/dist/daemon/startup-policy.js +0 -5
  418. package/dist/index.d.ts +2 -1
  419. package/dist/index.js +1 -1
  420. package/dist/migrations/__tests__/activation-concurrency.test.js +3 -2
  421. package/dist/migrations/__tests__/activation.test.js +9 -6
  422. package/dist/migrations/activation.d.ts +3 -2
  423. package/dist/migrations/activation.js +2 -4
  424. package/dist/migrations/corpus.d.ts +2 -5
  425. package/dist/migrations/corpus.js +9 -20
  426. package/dist/migrations/runner.d.ts +3 -1
  427. package/dist/migrations/runner.js +6 -2
  428. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +21 -89
  429. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +4 -2
  430. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +51 -33
  431. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +16 -2
  432. package/dist/pi-extensions/__tests__/pre-command-gate.test.js +13 -1
  433. package/dist/pi-extensions/canvas-inbox-watcher.js +98 -244
  434. package/dist/pi-extensions/canvas-passive-context.d.ts +4 -8
  435. package/dist/pi-extensions/canvas-passive-context.js +85 -37
  436. package/dist/pi-extensions/canvas-stophook.js +47 -31
  437. package/dist/shared/env.d.ts +1 -0
  438. package/dist/shared/env.js +3 -0
  439. package/package.json +1 -1
  440. package/runtime.lock.json +5 -5
  441. package/dist/clients/attach/__tests__/page-block.test.js +0 -54
  442. package/dist/clients/inbox/review-visibility.d.ts +0 -5
  443. package/dist/clients/inbox/review-visibility.js +0 -19
  444. package/dist/commands/canvas-rebuild-index.d.ts +0 -2
  445. package/dist/commands/canvas-rebuild-index.js +0 -46
  446. package/dist/core/__tests__/human-cancel-guard.test.js +0 -110
  447. package/dist/core/__tests__/human-deliver.test.d.ts +0 -1
  448. package/dist/core/__tests__/human-deliver.test.js +0 -256
  449. package/dist/core/__tests__/human-node-not-supervised.test.d.ts +0 -1
  450. package/dist/core/__tests__/human-node-not-supervised.test.js +0 -89
  451. package/dist/core/__tests__/integration/human-deliver-e2e.test.d.ts +0 -1
  452. package/dist/core/__tests__/integration/human-deliver-e2e.test.js +0 -131
  453. package/dist/core/__tests__/phase4-review-store.test.d.ts +0 -1
  454. package/dist/core/__tests__/phase4-review-store.test.js +0 -144
  455. package/dist/core/__tests__/watchdog-abort-arms-retry.test.d.ts +0 -1
  456. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +0 -110
  457. package/dist/core/canvas/human-deliveries.d.ts +0 -39
  458. package/dist/core/canvas/human-deliveries.js +0 -75
  459. package/dist/core/canvas/node-outcome-deliveries.d.ts +0 -64
  460. package/dist/core/canvas/node-outcome-deliveries.js +0 -159
  461. package/dist/core/feed/passive.d.ts +0 -3
  462. package/dist/core/feed/passive.js +0 -53
  463. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +0 -1
  464. package/dist/core/human/__tests__/inbox-cancel-worker.js +0 -7
  465. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +0 -1
  466. package/dist/core/human/__tests__/inbox-claim-worker.js +0 -17
  467. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +0 -1
  468. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +0 -8
  469. package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +0 -1
  470. package/dist/core/human/__tests__/integration/inbox-core.test.js +0 -145
  471. package/dist/core/human/__tests__/page-tickets.test.d.ts +0 -1
  472. package/dist/core/human/__tests__/page-tickets.test.js +0 -161
  473. package/dist/core/review/ticket-filter.d.ts +0 -17
  474. package/dist/core/review/ticket-filter.js +0 -21
  475. package/dist/core/runtime/broker/passive.d.ts +0 -17
  476. package/dist/core/runtime/broker/passive.js +0 -44
  477. package/dist/core/runtime/busy.d.ts +0 -46
  478. package/dist/core/runtime/busy.js +0 -150
  479. package/dist/daemon/__tests__/startup-block-marker.test.d.ts +0 -1
  480. package/dist/daemon/__tests__/startup-block-marker.test.js +0 -86
  481. package/dist/daemon/api/__tests__/review-terminal-conflict.test.d.ts +0 -1
  482. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +0 -98
  483. package/dist/daemon/human/deliver-action.d.ts +0 -3
  484. package/dist/daemon/human/deliver-action.js +0 -9
  485. package/dist/daemon/node-outcome/deliver-outcome.d.ts +0 -3
  486. package/dist/daemon/node-outcome/deliver-outcome.js +0 -9
  487. package/dist/daemon/reconcilers/human-delivery-lane.d.ts +0 -10
  488. package/dist/daemon/reconcilers/human-delivery-lane.js +0 -41
  489. package/dist/daemon/reconcilers/node-outcome-delivery-lane.d.ts +0 -10
  490. package/dist/daemon/reconcilers/node-outcome-delivery-lane.js +0 -41
  491. package/dist/daemon/startup-block-marker.d.ts +0 -25
  492. package/dist/daemon/startup-block-marker.js +0 -99
  493. /package/dist/{clients/attach/__tests__/page-block.test.d.ts → api/dto/mail.js} +0 -0
  494. /package/dist/{commands/sys/__tests__/migrate.test.d.ts → api/dto/recovery.js} +0 -0
  495. /package/dist/{core/__tests__/human-cancel-guard.test.d.ts → commands/__tests__/integration/migrate.test.d.ts} +0 -0
@@ -19,7 +19,7 @@ import { mkdtempSync, rmSync } from 'node:fs';
19
19
  import { tmpdir } from 'node:os';
20
20
  import { join } from 'node:path';
21
21
  import { createNode, subscribe } from '../../core/canvas/canvas.js';
22
- import { closeDb } from '../../core/canvas/db.js';
22
+ import { closeDb, migrate, openDb } from '../../core/canvas/db.js';
23
23
  import { nodeRoutes } from '../api/handlers/nodes.js';
24
24
  let home;
25
25
  function node(id, parent) {
@@ -41,7 +41,7 @@ async function listUnder(id) {
41
41
  return res.body.map((r) => r.node_id);
42
42
  }
43
43
  before(() => { home = mkdtempSync(join(tmpdir(), 'crtr-subtree-')); process.env['CRTR_HOME'] = home; });
44
- beforeEach(() => { closeDb(); rmSync(home, { recursive: true, force: true }); });
44
+ beforeEach(() => { closeDb(); rmSync(home, { recursive: true, force: true }); migrate(openDb()); });
45
45
  after(() => { closeDb(); rmSync(home, { recursive: true, force: true }); delete process.env['CRTR_HOME']; });
46
46
  test('a subtree query answered before any child exists does not poison later queries on the same daemon process', async () => {
47
47
  const coordinator = 'coordinator';
@@ -8,10 +8,12 @@ import { after, before, beforeEach, test } from 'node:test';
8
8
  import assert from 'node:assert/strict';
9
9
  import { mkdtempSync, rmSync, writeFileSync, utimesSync } from 'node:fs';
10
10
  import { join } from 'node:path';
11
- import { createNode, getNode, updateNode } from '../../../core/canvas/canvas.js';
12
- import { closeDb } from '../../../core/canvas/db.js';
13
- import { appendInbox, writeCursor } from '../../../core/feed/inbox.js';
14
- import { markBusy } from '../../../core/runtime/busy.js';
11
+ import { createNode, getNode } from '../../../core/canvas/canvas.js';
12
+ import { closeDb, migrate, openDb } from '../../../core/canvas/db.js';
13
+ import { resetSession } from '../../../core/canvas/sessions.js';
14
+ import { beginExecution, liveExecutionForNode } from '../../../core/canvas/executions.js';
15
+ import { enqueueNodeMail } from '../../../core/feed/messages.js';
16
+ import { openTurn } from '../../../core/canvas/recovery.js';
15
17
  import { beginPendingPark, isPendingPark } from '../../park-pending.js';
16
18
  import { brokerOperationRoutes } from '../handlers/broker-ops.js';
17
19
  let home = '';
@@ -27,6 +29,7 @@ before(() => {
27
29
  beforeEach(() => {
28
30
  closeDb();
29
31
  rmSync(home, { recursive: true, force: true });
32
+ migrate(openDb());
30
33
  });
31
34
  after(() => {
32
35
  closeDb();
@@ -49,6 +52,7 @@ function residentMidParkingTurn(id) {
49
52
  status: 'active',
50
53
  };
51
54
  createNode(meta);
55
+ beginExecution(id, { daemonEpoch: 'test' });
52
56
  beginPendingPark(id, Date.now());
53
57
  }
54
58
  async function settle(id, over = {}) {
@@ -58,6 +62,7 @@ async function settle(id, over = {}) {
58
62
  params: { id },
59
63
  query: new URLSearchParams(),
60
64
  body: {
65
+ expected_execution_id: liveExecutionForNode(id).executionId,
61
66
  stopReason: 'stop',
62
67
  backgroundJobsRunning: false,
63
68
  pushedFinal: false,
@@ -73,7 +78,7 @@ async function completePark(id) {
73
78
  path: `/v1/nodes/${id}/broker/park-complete`,
74
79
  params: { id },
75
80
  query: new URLSearchParams(),
76
- body: { outcome: 'completed' },
81
+ body: { expected_execution_id: liveExecutionForNode(id).executionId, outcome: 'completed' },
77
82
  };
78
83
  return (await parkCompleteRoute.handler(ctx)).body;
79
84
  }
@@ -83,7 +88,7 @@ async function recordParkActivity(id) {
83
88
  path: `/v1/nodes/${id}/broker/park-activity`,
84
89
  params: { id },
85
90
  query: new URLSearchParams(),
86
- body: {},
91
+ body: { expected_execution_id: liveExecutionForNode(id).executionId },
87
92
  };
88
93
  return (await parkActivityRoute.handler(ctx)).body;
89
94
  }
@@ -107,7 +112,8 @@ test('a human ask raised during the parking turn does not consume the pending ma
107
112
  });
108
113
  test('a main turn racing shadow completion keeps the broker live', async () => {
109
114
  residentMidParkingTurn('busy-main');
110
- markBusy('busy-main');
115
+ const executionId = beginExecution('busy-main', { daemonEpoch: 'test' });
116
+ openTurn(executionId, { reason: 'agent-start' });
111
117
  const directive = await completePark('busy-main');
112
118
  assert.deepEqual(directive, { action: 'stay_dormant' });
113
119
  assert.equal(getNode('busy-main').status, 'active');
@@ -116,7 +122,7 @@ test('a main turn racing shadow completion keeps the broker live', async () => {
116
122
  });
117
123
  test('wake-worthy mail arriving during the parking turn flips the verdict back to release', async () => {
118
124
  residentMidParkingTurn('mailed');
119
- appendInbox('mailed', { from: null, tier: 'normal', kind: 'message', label: 'x', data: { body: 'work' } });
125
+ enqueueNodeMail('mailed', { kind: 'message', label: 'x', bodyJson: { body: 'work' }, urgency: 'normal', wake: 1 });
120
126
  const directive = await completePark('mailed');
121
127
  assert.equal(directive.action, 'stay_dormant');
122
128
  assert.equal(getNode('mailed').status, 'active', 're-evaluation saw the new obligation and did not park');
@@ -125,8 +131,7 @@ test('wake-worthy mail arriving during the parking turn flips the verdict back t
125
131
  });
126
132
  test('a message already consumed by the main turn still releases the parking completion', async () => {
127
133
  residentMidParkingTurn('consumed-mail');
128
- const entry = appendInbox('consumed-mail', { from: null, tier: 'normal', kind: 'message', label: 'work', data: { body: 'work' } });
129
- writeCursor('consumed-mail', entry.entry_id);
134
+ enqueueNodeMail('consumed-mail', { kind: 'message', label: 'work', bodyJson: { body: 'work' }, urgency: 'normal', wake: 1 });
130
135
  const directive = await completePark('consumed-mail');
131
136
  assert.deepEqual(directive, { action: 'stay_dormant' });
132
137
  assert.equal(getNode('consumed-mail').status, 'active');
@@ -135,7 +140,7 @@ test('a message already consumed by the main turn still releases the parking com
135
140
  });
136
141
  test('a bound but absent main-session file is not activity', async () => {
137
142
  residentMidParkingTurn('empty-session');
138
- updateNode('empty-session', { pi_session_file: join(home, 'not-created-yet.jsonl') });
143
+ resetSession('empty-session', { sessionId: 'empty-session', transcriptPath: join(home, 'not-created-yet.jsonl') });
139
144
  const directive = await completePark('empty-session');
140
145
  assert.deepEqual(directive, { action: 'shutdown' });
141
146
  assert.equal(getNode('empty-session').status, 'done');
@@ -154,7 +159,7 @@ test('main-session activity already settled before completion releases parking',
154
159
  writeFileSync(sessionFile, 'main turn');
155
160
  const afterParkStart = new Date(Date.now() + 1000);
156
161
  utimesSync(sessionFile, afterParkStart, afterParkStart);
157
- updateNode('interactive-mail', { pi_session_file: sessionFile });
162
+ resetSession('interactive-mail', { sessionId: 'interactive-mail', transcriptPath: sessionFile });
158
163
  const directive = await completePark('interactive-mail');
159
164
  assert.deepEqual(directive, { action: 'stay_dormant' });
160
165
  assert.equal(getNode('interactive-mail').status, 'active');
@@ -3,10 +3,14 @@ import assert from 'node:assert/strict';
3
3
  import { createServer } from 'node:net';
4
4
  import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
- import { closeDb } from '../../../core/canvas/db.js';
6
+ import { closeDb, migrate, openDb } from '../../../core/canvas/db.js';
7
+ import { closeScopedStores } from '../../../core/scoped-state/db.js';
8
+ import { initializeFreshScopedStore } from '../../../core/scoped-state/migrate.js';
9
+ import { userScopeRoot } from '../../../core/scope.js';
7
10
  import { createNode, getNode } from '../../../core/canvas/canvas.js';
8
- import { contextDir, jobDir, viewSocketPath } from '../../../core/canvas/paths.js';
9
- import { recordFault } from '../../../core/runtime/fault.js';
11
+ import { contextDir, viewSocketPath } from '../../../core/canvas/paths.js';
12
+ import { beginExecution, recordExecutionPid } from '../../../core/canvas/executions.js';
13
+ import { openTurn, recordFault } from '../../../core/canvas/recovery.js';
10
14
  import { headlessBrokerHost } from '../../../core/runtime/host.js';
11
15
  import { resetFleetForTests } from '../../../core/runtime/fleet.js';
12
16
  import { bindTestFleet } from '../../../core/__tests__/helpers/fleet.js';
@@ -14,12 +18,21 @@ import { handleCreate } from '../handlers/nodes.js';
14
18
  import { canvasRoutes } from '../handlers/canvas.js';
15
19
  let home = '';
16
20
  const previousHome = process.env['CRTR_HOME'];
21
+ const previousUserHome = process.env['HOME'];
17
22
  const brokers = [];
18
23
  const launchedBrokers = new Map();
19
24
  let originalLaunch;
20
25
  before(() => {
26
+ // macOS Unix-domain sockets have a short path limit; keep the canvas home short.
21
27
  home = mkdtempSync('/tmp/crtr-snapshot-fields-');
22
28
  process.env['CRTR_HOME'] = home;
29
+ // The launch-config worker resolves the user scope from HOME, so it must point
30
+ // at this fixture's throwaway home and that store must exist. Do NOT chdir:
31
+ // the worker is forked with the parent's cwd, and outside the repo it cannot
32
+ // resolve the tsx loader the source test lane runs under.
33
+ process.env['HOME'] = home;
34
+ initializeFreshScopedStore({ kind: 'user', root: userScopeRoot() });
35
+ migrate(openDb());
23
36
  // Every launcher claims a slot from the ledger before it reaches the host, so
24
37
  // a spawn in-process needs a bound fleet (D-2).
25
38
  bindTestFleet();
@@ -42,11 +55,16 @@ after(async () => {
42
55
  resolve();
43
56
  })));
44
57
  closeDb();
58
+ closeScopedStores();
45
59
  rmSync(home, { recursive: true, force: true });
46
60
  if (previousHome === undefined)
47
61
  delete process.env['CRTR_HOME'];
48
62
  else
49
63
  process.env['CRTR_HOME'] = previousHome;
64
+ if (previousUserHome === undefined)
65
+ delete process.env['HOME'];
66
+ else
67
+ process.env['HOME'] = previousUserHome;
50
68
  });
51
69
  function meta(nodeId, overrides = {}) {
52
70
  return {
@@ -114,9 +132,13 @@ test('one canvas snapshot carries title, brief, jobs, busy, latch, fault, and co
114
132
  name: 'Busy outcome',
115
133
  parent: liveJobId,
116
134
  host_kind: 'broker',
117
- pi_pid: process.pid,
118
135
  }));
119
- writeFileSync(join(jobDir(busyId), 'busy'), '');
136
+ // The mid-turn cue is an open turn on the node's live execution, which the
137
+ // node row projects as `streaming` once its recorded pid is alive. pi_pid is a
138
+ // projection of the running execution, so the pid is stamped there.
139
+ const busyExecution = beginExecution(busyId, { daemonEpoch: null });
140
+ recordExecutionPid(busyExecution, busyId, process.pid);
141
+ openTurn(busyExecution, { reason: 'agent-start' });
120
142
  const finalId = 'snapshot-final';
121
143
  const finalizedAt = new Date().toISOString();
122
144
  createNode(meta(finalId, {
@@ -1,10 +1,12 @@
1
1
  import { after, afterEach, beforeEach, test } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { ApiError } from '../../../api/errors.js';
7
+ import { readRawScopeConfig, updateRawConfigAtomically } from '../../../core/config.js';
7
8
  import { resetScopeCache } from '../../../core/scope.js';
9
+ import { initializeFreshScopedStore } from '../../../core/scoped-state/migrate.js';
8
10
  import { modelConfigRoutes } from '../handlers/model-config.js';
9
11
  const previousHome = process.env.HOME;
10
12
  const previousAgentDir = process.env['PI_CODING_AGENT_DIR'];
@@ -29,6 +31,7 @@ beforeEach(() => {
29
31
  writeFileSync(join(agentDir, 'models.json'), JSON.stringify({
30
32
  providers: { northlight: { baseUrl: 'http://127.0.0.1:1', api: 'openai-completions', apiKey: 'test', models: ['u', 's', 'm', 'l'].map((id) => ({ id, name: id })) } },
31
33
  }));
34
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
32
35
  resetScopeCache();
33
36
  });
34
37
  afterEach(() => {
@@ -55,19 +58,16 @@ function context(body) {
55
58
  return { method: 'PUT', path: '/v1/model-config', params: {}, query: new URLSearchParams(), body };
56
59
  }
57
60
  test('PUT atomically replaces Core-owned blocks without touching unrelated config', async () => {
58
- const configPath = join(home, '.crouter', 'config.json');
59
- mkdirSync(join(home, '.crouter'));
60
- writeFileSync(configPath, JSON.stringify({ completion_bell: false, kinds: { developer: { tools: ['bash'], model: 'old/strong', orchestratorModel: 'old/ultra' } } }));
61
+ updateRawConfigAtomically('user', () => ({ completion_bell: false, kinds: { developer: { tools: ['bash'], model: 'old/strong', orchestratorModel: 'old/ultra' } } }));
61
62
  const result = await putRoute().handler(context(payload));
62
63
  assert.deepEqual(result, { status: 200, body: { config_version: 'core-doc-digest', delivered: true } });
63
- const written = JSON.parse(readFileSync(configPath, 'utf8'));
64
+ const written = readRawScopeConfig('user');
64
65
  assert.equal(written.completion_bell, false);
65
- assert.deepEqual(written.kinds.developer, { tools: ['bash'], model: 'cloud/medium', orchestratorModel: 'cloud/medium' });
66
+ assert.deepEqual(written.kinds?.['developer'], { tools: ['bash'], model: 'cloud/medium', orchestratorModel: 'cloud/medium' });
66
67
  assert.deepEqual(written.modelRoutes, payload.modelRoutes);
67
68
  });
68
69
  test('PUT rejects invalid payloads and absent baked refs before writing', async () => {
69
- const configPath = join(home, '.crouter', 'config.json');
70
70
  await assert.rejects(async () => putRoute().handler(context({ ...payload, modelRoutes: { ...payload.modelRoutes, northlight: { ...payload.modelRoutes.northlight, models: { strong: 'northlight/s' } } } })), (error) => error instanceof ApiError && error.status === 400 && error.code === 'invalid_request');
71
71
  await assert.rejects(async () => putRoute().handler(context({ ...payload, modelRoutes: { ...payload.modelRoutes, northlight: { ...payload.modelRoutes.northlight, models: { ...payload.modelRoutes.northlight.models, ultra: 'northlight/missing' } } } })), (error) => error instanceof ApiError && error.status === 422 && error.code === 'unprocessable');
72
- assert.throws(() => readFileSync(configPath, 'utf8'), { code: 'ENOENT' });
72
+ assert.equal(readRawScopeConfig('user'), null);
73
73
  });
@@ -3,8 +3,12 @@ import assert from 'node:assert/strict';
3
3
  import { createServer } from 'node:net';
4
4
  import { mkdtempSync, rmSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
- import { closeDb } from '../../../core/canvas/db.js';
6
+ import { closeDb, migrate, openDb } from '../../../core/canvas/db.js';
7
+ import { closeScopedStores } from '../../../core/scoped-state/db.js';
8
+ import { initializeFreshScopedStore } from '../../../core/scoped-state/migrate.js';
9
+ import { userScopeRoot } from '../../../core/scope.js';
7
10
  import { getNode } from '../../../core/canvas/canvas.js';
11
+ import { liveExecutionForNode } from '../../../core/canvas/executions.js';
8
12
  import { nodeDir } from '../../../core/canvas/paths.js';
9
13
  import { headlessBrokerHost } from '../../../core/runtime/host.js';
10
14
  import { resetFleetForTests } from '../../../core/runtime/fleet.js';
@@ -12,14 +16,19 @@ import { bindTestFleet } from '../../../core/__tests__/helpers/fleet.js';
12
16
  import { handleCreate, nodeRoutes } from '../handlers/nodes.js';
13
17
  import { brokerOperationRoutes } from '../handlers/broker-ops.js';
14
18
  let home = '';
15
- let originalHome;
19
+ let originalCanvasHome;
20
+ let originalUserHome;
16
21
  let originalLaunch;
17
22
  const brokers = [];
18
23
  before(() => {
19
- originalHome = process.env['CRTR_HOME'];
24
+ originalCanvasHome = process.env['CRTR_HOME'];
25
+ originalUserHome = process.env['HOME'];
20
26
  // macOS Unix-domain sockets have a short path limit; keep the canvas home short.
21
27
  home = mkdtempSync('/tmp/crtr-node-description-');
22
28
  process.env['CRTR_HOME'] = home;
29
+ process.env['HOME'] = home;
30
+ initializeFreshScopedStore({ kind: 'user', root: userScopeRoot() });
31
+ migrate(openDb());
23
32
  // Every launcher claims a slot from the ledger before it reaches the host, so
24
33
  // a spawn in-process needs a bound fleet (D-2).
25
34
  bindTestFleet();
@@ -41,11 +50,16 @@ after(async () => {
41
50
  resolve();
42
51
  })));
43
52
  closeDb();
53
+ closeScopedStores();
44
54
  rmSync(home, { recursive: true, force: true });
45
- if (originalHome === undefined)
55
+ if (originalCanvasHome === undefined)
46
56
  delete process.env['CRTR_HOME'];
47
57
  else
48
- process.env['CRTR_HOME'] = originalHome;
58
+ process.env['CRTR_HOME'] = originalCanvasHome;
59
+ if (originalUserHome === undefined)
60
+ delete process.env['HOME'];
61
+ else
62
+ process.env['HOME'] = originalUserHome;
49
63
  });
50
64
  function context(method, path, id, body) {
51
65
  return {
@@ -75,7 +89,10 @@ test('node create stores caller description and automatic naming leaves it and n
75
89
  assert.equal(detail.body.description, 'Review the worker conversation');
76
90
  const generatedNameRoute = brokerOperationRoutes.find((route) => route.method === 'POST' && route.pattern === '/v1/nodes/:id/broker/generated-name');
77
91
  assert.ok(generatedNameRoute);
92
+ const execution = liveExecutionForNode(nodeId);
93
+ assert.ok(execution);
78
94
  const generated = await generatedNameRoute.handler(context('POST', `/v1/nodes/${nodeId}/broker/generated-name`, nodeId, {
95
+ expected_execution_id: execution.executionId,
79
96
  kind: 'initial',
80
97
  description: 'Generated replacement',
81
98
  title: 'Generated replacement',
@@ -4,20 +4,31 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { createNode, getNode, listNodes } from '../../../core/canvas/canvas.js';
7
- import { closeDb } from '../../../core/canvas/db.js';
7
+ import { closeDb, migrate, openDb } from '../../../core/canvas/db.js';
8
8
  import { CrtrError } from '../../../core/errors.js';
9
+ import { resetScopeCache } from '../../../core/scope.js';
10
+ import { initializeFreshScopedStore } from '../../../core/scoped-state/migrate.js';
9
11
  import { handleConfig, handleCreate, handlePromote, handleYield } from '../handlers/nodes.js';
10
12
  const previousCrtrHome = process.env['CRTR_HOME'];
13
+ const previousHome = process.env.HOME;
14
+ const previousAgentDir = process.env['PI_CODING_AGENT_DIR'];
11
15
  let home = '';
12
16
  before(() => {
13
17
  closeDb();
14
18
  home = mkdtempSync(join(tmpdir(), 'crtr-node-model-validation-'));
19
+ process.env.HOME = home;
15
20
  process.env['CRTR_HOME'] = home;
21
+ process.env['PI_CODING_AGENT_DIR'] = join(home, 'agent');
22
+ resetScopeCache();
16
23
  });
17
24
  beforeEach(() => {
18
25
  closeDb();
19
26
  rmSync(home, { recursive: true, force: true });
20
27
  mkdirSync(home, { recursive: true });
28
+ resetScopeCache();
29
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
30
+ initializeFreshScopedStore({ kind: 'provider', root: process.env['PI_CODING_AGENT_DIR'] });
31
+ migrate(openDb());
21
32
  });
22
33
  after(() => {
23
34
  closeDb();
@@ -26,6 +37,15 @@ after(() => {
26
37
  delete process.env['CRTR_HOME'];
27
38
  else
28
39
  process.env['CRTR_HOME'] = previousCrtrHome;
40
+ if (previousHome === undefined)
41
+ delete process.env.HOME;
42
+ else
43
+ process.env.HOME = previousHome;
44
+ if (previousAgentDir === undefined)
45
+ delete process.env['PI_CODING_AGENT_DIR'];
46
+ else
47
+ process.env['PI_CODING_AGENT_DIR'] = previousAgentDir;
48
+ resetScopeCache();
29
49
  });
30
50
  function node(id, cwd = home) {
31
51
  return {
@@ -4,12 +4,11 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { createNode } from '../../../core/canvas/canvas.js';
7
- import { closeDb } from '../../../core/canvas/db.js';
7
+ import { closeDb, migrate, openDb } from '../../../core/canvas/db.js';
8
8
  import { reportsDir } from '../../../core/canvas/paths.js';
9
9
  import { invalidateTicketCounts } from '../../../core/canvas/attention.js';
10
- import { bindTicketReplyRoute } from '../../../core/human/convention.js';
11
- import { ticketDir } from '../../../core/human/root.js';
12
- import { submitPage } from '../../../core/human/tickets.js';
10
+ import { preparePage } from '../../../core/human/page-authoring.js';
11
+ import { createPageRequest } from '../../../core/human/requests.js';
13
12
  import { handleList } from '../handlers/nodes.js';
14
13
  const previousCrtrHome = process.env['CRTR_HOME'];
15
14
  let home = '';
@@ -23,6 +22,7 @@ beforeEach(() => {
23
22
  invalidateTicketCounts();
24
23
  rmSync(home, { recursive: true, force: true });
25
24
  mkdirSync(home, { recursive: true });
25
+ migrate(openDb());
26
26
  });
27
27
  after(() => {
28
28
  closeDb();
@@ -74,18 +74,16 @@ test('list activity query composes profile, lifecycle, topology filters and repo
74
74
  report('root', '20260817T090000', 'update', 'Started the task');
75
75
  report('root', '20260817T100000', 'final', 'Finished the task');
76
76
  report('root', '20260817T110000', 'update', 'Still monitoring the task');
77
- createNode(node('bridge', { kind: 'human', parent: 'root' }));
78
77
  const page = join(home, 'pending-page.tsx');
79
78
  writeFileSync(page, `export default function PendingPage() {
80
79
  return <Page title="Need a decision"><UserText id="answer" initialText="" /></Page>;
81
80
  }
82
81
  `);
83
- const ticket = submitPage({
84
- dir: ticketDir('bridge'),
85
- sourceFile: page,
86
- delivery: { placement: 'inline', inbox: true, reply: true },
82
+ createPageRequest({
83
+ request_id: 'pending-page',
84
+ prepared: preparePage({ sourceFile: page, source: { nodeId: 'root' }, delivery: { placement: 'inline', inbox: true, reply: true } }),
85
+ requester_node_id: 'root',
87
86
  });
88
- bindTicketReplyRoute(ticket.dir, 'bridge');
89
87
  invalidateTicketCounts();
90
88
  createNode(node('child', { parent: 'root' }));
91
89
  createNode(node('resident', { lifecycle: 'resident' }));
@@ -96,6 +94,6 @@ test('list activity query composes profile, lifecycle, topology filters and repo
96
94
  assert.equal(roots[0].activity?.latest_report?.body, 'Still monitoring the task');
97
95
  assert.equal(roots[0].activity?.pending_human_count, 1);
98
96
  const children = list('profile_id=activity-profile-7f3a9c01&parent=root');
99
- assert.deepEqual(children.map((row) => row.node_id), ['bridge', 'child']);
100
- assert.equal(children[1].activity, undefined);
97
+ assert.deepEqual(children.map((row) => row.node_id), ['child']);
98
+ assert.equal(children[0].activity, undefined);
101
99
  });
@@ -4,10 +4,11 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { createNode, getNode, listNodes } from '../../../core/canvas/canvas.js';
7
- import { closeDb } from '../../../core/canvas/db.js';
7
+ import { closeDb, migrate, openDb } from '../../../core/canvas/db.js';
8
8
  import { CrtrError } from '../../../core/errors.js';
9
9
  import { createProfile, loadProfileManifest, pauseProfile, profileManifestPath, ROOT_PROFILE_ID, setProfileDefaultKind } from '../../../core/profiles/manifest.js';
10
10
  import { resetScopeCache } from '../../../core/scope.js';
11
+ import { initializeFreshScopedStore } from '../../../core/scoped-state/migrate.js';
11
12
  import { reviveNode } from '../../../core/runtime/revive.js';
12
13
  import { resolveLaunchTarget } from '../../../core/runtime/launch-target.js';
13
14
  import { spawnNode } from '../../../core/runtime/nodes.js';
@@ -25,6 +26,8 @@ beforeEach(() => {
25
26
  process.env['CRTR_HOME'] = join(home, 'canvas');
26
27
  mkdirSync(process.env['CRTR_HOME'], { recursive: true });
27
28
  resetScopeCache();
29
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
30
+ migrate(openDb());
28
31
  });
29
32
  afterEach(() => {
30
33
  closeDb();
@@ -5,9 +5,10 @@ import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { routes } from '../../../api/index.js';
7
7
  import { CrtrError } from '../../../core/errors.js';
8
- import { closeDb } from '../../../core/canvas/db.js';
8
+ import { closeDb, migrate, openDb } from '../../../core/canvas/db.js';
9
9
  import { createProfile, loadProfileManifest } from '../../../core/profiles/manifest.js';
10
10
  import { resetScopeCache } from '../../../core/scope.js';
11
+ import { initializeFreshScopedStore } from '../../../core/scoped-state/migrate.js';
11
12
  import { profileRoutes } from '../handlers/profiles.js';
12
13
  const previousCrtrHome = process.env['CRTR_HOME'];
13
14
  const previousHome = process.env.HOME;
@@ -17,6 +18,8 @@ beforeEach(() => {
17
18
  home = mkdtempSync(join(tmpdir(), 'crtr-profile-metadata-home-'));
18
19
  process.env.HOME = home;
19
20
  process.env['CRTR_HOME'] = join(home, 'canvas');
21
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
22
+ migrate(openDb());
20
23
  resetScopeCache();
21
24
  });
22
25
  afterEach(() => {
@@ -2,27 +2,38 @@ import { after, before, beforeEach, test } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { mkdtempSync, rmSync } from 'node:fs';
4
4
  import { createServer } from 'node:net';
5
- import { createNode, getNode, openDb } from '../../../core/canvas/index.js';
5
+ import { createNode, getNode } from '../../../core/canvas/index.js';
6
6
  import { armCron, getCron } from '../../../core/canvas/crons.js';
7
- import { closeDb } from '../../../core/canvas/db.js';
7
+ import { closeDb, openDb, migrate } from '../../../core/canvas/db.js';
8
+ import { beginExecution, recordExecutionPid } from '../../../core/canvas/executions.js';
8
9
  import { viewSocketPath } from '../../../core/canvas/paths.js';
9
- import { readInboxSince } from '../../../core/feed/inbox.js';
10
+ function nodeMailCount(nodeId) {
11
+ return Number(openDb().prepare(`SELECT COUNT(*) AS count FROM deliveries
12
+ WHERE destination_kind = 'node_inbox' AND destination_id = ?`).get(nodeId).count);
13
+ }
10
14
  import { headlessBrokerHost } from '../../../core/runtime/host.js';
11
15
  import { bindTestFleet } from '../../../core/__tests__/helpers/fleet.js';
16
+ import { resetScopeCache } from '../../../core/scope.js';
17
+ import { initializeFreshScopedStore } from '../../../core/scoped-state/migrate.js';
12
18
  import { messageRoutes } from '../handlers/messages.js';
13
19
  import { nodeRoutes } from '../handlers/nodes.js';
14
20
  let home;
15
21
  const priorHome = process.env['CRTR_HOME'];
22
+ const priorUserHome = process.env.HOME;
16
23
  before(() => {
17
24
  // macOS limits Unix-socket paths to 104 bytes; the system temp directory's
18
25
  // per-user prefix is already most of that budget.
19
26
  home = mkdtempSync('/tmp/crtr-reopen-');
27
+ process.env.HOME = home;
20
28
  process.env['CRTR_HOME'] = home;
29
+ resetScopeCache();
21
30
  });
22
31
  beforeEach(() => {
23
32
  closeDb();
24
33
  rmSync(home, { recursive: true, force: true });
25
34
  bindTestFleet();
35
+ initializeFreshScopedStore({ kind: 'user', root: `${home}/.crouter` });
36
+ migrate(openDb());
26
37
  });
27
38
  after(() => {
28
39
  closeDb();
@@ -31,6 +42,11 @@ after(() => {
31
42
  delete process.env['CRTR_HOME'];
32
43
  else
33
44
  process.env['CRTR_HOME'] = priorHome;
45
+ if (priorUserHome === undefined)
46
+ delete process.env.HOME;
47
+ else
48
+ process.env.HOME = priorUserHome;
49
+ resetScopeCache();
34
50
  });
35
51
  function node(id, lifecycle, status, piPid) {
36
52
  return {
@@ -74,6 +90,8 @@ async function revive(id, body) {
74
90
  return route.handler(ctx);
75
91
  }
76
92
  async function startLiveBroker(id, failDelivery = false) {
93
+ const executionId = beginExecution(id, { daemonEpoch: null });
94
+ recordExecutionPid(executionId, id, process.pid);
77
95
  let observed = null;
78
96
  const server = createServer((socket) => {
79
97
  let pending = '';
@@ -162,7 +180,7 @@ test('reopen makes live terminal, finalized terminal, and parked targets residen
162
180
  assertReopened(liveId);
163
181
  assert.equal(liveBroker.deliveryState()?.lifecycle, 'resident', 'engine delivery sees resident lifecycle');
164
182
  assert.equal(liveBroker.deliveryState()?.final_report, null, 'engine delivery sees no final latch');
165
- assert.equal(readInboxSince(liveId).length, 0, 'live delivery does not append an inbox entry');
183
+ assert.equal(nodeMailCount(liveId), 0, 'live delivery does not create a durable delivery');
166
184
  }
167
185
  finally {
168
186
  await liveBroker.close();
@@ -175,12 +193,12 @@ test('reopen makes live terminal, finalized terminal, and parked targets residen
175
193
  finalize(finalizedId);
176
194
  await sendMessage(finalizedId, { body: 'new mandate', reopen: true });
177
195
  assertReopened(finalizedId);
178
- assert.equal(readInboxSince(finalizedId).length, 1, 'finalized target receives its durable message after reopening');
196
+ assert.equal(nodeMailCount(finalizedId), 1, 'finalized target receives one durable delivery after reopening');
179
197
  const parkedId = 'parked-resident';
180
198
  createNode(node(parkedId, 'resident', 'done'));
181
199
  await sendMessage(parkedId, { body: 'resume the parked session', reopen: true });
182
200
  assertReopened(parkedId);
183
- assert.equal(readInboxSince(parkedId).length, 1, 'parked target receives its durable message after reopening');
201
+ assert.equal(nodeMailCount(parkedId), 1, 'parked target receives one durable delivery after reopening');
184
202
  }
185
203
  finally {
186
204
  headlessBrokerHost.launch = originalLaunch;
@@ -222,7 +240,7 @@ test('a reopen commit failure delivers nothing', async () => {
222
240
  }
223
241
  assert.equal(getNode(id)?.lifecycle, 'resident', 'lifecycle commit precedes the failed latch CAS');
224
242
  assert.equal(getNode(id)?.final_report, finalReport, 'a failed CAS preserves the canonical-final pointer');
225
- assert.equal(readInboxSince(id).length, 0, 'no inbox entry precedes a failed reopen commit');
243
+ assert.equal(nodeMailCount(id), 0, 'no durable delivery precedes a failed reopen commit');
226
244
  });
227
245
  test('a delivery failure after reopen leaves the target resident, unlatched, and without a message', async () => {
228
246
  const id = 'delivery-failure';
@@ -234,7 +252,7 @@ test('a delivery failure after reopen leaves the target resident, unlatched, and
234
252
  assertReopened(id);
235
253
  assert.equal(broker.deliveryState()?.lifecycle, 'resident', 'failed engine delivery happened after reopen committed');
236
254
  assert.equal(broker.deliveryState()?.final_report, null, 'failed engine delivery saw the cleared latch');
237
- assert.equal(readInboxSince(id).length, 0, 'failed engine delivery creates no durable fallback message');
255
+ assert.equal(nodeMailCount(id), 0, 'failed engine delivery creates no durable fallback delivery');
238
256
  }
239
257
  finally {
240
258
  await broker.close();