@north-light/crouter 0.3.312 → 0.3.314

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 (497) 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 +757 -746
  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/fresh-home-commands.test.js +49 -0
  121. package/dist/core/__tests__/integration/host-teardown-process-group.test.js +9 -5
  122. package/dist/core/__tests__/integration/lifecycle-hooks.test.js +16 -3
  123. package/dist/core/__tests__/integration/plugin-revalidate.test.js +4 -0
  124. package/dist/core/__tests__/integration/profile-pause.test.js +4 -4
  125. package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +9 -12
  126. package/dist/core/__tests__/integration/revive.test.js +67 -21
  127. package/dist/core/__tests__/integration/spawn-root.test.js +51 -8
  128. package/dist/core/__tests__/integration/subscription-delivery.test.js +33 -21
  129. package/dist/core/__tests__/integration/worktree-land.test.js +5 -2
  130. package/dist/core/__tests__/integration/worktree-reap.test.js +15 -1
  131. package/dist/core/__tests__/kickoff.test.js +36 -39
  132. package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +2 -1
  133. package/dist/core/__tests__/lifecycle.test.js +2 -1
  134. package/dist/core/__tests__/live-lifecycle-prompt.test.js +13 -1
  135. package/dist/core/__tests__/memory-resolver-precedence.test.js +2 -0
  136. package/dist/core/__tests__/migration.test.js +145 -31
  137. package/dist/core/__tests__/model-pin-durability.test.js +4 -1
  138. package/dist/core/__tests__/model-routes-config.test.js +13 -5
  139. package/dist/core/__tests__/node-outcome.test.js +93 -26
  140. package/dist/core/__tests__/on-read-crouter-home-fence.test.js +2 -1
  141. package/dist/core/__tests__/on-read-dedup-resume.test.js +2 -1
  142. package/dist/core/__tests__/on-read-nested-store.test.js +2 -1
  143. package/dist/core/__tests__/passive-subscription.test.js +50 -157
  144. package/dist/core/__tests__/plugin-kinds.test.js +6 -4
  145. package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +6 -1
  146. package/dist/core/__tests__/plugin-page-components.test.js +6 -4
  147. package/dist/core/__tests__/preview-registry-sync.test.js +2 -0
  148. package/dist/core/__tests__/profile-project-memory-delivery.test.js +4 -1
  149. package/dist/core/__tests__/prune.test.js +11 -5
  150. package/dist/core/__tests__/push-final-guard.test.js +14 -7
  151. package/dist/core/__tests__/relaunch-root.test.js +30 -2
  152. package/dist/core/__tests__/remote-canvas-target.test.js +7 -1
  153. package/dist/core/__tests__/repository-root-identity.test.js +4 -0
  154. package/dist/core/__tests__/review-model-floor.test.js +6 -3
  155. package/dist/core/__tests__/revive-all.test.js +13 -3
  156. package/dist/core/__tests__/revive-capacity.test.js +26 -4
  157. package/dist/core/__tests__/revive-parked-fresh.test.js +31 -8
  158. package/dist/core/__tests__/seam/broker-attach-stream.test.js +1 -1
  159. package/dist/core/__tests__/seam/broker-cap-freeze.test.js +4 -3
  160. package/dist/core/__tests__/seam/broker-crash-teardown.test.js +11 -14
  161. package/dist/core/__tests__/seam/broker-provider-retry.test.js +85 -71
  162. package/dist/core/__tests__/seam/dormancy-release.test.js +33 -19
  163. package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +7 -5
  164. package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +20 -6
  165. package/dist/core/__tests__/seam/node-outcome-delivery.test.js +27 -3
  166. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +2 -1
  167. package/dist/core/__tests__/stop-guard.test.js +2 -1
  168. package/dist/core/__tests__/subscription-pool-credential-guard.test.js +4 -3
  169. package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +18 -4
  170. package/dist/core/__tests__/yield-ensures-daemon.test.js +2 -1
  171. package/dist/core/bootstrap.js +2 -0
  172. package/dist/core/broker-client/__tests__/transport-socket.test.js +51 -6
  173. package/dist/core/broker-client/transport-socket.d.ts +1 -0
  174. package/dist/core/broker-client/transport-socket.js +13 -5
  175. package/dist/core/canvas/__tests__/attention.test.js +29 -35
  176. package/dist/core/canvas/__tests__/history-transcript.test.js +6 -6
  177. package/dist/core/canvas/__tests__/render-remote.test.js +25 -9
  178. package/dist/core/canvas/attention.d.ts +2 -5
  179. package/dist/core/canvas/attention.js +15 -64
  180. package/dist/core/canvas/boot.d.ts +6 -7
  181. package/dist/core/canvas/boot.js +5 -9
  182. package/dist/core/canvas/canvas.d.ts +13 -109
  183. package/dist/core/canvas/canvas.js +140 -401
  184. package/dist/core/canvas/crons.d.ts +2 -0
  185. package/dist/core/canvas/crons.js +16 -15
  186. package/dist/core/canvas/daemon-owner.js +10 -0
  187. package/dist/core/canvas/db.d.ts +2 -2
  188. package/dist/core/canvas/db.js +2 -18
  189. package/dist/core/canvas/deliveries.d.ts +104 -0
  190. package/dist/core/canvas/deliveries.js +354 -0
  191. package/dist/core/canvas/executions.d.ts +29 -0
  192. package/dist/core/canvas/executions.js +68 -0
  193. package/dist/core/canvas/history.js +35 -35
  194. package/dist/core/canvas/index.d.ts +3 -1
  195. package/dist/core/canvas/index.js +3 -1
  196. package/dist/core/canvas/migrations.js +20 -12
  197. package/dist/core/canvas/nav-model.js +1 -3
  198. package/dist/core/canvas/nav-render.d.ts +4 -4
  199. package/dist/core/canvas/nav-render.js +11 -21
  200. package/dist/core/canvas/node-sql-migration.d.ts +3 -0
  201. package/dist/core/canvas/node-sql-migration.js +261 -0
  202. package/dist/core/canvas/paths.d.ts +2 -16
  203. package/dist/core/canvas/paths.js +2 -31
  204. package/dist/core/canvas/recovery.d.ts +76 -0
  205. package/dist/core/canvas/recovery.js +588 -0
  206. package/dist/core/canvas/remote-canvas-source.js +4 -0
  207. package/dist/core/canvas/render-source.d.ts +16 -27
  208. package/dist/core/canvas/render-source.js +16 -45
  209. package/dist/core/canvas/sessions.d.ts +33 -0
  210. package/dist/core/canvas/sessions.js +78 -0
  211. package/dist/core/canvas/types.d.ts +33 -33
  212. package/dist/core/canvas/types.js +2 -5
  213. package/dist/core/canvas/waits.d.ts +18 -0
  214. package/dist/core/canvas/waits.js +70 -0
  215. package/dist/core/canvas/worktrees.d.ts +40 -0
  216. package/dist/core/canvas/worktrees.js +93 -0
  217. package/dist/core/command.js +11 -0
  218. package/dist/core/config.d.ts +17 -12
  219. package/dist/core/config.js +106 -155
  220. package/dist/core/feed/__tests__/inbox-migrate.test.js +27 -31
  221. package/dist/core/feed/feed.d.ts +0 -6
  222. package/dist/core/feed/feed.js +68 -56
  223. package/dist/core/feed/inbox.d.ts +7 -81
  224. package/dist/core/feed/inbox.js +46 -378
  225. package/dist/core/feed/messages.d.ts +58 -0
  226. package/dist/core/feed/messages.js +217 -0
  227. package/dist/core/fs-utils.d.ts +4 -0
  228. package/dist/core/fs-utils.js +21 -1
  229. package/dist/core/human/answer.d.ts +1 -1
  230. package/dist/core/human/answer.js +1 -1
  231. package/dist/core/human/claim.d.ts +1 -1
  232. package/dist/core/human/claim.js +2 -4
  233. package/dist/core/human/component-docs.js +1 -1
  234. package/dist/core/human/feedback-companion.js +3 -2
  235. package/dist/core/human/feedback.d.ts +5 -8
  236. package/dist/core/human/feedback.js +57 -85
  237. package/dist/core/human/page-authoring.d.ts +30 -0
  238. package/dist/core/human/page-authoring.js +19 -0
  239. package/dist/core/human/requests.d.ts +136 -0
  240. package/dist/core/human/requests.js +515 -0
  241. package/dist/core/human/root.d.ts +0 -7
  242. package/dist/core/human/root.js +0 -17
  243. package/dist/core/human/scan.d.ts +2 -7
  244. package/dist/core/human/scan.js +48 -132
  245. package/dist/core/human/summary.d.ts +1 -1
  246. package/dist/core/human/summary.js +1 -1
  247. package/dist/core/human/tickets.d.ts +23 -83
  248. package/dist/core/human/tickets.js +92 -243
  249. package/dist/core/human/types.d.ts +5 -1
  250. package/dist/core/installed-plugins.js +8 -3
  251. package/dist/core/keybindings/__tests__/resolve.test.js +19 -17
  252. package/dist/core/locked-file.d.ts +6 -3
  253. package/dist/core/locked-file.js +36 -9
  254. package/dist/core/memory/extensions.js +2 -0
  255. package/dist/core/preview-registry.js +0 -1
  256. package/dist/core/profiles/__tests__/env-store.test.js +2 -0
  257. package/dist/core/profiles/default-binding.d.ts +0 -4
  258. package/dist/core/profiles/default-binding.js +12 -58
  259. package/dist/core/profiles/env-store.js +8 -3
  260. package/dist/core/profiles/manifest.d.ts +2 -37
  261. package/dist/core/profiles/manifest.js +35 -161
  262. package/dist/core/profiles/select.js +3 -0
  263. package/dist/core/review/__tests__/capture-origin.test.js +13 -2
  264. package/dist/core/review/__tests__/comments.test.js +28 -10
  265. package/dist/core/review/__tests__/remap.test.js +28 -10
  266. package/dist/core/review/__tests__/stage-identity.test.js +17 -7
  267. package/dist/core/review/birth.d.ts +1 -1
  268. package/dist/core/review/birth.js +34 -5
  269. package/dist/core/review/comments.js +1 -1
  270. package/dist/core/review/document.js +1 -1
  271. package/dist/core/review/project.d.ts +5 -1
  272. package/dist/core/review/project.js +14 -36
  273. package/dist/core/review/realize.d.ts +3 -6
  274. package/dist/core/review/realize.js +51 -168
  275. package/dist/core/review/remap.js +1 -1
  276. package/dist/core/review/stage.d.ts +3 -2
  277. package/dist/core/review/stage.js +2 -3
  278. package/dist/core/review/store.d.ts +3 -21
  279. package/dist/core/review/store.js +140 -186
  280. package/dist/core/review/types.d.ts +0 -1
  281. package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +9 -5
  282. package/dist/core/runtime/__tests__/spawn-env.test.js +8 -9
  283. package/dist/core/runtime/broker/auth-reload.js +9 -10
  284. package/dist/core/runtime/broker/daemon-ops.d.ts +25 -8
  285. package/dist/core/runtime/broker/daemon-ops.js +42 -9
  286. package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
  287. package/dist/core/runtime/broker/extension-abort.js +11 -0
  288. package/dist/core/runtime/broker/fault-retry.d.ts +15 -6
  289. package/dist/core/runtime/broker/fault-retry.js +142 -95
  290. package/dist/core/runtime/broker/inbox.d.ts +4 -32
  291. package/dist/core/runtime/broker/inbox.js +4 -92
  292. package/dist/core/runtime/broker/rebind.d.ts +1 -0
  293. package/dist/core/runtime/broker/rebind.js +21 -12
  294. package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
  295. package/dist/core/runtime/broker-persona-guidance.js +2 -13
  296. package/dist/core/runtime/broker.js +28 -22
  297. package/dist/core/runtime/close.d.ts +3 -9
  298. package/dist/core/runtime/close.js +16 -27
  299. package/dist/core/runtime/fault.d.ts +3 -93
  300. package/dist/core/runtime/fault.js +9 -419
  301. package/dist/core/runtime/kickoff.d.ts +3 -6
  302. package/dist/core/runtime/kickoff.js +12 -18
  303. package/dist/core/runtime/launch.js +1 -1
  304. package/dist/core/runtime/lifecycle.js +40 -7
  305. package/dist/core/runtime/placement.js +2 -2
  306. package/dist/core/runtime/recycle.js +8 -2
  307. package/dist/core/runtime/reset.js +22 -6
  308. package/dist/core/runtime/revive.js +226 -218
  309. package/dist/core/runtime/spawn.js +14 -3
  310. package/dist/core/scoped-state/db.d.ts +18 -0
  311. package/dist/core/scoped-state/db.js +135 -0
  312. package/dist/core/scoped-state/migrate.d.ts +8 -0
  313. package/dist/core/scoped-state/migrate.js +181 -0
  314. package/dist/core/scoped-state/paths.d.ts +9 -0
  315. package/dist/core/scoped-state/paths.js +27 -0
  316. package/dist/core/scoped-state/profiles.d.ts +12 -0
  317. package/dist/core/scoped-state/profiles.js +62 -0
  318. package/dist/core/scoped-state/providers.d.ts +16 -0
  319. package/dist/core/scoped-state/providers.js +8 -0
  320. package/dist/core/scoped-state/schema.d.ts +3 -0
  321. package/dist/core/scoped-state/schema.js +26 -0
  322. package/dist/core/scoped-state/settings.d.ts +28 -0
  323. package/dist/core/scoped-state/settings.js +82 -0
  324. package/dist/core/subscription-state.d.ts +29 -48
  325. package/dist/core/subscription-state.js +176 -712
  326. package/dist/core/worktree-close.js +4 -4
  327. package/dist/core/worktree-mutation-async.js +2 -2
  328. package/dist/core/worktree-sweep.js +11 -16
  329. package/dist/core/worktree.js +6 -12
  330. package/dist/daemon/__tests__/autostart-storm.test.js +1 -39
  331. package/dist/daemon/__tests__/helpers/source-daemon.d.ts +2 -2
  332. package/dist/daemon/__tests__/helpers/source-daemon.js +7 -6
  333. package/dist/daemon/__tests__/integration/migration-startup.test.js +59 -26
  334. package/dist/daemon/__tests__/node-deadline-lane.test.js +2 -1
  335. package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +39 -15
  336. package/dist/daemon/__tests__/node-outcome-delivery.test.js +39 -10
  337. package/dist/daemon/__tests__/reconciler-signature.test.js +2 -2
  338. package/dist/daemon/__tests__/subtree-filter-freshness.test.js +2 -2
  339. package/dist/daemon/api/__tests__/broker-settle-park.test.js +17 -12
  340. package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +27 -5
  341. package/dist/daemon/api/__tests__/model-config.test.js +8 -8
  342. package/dist/daemon/api/__tests__/node-create-description.test.js +22 -5
  343. package/dist/daemon/api/__tests__/node-model-validation.test.js +21 -1
  344. package/dist/daemon/api/__tests__/nodes-activity-query.test.js +10 -12
  345. package/dist/daemon/api/__tests__/profile-launch-gates.test.js +4 -1
  346. package/dist/daemon/api/__tests__/profile-metadata-route.test.js +4 -1
  347. package/dist/daemon/api/__tests__/reopen-delivery.test.js +26 -8
  348. package/dist/daemon/api/__tests__/seam/api-server.test.js +24 -32
  349. package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +4 -1
  350. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +5 -4
  351. package/dist/daemon/api/__tests__/seam/profile-delete.test.js +27 -41
  352. package/dist/daemon/api/__tests__/submit-result.test.js +3 -2
  353. package/dist/daemon/api/bridge.js +1 -1
  354. package/dist/daemon/api/handlers/bash-jobs.js +6 -7
  355. package/dist/daemon/api/handlers/broker-ops.js +47 -84
  356. package/dist/daemon/api/handlers/broker-recovery.d.ts +4 -0
  357. package/dist/daemon/api/handlers/broker-recovery.js +251 -0
  358. package/dist/daemon/api/handlers/canvas.js +2 -44
  359. package/dist/daemon/api/handlers/daemon.js +41 -0
  360. package/dist/daemon/api/handlers/feedback-comments.js +2 -2
  361. package/dist/daemon/api/handlers/health.js +10 -5
  362. package/dist/daemon/api/handlers/human-requests.js +168 -188
  363. package/dist/daemon/api/handlers/human.js +3 -151
  364. package/dist/daemon/api/handlers/inbox-page.d.ts +4 -0
  365. package/dist/daemon/api/handlers/inbox-page.js +89 -0
  366. package/dist/daemon/api/handlers/inbox.js +21 -120
  367. package/dist/daemon/api/handlers/messages.d.ts +1 -0
  368. package/dist/daemon/api/handlers/messages.js +73 -15
  369. package/dist/daemon/api/handlers/node-outcomes.js +58 -13
  370. package/dist/daemon/api/handlers/nodes.js +7 -13
  371. package/dist/daemon/api/handlers/reviews.js +4 -29
  372. package/dist/daemon/api/map.d.ts +25 -3
  373. package/dist/daemon/api/map.js +84 -14
  374. package/dist/daemon/api/server.js +68 -9
  375. package/dist/daemon/control.d.ts +18 -0
  376. package/dist/daemon/cron/disposition.d.ts +2 -0
  377. package/dist/daemon/cron/disposition.js +8 -5
  378. package/dist/daemon/cron/settle.js +37 -13
  379. package/dist/daemon/cron/sinks.d.ts +18 -1
  380. package/dist/daemon/cron/sinks.js +47 -93
  381. package/dist/daemon/crtrd-cli.js +4 -19
  382. package/dist/daemon/crtrd.d.ts +2 -0
  383. package/dist/daemon/crtrd.js +206 -81
  384. package/dist/daemon/fleet.js +5 -6
  385. package/dist/daemon/human/finish.d.ts +12 -24
  386. package/dist/daemon/human/finish.js +88 -285
  387. package/dist/daemon/human/settle.d.ts +40 -0
  388. package/dist/daemon/human/settle.js +89 -0
  389. package/dist/daemon/human/sweep.d.ts +20 -5
  390. package/dist/daemon/human/sweep.js +56 -60
  391. package/dist/daemon/manage.d.ts +21 -16
  392. package/dist/daemon/manage.js +85 -51
  393. package/dist/daemon/messaging/node-message.d.ts +1 -1
  394. package/dist/daemon/messaging/node-message.js +9 -12
  395. package/dist/daemon/park-activity.js +3 -3
  396. package/dist/daemon/reconcilers/bash-deadline.js +6 -7
  397. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  398. package/dist/daemon/reconcilers/broker-supervision.js +41 -19
  399. package/dist/daemon/reconcilers/controller-death.js +6 -18
  400. package/dist/daemon/reconcilers/delivery-lane.d.ts +9 -0
  401. package/dist/daemon/reconcilers/delivery-lane.js +130 -0
  402. package/dist/daemon/reconcilers/live-obligation.js +3 -3
  403. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  404. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -1
  405. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +10 -12
  406. package/dist/daemon/reconcilers/node-lifecycle/tick.js +5 -5
  407. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  408. package/dist/daemon/reconcilers/pending-review-submit.js +3 -3
  409. package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -8
  410. package/dist/daemon/reconcilers/storage-maintenance.js +13 -43
  411. package/dist/daemon/review/companion.js +5 -11
  412. package/dist/daemon/review/deliver.d.ts +1 -5
  413. package/dist/daemon/review/deliver.js +3 -52
  414. package/dist/daemon/review/finish.d.ts +2 -27
  415. package/dist/daemon/review/finish.js +79 -263
  416. package/dist/daemon/review/sweep.d.ts +3 -10
  417. package/dist/daemon/review/sweep.js +13 -131
  418. package/dist/daemon/startup-policy.d.ts +0 -5
  419. package/dist/daemon/startup-policy.js +0 -5
  420. package/dist/index.d.ts +2 -1
  421. package/dist/index.js +1 -1
  422. package/dist/migrations/__tests__/activation-concurrency.test.js +3 -2
  423. package/dist/migrations/__tests__/activation.test.js +9 -6
  424. package/dist/migrations/activation.d.ts +3 -2
  425. package/dist/migrations/activation.js +2 -4
  426. package/dist/migrations/corpus.d.ts +2 -5
  427. package/dist/migrations/corpus.js +9 -20
  428. package/dist/migrations/runner.d.ts +3 -1
  429. package/dist/migrations/runner.js +6 -2
  430. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +21 -89
  431. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +4 -2
  432. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +51 -33
  433. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +16 -2
  434. package/dist/pi-extensions/__tests__/pre-command-gate.test.js +13 -1
  435. package/dist/pi-extensions/canvas-inbox-watcher.js +98 -244
  436. package/dist/pi-extensions/canvas-passive-context.d.ts +4 -8
  437. package/dist/pi-extensions/canvas-passive-context.js +85 -37
  438. package/dist/pi-extensions/canvas-stophook.js +47 -31
  439. package/dist/shared/env.d.ts +1 -0
  440. package/dist/shared/env.js +3 -0
  441. package/package.json +1 -1
  442. package/runtime.lock.json +5 -5
  443. package/dist/clients/attach/__tests__/page-block.test.js +0 -54
  444. package/dist/clients/inbox/review-visibility.d.ts +0 -5
  445. package/dist/clients/inbox/review-visibility.js +0 -19
  446. package/dist/commands/canvas-rebuild-index.d.ts +0 -2
  447. package/dist/commands/canvas-rebuild-index.js +0 -46
  448. package/dist/core/__tests__/human-cancel-guard.test.js +0 -110
  449. package/dist/core/__tests__/human-deliver.test.js +0 -256
  450. package/dist/core/__tests__/human-node-not-supervised.test.d.ts +0 -1
  451. package/dist/core/__tests__/human-node-not-supervised.test.js +0 -89
  452. package/dist/core/__tests__/integration/human-deliver-e2e.test.d.ts +0 -1
  453. package/dist/core/__tests__/integration/human-deliver-e2e.test.js +0 -131
  454. package/dist/core/__tests__/phase4-review-store.test.d.ts +0 -1
  455. package/dist/core/__tests__/phase4-review-store.test.js +0 -144
  456. package/dist/core/__tests__/watchdog-abort-arms-retry.test.d.ts +0 -1
  457. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +0 -110
  458. package/dist/core/canvas/human-deliveries.d.ts +0 -39
  459. package/dist/core/canvas/human-deliveries.js +0 -75
  460. package/dist/core/canvas/node-outcome-deliveries.d.ts +0 -64
  461. package/dist/core/canvas/node-outcome-deliveries.js +0 -159
  462. package/dist/core/feed/passive.d.ts +0 -3
  463. package/dist/core/feed/passive.js +0 -53
  464. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +0 -1
  465. package/dist/core/human/__tests__/inbox-cancel-worker.js +0 -7
  466. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +0 -1
  467. package/dist/core/human/__tests__/inbox-claim-worker.js +0 -17
  468. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +0 -1
  469. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +0 -8
  470. package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +0 -1
  471. package/dist/core/human/__tests__/integration/inbox-core.test.js +0 -145
  472. package/dist/core/human/__tests__/page-tickets.test.d.ts +0 -1
  473. package/dist/core/human/__tests__/page-tickets.test.js +0 -161
  474. package/dist/core/review/ticket-filter.d.ts +0 -17
  475. package/dist/core/review/ticket-filter.js +0 -21
  476. package/dist/core/runtime/broker/passive.d.ts +0 -17
  477. package/dist/core/runtime/broker/passive.js +0 -44
  478. package/dist/core/runtime/busy.d.ts +0 -46
  479. package/dist/core/runtime/busy.js +0 -150
  480. package/dist/daemon/__tests__/startup-block-marker.test.d.ts +0 -1
  481. package/dist/daemon/__tests__/startup-block-marker.test.js +0 -86
  482. package/dist/daemon/api/__tests__/review-terminal-conflict.test.d.ts +0 -1
  483. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +0 -98
  484. package/dist/daemon/human/deliver-action.d.ts +0 -3
  485. package/dist/daemon/human/deliver-action.js +0 -9
  486. package/dist/daemon/node-outcome/deliver-outcome.d.ts +0 -3
  487. package/dist/daemon/node-outcome/deliver-outcome.js +0 -9
  488. package/dist/daemon/reconcilers/human-delivery-lane.d.ts +0 -10
  489. package/dist/daemon/reconcilers/human-delivery-lane.js +0 -41
  490. package/dist/daemon/reconcilers/node-outcome-delivery-lane.d.ts +0 -10
  491. package/dist/daemon/reconcilers/node-outcome-delivery-lane.js +0 -41
  492. package/dist/daemon/startup-block-marker.d.ts +0 -25
  493. package/dist/daemon/startup-block-marker.js +0 -99
  494. /package/dist/{clients/attach/__tests__/page-block.test.d.ts → api/dto/mail.js} +0 -0
  495. /package/dist/{commands/sys/__tests__/migrate.test.d.ts → api/dto/recovery.js} +0 -0
  496. /package/dist/{core/__tests__/human-cancel-guard.test.d.ts → commands/__tests__/integration/migrate.test.d.ts} +0 -0
  497. /package/dist/core/__tests__/{human-deliver.test.d.ts → integration/fresh-home-commands.test.d.ts} +0 -0
@@ -14,7 +14,7 @@ import { tmpdir } from 'node:os';
14
14
  import { join } from 'node:path';
15
15
  import { gitSync } from '../git.js';
16
16
  import { getNode } from '../canvas/canvas.js';
17
- import { closeDb } from '../canvas/db.js';
17
+ import { closeDb, migrate, openDb } from '../canvas/db.js';
18
18
  import { spawnNode } from '../runtime/nodes.js';
19
19
  import { spawnChild } from '../runtime/spawn.js';
20
20
  import { managedWorktreePath } from '../worktree.js';
@@ -41,6 +41,7 @@ beforeEach(() => {
41
41
  closeDb();
42
42
  rmSync(home, { recursive: true, force: true });
43
43
  process.env['CRTR_HOME'] = home;
44
+ migrate(openDb());
44
45
  });
45
46
  after(async () => {
46
47
  closeDb();
@@ -10,7 +10,7 @@ import { tmpdir } from 'node:os';
10
10
  import { join } from 'node:path';
11
11
  import { createNode, deliverAndSettleMessageWait, getNode, subscribe, setMessageWait, setStatus } from '../canvas/canvas.js';
12
12
  import { armCron, cancelCron, setCronState } from '../canvas/crons.js';
13
- import { closeDb, openDb } from '../canvas/db.js';
13
+ import { closeDb, openDb, migrate } from '../canvas/db.js';
14
14
  import { hasLiveObligation } from '../../daemon/reconcilers/live-obligation.js';
15
15
  import { contextDir } from '../canvas/paths.js';
16
16
  import { bashJobPaths } from '../bash-jobs.js';
@@ -61,6 +61,7 @@ before(() => {
61
61
  beforeEach(() => {
62
62
  closeDb();
63
63
  rmSync(home, { recursive: true, force: true });
64
+ migrate(openDb());
64
65
  });
65
66
  after(() => {
66
67
  closeDb();
@@ -6,18 +6,19 @@
6
6
  // an async writer whose provider returned an incomplete token set.
7
7
  import { before, test } from 'node:test';
8
8
  import assert from 'node:assert/strict';
9
- import { mkdtempSync, readFileSync } from 'node:fs';
9
+ import { mkdtempSync } from 'node:fs';
10
10
  import { tmpdir } from 'node:os';
11
11
  import { join } from 'node:path';
12
+ import { initializeFreshScopedStore } from '../scoped-state/migrate.js';
12
13
  const agentDir = mkdtempSync(join(tmpdir(), 'crtr-pool-guard-'));
13
14
  process.env['PI_CODING_AGENT_DIR'] = agentDir;
14
15
  // Imported dynamically so `PI_CODING_AGENT_DIR` is already set: the pool path is resolved per
15
16
  // access, but the import must not race the env write in any future refactor.
16
17
  let state;
17
18
  before(async () => {
19
+ initializeFreshScopedStore({ kind: 'provider', root: agentDir });
18
20
  state = await import('../subscription-state.js');
19
21
  });
20
- const POOL = join(agentDir, 'openai-codex-subscriptions.json');
21
22
  async function seed() {
22
23
  await state.writeSubscriptionPool('openai-codex', [
23
24
  {
@@ -33,7 +34,7 @@ async function seed() {
33
34
  ]);
34
35
  }
35
36
  function stored() {
36
- const pool = JSON.parse(readFileSync(POOL, 'utf8'));
37
+ const pool = state.readSubscriptionPool('openai-codex');
37
38
  assert.equal(pool.length, 1, 'the row itself must survive every refused write');
38
39
  return pool[0];
39
40
  }
@@ -10,27 +10,41 @@
10
10
  // Run: node --import tsx/esm --test src/core/__tests__/warm-claim-preference-snapshot.test.ts
11
11
  import { test, before, beforeEach, after } from 'node:test';
12
12
  import assert from 'node:assert/strict';
13
- import { mkdtempSync, mkdirSync, rmSync } from 'node:fs';
13
+ import { mkdtempSync, rmSync } from 'node:fs';
14
14
  import { tmpdir } from 'node:os';
15
15
  import { join } from 'node:path';
16
- import { closeDb } from '../canvas/db.js';
16
+ import { closeDb, migrate, openDb } from '../canvas/db.js';
17
+ import { resetScopeCache } from '../scope.js';
18
+ import { closeScopedStores } from '../scoped-state/db.js';
19
+ import { initializeFreshScopedStore } from '../scoped-state/migrate.js';
17
20
  import { spawnNode } from '../runtime/nodes.js';
18
21
  import { deliverBearingsLive } from '../runtime/deliver-live.js';
19
22
  import { loadContextExposureState } from '../substrate/injected-store.js';
20
23
  let home;
24
+ const previousHome = process.env['HOME'];
21
25
  before(() => {
22
26
  home = mkdtempSync(join(tmpdir(), 'crtr-warm-snapshot-'));
23
- process.env['CRTR_HOME'] = home;
27
+ process.env['HOME'] = home;
28
+ process.env['CRTR_HOME'] = join(home, 'canvas');
24
29
  });
25
30
  beforeEach(() => {
26
31
  closeDb();
32
+ closeScopedStores();
27
33
  rmSync(home, { recursive: true, force: true });
28
- mkdirSync(home, { recursive: true });
34
+ resetScopeCache();
35
+ initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
36
+ migrate(openDb());
29
37
  });
30
38
  after(() => {
31
39
  closeDb();
40
+ closeScopedStores();
32
41
  rmSync(home, { recursive: true, force: true });
33
42
  delete process.env['CRTR_HOME'];
43
+ if (previousHome === undefined)
44
+ delete process.env['HOME'];
45
+ else
46
+ process.env['HOME'] = previousHome;
47
+ resetScopeCache();
34
48
  });
35
49
  test('the claim path persists a frozen preference snapshot', async () => {
36
50
  const meta = await spawnNode({ kind: 'general', cwd: '/tmp/work', parent: null });
@@ -13,7 +13,7 @@ import { mkdtempSync, rmSync } from 'node:fs';
13
13
  import { tmpdir } from 'node:os';
14
14
  import { join } from 'node:path';
15
15
  import { createNode, getNode } from '../canvas/canvas.js';
16
- import { closeDb } from '../canvas/db.js';
16
+ import { closeDb, migrate, openDb } from '../canvas/db.js';
17
17
  import { requestYield } from '../runtime/promote.js';
18
18
  let home;
19
19
  function mkOrchestrator(id) {
@@ -36,6 +36,7 @@ before(() => {
36
36
  beforeEach(() => {
37
37
  closeDb();
38
38
  rmSync(home, { recursive: true, force: true });
39
+ migrate(openDb());
39
40
  });
40
41
  after(() => {
41
42
  closeDb();
@@ -2,6 +2,7 @@ import { homedir } from 'node:os';
2
2
  import { join } from 'node:path';
3
3
  import { findProjectScopeRoot, resetScopeCache, userScopeRoot } from './scope.js';
4
4
  import { ensureScopeInitialized } from './config.js';
5
+ import { initializeFreshScopedStore } from './scoped-state/migrate.js';
5
6
  import { CRTR_DIR_NAME } from '../types.js';
6
7
  import { envDebug } from '../shared/env.js';
7
8
  const SKIP_SUBCOMMANDS = new Set([
@@ -29,6 +30,7 @@ export function ensureProjectScope(argv) {
29
30
  return;
30
31
  if (shouldSkipForArgv(argv))
31
32
  return;
33
+ initializeFreshScopedStore({ kind: 'user', root: userScopeRoot() });
32
34
  // Already inside a project scope (here or in an ancestor) — nothing to do.
33
35
  if (findProjectScopeRoot() !== null)
34
36
  return;
@@ -1,24 +1,69 @@
1
1
  import assert from 'node:assert/strict';
2
- import { mkdirSync, mkdtempSync, rmSync } from 'node:fs';
2
+ import { existsSync, mkdtempSync, rmSync } from 'node:fs';
3
3
  import test from 'node:test';
4
- import { nodeDir } from '../../canvas/paths.js';
5
- import { readFault } from '../../runtime/fault.js';
4
+ import { CrtrClient } from '../../../api/client.js';
5
+ import { createNode } from '../../canvas/canvas.js';
6
+ import { closeDb, migrate, openDb } from '../../canvas/db.js';
7
+ import { apiSocketPath } from '../../canvas/paths.js';
8
+ import { readFault } from '../../canvas/recovery.js';
9
+ import { createApiServer } from '../../../daemon/api/server.js';
6
10
  import { SocketTransport } from '../transport-socket.js';
11
+ async function waitFor(check, label) {
12
+ for (let i = 0; i < 200; i++) {
13
+ if (check())
14
+ return;
15
+ await new Promise((resolve) => setTimeout(resolve, 5));
16
+ }
17
+ throw new Error(`timed out waiting for ${label}`);
18
+ }
19
+ async function waitForSocket() {
20
+ const client = CrtrClient.forLocalSocket({ autostart: false });
21
+ await waitFor(() => existsSync(apiSocketPath()), 'the API socket path');
22
+ for (let i = 0; i < 200; i++) {
23
+ try {
24
+ await client.healthz();
25
+ return;
26
+ }
27
+ catch {
28
+ await new Promise((resolve) => setTimeout(resolve, 5));
29
+ }
30
+ }
31
+ throw new Error('timed out waiting for the API socket');
32
+ }
33
+ function node(nodeId) {
34
+ return {
35
+ node_id: nodeId,
36
+ name: nodeId,
37
+ created: new Date().toISOString(),
38
+ cwd: '/tmp/work',
39
+ kind: 'general',
40
+ mode: 'base',
41
+ lifecycle: 'terminal',
42
+ status: 'active',
43
+ };
44
+ }
7
45
  test('a missing dormant broker does not leave a viewer↔broker fault', async () => {
8
46
  const previousHome = process.env['CRTR_HOME'];
9
47
  const home = mkdtempSync('/tmp/crtr-transport-socket-');
48
+ let server;
10
49
  process.env['CRTR_HOME'] = home;
50
+ closeDb();
51
+ migrate(openDb());
11
52
  try {
53
+ server = createApiServer();
54
+ await waitForSocket();
12
55
  const nodeId = 'dormant-node';
13
- mkdirSync(nodeDir(nodeId), { recursive: true });
56
+ createNode(node(nodeId));
14
57
  const transport = new SocketTransport(nodeId);
15
58
  await assert.rejects(transport.redial());
16
- assert.equal(readFault(nodeId)?.link, 'viewer↔broker', 'an ordinary failed redial records the outage');
59
+ await waitFor(() => readFault(nodeId)?.link === 'viewer↔broker', 'the failed redial fault');
17
60
  await assert.rejects(transport.redial({ brokerUnavailableIsExpected: true }));
18
- assert.equal(readFault(nodeId), null, 'a dormant node with no broker is normal, not a fault');
61
+ await waitFor(() => readFault(nodeId) === null, 'the expected-unavailable fault clear');
19
62
  transport.destroy();
20
63
  }
21
64
  finally {
65
+ await server?.close();
66
+ closeDb();
22
67
  if (previousHome === undefined)
23
68
  delete process.env['CRTR_HOME'];
24
69
  else
@@ -20,6 +20,7 @@ export declare class SocketTransport extends EventEmitter implements Transport {
20
20
  redial(options?: RedialOptions): Promise<void>;
21
21
  send(frame: ClientToBroker): void;
22
22
  destroy(): void;
23
+ private clearSocketFault;
23
24
  private onData;
24
25
  private onError;
25
26
  private onClose;
@@ -11,7 +11,8 @@ import { EventEmitter } from 'node:events';
11
11
  import { createConnection } from 'node:net';
12
12
  import { viewSocketPath } from '../canvas/paths.js';
13
13
  import { classify } from '../fault-classifier.js';
14
- import { clearFault, recordFault } from '../runtime/fault.js';
14
+ import { clearNodeFault, recordNodeFault } from '../runtime/broker/daemon-ops.js';
15
+ import { emitEvent } from '../events/emit.js';
15
16
  import { CLIENT_READ_CAPS, encodeFrame, FrameDecoder, FrameOverflowError, } from '../runtime/broker-protocol.js';
16
17
  import { BrokerUnavailableError } from './transport.js';
17
18
  export class SocketTransport extends EventEmitter {
@@ -37,7 +38,7 @@ export class SocketTransport extends EventEmitter {
37
38
  this.redialFaultRecorded = true;
38
39
  }
39
40
  const classified = classify('viewer↔broker', err);
40
- recordFault(this.nodeId, {
41
+ void recordNodeFault(this.nodeId, {
41
42
  link: 'viewer↔broker',
42
43
  op,
43
44
  kind: classified.kind,
@@ -45,6 +46,8 @@ export class SocketTransport extends EventEmitter {
45
46
  ? { disposition: 'auto', by: 'client' }
46
47
  : { disposition: 'manual' },
47
48
  message: err instanceof Error ? err.message : String(err),
49
+ }).catch((error) => {
50
+ emitEvent({ event: 'broker.daemon.operation.failed', level: 'error', node_id: this.nodeId, error, fields: { operation: 'viewer_fault_record' } });
48
51
  });
49
52
  }
50
53
  connect() {
@@ -52,7 +55,7 @@ export class SocketTransport extends EventEmitter {
52
55
  this.socket = socket;
53
56
  socket.on('connect', () => {
54
57
  this.redialFaultRecorded = false;
55
- clearFault(this.nodeId, { link: 'viewer↔broker' });
58
+ this.clearSocketFault();
56
59
  this.emit('connect');
57
60
  });
58
61
  socket.on('data', (chunk) => this.onData(chunk));
@@ -68,7 +71,7 @@ export class SocketTransport extends EventEmitter {
68
71
  this.closeEmitted = false;
69
72
  if (options.brokerUnavailableIsExpected) {
70
73
  this.redialFaultRecorded = false;
71
- clearFault(this.nodeId, { link: 'viewer↔broker' });
74
+ this.clearSocketFault();
72
75
  }
73
76
  return new Promise((resolve, reject) => {
74
77
  const socket = createConnection(this.socketPath);
@@ -79,7 +82,7 @@ export class SocketTransport extends EventEmitter {
79
82
  return;
80
83
  settled = true;
81
84
  this.redialFaultRecorded = false;
82
- clearFault(this.nodeId, { link: 'viewer↔broker' });
85
+ this.clearSocketFault();
83
86
  this.emit('connect');
84
87
  resolve();
85
88
  });
@@ -127,6 +130,11 @@ export class SocketTransport extends EventEmitter {
127
130
  }
128
131
  }
129
132
  }
133
+ clearSocketFault() {
134
+ void clearNodeFault(this.nodeId, { link: 'viewer↔broker' }).catch((error) => {
135
+ emitEvent({ event: 'broker.daemon.operation.failed', level: 'error', node_id: this.nodeId, error, fields: { operation: 'viewer_fault_clear' } });
136
+ });
137
+ }
130
138
  onData(chunk) {
131
139
  let frames;
132
140
  try {
@@ -1,14 +1,14 @@
1
- // attention.test.ts — tickets are keyed by their human bridge node directory.
1
+ // attention.test.ts — pending requests are attributed by requester identity.
2
2
  import { test, before, beforeEach, after } from 'node:test';
3
3
  import assert from 'node:assert/strict';
4
- import { mkdtempSync, rmSync, mkdirSync } from 'node:fs';
4
+ import { mkdtempSync, rmSync } from 'node:fs';
5
5
  import { tmpdir } from 'node:os';
6
6
  import { join } from 'node:path';
7
- import { atomicWriteJson, bindTicketReplyRoute, pageManifestPath } from '../../human/convention.js';
7
+ import { createPageRequest } from '../../human/requests.js';
8
8
  import { createNode } from '../canvas.js';
9
9
  import { closeDb } from '../db.js';
10
- import { nodeDir } from '../paths.js';
11
10
  import { ticketCountsForNodes, pendingTicketsForView, invalidateTicketCounts } from '../attention.js';
11
+ import { migrate, openDb } from '../db.js';
12
12
  function meta(id, cwd, extra) {
13
13
  return {
14
14
  node_id: id,
@@ -22,26 +22,25 @@ function meta(id, cwd, extra) {
22
22
  ...extra,
23
23
  };
24
24
  }
25
- // A ticket only counts as attention when it routes a reply back, so the fixture binds
26
- // the reply route the same way `human send` does before writing the page manifest.
27
- function seedPage(bridgeId) {
28
- const dir = nodeDir(bridgeId);
29
- mkdirSync(dir, { recursive: true });
30
- bindTicketReplyRoute(dir, bridgeId);
31
- atomicWriteJson(pageManifestPath(dir), {
32
- schema: 'crtr.page/v2',
33
- dialect: 'jsx',
34
- title: bridgeId,
35
- subtitle: 'Acknowledge this ticket so the request can proceed.',
36
- delivery: { placement: 'inline', inbox: true, reply: true },
37
- document: 'page.tsx',
38
- steps: 1,
39
- slots: [],
25
+ function seedPage(requestId, requesterNodeId) {
26
+ createPageRequest({
27
+ request_id: requestId,
28
+ requester_node_id: requesterNodeId,
29
+ prepared: {
30
+ document: '<html><head><title>Request</title></head><body>Request</body></html>',
31
+ manifest: {
32
+ schema: 'crtr.page/v2',
33
+ dialect: 'html',
34
+ title: requestId,
35
+ subtitle: 'Acknowledge this ticket so the request can proceed.',
36
+ delivery: { placement: 'inline', inbox: true, reply: true },
37
+ document: 'page.html',
38
+ steps: 1,
39
+ slots: [],
40
+ },
41
+ },
40
42
  });
41
43
  }
42
- function bridge(id, parent, cwd) {
43
- createNode(meta(id, cwd, { kind: 'human', parent }));
44
- }
45
44
  let home;
46
45
  let sharedCwd;
47
46
  let soloCwd;
@@ -55,6 +54,7 @@ beforeEach(() => {
55
54
  closeDb();
56
55
  invalidateTicketCounts();
57
56
  rmSync(home, { recursive: true, force: true });
57
+ migrate(openDb());
58
58
  });
59
59
  after(() => {
60
60
  closeDb();
@@ -62,27 +62,21 @@ after(() => {
62
62
  rmSync(d, { recursive: true, force: true });
63
63
  delete process.env['CRTR_HOME'];
64
64
  });
65
- test('ticketCountsForNodes follows bridge parents even when asking nodes share a cwd', () => {
65
+ test('ticketCountsForNodes follows requester identity even when asking nodes share a cwd', () => {
66
66
  createNode(meta('a', sharedCwd));
67
67
  createNode(meta('b', sharedCwd));
68
68
  createNode(meta('c', soloCwd));
69
- bridge('ha1', 'a', sharedCwd);
70
- bridge('ha2', 'a', sharedCwd);
71
- bridge('hb', 'b', sharedCwd);
72
- bridge('hc', 'c', soloCwd);
73
- seedPage('ha1');
74
- seedPage('ha2');
75
- seedPage('hb');
76
- seedPage('hc');
69
+ seedPage('request-a1', 'a');
70
+ seedPage('request-a2', 'a');
71
+ seedPage('request-b', 'b');
72
+ seedPage('request-c', 'c');
77
73
  assert.deepEqual(ticketCountsForNodes(['a', 'b', 'c']), { a: 2, b: 1, c: 1 });
78
74
  });
79
75
  test('pendingTicketsForView returns the asking node rather than a cwd bucket', () => {
80
76
  createNode(meta('a', sharedCwd));
81
77
  createNode(meta('b', sharedCwd));
82
- bridge('ha', 'a', sharedCwd);
83
- bridge('hb', 'b', sharedCwd);
84
- seedPage('ha');
85
- seedPage('hb');
78
+ seedPage('request-a', 'a');
79
+ seedPage('request-b', 'b');
86
80
  assert.deepEqual(pendingTicketsForView('a').map(({ node_id, count }) => ({ node_id, count })), [
87
81
  { node_id: 'a', count: 1 },
88
82
  ]);
@@ -8,12 +8,12 @@
8
8
  // regression rather than a reader bug, so it is worth pinning.
9
9
  import { test, before, beforeEach, after } from 'node:test';
10
10
  import assert from 'node:assert/strict';
11
- import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from 'node:fs';
11
+ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
12
12
  import { tmpdir } from 'node:os';
13
13
  import { join } from 'node:path';
14
14
  import { createNode } from '../canvas.js';
15
- import { closeDb } from '../db.js';
16
- import { nodeDir, sessionPtrPath } from '../paths.js';
15
+ import { closeDb, migrate, openDb } from '../db.js';
16
+ import { resetSession } from '../sessions.js';
17
17
  import { nodeArtifacts, groupCorpus } from '../history.js';
18
18
  const NODE = 'test-transcript-node';
19
19
  function meta(id, cwd) {
@@ -45,8 +45,6 @@ function stampEntry(msgTs, origin) {
45
45
  /** A session file in the real on-disk shape: stamps precede their messages,
46
46
  * one inbound turn is unstamped, and an assistant turn sits between them. */
47
47
  function seedSession(home) {
48
- const dir = nodeDir(NODE);
49
- mkdirSync(dir, { recursive: true });
50
48
  const file = join(home, 'session.jsonl');
51
49
  writeFileSync(file, [
52
50
  JSON.stringify({ type: 'custom', customType: 'crtr-stamp', data: { v: 1, kind: 'session', payload: { node: NODE, crtr: '0.0.0' } } }),
@@ -57,7 +55,7 @@ function seedSession(home) {
57
55
  messageEntry('user', 'a delivery', 2000),
58
56
  messageEntry('user', 'no stamp for this one', 3000),
59
57
  ].join('\n'), 'utf8');
60
- writeFileSync(sessionPtrPath(NODE), file, 'utf8');
58
+ resetSession(NODE, { sessionId: 'history-transcript-session', transcriptPath: file });
61
59
  }
62
60
  let home;
63
61
  let cwd;
@@ -68,6 +66,8 @@ before(() => {
68
66
  });
69
67
  beforeEach(() => {
70
68
  closeDb();
69
+ rmSync(home, { recursive: true, force: true });
70
+ migrate(openDb());
71
71
  });
72
72
  after(() => {
73
73
  closeDb();
@@ -1,9 +1,12 @@
1
1
  // render-remote.test.ts — the safe-defaults contract for `render.ts`'s
2
2
  // `*FromSource` functions when given a `RemoteCanvasSource`: every field that
3
- // would require a local disk/SQLite read (hanging, streaming, viewed, ctx
4
- // tokens, asks, goal, prompts, lastAssistant) must come back suppressed to
5
- // its safe default instead of touching this process's local state. Reuses
6
- // the mock-server harness shape from `remote-canvas-source.test.ts`.
3
+ // would require a local disk/SQLite read (viewed, ctx tokens, asks, goal,
4
+ // prompts, lastAssistant) must come back suppressed to its safe default
5
+ // instead of touching this process's local state. `hanging`/`streaming` are
6
+ // not suppressed — they are projected by the REMOTE daemon and arrive on the
7
+ // row, so the contract for them is that the row carries the remote fault and
8
+ // never the local one. Reuses the mock-server harness shape from
9
+ // `remote-canvas-source.test.ts`.
7
10
  //
8
11
  // This is adversarial, not merely a clean-machine assertion: BEFORE calling
9
12
  // the render functions, the test seeds real, CONFLICTING local state for the
@@ -23,10 +26,10 @@ import { atomicWriteJson, pageManifestPath } from '#core/human/convention';
23
26
  import { RemoteCanvasSource } from '../remote-canvas-source.js';
24
27
  import { dashboardRowsAllFromSource, enrichRowsFromSource, loadPreviewFromSource, renderForestFromSource } from '../render-source.js';
25
28
  import { createNode } from '../canvas.js';
26
- import { closeDb } from '../db.js';
29
+ import { closeDb, migrate, openDb } from '../db.js';
27
30
  import { openFocusRow } from '../focuses.js';
28
31
  import { jobDir, contextDir, nodeDir } from '../paths.js';
29
- import { recordFault } from '../../runtime/fault.js';
32
+ import { recordFault } from '../recovery.js';
30
33
  function startMockCrtrServer(route) {
31
34
  return new Promise((resolve) => {
32
35
  const server = createServer((req, res) => {
@@ -63,8 +66,9 @@ function meta(id, extra) {
63
66
  ...extra,
64
67
  };
65
68
  }
66
- function row(id) {
69
+ function row(id, fault) {
67
70
  return {
71
+ ...(fault === undefined ? {} : { fault }),
68
72
  node_id: id,
69
73
  name: id,
70
74
  kind: 'general',
@@ -97,6 +101,7 @@ beforeEach(() => {
97
101
  closeDb();
98
102
  rmSync(home, { recursive: true, force: true });
99
103
  rmSync(nodeDir('poison-ask'), { recursive: true, force: true });
104
+ migrate(openDb());
100
105
  });
101
106
  after(() => {
102
107
  closeDb();
@@ -146,11 +151,22 @@ function seedPoisonedLocalState() {
146
151
  ].join('\n'));
147
152
  return sf;
148
153
  }
154
+ /** What the remote daemon projected onto its own row — the only fault a remote
155
+ * row may ever show. */
156
+ const remoteFault = {
157
+ link: 'daemon→node',
158
+ op: 'remote turn',
159
+ kind: 'wedged',
160
+ retry: { disposition: 'manual' },
161
+ message: 'remote daemon fault',
162
+ since: new Date().toISOString(),
163
+ operation_id: '44444444444444444444444444444444',
164
+ };
149
165
  test('dashboardRowsAllFromSource / enrichRowsFromSource / loadPreviewFromSource suppress every local-read field to its safe default for a RemoteCanvasSource, even with conflicting local state for the same node id', async (t) => {
150
166
  sessionFile = seedPoisonedLocalState();
151
167
  const server = await startMockCrtrServer((args) => {
152
168
  if (args[1] === 'node' && args[2] === 'inspect' && args[3] === 'list') {
153
- return { body: { nodes: [row('a')] } };
169
+ return { body: { nodes: [row('a', remoteFault)] } };
154
170
  }
155
171
  if (args[1] === 'node' && args[2] === 'inspect' && args[3] === 'show') {
156
172
  return {
@@ -177,7 +193,7 @@ test('dashboardRowsAllFromSource / enrichRowsFromSource / loadPreviewFromSource
177
193
  const rows = await dashboardRowsAllFromSource(source);
178
194
  assert.equal(rows.length, 1);
179
195
  const r = rows[0];
180
- assert.equal(r.hanging, null, 'local active fault must not leak into a remote row');
196
+ assert.equal(r.hanging?.message, 'remote daemon fault', 'the remote row must carry the fault its own daemon projected');
181
197
  assert.equal(r.streaming, false);
182
198
  assert.equal(r.viewed, false, 'local focus must not leak into a remote row');
183
199
  await enrichRowsFromSource(source, rows);
@@ -3,13 +3,10 @@ export interface TicketEntry {
3
3
  name: string;
4
4
  cwd: string;
5
5
  count: number;
6
- /** Open ticket titles for this node, newest first (scan order). */
6
+ /** Open ticket titles for this node, newest first. */
7
7
  subjects: string[];
8
8
  }
9
- /** Drop the cached walk. Callers that swap the canvas home out from under a live
10
- * process (tests, and any in-process home switch) must call this: the cache is
11
- * keyed only by time, so a stale window would otherwise serve the old home's
12
- * counts. */
9
+ /** Kept for callers that reset a canvas home in process. SQL has no directory-scan cache to invalidate. */
13
10
  export declare function invalidateTicketCounts(): void;
14
11
  /** Count pending tickets asked by one node. */
15
12
  export declare function countTickets(nodeId: string): number;