@north-light/crouter 0.3.311 → 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 (520) 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 +17 -5
  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 +312 -1
  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 +62 -19
  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 +4 -3
  140. package/dist/core/__tests__/on-read-dedup-resume.test.js +8 -7
  141. package/dist/core/__tests__/on-read-nested-store.test.js +8 -7
  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 +35 -32
  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 +5 -4
  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 +19 -5
  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/command-hooks/artifact.d.ts +6 -0
  217. package/dist/core/command-hooks/artifact.js +22 -6
  218. package/dist/core/command-hooks/discovery.d.ts +2 -0
  219. package/dist/core/command-hooks/discovery.js +2 -0
  220. package/dist/core/command-hooks/lifecycle-catalog.d.ts +20 -2
  221. package/dist/core/command-hooks/lifecycle-catalog.js +7 -2
  222. package/dist/core/command-hooks/lifecycle-create.d.ts +4 -0
  223. package/dist/core/command-hooks/lifecycle-create.js +51 -0
  224. package/dist/core/command-hooks/schema.d.ts +2 -2
  225. package/dist/core/command-hooks/schema.js +5 -4
  226. package/dist/core/command-hooks/transport/exec-invoke.js +3 -1
  227. package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +18 -8
  228. package/dist/core/command-hooks/transport/exec-lifecycle.js +89 -30
  229. package/dist/core/config.d.ts +17 -12
  230. package/dist/core/config.js +106 -155
  231. package/dist/core/errors.d.ts +1 -0
  232. package/dist/core/errors.js +4 -0
  233. package/dist/core/feed/__tests__/inbox-migrate.test.js +27 -31
  234. package/dist/core/feed/feed.d.ts +0 -6
  235. package/dist/core/feed/feed.js +68 -56
  236. package/dist/core/feed/inbox.d.ts +7 -81
  237. package/dist/core/feed/inbox.js +46 -378
  238. package/dist/core/feed/messages.d.ts +58 -0
  239. package/dist/core/feed/messages.js +217 -0
  240. package/dist/core/fs-utils.d.ts +4 -0
  241. package/dist/core/fs-utils.js +21 -1
  242. package/dist/core/human/answer.d.ts +1 -1
  243. package/dist/core/human/answer.js +1 -1
  244. package/dist/core/human/claim.d.ts +1 -1
  245. package/dist/core/human/claim.js +2 -4
  246. package/dist/core/human/component-docs.js +1 -1
  247. package/dist/core/human/feedback-companion.js +4 -3
  248. package/dist/core/human/feedback.d.ts +5 -8
  249. package/dist/core/human/feedback.js +57 -85
  250. package/dist/core/human/page-authoring.d.ts +30 -0
  251. package/dist/core/human/page-authoring.js +19 -0
  252. package/dist/core/human/requests.d.ts +136 -0
  253. package/dist/core/human/requests.js +515 -0
  254. package/dist/core/human/root.d.ts +0 -7
  255. package/dist/core/human/root.js +0 -17
  256. package/dist/core/human/scan.d.ts +2 -7
  257. package/dist/core/human/scan.js +48 -132
  258. package/dist/core/human/summary.d.ts +1 -1
  259. package/dist/core/human/summary.js +1 -1
  260. package/dist/core/human/tickets.d.ts +23 -83
  261. package/dist/core/human/tickets.js +92 -243
  262. package/dist/core/human/types.d.ts +5 -1
  263. package/dist/core/installed-plugins.js +8 -3
  264. package/dist/core/keybindings/__tests__/resolve.test.js +19 -17
  265. package/dist/core/locked-file.d.ts +6 -3
  266. package/dist/core/locked-file.js +36 -9
  267. package/dist/core/memory/extensions.js +2 -0
  268. package/dist/core/preview-registry.js +0 -1
  269. package/dist/core/profiles/__tests__/env-store.test.js +2 -0
  270. package/dist/core/profiles/default-binding.d.ts +0 -4
  271. package/dist/core/profiles/default-binding.js +12 -58
  272. package/dist/core/profiles/env-store.js +8 -3
  273. package/dist/core/profiles/manifest.d.ts +2 -37
  274. package/dist/core/profiles/manifest.js +35 -161
  275. package/dist/core/profiles/select.js +3 -0
  276. package/dist/core/review/__tests__/capture-origin.test.js +13 -2
  277. package/dist/core/review/__tests__/comments.test.js +28 -10
  278. package/dist/core/review/__tests__/remap.test.js +28 -10
  279. package/dist/core/review/__tests__/stage-identity.test.js +17 -7
  280. package/dist/core/review/birth.d.ts +1 -1
  281. package/dist/core/review/birth.js +34 -5
  282. package/dist/core/review/comments.js +1 -1
  283. package/dist/core/review/companion.d.ts +1 -1
  284. package/dist/core/review/companion.js +2 -2
  285. package/dist/core/review/document.js +1 -1
  286. package/dist/core/review/project.d.ts +5 -1
  287. package/dist/core/review/project.js +14 -36
  288. package/dist/core/review/realize.d.ts +3 -6
  289. package/dist/core/review/realize.js +51 -168
  290. package/dist/core/review/remap.js +1 -1
  291. package/dist/core/review/stage.d.ts +3 -2
  292. package/dist/core/review/stage.js +2 -3
  293. package/dist/core/review/store.d.ts +3 -21
  294. package/dist/core/review/store.js +140 -186
  295. package/dist/core/review/types.d.ts +0 -1
  296. package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +9 -5
  297. package/dist/core/runtime/__tests__/spawn-env.test.js +8 -9
  298. package/dist/core/runtime/broker/auth-reload.js +9 -10
  299. package/dist/core/runtime/broker/daemon-ops.d.ts +25 -8
  300. package/dist/core/runtime/broker/daemon-ops.js +42 -9
  301. package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
  302. package/dist/core/runtime/broker/extension-abort.js +11 -0
  303. package/dist/core/runtime/broker/fault-retry.d.ts +15 -6
  304. package/dist/core/runtime/broker/fault-retry.js +142 -95
  305. package/dist/core/runtime/broker/inbox.d.ts +4 -32
  306. package/dist/core/runtime/broker/inbox.js +4 -92
  307. package/dist/core/runtime/broker/rebind.d.ts +1 -0
  308. package/dist/core/runtime/broker/rebind.js +21 -12
  309. package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
  310. package/dist/core/runtime/broker-persona-guidance.js +2 -13
  311. package/dist/core/runtime/broker.js +28 -22
  312. package/dist/core/runtime/close.d.ts +3 -9
  313. package/dist/core/runtime/close.js +16 -27
  314. package/dist/core/runtime/fault.d.ts +3 -93
  315. package/dist/core/runtime/fault.js +9 -419
  316. package/dist/core/runtime/kickoff.d.ts +3 -6
  317. package/dist/core/runtime/kickoff.js +12 -18
  318. package/dist/core/runtime/launch.js +1 -1
  319. package/dist/core/runtime/lifecycle.js +40 -7
  320. package/dist/core/runtime/nodes.d.ts +5 -1
  321. package/dist/core/runtime/nodes.js +26 -11
  322. package/dist/core/runtime/placement.js +2 -2
  323. package/dist/core/runtime/recycle.js +24 -14
  324. package/dist/core/runtime/reset.js +26 -7
  325. package/dist/core/runtime/revive.js +226 -217
  326. package/dist/core/runtime/spawn.d.ts +4 -1
  327. package/dist/core/runtime/spawn.js +43 -5
  328. package/dist/core/runtime/warm-pool.d.ts +2 -2
  329. package/dist/core/runtime/warm-pool.js +23 -3
  330. package/dist/core/scoped-state/db.d.ts +7 -0
  331. package/dist/core/scoped-state/db.js +92 -0
  332. package/dist/core/scoped-state/migrate.d.ts +11 -0
  333. package/dist/core/scoped-state/migrate.js +198 -0
  334. package/dist/core/scoped-state/paths.d.ts +9 -0
  335. package/dist/core/scoped-state/paths.js +27 -0
  336. package/dist/core/scoped-state/profiles.d.ts +12 -0
  337. package/dist/core/scoped-state/profiles.js +62 -0
  338. package/dist/core/scoped-state/providers.d.ts +16 -0
  339. package/dist/core/scoped-state/providers.js +8 -0
  340. package/dist/core/scoped-state/schema.d.ts +3 -0
  341. package/dist/core/scoped-state/schema.js +26 -0
  342. package/dist/core/scoped-state/settings.d.ts +28 -0
  343. package/dist/core/scoped-state/settings.js +82 -0
  344. package/dist/core/subscription-state.d.ts +29 -48
  345. package/dist/core/subscription-state.js +176 -712
  346. package/dist/core/worktree-close.js +4 -4
  347. package/dist/core/worktree-mutation-async.js +2 -2
  348. package/dist/core/worktree-sweep.js +11 -16
  349. package/dist/core/worktree.js +6 -12
  350. package/dist/daemon/__tests__/autostart-storm.test.js +1 -39
  351. package/dist/daemon/__tests__/helpers/source-daemon.d.ts +2 -2
  352. package/dist/daemon/__tests__/helpers/source-daemon.js +7 -6
  353. package/dist/daemon/__tests__/integration/migration-startup.test.js +59 -26
  354. package/dist/daemon/__tests__/node-deadline-lane.test.js +2 -1
  355. package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +41 -17
  356. package/dist/daemon/__tests__/node-outcome-delivery.test.js +39 -10
  357. package/dist/daemon/__tests__/reconciler-signature.test.js +2 -2
  358. package/dist/daemon/__tests__/subtree-filter-freshness.test.js +2 -2
  359. package/dist/daemon/api/__tests__/broker-settle-park.test.js +17 -12
  360. package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +27 -5
  361. package/dist/daemon/api/__tests__/model-config.test.js +8 -8
  362. package/dist/daemon/api/__tests__/node-create-description.test.js +22 -5
  363. package/dist/daemon/api/__tests__/node-model-validation.test.js +21 -1
  364. package/dist/daemon/api/__tests__/nodes-activity-query.test.js +10 -12
  365. package/dist/daemon/api/__tests__/profile-launch-gates.test.js +6 -3
  366. package/dist/daemon/api/__tests__/profile-metadata-route.test.js +4 -1
  367. package/dist/daemon/api/__tests__/reopen-delivery.test.js +26 -8
  368. package/dist/daemon/api/__tests__/seam/api-server.test.js +24 -32
  369. package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +4 -1
  370. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +5 -4
  371. package/dist/daemon/api/__tests__/seam/profile-delete.test.js +29 -43
  372. package/dist/daemon/api/__tests__/submit-result.test.js +3 -2
  373. package/dist/daemon/api/bridge.js +1 -1
  374. package/dist/daemon/api/handlers/bash-jobs.js +6 -7
  375. package/dist/daemon/api/handlers/broker-ops.js +47 -84
  376. package/dist/daemon/api/handlers/broker-recovery.d.ts +4 -0
  377. package/dist/daemon/api/handlers/broker-recovery.js +251 -0
  378. package/dist/daemon/api/handlers/canvas.js +2 -44
  379. package/dist/daemon/api/handlers/daemon.js +41 -0
  380. package/dist/daemon/api/handlers/feedback-comments.js +2 -2
  381. package/dist/daemon/api/handlers/health.js +10 -5
  382. package/dist/daemon/api/handlers/human-requests.js +168 -188
  383. package/dist/daemon/api/handlers/human.js +3 -148
  384. package/dist/daemon/api/handlers/inbox-page.d.ts +4 -0
  385. package/dist/daemon/api/handlers/inbox-page.js +89 -0
  386. package/dist/daemon/api/handlers/inbox.js +21 -120
  387. package/dist/daemon/api/handlers/messages.d.ts +1 -0
  388. package/dist/daemon/api/handlers/messages.js +73 -15
  389. package/dist/daemon/api/handlers/node-outcomes.js +58 -13
  390. package/dist/daemon/api/handlers/nodes.d.ts +1 -0
  391. package/dist/daemon/api/handlers/nodes.js +41 -42
  392. package/dist/daemon/api/handlers/reviews.js +4 -29
  393. package/dist/daemon/api/map.d.ts +25 -3
  394. package/dist/daemon/api/map.js +84 -14
  395. package/dist/daemon/api/server.js +68 -9
  396. package/dist/daemon/control.d.ts +18 -0
  397. package/dist/daemon/cron/disposition.d.ts +2 -0
  398. package/dist/daemon/cron/disposition.js +8 -5
  399. package/dist/daemon/cron/settle.js +37 -13
  400. package/dist/daemon/cron/sinks.d.ts +18 -1
  401. package/dist/daemon/cron/sinks.js +47 -93
  402. package/dist/daemon/crtrd-cli.js +4 -19
  403. package/dist/daemon/crtrd.d.ts +2 -0
  404. package/dist/daemon/crtrd.js +206 -81
  405. package/dist/daemon/fleet.js +5 -6
  406. package/dist/daemon/human/finish.d.ts +12 -24
  407. package/dist/daemon/human/finish.js +88 -285
  408. package/dist/daemon/human/settle.d.ts +40 -0
  409. package/dist/daemon/human/settle.js +89 -0
  410. package/dist/daemon/human/sweep.d.ts +20 -5
  411. package/dist/daemon/human/sweep.js +56 -60
  412. package/dist/daemon/manage.d.ts +21 -16
  413. package/dist/daemon/manage.js +85 -51
  414. package/dist/daemon/messaging/node-message.d.ts +1 -1
  415. package/dist/daemon/messaging/node-message.js +9 -12
  416. package/dist/daemon/park-activity.js +3 -3
  417. package/dist/daemon/reconcilers/bash-deadline.js +6 -7
  418. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  419. package/dist/daemon/reconcilers/broker-supervision.js +41 -19
  420. package/dist/daemon/reconcilers/controller-death.js +6 -18
  421. package/dist/daemon/reconcilers/delivery-lane.d.ts +9 -0
  422. package/dist/daemon/reconcilers/delivery-lane.js +130 -0
  423. package/dist/daemon/reconcilers/live-obligation.js +3 -3
  424. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  425. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -1
  426. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +10 -12
  427. package/dist/daemon/reconcilers/node-lifecycle/tick.js +5 -5
  428. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  429. package/dist/daemon/reconcilers/pending-review-submit.js +3 -3
  430. package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -8
  431. package/dist/daemon/reconcilers/storage-maintenance.js +13 -43
  432. package/dist/daemon/review/companion.js +5 -11
  433. package/dist/daemon/review/deliver.d.ts +1 -5
  434. package/dist/daemon/review/deliver.js +3 -52
  435. package/dist/daemon/review/finish.d.ts +2 -27
  436. package/dist/daemon/review/finish.js +79 -263
  437. package/dist/daemon/review/sweep.d.ts +3 -10
  438. package/dist/daemon/review/sweep.js +13 -131
  439. package/dist/daemon/startup-policy.d.ts +0 -5
  440. package/dist/daemon/startup-policy.js +0 -5
  441. package/dist/hook-authoring.d.ts +28 -2
  442. package/dist/hook-authoring.js +53 -1
  443. package/dist/index.d.ts +3 -2
  444. package/dist/index.js +1 -1
  445. package/dist/migrations/__tests__/activation-concurrency.test.js +3 -2
  446. package/dist/migrations/__tests__/activation.test.js +9 -6
  447. package/dist/migrations/activation.d.ts +3 -2
  448. package/dist/migrations/activation.js +2 -4
  449. package/dist/migrations/corpus.d.ts +2 -5
  450. package/dist/migrations/corpus.js +9 -20
  451. package/dist/migrations/runner.d.ts +3 -1
  452. package/dist/migrations/runner.js +6 -2
  453. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +21 -89
  454. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +4 -2
  455. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +51 -33
  456. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +16 -2
  457. package/dist/pi-extensions/__tests__/pre-command-gate.test.js +13 -1
  458. package/dist/pi-extensions/canvas-inbox-watcher.js +98 -244
  459. package/dist/pi-extensions/canvas-passive-context.d.ts +4 -8
  460. package/dist/pi-extensions/canvas-passive-context.js +85 -37
  461. package/dist/pi-extensions/canvas-stophook.js +47 -31
  462. package/dist/shared/env.d.ts +1 -0
  463. package/dist/shared/env.js +3 -0
  464. package/package.json +1 -1
  465. package/runtime.lock.json +5 -5
  466. package/dist/clients/attach/__tests__/page-block.test.js +0 -54
  467. package/dist/clients/inbox/review-visibility.d.ts +0 -5
  468. package/dist/clients/inbox/review-visibility.js +0 -19
  469. package/dist/commands/canvas-rebuild-index.d.ts +0 -2
  470. package/dist/commands/canvas-rebuild-index.js +0 -46
  471. package/dist/core/__tests__/human-cancel-guard.test.js +0 -110
  472. package/dist/core/__tests__/human-deliver.test.d.ts +0 -1
  473. package/dist/core/__tests__/human-deliver.test.js +0 -256
  474. package/dist/core/__tests__/human-node-not-supervised.test.d.ts +0 -1
  475. package/dist/core/__tests__/human-node-not-supervised.test.js +0 -89
  476. package/dist/core/__tests__/integration/human-deliver-e2e.test.d.ts +0 -1
  477. package/dist/core/__tests__/integration/human-deliver-e2e.test.js +0 -131
  478. package/dist/core/__tests__/phase4-review-store.test.d.ts +0 -1
  479. package/dist/core/__tests__/phase4-review-store.test.js +0 -144
  480. package/dist/core/__tests__/watchdog-abort-arms-retry.test.d.ts +0 -1
  481. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +0 -110
  482. package/dist/core/canvas/human-deliveries.d.ts +0 -39
  483. package/dist/core/canvas/human-deliveries.js +0 -75
  484. package/dist/core/canvas/node-outcome-deliveries.d.ts +0 -64
  485. package/dist/core/canvas/node-outcome-deliveries.js +0 -159
  486. package/dist/core/feed/passive.d.ts +0 -3
  487. package/dist/core/feed/passive.js +0 -53
  488. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +0 -1
  489. package/dist/core/human/__tests__/inbox-cancel-worker.js +0 -7
  490. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +0 -1
  491. package/dist/core/human/__tests__/inbox-claim-worker.js +0 -17
  492. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +0 -1
  493. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +0 -8
  494. package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +0 -1
  495. package/dist/core/human/__tests__/integration/inbox-core.test.js +0 -145
  496. package/dist/core/human/__tests__/page-tickets.test.d.ts +0 -1
  497. package/dist/core/human/__tests__/page-tickets.test.js +0 -161
  498. package/dist/core/review/ticket-filter.d.ts +0 -17
  499. package/dist/core/review/ticket-filter.js +0 -21
  500. package/dist/core/runtime/broker/passive.d.ts +0 -17
  501. package/dist/core/runtime/broker/passive.js +0 -44
  502. package/dist/core/runtime/busy.d.ts +0 -46
  503. package/dist/core/runtime/busy.js +0 -150
  504. package/dist/daemon/__tests__/startup-block-marker.test.d.ts +0 -1
  505. package/dist/daemon/__tests__/startup-block-marker.test.js +0 -86
  506. package/dist/daemon/api/__tests__/review-terminal-conflict.test.d.ts +0 -1
  507. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +0 -98
  508. package/dist/daemon/human/deliver-action.d.ts +0 -3
  509. package/dist/daemon/human/deliver-action.js +0 -9
  510. package/dist/daemon/node-outcome/deliver-outcome.d.ts +0 -3
  511. package/dist/daemon/node-outcome/deliver-outcome.js +0 -9
  512. package/dist/daemon/reconcilers/human-delivery-lane.d.ts +0 -10
  513. package/dist/daemon/reconcilers/human-delivery-lane.js +0 -41
  514. package/dist/daemon/reconcilers/node-outcome-delivery-lane.d.ts +0 -10
  515. package/dist/daemon/reconcilers/node-outcome-delivery-lane.js +0 -41
  516. package/dist/daemon/startup-block-marker.d.ts +0 -25
  517. package/dist/daemon/startup-block-marker.js +0 -99
  518. /package/dist/{clients/attach/__tests__/page-block.test.d.ts → api/dto/mail.js} +0 -0
  519. /package/dist/{commands/sys/__tests__/migrate.test.d.ts → api/dto/recovery.js} +0 -0
  520. /package/dist/{core/__tests__/human-cancel-guard.test.d.ts → commands/__tests__/integration/migrate.test.d.ts} +0 -0
@@ -7,9 +7,11 @@
7
7
  // metadata-only rows, and stable ordering, all over real on-disk fixtures.
8
8
  import { test, describe, before, beforeEach, after } from 'node:test';
9
9
  import assert from 'node:assert/strict';
10
- import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
10
+ import { mkdtempSync, mkdirSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
11
11
  import { tmpdir } from 'node:os';
12
12
  import { join } from 'node:path';
13
+ import { ensureScopeInitialized } from '../config.js';
14
+ import { closeScopedStores } from '../scoped-state/db.js';
13
15
  import { resetScopeCache } from '../scope.js';
14
16
  import { clearSessionCache } from '../substrate/session-cache.js';
15
17
  import { memoryDir as nodeMemoryDir } from '../runtime/memory.js';
@@ -70,8 +72,9 @@ describe('buildRefInventory (fixture-backed corpus)', () => {
70
72
  prevCwd = process.cwd();
71
73
  });
72
74
  beforeEach(() => {
75
+ closeScopedStores();
73
76
  canvasHome = mkdtempSync(join(tmpdir(), 'crtr-inline-ref-canvas-'));
74
- userHome = mkdtempSync(join(tmpdir(), 'crtr-inline-ref-user-'));
77
+ userHome = realpathSync(mkdtempSync(join(tmpdir(), 'crtr-inline-ref-user-')));
75
78
  projectBase = mkdtempSync(join(tmpdir(), 'crtr-inline-ref-project-'));
76
79
  projectRoot = join(projectBase, 'root');
77
80
  mkdirSync(projectRoot, { recursive: true });
@@ -84,9 +87,11 @@ describe('buildRefInventory (fixture-backed corpus)', () => {
84
87
  process.env['CRTR_NODE_ID'] = NODE_ID;
85
88
  process.chdir(projectRoot);
86
89
  resetScopeCache();
90
+ ensureScopeInitialized('user', join(userHome, '.crouter'));
87
91
  clearSessionCache();
88
92
  });
89
93
  after(() => {
94
+ closeScopedStores();
90
95
  process.chdir(prevCwd);
91
96
  resetScopeCache();
92
97
  clearSessionCache();
@@ -34,7 +34,9 @@ import { tmpdir } from 'node:os';
34
34
  import { dirname, join } from 'node:path';
35
35
  import { fileURLToPath } from 'node:url';
36
36
  import { createNode } from '../../canvas/canvas.js';
37
- import { closeDb } from '../../canvas/db.js';
37
+ import { closeDb, migrate, openDb } from '../../canvas/db.js';
38
+ import { closeScopedStores } from '../../scoped-state/db.js';
39
+ import { initializeFreshScopedStore } from '../../scoped-state/migrate.js';
38
40
  import { resolveForkSource } from '../../runtime/spawn.js';
39
41
  import { createAgentSessionServices, createAgentSessionFromServices, SessionManager, VERSION, } from '../../runtime/broker-sdk.js';
40
42
  import { buildBrokerSession } from '../../runtime/broker.js';
@@ -56,11 +58,41 @@ const realEngine = {
56
58
  VERSION,
57
59
  };
58
60
  let dir;
61
+ let home;
62
+ let agentDir;
63
+ const previousHome = process.env['HOME'];
64
+ const previousCanvasHome = process.env['CRTR_HOME'];
65
+ const previousAgentDir = process.env['PI_CODING_AGENT_DIR'];
59
66
  before(() => {
60
67
  dir = mkdtempSync(join(tmpdir(), 'crtr-fork-seam-'));
68
+ home = mkdtempSync(join(tmpdir(), 'crtr-fork-home-'));
69
+ closeDb();
70
+ closeScopedStores();
71
+ process.env['HOME'] = home;
72
+ process.env['CRTR_HOME'] = join(home, '.crouter', 'canvas');
73
+ agentDir = join(home, '.pi', 'agent');
74
+ process.env['PI_CODING_AGENT_DIR'] = agentDir;
75
+ migrate(openDb());
76
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
77
+ initializeFreshScopedStore({ kind: 'provider', root: agentDir });
61
78
  });
62
79
  after(() => {
80
+ closeDb();
81
+ closeScopedStores();
82
+ if (previousHome === undefined)
83
+ delete process.env['HOME'];
84
+ else
85
+ process.env['HOME'] = previousHome;
86
+ if (previousCanvasHome === undefined)
87
+ delete process.env['CRTR_HOME'];
88
+ else
89
+ process.env['CRTR_HOME'] = previousCanvasHome;
90
+ if (previousAgentDir === undefined)
91
+ delete process.env['PI_CODING_AGENT_DIR'];
92
+ else
93
+ process.env['PI_CODING_AGENT_DIR'] = previousAgentDir;
63
94
  rmSync(dir, { recursive: true, force: true });
95
+ rmSync(home, { recursive: true, force: true });
64
96
  });
65
97
  /** A minimal but VALID pi session .jsonl (the exact on-disk shape v3 emits): a
66
98
  * `session` header line + two `message` entries. This is what a node that has
@@ -135,10 +167,8 @@ function nodeRow(id, over = {}) {
135
167
  };
136
168
  }
137
169
  test('resolveForkSource refuses every reference that resolves to no forkable session file', () => {
138
- const home = mkdtempSync(join(tmpdir(), 'crtr-fork-resolve-'));
139
170
  const sessions = mkdtempSync(join(tmpdir(), 'crtr-pi-agent-'));
140
- const previousHome = process.env['CRTR_HOME'];
141
- process.env['CRTR_HOME'] = home;
171
+ const previousSessions = process.env['PI_CODING_AGENT_DIR'];
142
172
  process.env['PI_CODING_AGENT_DIR'] = sessions;
143
173
  try {
144
174
  // Broker-cut contract (U6/§B.broker): the broker forks an absolute .jsonl
@@ -154,13 +184,10 @@ test('resolveForkSource refuses every reference that resolves to no forkable ses
154
184
  assert.throws(() => resolveForkSource(' '), /requires a node id/);
155
185
  }
156
186
  finally {
157
- closeDb();
158
- delete process.env['PI_CODING_AGENT_DIR'];
159
- if (previousHome === undefined)
160
- delete process.env['CRTR_HOME'];
187
+ if (previousSessions === undefined)
188
+ delete process.env['PI_CODING_AGENT_DIR'];
161
189
  else
162
- process.env['CRTR_HOME'] = previousHome;
163
- rmSync(home, { recursive: true, force: true });
190
+ process.env['PI_CODING_AGENT_DIR'] = previousSessions;
164
191
  rmSync(sessions, { recursive: true, force: true });
165
192
  }
166
193
  });
@@ -31,6 +31,9 @@ import { isLeadingEngineCommand, resolveSteerCall, chooseGuidanceDeliveryMode, p
31
31
  import { isHiddenJsonlBranchEntry, stripHiddenEntriesFromJsonlExport, } from '../../runtime/broker/frame-session.js';
32
32
  import { CANVAS_EXTENSIONS } from '../../runtime/launch.js';
33
33
  import { prepareAdvertisedCommandPersistence, promptWithAdvertisedCommandInvocation, } from '../../runtime/advertised-command-invocation.js';
34
+ import { closeDb, migrate, openDb } from '../../canvas/db.js';
35
+ import { closeScopedStores } from '../../scoped-state/db.js';
36
+ import { initializeFreshScopedStore } from '../../scoped-state/migrate.js';
34
37
  // The REAL engine, assembled from broker-sdk's static SDK re-exports — bypasses
35
38
  // the CRTR_BROKER_ENGINE seam entirely so these tests can never accidentally hit
36
39
  // the fake (the whole point: prove the wiring the mock hid).
@@ -46,7 +49,22 @@ const C5_EXT = join(HERE, 'fixtures', 'c5-command-boundary-ext.ts');
46
49
  const priorModelIntent = process.env['CRTR_MODEL_INTENT'];
47
50
  const priorNodeCwd = process.env['CRTR_NODE_CWD'];
48
51
  const priorProfileId = process.env['CRTR_PROFILE_ID'];
52
+ const priorHome = process.env['HOME'];
53
+ const priorCanvasHome = process.env['CRTR_HOME'];
54
+ const priorAgentDir = process.env['PI_CODING_AGENT_DIR'];
55
+ let home;
56
+ let agentDir;
49
57
  before(() => {
58
+ home = mkdtempSync(join(tmpdir(), 'crtr-sdk-wiring-home-'));
59
+ agentDir = join(home, '.pi', 'agent');
60
+ closeDb();
61
+ closeScopedStores();
62
+ process.env['HOME'] = home;
63
+ process.env['CRTR_HOME'] = join(home, '.crouter', 'canvas');
64
+ process.env['PI_CODING_AGENT_DIR'] = agentDir;
65
+ migrate(openDb());
66
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
67
+ initializeFreshScopedStore({ kind: 'provider', root: agentDir });
50
68
  // buildBrokerSession normally receives its environment through buildBrokerEnv,
51
69
  // which strips the launcher's CRTR_* values before applying the target recipe.
52
70
  // These direct SDK tests bypass that boundary, so clear the ambient node's
@@ -56,6 +74,8 @@ before(() => {
56
74
  delete process.env['CRTR_PROFILE_ID'];
57
75
  });
58
76
  after(() => {
77
+ closeDb();
78
+ closeScopedStores();
59
79
  if (priorModelIntent === undefined)
60
80
  delete process.env['CRTR_MODEL_INTENT'];
61
81
  else
@@ -68,6 +88,19 @@ after(() => {
68
88
  delete process.env['CRTR_PROFILE_ID'];
69
89
  else
70
90
  process.env['CRTR_PROFILE_ID'] = priorProfileId;
91
+ if (priorHome === undefined)
92
+ delete process.env['HOME'];
93
+ else
94
+ process.env['HOME'] = priorHome;
95
+ if (priorCanvasHome === undefined)
96
+ delete process.env['CRTR_HOME'];
97
+ else
98
+ process.env['CRTR_HOME'] = priorCanvasHome;
99
+ if (priorAgentDir === undefined)
100
+ delete process.env['PI_CODING_AGENT_DIR'];
101
+ else
102
+ process.env['PI_CODING_AGENT_DIR'] = priorAgentDir;
103
+ rmSync(home, { recursive: true, force: true });
71
104
  });
72
105
  function brokerExts() {
73
106
  return [...CANVAS_EXTENSIONS, C3_EXT];
@@ -157,10 +190,19 @@ test('C3c — mandatory canvas extensions must be loaded, not merely passed in a
157
190
  function runIsolatedManagedLaunch(pool) {
158
191
  const home = mkdtempSync(join(tmpdir(), 'crtr-c3-managed-home-'));
159
192
  const cwd = mkdtempSync(join(tmpdir(), 'crtr-c3-managed-cwd-'));
193
+ const canvasHome = join(home, '.crouter', 'canvas');
194
+ const agentDir = join(home, '.pi', 'agent');
160
195
  const script = `
196
+ process.env.CRTR_HOME = ${JSON.stringify(canvasHome)};
197
+ process.env.PI_CODING_AGENT_DIR = ${JSON.stringify(agentDir)};
161
198
  const { createAgentSessionServices, createAgentSessionFromServices, SessionManager, VERSION } = await import(${JSON.stringify(new URL('../../runtime/broker-sdk.ts', import.meta.url).href)});
162
199
  const { buildBrokerSession } = await import(${JSON.stringify(new URL('../../runtime/broker.ts', import.meta.url).href)});
200
+ const { migrate, openDb } = await import(${JSON.stringify(new URL('../../canvas/db.ts', import.meta.url).href)});
201
+ const { initializeFreshScopedStore } = await import(${JSON.stringify(new URL('../../scoped-state/migrate.ts', import.meta.url).href)});
163
202
  const { writeSubscriptionPool } = await import(${JSON.stringify(new URL('../../subscription-state.ts', import.meta.url).href)});
203
+ migrate(openDb());
204
+ initializeFreshScopedStore({ kind: 'user', root: ${JSON.stringify(join(home, '.crouter'))} });
205
+ initializeFreshScopedStore({ kind: 'provider', root: ${JSON.stringify(agentDir)} });
164
206
  await writeSubscriptionPool('anthropic', ${JSON.stringify(pool)});
165
207
  const realEngine = { createAgentSessionServices, createAgentSessionFromServices, SessionManager, VERSION };
166
208
  const engine = {
@@ -23,7 +23,7 @@
23
23
  // SIMULATES pi's retry slice by popping the last assistant off the live
24
24
  // `agent.state.messages` (leaving the persisted tree intact), and asserts the
25
25
  // snapshot follows the persisted history, not the sliced live array.
26
- import { test } from 'node:test';
26
+ import { afterEach, beforeEach, test } from 'node:test';
27
27
  import assert from 'node:assert/strict';
28
28
  import { mkdtempSync, rmSync } from 'node:fs';
29
29
  import { tmpdir } from 'node:os';
@@ -33,7 +33,10 @@ import { createAgentSessionServices, createAgentSessionFromServices, SessionMana
33
33
  import { CANVAS_EXTENSIONS } from '../../runtime/launch.js';
34
34
  import { buildBrokerSession, snapshotMessages } from '../../runtime/broker.js';
35
35
  import { createNode } from '../../canvas/canvas.js';
36
- import { closeDb } from '../../canvas/db.js';
36
+ import { closeDb, migrate, openDb } from '../../canvas/db.js';
37
+ import { resetSession } from '../../canvas/sessions.js';
38
+ import { closeScopedStores } from '../../scoped-state/db.js';
39
+ import { initializeFreshScopedStore } from '../../scoped-state/migrate.js';
37
40
  import { readNodeMessagesPage, transcriptMarkdown } from '../../runtime/node-read.js';
38
41
  // M-9 (broker.ts fault-and-die model gate): a boot with no cfg.model now calls
39
42
  // the REAL SDK's modelRegistry.getAvailable() and faults if it's empty, which it
@@ -49,6 +52,40 @@ const realEngine = {
49
52
  SessionManager,
50
53
  VERSION,
51
54
  };
55
+ let home;
56
+ let agentDir;
57
+ const previousHome = process.env['HOME'];
58
+ const previousCanvasHome = process.env['CRTR_HOME'];
59
+ const previousAgentDir = process.env['PI_CODING_AGENT_DIR'];
60
+ beforeEach(() => {
61
+ home = mkdtempSync(join(tmpdir(), 'crtr-snaphist-home-'));
62
+ agentDir = join(home, '.pi', 'agent');
63
+ closeDb();
64
+ closeScopedStores();
65
+ process.env['HOME'] = home;
66
+ process.env['CRTR_HOME'] = join(home, '.crouter', 'canvas');
67
+ process.env['PI_CODING_AGENT_DIR'] = agentDir;
68
+ migrate(openDb());
69
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
70
+ initializeFreshScopedStore({ kind: 'provider', root: agentDir });
71
+ });
72
+ afterEach(() => {
73
+ closeDb();
74
+ closeScopedStores();
75
+ if (previousHome === undefined)
76
+ delete process.env['HOME'];
77
+ else
78
+ process.env['HOME'] = previousHome;
79
+ if (previousCanvasHome === undefined)
80
+ delete process.env['CRTR_HOME'];
81
+ else
82
+ process.env['CRTR_HOME'] = previousCanvasHome;
83
+ if (previousAgentDir === undefined)
84
+ delete process.env['PI_CODING_AGENT_DIR'];
85
+ else
86
+ process.env['PI_CODING_AGENT_DIR'] = previousAgentDir;
87
+ rmSync(home, { recursive: true, force: true });
88
+ });
52
89
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
90
  function userMsg(text) {
54
91
  return { role: 'user', content: [{ type: 'text', text }] };
@@ -129,11 +166,7 @@ test('broker welcome snapshot serves the persisted history, not pi\u2019s sliced
129
166
  }
130
167
  });
131
168
  test('readNodeMessagesPage keeps a tool call with all following tool results across cursor pages', async () => {
132
- const home = mkdtempSync(join(tmpdir(), 'crtr-page-tools-home-'));
133
169
  const sessionCwd = mkdtempSync(join(tmpdir(), 'crtr-page-tools-session-'));
134
- const prevHome = process.env['CRTR_HOME'];
135
- process.env['CRTR_HOME'] = home;
136
- closeDb();
137
170
  try {
138
171
  const seed = SessionManager.create(sessionCwd);
139
172
  seed.appendMessage(userMsg('before the tool run'));
@@ -161,6 +194,7 @@ test('readNodeMessagesPage keeps a tool call with all following tool results acr
161
194
  status: 'active',
162
195
  pi_session_file: sessionFile,
163
196
  });
197
+ resetSession(nodeId, { sessionId: seed.getSessionId(), transcriptPath: sessionFile });
164
198
  const newest = await readNodeMessagesPage(nodeId, { limit: 3 });
165
199
  assert.equal(newest.messages[0].role, 'assistant', 'the page walks back from the tool-result cut to its call');
166
200
  assert.deepEqual(newest.messages.slice(1, 3).map((message) => message.role), ['toolResult', 'toolResult'], 'all tool results share the page with their call');
@@ -171,11 +205,6 @@ test('readNodeMessagesPage keeps a tool call with all following tool results acr
171
205
  assert.deepEqual([...(older.messageIds ?? []), ...(newest.messageIds ?? [])], SessionManager.open(sessionFile).getEntries().map(({ id }) => id), 'stable ids remain aligned across the widened page boundary');
172
206
  }
173
207
  finally {
174
- closeDb();
175
- process.env['CRTR_HOME'] = prevHome;
176
- if (prevHome === undefined)
177
- delete process.env['CRTR_HOME'];
178
- rmSync(home, { recursive: true, force: true });
179
208
  rmSync(sessionCwd, { recursive: true, force: true });
180
209
  }
181
210
  });
@@ -187,11 +216,7 @@ test('readNodeMessagesPage keeps a tool call with all following tool results acr
187
216
  // carve-out — while leaving the raw, verbatim human turn (including a literal
188
217
  // `/dev`-shaped token that resembles a memory reference) completely untouched.
189
218
  test('transcriptMarkdown keeps verbatim user text while excluding display:false custom messages', async () => {
190
- const home = mkdtempSync(join(tmpdir(), 'crtr-transcript-home-'));
191
219
  const sessionCwd = mkdtempSync(join(tmpdir(), 'crtr-transcript-session-'));
192
- const prevHome = process.env['CRTR_HOME'];
193
- process.env['CRTR_HOME'] = home;
194
- closeDb();
195
220
  try {
196
221
  const seed = SessionManager.create(sessionCwd);
197
222
  seed.appendMessage(userMsg('read /dev before starting'));
@@ -220,17 +245,13 @@ test('transcriptMarkdown keeps verbatim user text while excluding display:false
220
245
  status: 'active',
221
246
  pi_session_file: sessionFile,
222
247
  });
248
+ resetSession(nodeId, { sessionId: seed.getSessionId(), transcriptPath: sessionFile });
223
249
  const markdown = await transcriptMarkdown(nodeId);
224
250
  assert.ok(markdown.includes('read /dev before starting'), 'raw human text (including the literal /dev token) remains verbatim');
225
251
  assert.ok(markdown.includes('acknowledged'), 'ordinary assistant turn still renders');
226
252
  assert.ok(!markdown.includes('hidden guidance the human never typed'), 'display:false custom content is excluded from the transcript');
227
253
  }
228
254
  finally {
229
- closeDb();
230
- process.env['CRTR_HOME'] = prevHome;
231
- if (prevHome === undefined)
232
- delete process.env['CRTR_HOME'];
233
- rmSync(home, { recursive: true, force: true });
234
255
  rmSync(sessionCwd, { recursive: true, force: true });
235
256
  }
236
257
  });
@@ -238,11 +259,7 @@ test('transcriptMarkdown keeps verbatim user text while excluding display:false
238
259
  // decide whether content is empty, never to alter the emitted bytes of
239
260
  // nonempty human text (leading/trailing whitespace included).
240
261
  test('transcriptMarkdown emits nonempty human text with leading/trailing whitespace unchanged', async () => {
241
- const home = mkdtempSync(join(tmpdir(), 'crtr-transcript-home-'));
242
262
  const sessionCwd = mkdtempSync(join(tmpdir(), 'crtr-transcript-session-'));
243
- const prevHome = process.env['CRTR_HOME'];
244
- process.env['CRTR_HOME'] = home;
245
- closeDb();
246
263
  try {
247
264
  const seed = SessionManager.create(sessionCwd);
248
265
  seed.appendMessage(userMsg(' read /dev before starting '));
@@ -261,15 +278,11 @@ test('transcriptMarkdown emits nonempty human text with leading/trailing whitesp
261
278
  status: 'active',
262
279
  pi_session_file: sessionFile,
263
280
  });
281
+ resetSession(nodeId, { sessionId: seed.getSessionId(), transcriptPath: sessionFile });
264
282
  const markdown = await transcriptMarkdown(nodeId);
265
283
  assert.ok(markdown.includes(' read /dev before starting \n'), 'human text keeps its leading/trailing whitespace byte-identical');
266
284
  }
267
285
  finally {
268
- closeDb();
269
- process.env['CRTR_HOME'] = prevHome;
270
- if (prevHome === undefined)
271
- delete process.env['CRTR_HOME'];
272
- rmSync(home, { recursive: true, force: true });
273
286
  rmSync(sessionCwd, { recursive: true, force: true });
274
287
  }
275
288
  });
@@ -1,39 +1,41 @@
1
1
  // Run with: npm run test:integration
2
2
  //
3
- // Regression coverage for #938/#1081. The busy marker survives an interrupted
4
- // turn for recovery, but supervision must only treat a marker written after the
5
- // current broker launch as that broker's progress clock. The daemon also must
6
- // revalidate that clock after asynchronous ps sampling and report a failed
7
- // SIGTERM honestly.
3
+ // Regression coverage for #938/#1081. Supervision only trusts progress from the
4
+ // current execution, revalidates it after asynchronous ps sampling, and reports
5
+ // a failed SIGTERM honestly.
8
6
  import { test } from 'node:test';
9
7
  import assert from 'node:assert/strict';
10
- import { readFileSync, utimesSync } from 'node:fs';
8
+ import { readFileSync } from 'node:fs';
11
9
  import { join } from 'node:path';
12
10
  import { createHeadlessHarness } from '../helpers/harness.js';
13
- import { getRow, recordLaunch, recordPid, subscribe } from '../../canvas/canvas.js';
14
- import { jobDir } from '../../canvas/paths.js';
15
- import { markBusy } from '../../runtime/busy.js';
11
+ import { listNodes, recordLaunch, subscribe } from '../../canvas/index.js';
12
+ import { openDb } from '../../canvas/db.js';
13
+ import { beginExecution, abortExecution, recordExecutionPid } from '../../canvas/executions.js';
14
+ import { openTurn, recordTurnProgress } from '../../canvas/recovery.js';
16
15
  import { BrokerSupervisionReconciler, WEDGE_QUIET_MS } from '../../../daemon/reconcilers/broker-supervision.js';
17
- const T0 = 20_000_000;
18
- function setBusyAt(id, at) {
19
- markBusy(id);
20
- utimesSync(join(jobDir(id), 'busy'), at / 1_000, at / 1_000);
21
- }
22
16
  function context(h, id) {
23
17
  return {
24
- rows: [getRow(id)],
18
+ rows: listNodes().filter((row) => row.node_id === id),
25
19
  fleet: h.fleet,
26
20
  lifecycle: { acceptsDetachedWork: () => false, registerDetached: () => { } },
27
21
  };
28
22
  }
29
- test('wedge supervision discards a busy marker refreshed while ps sampling', async () => {
23
+ function startBusyExecution(h, id) {
24
+ recordLaunch(id, new Date().toISOString());
25
+ const executionId = beginExecution(id, { daemonEpoch: h.fleet.epoch() });
26
+ recordExecutionPid(executionId, id, process.pid);
27
+ openTurn(executionId, { reason: 'agent-start' });
28
+ h.fleet.register(id, { pid: process.pid, exited: new Promise(() => { }) });
29
+ return executionId;
30
+ }
31
+ test('wedge supervision discards current-execution progress refreshed while ps sampling', async () => {
30
32
  const h = await createHeadlessHarness({ sessionPrefix: 'crtr-wedge-sample' });
31
33
  try {
32
34
  const id = h.fabricateBrokerNode({ status: 'active', pi_session_id: 'wedge-sample' });
33
- recordLaunch(id, new Date(T0 - WEDGE_QUIET_MS - 1).toISOString());
34
- recordPid(id, process.pid);
35
- h.fleet.register(id, { pid: process.pid, exited: new Promise(() => { }) });
36
- setBusyAt(id, T0 - WEDGE_QUIET_MS);
35
+ const executionId = startBusyExecution(h, id);
36
+ // Ensure the first observation is older than the later progress update even
37
+ // when both production calls would otherwise share an ISO millisecond.
38
+ openDb().prepare('UPDATE executions SET turn_progress_at = ? WHERE execution_id = ?').run(new Date(Date.now() - 1).toISOString(), executionId);
37
39
  let finishSample;
38
40
  const sampled = new Promise((resolve) => { finishSample = resolve; });
39
41
  const signals = [];
@@ -41,23 +43,25 @@ test('wedge supervision discards a busy marker refreshed while ps sampling', asy
41
43
  readTreeSample: async () => sampled,
42
44
  signal: (_pid, signal) => { signals.push(signal); },
43
45
  });
44
- const running = supervisor.run(T0, context(h, id));
45
- setBusyAt(id, T0 - 1);
46
+ const running = supervisor.run(Date.now() + WEDGE_QUIET_MS + 1, context(h, id));
47
+ recordTurnProgress(executionId);
46
48
  finishSample({ cpuPercent: 0, hasDescendants: false });
47
49
  await running;
48
- assert.deepEqual(signals, [], 'a marker updated while ps ran cannot produce a wedge SIGTERM');
50
+ assert.deepEqual(signals, [], 'progress updated while ps ran cannot produce a wedge SIGTERM');
49
51
  }
50
52
  finally {
51
53
  await h.dispose();
52
54
  }
53
55
  });
54
- test('wedge supervision does not attribute a predecessor busy marker to a new broker', async () => {
56
+ test('wedge supervision does not attribute a predecessor turn to a new broker', async () => {
55
57
  const h = await createHeadlessHarness({ sessionPrefix: 'crtr-wedge-predecessor' });
56
58
  try {
57
59
  const id = h.fabricateBrokerNode({ status: 'active', pi_session_id: 'wedge-predecessor' });
58
- setBusyAt(id, T0 - WEDGE_QUIET_MS - 1);
59
- recordLaunch(id, new Date(T0).toISOString());
60
- recordPid(id, process.pid);
60
+ const predecessor = startBusyExecution(h, id);
61
+ abortExecution(predecessor, { reason: 'test replacement' });
62
+ h.fleet.forget(id);
63
+ const replacement = beginExecution(id, { daemonEpoch: h.fleet.epoch() });
64
+ recordExecutionPid(replacement, id, process.pid);
61
65
  h.fleet.register(id, { pid: process.pid, exited: new Promise(() => { }) });
62
66
  let samples = 0;
63
67
  const supervisor = new BrokerSupervisionReconciler({
@@ -65,10 +69,10 @@ test('wedge supervision does not attribute a predecessor busy marker to a new br
65
69
  samples += 1;
66
70
  return { cpuPercent: 0, hasDescendants: false };
67
71
  },
68
- signal: () => { throw new Error('a predecessor marker must not reach the signal path'); },
72
+ signal: () => { throw new Error('a predecessor turn must not reach the signal path'); },
69
73
  });
70
- await supervisor.run(T0, context(h, id));
71
- assert.equal(samples, 0, 'the old marker is not a progress observation for the new broker');
74
+ await supervisor.run(Date.now() + WEDGE_QUIET_MS + 1, context(h, id));
75
+ assert.equal(samples, 0, 'the old execution is not a progress observation for the replacement');
72
76
  }
73
77
  finally {
74
78
  await h.dispose();
@@ -80,15 +84,12 @@ test('wedge supervision reports a throwing SIGTERM as an attempted, failed kick'
80
84
  const parent = h.fabricateBrokerNode({ status: 'active' });
81
85
  const id = h.fabricateBrokerNode({ status: 'active', pi_session_id: 'wedge-signal' });
82
86
  subscribe(parent, id);
83
- recordLaunch(id, new Date(T0 - WEDGE_QUIET_MS - 1).toISOString());
84
- recordPid(id, process.pid);
85
- h.fleet.register(id, { pid: process.pid, exited: new Promise(() => { }) });
86
- setBusyAt(id, T0 - WEDGE_QUIET_MS);
87
+ startBusyExecution(h, id);
87
88
  const supervisor = new BrokerSupervisionReconciler({
88
89
  readTreeSample: async () => ({ cpuPercent: 0, hasDescendants: false }),
89
90
  signal: () => { throw new Error('EPERM'); },
90
91
  });
91
- await supervisor.run(T0, context(h, id));
92
+ await supervisor.run(Date.now() + WEDGE_QUIET_MS + 1, context(h, id));
92
93
  const notice = h.inbox(parent).at(-1);
93
94
  assert.match(notice.label, /attempted SIGTERM to the broker, but the signal call failed/);
94
95
  assert.equal(notice.data?.['kick_attempted'], true);
@@ -38,6 +38,9 @@ import { renderRoot, renderBranch, renderLeafArgv } from '../../help.js';
38
38
  import { renderResult } from '../../render.js';
39
39
  import { CrtrError } from '../../errors.js';
40
40
  import { resetScopeCache } from '../../scope.js';
41
+ import { readConfig, updateRawConfigAtomically, writeRawConfig } from '../../config.js';
42
+ import { closeScopedStores } from '../../scoped-state/db.js';
43
+ import { initializeFreshScopedStore } from '../../scoped-state/migrate.js';
41
44
  import { createProfile } from '../../profiles/manifest.js';
42
45
  import { listInstalledPluginsInRoot } from '../../resolver.js';
43
46
  import { pluginShow } from '../../../commands/pkg/plugin-inspect.js';
@@ -198,7 +201,12 @@ function installPlugin(scopeRoot, name, opts = {}) {
198
201
  ...(opts.sourceMarketplace !== undefined ? { source_marketplace: opts.sourceMarketplace } : {}),
199
202
  };
200
203
  if (Object.keys(config).length > 0) {
201
- writeFileSync(join(scopeRoot, 'config.json'), JSON.stringify({ plugins: { [name]: config } }));
204
+ if (scopeRoot === userRoot) {
205
+ updateRawConfigAtomically('user', (raw) => ({ ...raw, plugins: { ...raw.plugins, [name]: config } }));
206
+ }
207
+ else {
208
+ writeFileSync(join(scopeRoot, 'config.json'), JSON.stringify({ plugins: { [name]: config } }));
209
+ }
202
210
  }
203
211
  return root;
204
212
  }
@@ -227,7 +235,7 @@ after(() => {
227
235
  // after(...[home, ...]) would only see the LAST test's set and leak the rest).
228
236
  const tempDirs = [];
229
237
  function mintDir(prefix) {
230
- const d = mkdtempSync(join(tmpdir(), prefix));
238
+ const d = realpathSync(mkdtempSync(join(tmpdir(), prefix)));
231
239
  tempDirs.push(d);
232
240
  return d;
233
241
  }
@@ -235,6 +243,7 @@ beforeEach(() => {
235
243
  home = mintDir('crtr-cmdplugin-home-');
236
244
  process.env['HOME'] = home;
237
245
  userRoot = join(home, '.crouter');
246
+ initializeFreshScopedStore({ kind: 'user', root: userRoot });
238
247
  mkdirSync(join(userRoot, 'plugins'), { recursive: true });
239
248
  projectDir = mintDir('crtr-cmdplugin-proj-');
240
249
  projectRoot = join(projectDir, '.crouter');
@@ -243,6 +252,7 @@ beforeEach(() => {
243
252
  resetScopeCache();
244
253
  });
245
254
  after(() => {
255
+ closeScopedStores();
246
256
  for (const d of tempDirs) {
247
257
  try {
248
258
  rmSync(d, { recursive: true, force: true });
@@ -743,10 +753,10 @@ describe('lifecycle without restart', () => {
743
753
  installPlugin(userRoot, 'deploy-tools');
744
754
  assert.equal(discover().length, 1);
745
755
  // disable (config edit only — no restart)
746
- writeFileSync(join(userRoot, 'config.json'), JSON.stringify({ plugins: { 'deploy-tools': { enabled: false } } }));
756
+ writeRawConfig('user', { plugins: { 'deploy-tools': { enabled: false } } });
747
757
  assert.equal(discover().length, 0);
748
758
  // re-enable + edit the declaration (rename the top-level command)
749
- writeFileSync(join(userRoot, 'config.json'), JSON.stringify({ plugins: { 'deploy-tools': { enabled: true } } }));
759
+ writeRawConfig('user', { plugins: { 'deploy-tools': { enabled: true } } });
750
760
  writeFileSync(join(userRoot, 'plugins', 'deploy-tools', 'commands.json'), JSON.stringify(commandsJson('deploy')));
751
761
  const afterEdit = discover();
752
762
  assert.equal(afterEdit.length, 1);
@@ -1046,8 +1056,7 @@ describe('memory corpus gate across the plugin lifecycle', () => {
1046
1056
  return root;
1047
1057
  }
1048
1058
  function userConfig() {
1049
- const path = join(userRoot, 'config.json');
1050
- return existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : { plugins: {} };
1059
+ return readConfig('user');
1051
1060
  }
1052
1061
  test('a local install migrates the caller-owned linked corpus in place and reports it', async () => {
1053
1062
  const source = pluginSource('memfix');