@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
@@ -0,0 +1,93 @@
1
+ import { openDb, withCanvasWrite } from './db.js';
2
+ function json(value) {
3
+ const encoded = JSON.stringify(value);
4
+ if (encoded === undefined)
5
+ throw new TypeError('worktree value must be JSON-serializable');
6
+ return encoded;
7
+ }
8
+ function parse(value) {
9
+ if (typeof value !== 'string')
10
+ return undefined;
11
+ return JSON.parse(value);
12
+ }
13
+ export function readWorktree(nodeId) {
14
+ const row = openDb().prepare('SELECT * FROM worktrees WHERE node_id = ?').get(nodeId);
15
+ if (row === undefined)
16
+ return null;
17
+ const sweepObserved = parse(row['sweep_observed_json']);
18
+ const attempts = row['attempts'];
19
+ const sweep = sweepObserved === undefined ? undefined : {
20
+ reason: row['sweep_reason'],
21
+ ...(row['sweep_detail'] === null ? {} : { detail: row['sweep_detail'] }),
22
+ observed: sweepObserved,
23
+ attempts,
24
+ last_attempt: row['sweep_last_at'],
25
+ next_attempt: row['next_attempt_at'],
26
+ ...(row['quarantined'] === 1 ? { quarantined: true } : {}),
27
+ };
28
+ return {
29
+ state: row['state'],
30
+ ...(row['cleanup_state'] === null ? {} : { cleanup: row['cleanup_state'] }),
31
+ path: row['path'],
32
+ branch: row['branch'],
33
+ repo_root: row['repo_root'],
34
+ base_ref: row['base_ref'],
35
+ base_sha: row['base_sha'],
36
+ created: row['created_at'],
37
+ ...(row['closed_at'] === null ? {} : { closed: row['closed_at'] }),
38
+ ...(parse(row['abandoned_json']) === undefined ? {} : { abandoned: parse(row['abandoned_json']) }),
39
+ ...(parse(row['land_intent_json']) === undefined ? {} : { land_intent: parse(row['land_intent_json']) }),
40
+ ...(sweep === undefined ? {} : { sweep }),
41
+ ...(parse(row['disposal_json']) === undefined ? {} : { disposal: parse(row['disposal_json']) }),
42
+ };
43
+ }
44
+ export function openWorktree(nodeId, worktree, db = openDb()) {
45
+ db.prepare(`INSERT INTO worktrees (node_id, state, cleanup_state, path, branch, repo_root, base_ref, base_sha, created_at, closed_at, next_attempt_at, attempts, quarantined, sweep_reason, sweep_detail, sweep_last_at, sweep_observed_json, abandoned_json, land_intent_json, disposal_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`).run(nodeId, worktree.state, worktree.cleanup ?? null, worktree.path, worktree.branch, worktree.repo_root, worktree.base_ref, worktree.base_sha, worktree.created, worktree.closed ?? null);
46
+ }
47
+ export function closeWorktree(nodeId, input) {
48
+ openDb().prepare("UPDATE worktrees SET state = 'closed', cleanup_state = ?, closed_at = ?, land_intent_json = NULL, sweep_reason = NULL, sweep_detail = NULL, sweep_last_at = NULL, sweep_observed_json = NULL, next_attempt_at = NULL, attempts = 0, quarantined = 0 WHERE node_id = ?").run(input.cleanup, input.closedAt, nodeId);
49
+ }
50
+ /** Complete a worktree close and repoint the node in the same SQL transaction.
51
+ * A close invalidates the active transcript because Pi remains in the old
52
+ * checkout; the next launch starts from the durable base checkout. */
53
+ export function closeWorktreeAndRepoint(nodeId, input) {
54
+ withCanvasWrite((db) => {
55
+ db.prepare('UPDATE nodes SET cwd = ? WHERE node_id = ?').run(input.cwd, nodeId);
56
+ if (input.unbindSession)
57
+ db.prepare('UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL').run(input.closedAt, nodeId);
58
+ db.prepare("UPDATE worktrees SET state = 'closed', cleanup_state = ?, closed_at = ?, land_intent_json = NULL, sweep_reason = NULL, sweep_detail = NULL, sweep_last_at = NULL, sweep_observed_json = NULL, next_attempt_at = NULL, attempts = 0, quarantined = 0 WHERE node_id = ?").run(input.cleanup, input.closedAt, nodeId);
59
+ });
60
+ }
61
+ export function abandonWorktree(nodeId, abandoned) {
62
+ openDb().prepare("UPDATE worktrees SET state = 'abandoned', abandoned_json = ? WHERE node_id = ? AND abandoned_json IS NULL").run(json(abandoned), nodeId);
63
+ }
64
+ export function abandonWorktreeAndRepoint(nodeId, input) {
65
+ withCanvasWrite((db) => {
66
+ db.prepare('UPDATE nodes SET cwd = ? WHERE node_id = ?').run(input.cwd, nodeId);
67
+ db.prepare("UPDATE worktrees SET state = 'abandoned', abandoned_json = ? WHERE node_id = ? AND abandoned_json IS NULL").run(json(input.abandoned), nodeId);
68
+ });
69
+ }
70
+ export function recordLandIntent(nodeId, intent) {
71
+ openDb().prepare('UPDATE worktrees SET land_intent_json = ? WHERE node_id = ? AND land_intent_json IS NULL').run(json(intent), nodeId);
72
+ }
73
+ export function recordDisposalGrant(nodeId, disposal) {
74
+ openDb().prepare('UPDATE worktrees SET disposal_json = ? WHERE node_id = ? AND disposal_json IS NULL').run(json(disposal), nodeId);
75
+ }
76
+ export function recordSweepAttempt(nodeId, input) {
77
+ openDb().prepare('UPDATE worktrees SET sweep_reason = ?, sweep_detail = ?, sweep_observed_json = ?, attempts = ?, sweep_last_at = ?, next_attempt_at = ?, quarantined = ? WHERE node_id = ?').run(input.reason, input.detail ?? null, json(input.observed), input.attempts, input.lastAttemptAt, input.nextAttemptAt, input.quarantined ? 1 : 0, nodeId);
78
+ }
79
+ export function completeCleanup(nodeId) {
80
+ openDb().prepare("UPDATE worktrees SET state = 'closed', cleanup_state = 'complete', sweep_reason = NULL, sweep_detail = NULL, sweep_last_at = NULL, sweep_observed_json = NULL, next_attempt_at = NULL, attempts = 0, quarantined = 0 WHERE node_id = ?").run(nodeId);
81
+ }
82
+ export function hasUnreconciledWorktree(nodeId) {
83
+ return openDb().prepare("SELECT 1 FROM worktrees WHERE node_id = ? AND state != 'abandoned' AND (state = 'open' OR cleanup_state IS NULL OR cleanup_state != 'complete')").get(nodeId) !== undefined;
84
+ }
85
+ export function sweepCandidates(now) {
86
+ return openDb().prepare(`SELECT w.node_id FROM worktrees w JOIN nodes n ON n.node_id = w.node_id WHERE n.status IN ('done', 'dead', 'canceled') AND n.frozen_at IS NULL AND w.state IN ('open', 'closed') AND (w.state = 'open' OR w.cleanup_state IS NULL OR w.cleanup_state != 'complete') AND (w.state = 'closed' OR (n.status = 'done' AND n.final_report IS NOT NULL)) AND (w.next_attempt_at IS NULL OR w.next_attempt_at <= ?) ORDER BY w.next_attempt_at, w.node_id`).all(now).map(({ node_id }) => node_id);
87
+ }
88
+ export function quarantinedWorktrees() {
89
+ return openDb().prepare('SELECT node_id FROM worktrees WHERE quarantined = 1 ORDER BY sweep_last_at').all().flatMap(({ node_id }) => {
90
+ const worktree = readWorktree(node_id);
91
+ return worktree === null ? [] : [{ nodeId: node_id, worktree }];
92
+ });
93
+ }
@@ -3,23 +3,28 @@ import { type BindingId } from './keybindings/catalog.js';
3
3
  export declare function configPath(scope: Scope): string | null;
4
4
  export declare function statePath(scope: Scope): string | null;
5
5
  export declare function readConfig(scope: Scope): ResolvedScopeConfig;
6
- /** Read the config that lives at an EXACT scope-root dir, rather than the
7
- * resolved nearest root for a scope. Lets a caller iterate each visible
8
- * project root's own config when several are in scope (nested `.crouter` dirs
9
- * or a profile-widened stack), instead of collapsing them onto the nearest. */
10
6
  export declare function readConfigAtRoot(root: string): ResolvedScopeConfig;
11
7
  export declare function readState(scope: Scope): ScopeState;
8
+ export type RawSettingsTarget = {
9
+ scope: 'user';
10
+ } | {
11
+ scope: 'profile';
12
+ profileId: string;
13
+ };
14
+ export declare class InvalidRawSettingsError extends Error {
15
+ constructor(cause: unknown);
16
+ }
17
+ export declare function readRawSettingsForTarget(target: RawSettingsTarget): {
18
+ settings: Record<string, unknown> | null;
19
+ revision: string;
20
+ };
21
+ export declare function replaceRawSettingsForTarget(target: RawSettingsTarget, next: Record<string, unknown>, ifRevision: string): {
22
+ revision: string;
23
+ changed: boolean;
24
+ };
12
25
  type RawConfig = Record<string, unknown>;
13
26
  export declare function updateRawConfigAtomically(scope: Scope, mutate: (latest: RawConfig) => RawConfig): RawConfig;
14
27
  export declare function writeConfig(scope: Scope, config: ScopeConfig): void;
15
- /** Persist a RAW PARTIAL config to a scope's config.json exactly as given.
16
- * Unlike `writeConfig`, this makes no promise that every field is present --
17
- * callers pass the sparse partial that should live on disk, so an untouched
18
- * key stays absent (and `readConfig`/`mergeConfig` re-derive it live from
19
- * whichever build is running). This is the single central primitive every
20
- * mutation path funnels through so no writer ever freezes a fully
21
- * materialized `modelLadders` (concrete model ids that go stale across
22
- * builds -- the live-Hearth freeze bug) onto disk. */
23
28
  export declare function writeRawConfig(scope: Scope, config: Partial<ScopeConfig>): void;
24
29
  export declare function writeState(scope: Scope, state: ScopeState): void;
25
30
  export declare function ensureScopeInitialized(scope: Scope, root: string): void;
@@ -1,14 +1,17 @@
1
1
  import { envProfileId } from '../shared/env.js';
2
- import { dirname, join } from 'node:path';
2
+ import { basename, dirname, join } from 'node:path';
3
3
  import { isDeepStrictEqual } from 'node:util';
4
4
  import { CONFIG_FILE, STATE_FILE, CONDENSED_HISTORY_MODES, MOUSE_MODE_DEFAULTS, WHIP_MESSAGE_MODES, DEFAULT_WHIP_MESSAGES, defaultScopeConfig, defaultScopeState, defaultModelLaddersConfig, defaultKindsConfig, defaultRemoteCanvasConfig } from '../types.js';
5
5
  import { BINDING_CATALOG, BINDING_IDS, isAttachPaneBinding } from './keybindings/catalog.js';
6
- import { usage } from './errors.js';
6
+ import { notFound, usage } from './errors.js';
7
7
  import { emitEvent } from './events/emit.js';
8
- import { atomicWriteJson, readJsonIfExists, writeJson, ensureDir } from './fs-utils.js';
9
- import { scopeRoot, requireScopeRoot, findProjectScopeRoots } from './scope.js';
8
+ import { atomicWriteJson, readJsonIfExists, ensureDir } from './fs-utils.js';
9
+ import { scopeRoot, requireScopeRoot, findProjectScopeRoots, userScopeRoot } from './scope.js';
10
10
  import { listInstalledPluginsInRoot } from './installed-plugins.js';
11
- import { profileRoot } from './profiles/manifest.js';
11
+ import { profileRoot, listProfiles } from './profiles/manifest.js';
12
+ import { canonicalRoot, projectStore, userStore } from './scoped-state/paths.js';
13
+ import { convertLegacyScopedStore, initializeFreshScopedStore } from './scoped-state/migrate.js';
14
+ import { mutateRawSettings, readBookkeeping, readRawSettings, readRawSettingsWithRevision, replaceRawSettings, writeBookkeeping, writeRawSettings } from './scoped-state/settings.js';
12
15
  import { withExclusiveDirectoryLock } from './exclusive-lock.js';
13
16
  import { SCOPE_CONFIG_KEYS } from './user-settings.js';
14
17
  import { normalizeWorkingGerunds } from '../shared/working-activity.js';
@@ -16,6 +19,10 @@ import { mergePageComponentLayers, normalizePageComponents } from './human/page-
16
19
  function configPathFor(root) {
17
20
  return join(root, CONFIG_FILE);
18
21
  }
22
+ function withConfigPathLock(path, run) {
23
+ ensureDir(dirname(path));
24
+ return withExclusiveDirectoryLock(`${path}.lock`, () => run(path), { timeoutError: () => new Error(`timed out waiting for config lock: ${path}`) });
25
+ }
19
26
  function statePathFor(root) {
20
27
  return join(root, STATE_FILE);
21
28
  }
@@ -27,100 +34,83 @@ export function statePath(scope) {
27
34
  const root = scopeRoot(scope);
28
35
  return root ? statePathFor(root) : null;
29
36
  }
30
- export function readConfig(scope) {
31
- const root = scopeRoot(scope);
32
- if (!root)
33
- return defaultScopeConfig();
34
- return readConfigAtRoot(root);
35
- }
36
- /** Read the config that lives at an EXACT scope-root dir, rather than the
37
- * resolved nearest root for a scope. Lets a caller iterate each visible
38
- * project root's own config when several are in scope (nested `.crouter` dirs
39
- * or a profile-widened stack), instead of collapsing them onto the nearest. */
40
- export function readConfigAtRoot(root) {
41
- const existing = readJsonIfExists(configPathFor(root));
42
- if (!existing)
43
- return defaultScopeConfig();
44
- return mergeConfig(existing);
45
- }
46
- export function readState(scope) {
47
- const root = scopeRoot(scope);
48
- if (!root)
49
- return defaultScopeState();
50
- const existing = readJsonIfExists(statePathFor(root));
51
- if (!existing)
52
- return defaultScopeState();
53
- return {
54
- marketplaces: existing.marketplaces ?? {},
55
- plugins: existing.plugins ?? {},
56
- last_self_check: existing.last_self_check,
57
- activeCanvas: existing.activeCanvas ?? null,
58
- };
59
- }
60
- function withConfigPathLock(path, run) {
61
- ensureDir(dirname(path));
62
- return withExclusiveDirectoryLock(`${path}.lock`, () => run(path), {
63
- timeoutError: () => new Error(`timed out waiting for config lock: ${path}`),
64
- });
37
+ function settingsOwnerForRoot(root) {
38
+ const canonical = canonicalRoot(root);
39
+ const userRoot = canonicalRoot(userScopeRoot());
40
+ if (canonical === userRoot)
41
+ return { store: userStore(userRoot), key: 'user', kind: 'user', root: userRoot };
42
+ // Project roots can be classified without opening the user store. This keeps a
43
+ // fresh project usable when an unrelated legacy user root still needs conversion.
44
+ if (basename(canonical) === '.crouter') {
45
+ convertLegacyScopedStore({ kind: 'project', root: canonical });
46
+ return { store: projectStore(canonical), key: 'project', kind: 'project', root: canonical };
47
+ }
48
+ for (const profile of listProfiles()) {
49
+ const profilePath = canonicalRoot(profileRoot(profile.profileId));
50
+ if (canonical === profilePath)
51
+ return { store: userStore(userRoot), key: `profile:${profile.profileId}`, kind: 'profile', root: profilePath, profileId: profile.profileId };
52
+ }
53
+ throw new Error(`settings root is not a recognized owner: ${root}`);
54
+ }
55
+ function readRawAtRoot(root) {
56
+ const owner = settingsOwnerForRoot(root);
57
+ if (owner.kind === 'project')
58
+ return readJsonIfExists(configPathFor(owner.root));
59
+ return readRawSettings(owner);
60
+ }
61
+ function writeRawAtRoot(root, raw) {
62
+ const owner = settingsOwnerForRoot(root);
63
+ if (owner.kind === 'project') {
64
+ withConfigPathLock(configPathFor(owner.root), (path) => atomicWriteJson(path, raw));
65
+ return;
66
+ }
67
+ writeRawSettings(owner, raw);
68
+ }
69
+ function mutateRawAtRoot(root, mutate) {
70
+ const owner = settingsOwnerForRoot(root);
71
+ if (owner.kind === 'project')
72
+ return withConfigPathLock(configPathFor(owner.root), (path) => { const result = mutate(readJsonIfExists(path) ?? {}); atomicWriteJson(path, result.next); return result.value; });
73
+ return mutateRawSettings(owner, (raw) => mutate(raw));
74
+ }
75
+ export function readConfig(scope) { const root = scopeRoot(scope); return root ? readConfigAtRoot(root) : defaultScopeConfig(); }
76
+ export function readConfigAtRoot(root) { const existing = readRawAtRoot(root); return existing ? mergeConfig(existing) : defaultScopeConfig(); }
77
+ export function readState(scope) { const root = scopeRoot(scope); if (!root)
78
+ return defaultScopeState(); return readBookkeeping(settingsOwnerForRoot(root)); }
79
+ export class InvalidRawSettingsError extends Error {
80
+ constructor(cause) {
81
+ super(`settings cannot be merged: ${cause instanceof Error ? cause.message : String(cause)}`);
82
+ this.name = 'InvalidRawSettingsError';
83
+ }
65
84
  }
66
- function withConfigLock(scope, run) {
67
- const root = requireScopeRoot(scope);
68
- return withConfigPathLock(configPathFor(root), run);
85
+ function rawSettingsOwnerForTarget(target) {
86
+ if (target.scope === 'user')
87
+ return settingsOwnerForRoot(userScopeRoot());
88
+ if (!listProfiles().some((profile) => profile.profileId === target.profileId)) {
89
+ throw notFound(`profile not found: ${target.profileId}`, { received: target.profileId, next: 'Run `crtr profile list` to see available profiles.' });
90
+ }
91
+ return settingsOwnerForRoot(profileRoot(target.profileId));
69
92
  }
70
- export function updateRawConfigAtomically(scope, mutate) {
71
- return withConfigLock(scope, (path) => {
72
- const latest = readJsonIfExists(path) ?? {};
73
- const next = mutate(latest);
74
- atomicWriteJson(path, next);
75
- return next;
76
- });
93
+ export function readRawSettingsForTarget(target) {
94
+ return readRawSettingsWithRevision(rawSettingsOwnerForTarget(target));
77
95
  }
78
- export function writeConfig(scope, config) {
79
- withConfigLock(scope, (path) => atomicWriteJson(path, config));
80
- }
81
- /** Persist a RAW PARTIAL config to a scope's config.json exactly as given.
82
- * Unlike `writeConfig`, this makes no promise that every field is present --
83
- * callers pass the sparse partial that should live on disk, so an untouched
84
- * key stays absent (and `readConfig`/`mergeConfig` re-derive it live from
85
- * whichever build is running). This is the single central primitive every
86
- * mutation path funnels through so no writer ever freezes a fully
87
- * materialized `modelLadders` (concrete model ids that go stale across
88
- * builds -- the live-Hearth freeze bug) onto disk. */
89
- export function writeRawConfig(scope, config) {
90
- withConfigLock(scope, (path) => atomicWriteJson(path, config));
91
- }
92
- export function writeState(scope, state) {
93
- const root = requireScopeRoot(scope);
94
- ensureDir(root);
95
- writeJson(statePathFor(root), state);
96
- }
97
- export function ensureScopeInitialized(scope, root) {
98
- ensureDir(root);
99
- withConfigPathLock(configPathFor(root), (cfgPath) => {
100
- if (readJsonIfExists(cfgPath))
101
- return;
102
- // Persist no materialized model ladder or keybinding defaults. `modelLadders` holds concrete model ids (e.g.
103
- // "openai-codex/gpt-5.6-sol:high") that are only valid as long as they match whatever
104
- // pi model registry this crouter build ships. Baking a materialized snapshot here would
105
- // freeze this scope's ladder to whatever ids happened to be current the moment it was
106
- // first initialized -- a later crouter/pi upgrade (or a rollback) that changes the
107
- // registry can then never reach it: the stale persisted override still wins over the
108
- // new build's compiled defaults in `mergeConfig`/`mergeModelLadders`, producing a
109
- // fallback rung `resolveViableFallback` rejects as unregistered while the terminal
110
- // error misleadingly claims the fallback provider needs authenticating (see live
111
- // incident: a home's config.json was seeded with `gpt-5.6-*` ladder entries from a
112
- // build newer than the one actually installed, so its own model registry never had
113
- // them). Omitting the key here is safe: `readConfig`/`mergeConfig` already default-fill
114
- // a missing `modelLadders` from whatever build is CURRENTLY running, and an explicit
115
- // user override (`sys config set modelLadders...`) still persists and still wins.
116
- // Keybindings are sparse user overrides, so an untouched scope omits that member too.
117
- const { modelLadders: _omittedModelLadders, keybindings: _omittedKeybindings, tmux_passthrough: _omittedTmuxPassthrough, brokerThresholds, lifecycle, ...rest } = defaultScopeConfig();
118
- // Broker thresholds and lifecycle timing are host-wide daemon policy, so
119
- // only user scope persists them. Project config must never acquire a
120
- // machine setting.
121
- atomicWriteJson(cfgPath, scope === 'user' ? { ...rest, brokerThresholds, lifecycle } : rest);
96
+ export function replaceRawSettingsForTarget(target, next, ifRevision) {
97
+ return replaceRawSettings(rawSettingsOwnerForTarget(target), next, ifRevision, (settings) => {
98
+ try {
99
+ mergeConfig(settings);
100
+ }
101
+ catch (error) {
102
+ throw new InvalidRawSettingsError(error);
103
+ }
122
104
  });
123
105
  }
106
+ export function updateRawConfigAtomically(scope, mutate) { const root = requireScopeRoot(scope); return mutateRawAtRoot(root, (latest) => { const next = mutate(latest); return { value: next, next }; }); }
107
+ export function writeConfig(scope, config) { writeRawAtRoot(requireScopeRoot(scope), config); }
108
+ export function writeRawConfig(scope, config) { writeRawAtRoot(requireScopeRoot(scope), config); }
109
+ export function writeState(scope, state) { const root = requireScopeRoot(scope); writeBookkeeping(settingsOwnerForRoot(root), state); }
110
+ export function ensureScopeInitialized(scope, root) { ensureDir(root); const owner = scope === 'user' ? settingsOwnerForRoot(userScopeRoot()) : settingsOwnerForRoot(root); initializeFreshScopedStore({ kind: owner.kind === 'user' ? 'user' : 'project', root: owner.store.root }); if (owner.kind === 'project' && readJsonIfExists(configPathFor(owner.root)) === null) {
111
+ const { modelLadders: _a, keybindings: _b, tmux_passthrough: _c, brokerThresholds, lifecycle, ...rest } = defaultScopeConfig();
112
+ writeRawAtRoot(owner.root, rest);
113
+ } }
124
114
  function normalizeKeybindings(raw) {
125
115
  if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
126
116
  return {};
@@ -798,7 +788,7 @@ function mergeConfig(partial) {
798
788
  * for why `readConfig(scope)`, which already defaults-fills, is unusable
799
789
  * for cross-scope layering). */
800
790
  export function readRawConfigAtRoot(root) {
801
- return readJsonIfExists(configPathFor(root));
791
+ return readRawAtRoot(root);
802
792
  }
803
793
  export function readRawScopeConfig(scope) {
804
794
  const root = scopeRoot(scope);
@@ -814,7 +804,7 @@ function readRawProfileConfig(profileId) {
814
804
  if (profileId === null || profileId === '')
815
805
  return null;
816
806
  try {
817
- return readJsonIfExists(configPathFor(profileRoot(profileId)));
807
+ return readRawAtRoot(profileRoot(profileId));
818
808
  }
819
809
  catch {
820
810
  return null;
@@ -832,7 +822,7 @@ function readRawProjectScopeConfigs(targetCwd, targetProfileId) {
832
822
  const farthestFirst = [...nearestFirst].reverse();
833
823
  // A root with no config.json still contributes: its installed plugins may
834
824
  // declare kinds, so the ROOT rides along and `raw` stays null.
835
- return farthestFirst.map((root) => ({ root, raw: readJsonIfExists(configPathFor(root)) }));
825
+ return farthestFirst.map((root) => ({ root, raw: readRawAtRoot(root) }));
836
826
  }
837
827
  /** Merge launch knobs (`kinds`, `modelLadders`) across scopes in
838
828
  * project stack > profile > user > builtin precedence — the same precedence
@@ -994,27 +984,21 @@ function sparseModelLaddersToPersist(rawLadders, baseline, mutated) {
994
984
  * `sys config set` never freezes a full concrete `modelLadders` to disk,
995
985
  * and a direct ladder-rung set still persists only the touched rung -- all
996
986
  * through one lock-protected atomic update path. */
997
- function mutateConfigAtPath(path, mutate) {
998
- return withConfigPathLock(path, (lockedPath) => {
999
- const raw = readJsonIfExists(lockedPath) ?? {};
987
+ function mutateConfigAtRoot(root, mutate) {
988
+ return mutateRawAtRoot(root, (raw) => {
1000
989
  const baseline = mergeConfig(raw);
1001
990
  const cfg = mergeConfig(raw);
1002
991
  mutate(cfg);
1003
992
  const partial = { ...raw };
1004
- for (const key of SCOPE_CONFIG_KEYS) {
1005
- if (key === 'modelLadders')
1006
- continue;
1007
- if (!isDeepStrictEqual(cfg[key], baseline[key])) {
993
+ for (const key of SCOPE_CONFIG_KEYS)
994
+ if (key !== 'modelLadders' && !isDeepStrictEqual(cfg[key], baseline[key]))
1008
995
  partial[key] = cfg[key];
1009
- }
1010
- }
1011
996
  const ladders = sparseModelLaddersToPersist(raw.modelLadders, baseline.modelLadders, cfg.modelLadders);
1012
997
  if (ladders !== undefined)
1013
998
  partial.modelLadders = ladders;
1014
999
  else
1015
1000
  delete partial.modelLadders;
1016
- atomicWriteJson(lockedPath, partial);
1017
- return cfg;
1001
+ return { value: cfg, next: partial };
1018
1002
  });
1019
1003
  }
1020
1004
  /** Persist an EXPLICIT sparse `modelLadders` intent at one config root: the
@@ -1029,21 +1013,10 @@ function mutateConfigAtPath(path, mutate) {
1029
1013
  * evaporates as soon as the default moves. Explicit intent is recorded as
1030
1014
  * written. Mirrors `persistDefaultKindModel`. */
1031
1015
  export function persistModelLadders(root, patch) {
1032
- const path = configPathFor(root);
1033
- ensureDir(root);
1034
- withConfigPathLock(path, (lockedPath) => {
1035
- const raw = readJsonIfExists(lockedPath) ?? {};
1036
- const current = (raw.modelLadders ?? {});
1037
- const next = { ...current };
1038
- if (patch.defaultProvider !== undefined)
1039
- next.defaultProvider = patch.defaultProvider;
1040
- for (const provider of ['anthropic', 'openai']) {
1041
- const rungs = patch[provider];
1042
- if (rungs !== undefined)
1043
- next[provider] = { ...(current[provider] ?? {}), ...rungs };
1044
- }
1045
- atomicWriteJson(lockedPath, { ...raw, modelLadders: next });
1046
- });
1016
+ mutateRawAtRoot(root, (raw) => { const current = (raw.modelLadders ?? {}); const next = { ...current }; if (patch.defaultProvider !== undefined)
1017
+ next.defaultProvider = patch.defaultProvider; for (const provider of ['anthropic', 'openai'])
1018
+ if (patch[provider] !== undefined)
1019
+ next[provider] = { ...(current[provider] ?? {}), ...patch[provider] }; return { value: undefined, next: { ...raw, modelLadders: next } }; });
1047
1020
  }
1048
1021
  /** Persist one complete route at one exact config root. The route is the only
1049
1022
  * raw route entry touched; unrelated routes and local ladder defaults remain
@@ -1054,33 +1027,18 @@ export function persistModelRoute(root, routeId, route) {
1054
1027
  assertCompleteModelRoute(routeId, route);
1055
1028
  else if (routeId.trim() === '')
1056
1029
  throw new Error('model route id must be a non-empty string');
1057
- const path = configPathFor(root);
1058
- ensureDir(root);
1059
- withConfigPathLock(path, (lockedPath) => {
1060
- const raw = readJsonIfExists(lockedPath) ?? {};
1061
- const routes = copyRouteRecord((raw.modelRoutes ?? {}));
1062
- if (route === undefined)
1063
- delete routes[routeId];
1064
- else {
1065
- const current = routes[routeId];
1066
- setRouteRecord(routes, routeId, {
1067
- ...(current !== null && typeof current === 'object' && !Array.isArray(current) ? current : {}),
1068
- ...route,
1069
- models: { ...route.models },
1070
- });
1071
- }
1072
- const next = { ...raw };
1073
- if (Object.keys(routes).length === 0)
1074
- delete next.modelRoutes;
1075
- else
1076
- next.modelRoutes = routes;
1077
- atomicWriteJson(lockedPath, next);
1078
- });
1030
+ mutateRawAtRoot(root, (raw) => { const routes = copyRouteRecord((raw.modelRoutes ?? {})); if (route === undefined)
1031
+ delete routes[routeId];
1032
+ else
1033
+ setRouteRecord(routes, routeId, { ...route, models: { ...route.models } }); const next = { ...raw }; if (Object.keys(routes).length === 0)
1034
+ delete next.modelRoutes;
1035
+ else
1036
+ next.modelRoutes = routes; return { value: undefined, next }; });
1079
1037
  }
1080
1038
  /** Mutate one exact config root. Setup uses this for profile and explicit
1081
1039
  * project targets that cannot be represented by the user/project Scope enum. */
1082
1040
  export function updateConfigAtRoot(root, mutate) {
1083
- return mutateConfigAtPath(configPathFor(root), mutate);
1041
+ return mutateConfigAtRoot(root, mutate);
1084
1042
  }
1085
1043
  export function updateConfig(scope, mutate) {
1086
1044
  return updateConfigAtRoot(requireScopeRoot(scope), mutate);
@@ -1090,15 +1048,8 @@ export function updateConfig(scope, mutate) {
1090
1048
  * scopes instead of freezing a materialized registry snapshot. */
1091
1049
  export function persistDefaultKindModel(opts) {
1092
1050
  const field = opts.orchestrator === true ? 'orchestratorModel' : 'model';
1093
- const path = configPathFor(opts.root);
1094
- ensureDir(opts.root);
1095
- withConfigPathLock(path, (lockedPath) => {
1096
- const raw = readJsonIfExists(lockedPath) ?? {};
1097
- const kinds = { ...(raw.kinds ?? {}) };
1098
- kinds[opts.kind] = { ...(kinds[opts.kind] ?? {}), [field]: opts.model };
1099
- atomicWriteJson(lockedPath, { ...raw, kinds });
1100
- });
1101
- return { path, field };
1051
+ mutateRawAtRoot(opts.root, (raw) => { const kinds = { ...(raw.kinds ?? {}), [opts.kind]: { ...(raw.kinds ?? {})[opts.kind], [field]: opts.model } }; return { value: undefined, next: { ...raw, kinds: kinds } }; });
1052
+ return { path: configPathFor(opts.root), field };
1102
1053
  }
1103
1054
  export function updateState(scope, mutate) {
1104
1055
  const s = readState(scope);
@@ -1,49 +1,45 @@
1
- // Regression (2026-07-22 revive-loop flap): removing legacy inbox compat
2
- // (e2904a09) with no on-host cutover left every pre-cutover node fatally
3
- // unreadable — the broker crashed at inbox seed and the daemon revived it
4
- // forever, flashing "node refreshing — reconnecting…" in every attached
5
- // viewer. The boot migration must rewrite identity-less rows and map the
6
- // ISO-timestamp cursor boundary onto an exact entry identity the strict
7
- // reader accepts.
1
+ // Retained legacy mailbox import: the SQL cutover preserves historical inbox
2
+ // bytes by importing them into messages and deliveries without leaving a
3
+ // runtime filesystem reader.
8
4
  import { test } from 'node:test';
9
5
  import assert from 'node:assert/strict';
10
- import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
6
+ import { DatabaseSync } from 'node:sqlite';
7
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
11
8
  import { join } from 'node:path';
12
9
  import { tmpdir } from 'node:os';
13
- import { migrateLegacyInboxIdentities } from '../inbox-migrate.js';
14
- import { readCursor, readInboxSince } from '../inbox.js';
15
- import { nodeDir, inboxPath } from '../../canvas/paths.js';
16
- test('legacy inbox rows and ISO cursor migrate to strict identities once', () => {
10
+ import { migrateMessagingState } from '../../canvas/deliveries.js';
11
+ import { inboxPath, nodeDir } from '../../canvas/paths.js';
12
+ test('legacy inbox rows and cursor import once into acknowledged and pending SQL deliveries', () => {
17
13
  const home = mkdtempSync(join(tmpdir(), 'crtr-inboxmigrate-'));
18
14
  const orig = process.env['CRTR_HOME'];
19
15
  process.env['CRTR_HOME'] = home;
20
16
  const nodeId = 'mrtest01-aabbccdd';
17
+ const db = new DatabaseSync(join(home, 'canvas.db'));
21
18
  try {
19
+ db.exec('CREATE TABLE nodes (node_id TEXT PRIMARY KEY, waiting_for TEXT, waiting_for_generation INTEGER)');
20
+ db.prepare('INSERT INTO nodes (node_id, waiting_for, waiting_for_generation) VALUES (?, NULL, 0)').run(nodeId);
21
+ db.exec('CREATE TABLE human_action_deliveries (request_id TEXT, state TEXT, attempt INTEGER, argv_json TEXT, cwd TEXT, completion_json TEXT, next_attempt_at INTEGER, claimed_at INTEGER, claim_owner TEXT, accepted_at INTEGER, permanent_failed_at INTEGER, last_failure_json TEXT, created_at INTEGER, updated_at INTEGER)');
22
+ db.exec('CREATE TABLE node_outcome_deliveries (node_id TEXT, state TEXT, attempt INTEGER, action_name TEXT, argv_json TEXT, cwd TEXT, config_origin TEXT, payload_json TEXT, document_json TEXT, next_attempt_at INTEGER, claimed_at INTEGER, claim_owner TEXT, accepted_at INTEGER, permanent_failed_at INTEGER, last_failure_json TEXT, created_at INTEGER, updated_at INTEGER)');
22
23
  mkdirSync(nodeDir(nodeId), { recursive: true });
23
24
  const lines = [
24
- '{"ts":"2026-07-09T22:54:06.294Z","from":"mrpeer1-00000001","tier":"normal","kind":"final","label":"one"}',
25
- '{"ts":"2026-07-10T01:00:00.000Z","from":"mrpeer1-00000001","tier":"normal","kind":"update","label":"two"}',
25
+ '{"entry_id":"11111111111111111111111111111111","operation_id":"22222222222222222222222222222222","ts":"2026-07-09T22:54:06.294Z","from":"mrpeer1-00000001","tier":"normal","kind":"final","label":"one"}',
26
+ '{"entry_id":"33333333333333333333333333333333","operation_id":"44444444444444444444444444444444","ts":"2026-07-10T01:00:00.000Z","from":"mrpeer1-00000001","tier":"normal","kind":"update","label":"two"}',
26
27
  ];
27
28
  writeFileSync(inboxPath(nodeId), `${lines.join('\n')}\n`, 'utf8');
28
- writeFileSync(`${inboxPath(nodeId)}.cursor`, '2026-07-09T22:54:06.294Z', 'utf8');
29
- const first = migrateLegacyInboxIdentities();
30
- assert.equal(first.nodes, 1);
31
- assert.equal(first.entries, 2);
32
- assert.equal(first.cursors, 1);
33
- assert.equal(first.failures, 0);
34
- // The strict reader consumes the migrated state: cursor covers entry one,
35
- // exactly entry two is unread.
36
- const cursor = readCursor(nodeId);
37
- assert.notEqual(cursor, undefined);
38
- const unread = readInboxSince(nodeId, cursor);
39
- assert.equal(unread.length, 1);
40
- assert.equal(unread[0].ts, '2026-07-10T01:00:00.000Z');
41
- const migratedRaw = readFileSync(inboxPath(nodeId), 'utf8');
42
- const second = migrateLegacyInboxIdentities();
43
- assert.deepEqual(second, { nodes: 0, entries: 0, cursors: 0, failures: 0 });
44
- assert.equal(readFileSync(inboxPath(nodeId), 'utf8'), migratedRaw, 'second run is a no-op');
29
+ writeFileSync(`${inboxPath(nodeId)}.cursor`, '11111111111111111111111111111111', 'utf8');
30
+ migrateMessagingState(db);
31
+ const deliveries = db.prepare(`SELECT m.message_id, m.created_at, d.state, d.acknowledged_at
32
+ FROM deliveries d JOIN messages m ON m.message_id = d.message_id
33
+ WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? ORDER BY m.seq`).all(nodeId);
34
+ assert.deepEqual(deliveries.map(({ message_id, state }) => ({ message_id, state })), [
35
+ { message_id: '11111111111111111111111111111111', state: 'acknowledged' },
36
+ { message_id: '33333333333333333333333333333333', state: 'pending' },
37
+ ], 'the retained file rows become ordered SQL message/delivery facts and the legacy cursor becomes acknowledgement');
38
+ assert.equal(deliveries[0].acknowledged_at, Date.parse('2026-07-09T22:54:06.294Z'));
39
+ assert.equal(deliveries[1].created_at, '2026-07-10T01:00:00.000Z');
45
40
  }
46
41
  finally {
42
+ db.close();
47
43
  if (orig === undefined)
48
44
  delete process.env['CRTR_HOME'];
49
45
  else
@@ -27,12 +27,6 @@ export declare class FinalizationError extends Error {
27
27
  readonly reportPath?: string | undefined;
28
28
  constructor(code: 'already_finalized' | 'finalization_forbidden' | 'unknown_node', reportPath?: string | undefined);
29
29
  }
30
- export declare class FinalDeliveryError extends Error {
31
- readonly reportPath: string;
32
- readonly deliveredTo: string[];
33
- readonly failedTo: string[];
34
- constructor(reportPath: string, deliveredTo: string[], failedTo: string[]);
35
- }
36
30
  export declare function push(nodeId: string, opts: PushOpts): Promise<PushResult>;
37
31
  export declare function pushUpdate(nodeId: string, body: string, opts?: {
38
32
  from?: string;