@north-light/crouter 0.3.311 → 0.3.313

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (520) hide show
  1. package/dist/api/client.d.ts +27 -30
  2. package/dist/api/client.js +80 -67
  3. package/dist/api/dto/broker-ops.d.ts +10 -20
  4. package/dist/api/dto/canvas.d.ts +1 -10
  5. package/dist/api/dto/health.d.ts +113 -0
  6. package/dist/api/dto/human-requests.d.ts +14 -3
  7. package/dist/api/dto/human.d.ts +2 -48
  8. package/dist/api/dto/human.js +3 -2
  9. package/dist/api/dto/inbox.d.ts +14 -0
  10. package/dist/api/dto/mail.d.ts +43 -0
  11. package/dist/api/dto/nodes.d.ts +11 -8
  12. package/dist/api/dto/recovery.d.ts +96 -0
  13. package/dist/api/dto/reviews.d.ts +2 -2
  14. package/dist/api/routes.d.ts +9 -6
  15. package/dist/api/routes.js +11 -11
  16. package/dist/build-root.d.ts +4 -0
  17. package/dist/build-root.js +11 -1
  18. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +35 -47
  19. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +1 -1
  20. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +12 -5
  21. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +12 -5
  22. package/dist/cli.js +10 -1
  23. package/dist/clients/__tests__/helpers/human-daemon.d.ts +11 -0
  24. package/dist/clients/__tests__/helpers/human-daemon.js +60 -0
  25. package/dist/clients/attach/chrome/canvas-panels.js +1 -1
  26. package/dist/clients/attach/chrome/inbox-strip.d.ts +3 -3
  27. package/dist/clients/attach/chrome/inbox-strip.js +17 -9
  28. package/dist/clients/attach/chrome/ticket-panel.d.ts +2 -2
  29. package/dist/clients/attach/chrome/ticket-panel.js +77 -46
  30. package/dist/clients/attach/overlays/graph.js +6 -9
  31. package/dist/clients/attach/render/chat-view.d.ts +5 -4
  32. package/dist/clients/attach/render/chat-view.js +22 -13
  33. package/dist/clients/attach/render/page-block.d.ts +11 -7
  34. package/dist/clients/attach/render/page-block.js +64 -55
  35. package/dist/clients/attach/viewer.js +746 -735
  36. package/dist/clients/inbox/__tests__/integration/inbox-controller.test.js +56 -56
  37. package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.js +45 -32
  38. package/dist/clients/inbox/controller.d.ts +42 -14
  39. package/dist/clients/inbox/controller.js +240 -124
  40. package/dist/clients/inbox/dto-adapt.d.ts +28 -0
  41. package/dist/clients/inbox/dto-adapt.js +93 -0
  42. package/dist/clients/inbox/page-adapter.d.ts +5 -4
  43. package/dist/clients/inbox/page-adapter.js +12 -12
  44. package/dist/clients/inbox/resolve.d.ts +10 -5
  45. package/dist/clients/inbox/resolve.js +13 -12
  46. package/dist/clients/inbox/review/review-client.d.ts +0 -1
  47. package/dist/clients/inbox/review/review-client.js +0 -4
  48. package/dist/clients/inbox/review-adapter.d.ts +2 -1
  49. package/dist/clients/inbox/review-adapter.js +3 -5
  50. package/dist/clients/inbox/surface.d.ts +2 -2
  51. package/dist/clients/inbox/surface.js +19 -8
  52. package/dist/clients/inbox/tui.d.ts +3 -3
  53. package/dist/commands/__tests__/human.test.js +31 -15
  54. package/dist/commands/__tests__/integration/dashboard-snapshot.test.js +36 -11
  55. package/dist/commands/{sys/__tests__ → __tests__/integration}/migrate.test.js +142 -36
  56. package/dist/commands/__tests__/revive-now-gate.test.js +2 -0
  57. package/dist/commands/api-client.d.ts +5 -4
  58. package/dist/commands/api-client.js +13 -7
  59. package/dist/commands/canvas-history/shared.js +1 -1
  60. package/dist/commands/canvas-history.js +1 -1
  61. package/dist/commands/canvas-roster.js +1 -1
  62. package/dist/commands/canvas.js +1 -2
  63. package/dist/commands/human/feedback.js +20 -17
  64. package/dist/commands/human/prompts.js +45 -36
  65. package/dist/commands/human/queue.js +73 -123
  66. package/dist/commands/human/review.js +6 -16
  67. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +2 -0
  68. package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +2 -0
  69. package/dist/commands/memory/__tests__/repository-root-lint.test.js +2 -0
  70. package/dist/commands/node-inspect-artifacts.js +1 -1
  71. package/dist/commands/node-lifecycle-revive.d.ts +2 -2
  72. package/dist/commands/node-lifecycle-revive.js +9 -19
  73. package/dist/commands/pkg/plugin-manage.js +0 -1
  74. package/dist/commands/profile/show.js +4 -12
  75. package/dist/commands/surface-tmux-spread.js +1 -5
  76. package/dist/commands/sys/__tests__/config-model-ladders.test.js +23 -30
  77. package/dist/commands/sys/__tests__/sync-project-guidance.test.js +37 -11
  78. package/dist/commands/sys/branch.d.ts +2 -0
  79. package/dist/commands/sys/branch.js +19 -0
  80. package/dist/commands/sys/config.js +106 -33
  81. package/dist/commands/sys/daemon.d.ts +2 -0
  82. package/dist/commands/sys/daemon.js +130 -7
  83. package/dist/commands/sys/doctor.js +5 -15
  84. package/dist/commands/sys/migrate.js +21 -92
  85. package/dist/commands/sys/setup-settings-runner.js +4 -2
  86. package/dist/commands/sys.js +2 -15
  87. package/dist/core/__tests__/boot-fault-attempt.test.js +23 -1
  88. package/dist/core/__tests__/boot.test.js +32 -25
  89. package/dist/core/__tests__/broker-launch-candidates.test.js +49 -0
  90. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +149 -176
  91. package/dist/core/__tests__/canvas-inbox-watcher-naming.test.js +59 -10
  92. package/dist/core/__tests__/canvas-inbox-watcher.test.js +76 -20
  93. package/dist/core/__tests__/canvas.test.js +18 -47
  94. package/dist/core/__tests__/child-death-wake.test.js +29 -7
  95. package/dist/core/__tests__/cli-help-contract.test.js +2 -0
  96. package/dist/core/__tests__/close.test.js +29 -10
  97. package/dist/core/__tests__/collectible.test.js +2 -1
  98. package/dist/core/__tests__/config-change-delta.test.js +2 -0
  99. package/dist/core/__tests__/context-intro.test.js +17 -5
  100. package/dist/core/__tests__/cron-armed-context-failure.test.js +17 -12
  101. package/dist/core/__tests__/cron-held-settlement.test.js +21 -3
  102. package/dist/core/__tests__/cron-node-sink-parked-root.test.js +29 -10
  103. package/dist/core/__tests__/cron-self-cancel-delivery.test.js +14 -2
  104. package/dist/core/__tests__/cron-timeout-descendants.test.js +13 -1
  105. package/dist/core/__tests__/daemon-boot.test.js +51 -14
  106. package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
  107. package/dist/core/__tests__/fixtures/fake-engine.js +8 -3
  108. package/dist/core/__tests__/focuses.test.js +10 -5
  109. package/dist/core/__tests__/helpers/harness.js +50 -18
  110. package/dist/core/__tests__/history-inbox.test.js +12 -16
  111. package/dist/core/__tests__/human-action-delivery.test.js +48 -28
  112. package/dist/core/__tests__/human-actions.test.js +7 -3
  113. package/dist/core/__tests__/inline-memory-refs.test.js +7 -2
  114. package/dist/core/__tests__/integration/broker-fork-seam.test.js +37 -10
  115. package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +42 -0
  116. package/dist/core/__tests__/integration/broker-snapshot-history.test.js +42 -29
  117. package/dist/core/__tests__/integration/broker-wedge-supervision.test.js +36 -35
  118. package/dist/core/__tests__/integration/command-plugins.test.js +15 -6
  119. package/dist/core/__tests__/integration/deferred-no-wake.test.js +113 -92
  120. package/dist/core/__tests__/integration/host-teardown-process-group.test.js +9 -5
  121. package/dist/core/__tests__/integration/lifecycle-hooks.test.js +312 -1
  122. package/dist/core/__tests__/integration/plugin-revalidate.test.js +4 -0
  123. package/dist/core/__tests__/integration/profile-pause.test.js +4 -4
  124. package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +9 -12
  125. package/dist/core/__tests__/integration/revive.test.js +67 -21
  126. package/dist/core/__tests__/integration/spawn-root.test.js +62 -19
  127. package/dist/core/__tests__/integration/subscription-delivery.test.js +33 -21
  128. package/dist/core/__tests__/integration/worktree-land.test.js +5 -2
  129. package/dist/core/__tests__/integration/worktree-reap.test.js +15 -1
  130. package/dist/core/__tests__/kickoff.test.js +36 -39
  131. package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +2 -1
  132. package/dist/core/__tests__/lifecycle.test.js +2 -1
  133. package/dist/core/__tests__/live-lifecycle-prompt.test.js +13 -1
  134. package/dist/core/__tests__/memory-resolver-precedence.test.js +2 -0
  135. package/dist/core/__tests__/migration.test.js +145 -31
  136. package/dist/core/__tests__/model-pin-durability.test.js +4 -1
  137. package/dist/core/__tests__/model-routes-config.test.js +13 -5
  138. package/dist/core/__tests__/node-outcome.test.js +93 -26
  139. package/dist/core/__tests__/on-read-crouter-home-fence.test.js +4 -3
  140. package/dist/core/__tests__/on-read-dedup-resume.test.js +8 -7
  141. package/dist/core/__tests__/on-read-nested-store.test.js +8 -7
  142. package/dist/core/__tests__/passive-subscription.test.js +50 -157
  143. package/dist/core/__tests__/plugin-kinds.test.js +6 -4
  144. package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +6 -1
  145. package/dist/core/__tests__/plugin-page-components.test.js +6 -4
  146. package/dist/core/__tests__/preview-registry-sync.test.js +2 -0
  147. package/dist/core/__tests__/profile-project-memory-delivery.test.js +35 -32
  148. package/dist/core/__tests__/prune.test.js +11 -5
  149. package/dist/core/__tests__/push-final-guard.test.js +14 -7
  150. package/dist/core/__tests__/relaunch-root.test.js +30 -2
  151. package/dist/core/__tests__/remote-canvas-target.test.js +7 -1
  152. package/dist/core/__tests__/repository-root-identity.test.js +4 -0
  153. package/dist/core/__tests__/review-model-floor.test.js +6 -3
  154. package/dist/core/__tests__/revive-all.test.js +13 -3
  155. package/dist/core/__tests__/revive-capacity.test.js +26 -4
  156. package/dist/core/__tests__/revive-parked-fresh.test.js +31 -8
  157. package/dist/core/__tests__/seam/broker-attach-stream.test.js +1 -1
  158. package/dist/core/__tests__/seam/broker-cap-freeze.test.js +4 -3
  159. package/dist/core/__tests__/seam/broker-crash-teardown.test.js +11 -14
  160. package/dist/core/__tests__/seam/broker-provider-retry.test.js +85 -71
  161. package/dist/core/__tests__/seam/dormancy-release.test.js +33 -19
  162. package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +7 -5
  163. package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +20 -6
  164. package/dist/core/__tests__/seam/node-outcome-delivery.test.js +27 -3
  165. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +5 -4
  166. package/dist/core/__tests__/stop-guard.test.js +2 -1
  167. package/dist/core/__tests__/subscription-pool-credential-guard.test.js +4 -3
  168. package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +19 -5
  169. package/dist/core/__tests__/yield-ensures-daemon.test.js +2 -1
  170. package/dist/core/bootstrap.js +2 -0
  171. package/dist/core/broker-client/__tests__/transport-socket.test.js +51 -6
  172. package/dist/core/broker-client/transport-socket.d.ts +1 -0
  173. package/dist/core/broker-client/transport-socket.js +13 -5
  174. package/dist/core/canvas/__tests__/attention.test.js +29 -35
  175. package/dist/core/canvas/__tests__/history-transcript.test.js +6 -6
  176. package/dist/core/canvas/__tests__/render-remote.test.js +25 -9
  177. package/dist/core/canvas/attention.d.ts +2 -5
  178. package/dist/core/canvas/attention.js +15 -64
  179. package/dist/core/canvas/boot.d.ts +6 -7
  180. package/dist/core/canvas/boot.js +5 -9
  181. package/dist/core/canvas/canvas.d.ts +13 -109
  182. package/dist/core/canvas/canvas.js +140 -401
  183. package/dist/core/canvas/crons.d.ts +2 -0
  184. package/dist/core/canvas/crons.js +16 -15
  185. package/dist/core/canvas/daemon-owner.js +10 -0
  186. package/dist/core/canvas/db.d.ts +2 -2
  187. package/dist/core/canvas/db.js +2 -18
  188. package/dist/core/canvas/deliveries.d.ts +104 -0
  189. package/dist/core/canvas/deliveries.js +354 -0
  190. package/dist/core/canvas/executions.d.ts +29 -0
  191. package/dist/core/canvas/executions.js +68 -0
  192. package/dist/core/canvas/history.js +35 -35
  193. package/dist/core/canvas/index.d.ts +3 -1
  194. package/dist/core/canvas/index.js +3 -1
  195. package/dist/core/canvas/migrations.js +20 -12
  196. package/dist/core/canvas/nav-model.js +1 -3
  197. package/dist/core/canvas/nav-render.d.ts +4 -4
  198. package/dist/core/canvas/nav-render.js +11 -21
  199. package/dist/core/canvas/node-sql-migration.d.ts +3 -0
  200. package/dist/core/canvas/node-sql-migration.js +261 -0
  201. package/dist/core/canvas/paths.d.ts +2 -16
  202. package/dist/core/canvas/paths.js +2 -31
  203. package/dist/core/canvas/recovery.d.ts +76 -0
  204. package/dist/core/canvas/recovery.js +588 -0
  205. package/dist/core/canvas/remote-canvas-source.js +4 -0
  206. package/dist/core/canvas/render-source.d.ts +16 -27
  207. package/dist/core/canvas/render-source.js +16 -45
  208. package/dist/core/canvas/sessions.d.ts +33 -0
  209. package/dist/core/canvas/sessions.js +78 -0
  210. package/dist/core/canvas/types.d.ts +33 -33
  211. package/dist/core/canvas/types.js +2 -5
  212. package/dist/core/canvas/waits.d.ts +18 -0
  213. package/dist/core/canvas/waits.js +70 -0
  214. package/dist/core/canvas/worktrees.d.ts +40 -0
  215. package/dist/core/canvas/worktrees.js +93 -0
  216. package/dist/core/command-hooks/artifact.d.ts +6 -0
  217. package/dist/core/command-hooks/artifact.js +22 -6
  218. package/dist/core/command-hooks/discovery.d.ts +2 -0
  219. package/dist/core/command-hooks/discovery.js +2 -0
  220. package/dist/core/command-hooks/lifecycle-catalog.d.ts +20 -2
  221. package/dist/core/command-hooks/lifecycle-catalog.js +7 -2
  222. package/dist/core/command-hooks/lifecycle-create.d.ts +4 -0
  223. package/dist/core/command-hooks/lifecycle-create.js +51 -0
  224. package/dist/core/command-hooks/schema.d.ts +2 -2
  225. package/dist/core/command-hooks/schema.js +5 -4
  226. package/dist/core/command-hooks/transport/exec-invoke.js +3 -1
  227. package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +18 -8
  228. package/dist/core/command-hooks/transport/exec-lifecycle.js +89 -30
  229. package/dist/core/config.d.ts +17 -12
  230. package/dist/core/config.js +106 -155
  231. package/dist/core/errors.d.ts +1 -0
  232. package/dist/core/errors.js +4 -0
  233. package/dist/core/feed/__tests__/inbox-migrate.test.js +27 -31
  234. package/dist/core/feed/feed.d.ts +0 -6
  235. package/dist/core/feed/feed.js +68 -56
  236. package/dist/core/feed/inbox.d.ts +7 -81
  237. package/dist/core/feed/inbox.js +46 -378
  238. package/dist/core/feed/messages.d.ts +58 -0
  239. package/dist/core/feed/messages.js +217 -0
  240. package/dist/core/fs-utils.d.ts +4 -0
  241. package/dist/core/fs-utils.js +21 -1
  242. package/dist/core/human/answer.d.ts +1 -1
  243. package/dist/core/human/answer.js +1 -1
  244. package/dist/core/human/claim.d.ts +1 -1
  245. package/dist/core/human/claim.js +2 -4
  246. package/dist/core/human/component-docs.js +1 -1
  247. package/dist/core/human/feedback-companion.js +4 -3
  248. package/dist/core/human/feedback.d.ts +5 -8
  249. package/dist/core/human/feedback.js +57 -85
  250. package/dist/core/human/page-authoring.d.ts +30 -0
  251. package/dist/core/human/page-authoring.js +19 -0
  252. package/dist/core/human/requests.d.ts +136 -0
  253. package/dist/core/human/requests.js +515 -0
  254. package/dist/core/human/root.d.ts +0 -7
  255. package/dist/core/human/root.js +0 -17
  256. package/dist/core/human/scan.d.ts +2 -7
  257. package/dist/core/human/scan.js +48 -132
  258. package/dist/core/human/summary.d.ts +1 -1
  259. package/dist/core/human/summary.js +1 -1
  260. package/dist/core/human/tickets.d.ts +23 -83
  261. package/dist/core/human/tickets.js +92 -243
  262. package/dist/core/human/types.d.ts +5 -1
  263. package/dist/core/installed-plugins.js +8 -3
  264. package/dist/core/keybindings/__tests__/resolve.test.js +19 -17
  265. package/dist/core/locked-file.d.ts +6 -3
  266. package/dist/core/locked-file.js +36 -9
  267. package/dist/core/memory/extensions.js +2 -0
  268. package/dist/core/preview-registry.js +0 -1
  269. package/dist/core/profiles/__tests__/env-store.test.js +2 -0
  270. package/dist/core/profiles/default-binding.d.ts +0 -4
  271. package/dist/core/profiles/default-binding.js +12 -58
  272. package/dist/core/profiles/env-store.js +8 -3
  273. package/dist/core/profiles/manifest.d.ts +2 -37
  274. package/dist/core/profiles/manifest.js +35 -161
  275. package/dist/core/profiles/select.js +3 -0
  276. package/dist/core/review/__tests__/capture-origin.test.js +13 -2
  277. package/dist/core/review/__tests__/comments.test.js +28 -10
  278. package/dist/core/review/__tests__/remap.test.js +28 -10
  279. package/dist/core/review/__tests__/stage-identity.test.js +17 -7
  280. package/dist/core/review/birth.d.ts +1 -1
  281. package/dist/core/review/birth.js +34 -5
  282. package/dist/core/review/comments.js +1 -1
  283. package/dist/core/review/companion.d.ts +1 -1
  284. package/dist/core/review/companion.js +2 -2
  285. package/dist/core/review/document.js +1 -1
  286. package/dist/core/review/project.d.ts +5 -1
  287. package/dist/core/review/project.js +14 -36
  288. package/dist/core/review/realize.d.ts +3 -6
  289. package/dist/core/review/realize.js +51 -168
  290. package/dist/core/review/remap.js +1 -1
  291. package/dist/core/review/stage.d.ts +3 -2
  292. package/dist/core/review/stage.js +2 -3
  293. package/dist/core/review/store.d.ts +3 -21
  294. package/dist/core/review/store.js +140 -186
  295. package/dist/core/review/types.d.ts +0 -1
  296. package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +9 -5
  297. package/dist/core/runtime/__tests__/spawn-env.test.js +8 -9
  298. package/dist/core/runtime/broker/auth-reload.js +9 -10
  299. package/dist/core/runtime/broker/daemon-ops.d.ts +25 -8
  300. package/dist/core/runtime/broker/daemon-ops.js +42 -9
  301. package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
  302. package/dist/core/runtime/broker/extension-abort.js +11 -0
  303. package/dist/core/runtime/broker/fault-retry.d.ts +15 -6
  304. package/dist/core/runtime/broker/fault-retry.js +142 -95
  305. package/dist/core/runtime/broker/inbox.d.ts +4 -32
  306. package/dist/core/runtime/broker/inbox.js +4 -92
  307. package/dist/core/runtime/broker/rebind.d.ts +1 -0
  308. package/dist/core/runtime/broker/rebind.js +21 -12
  309. package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
  310. package/dist/core/runtime/broker-persona-guidance.js +2 -13
  311. package/dist/core/runtime/broker.js +28 -22
  312. package/dist/core/runtime/close.d.ts +3 -9
  313. package/dist/core/runtime/close.js +16 -27
  314. package/dist/core/runtime/fault.d.ts +3 -93
  315. package/dist/core/runtime/fault.js +9 -419
  316. package/dist/core/runtime/kickoff.d.ts +3 -6
  317. package/dist/core/runtime/kickoff.js +12 -18
  318. package/dist/core/runtime/launch.js +1 -1
  319. package/dist/core/runtime/lifecycle.js +40 -7
  320. package/dist/core/runtime/nodes.d.ts +5 -1
  321. package/dist/core/runtime/nodes.js +26 -11
  322. package/dist/core/runtime/placement.js +2 -2
  323. package/dist/core/runtime/recycle.js +24 -14
  324. package/dist/core/runtime/reset.js +26 -7
  325. package/dist/core/runtime/revive.js +226 -217
  326. package/dist/core/runtime/spawn.d.ts +4 -1
  327. package/dist/core/runtime/spawn.js +43 -5
  328. package/dist/core/runtime/warm-pool.d.ts +2 -2
  329. package/dist/core/runtime/warm-pool.js +23 -3
  330. package/dist/core/scoped-state/db.d.ts +7 -0
  331. package/dist/core/scoped-state/db.js +92 -0
  332. package/dist/core/scoped-state/migrate.d.ts +11 -0
  333. package/dist/core/scoped-state/migrate.js +198 -0
  334. package/dist/core/scoped-state/paths.d.ts +9 -0
  335. package/dist/core/scoped-state/paths.js +27 -0
  336. package/dist/core/scoped-state/profiles.d.ts +12 -0
  337. package/dist/core/scoped-state/profiles.js +62 -0
  338. package/dist/core/scoped-state/providers.d.ts +16 -0
  339. package/dist/core/scoped-state/providers.js +8 -0
  340. package/dist/core/scoped-state/schema.d.ts +3 -0
  341. package/dist/core/scoped-state/schema.js +26 -0
  342. package/dist/core/scoped-state/settings.d.ts +28 -0
  343. package/dist/core/scoped-state/settings.js +82 -0
  344. package/dist/core/subscription-state.d.ts +29 -48
  345. package/dist/core/subscription-state.js +176 -712
  346. package/dist/core/worktree-close.js +4 -4
  347. package/dist/core/worktree-mutation-async.js +2 -2
  348. package/dist/core/worktree-sweep.js +11 -16
  349. package/dist/core/worktree.js +6 -12
  350. package/dist/daemon/__tests__/autostart-storm.test.js +1 -39
  351. package/dist/daemon/__tests__/helpers/source-daemon.d.ts +2 -2
  352. package/dist/daemon/__tests__/helpers/source-daemon.js +7 -6
  353. package/dist/daemon/__tests__/integration/migration-startup.test.js +59 -26
  354. package/dist/daemon/__tests__/node-deadline-lane.test.js +2 -1
  355. package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +41 -17
  356. package/dist/daemon/__tests__/node-outcome-delivery.test.js +39 -10
  357. package/dist/daemon/__tests__/reconciler-signature.test.js +2 -2
  358. package/dist/daemon/__tests__/subtree-filter-freshness.test.js +2 -2
  359. package/dist/daemon/api/__tests__/broker-settle-park.test.js +17 -12
  360. package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +27 -5
  361. package/dist/daemon/api/__tests__/model-config.test.js +8 -8
  362. package/dist/daemon/api/__tests__/node-create-description.test.js +22 -5
  363. package/dist/daemon/api/__tests__/node-model-validation.test.js +21 -1
  364. package/dist/daemon/api/__tests__/nodes-activity-query.test.js +10 -12
  365. package/dist/daemon/api/__tests__/profile-launch-gates.test.js +6 -3
  366. package/dist/daemon/api/__tests__/profile-metadata-route.test.js +4 -1
  367. package/dist/daemon/api/__tests__/reopen-delivery.test.js +26 -8
  368. package/dist/daemon/api/__tests__/seam/api-server.test.js +24 -32
  369. package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +4 -1
  370. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +5 -4
  371. package/dist/daemon/api/__tests__/seam/profile-delete.test.js +29 -43
  372. package/dist/daemon/api/__tests__/submit-result.test.js +3 -2
  373. package/dist/daemon/api/bridge.js +1 -1
  374. package/dist/daemon/api/handlers/bash-jobs.js +6 -7
  375. package/dist/daemon/api/handlers/broker-ops.js +47 -84
  376. package/dist/daemon/api/handlers/broker-recovery.d.ts +4 -0
  377. package/dist/daemon/api/handlers/broker-recovery.js +251 -0
  378. package/dist/daemon/api/handlers/canvas.js +2 -44
  379. package/dist/daemon/api/handlers/daemon.js +41 -0
  380. package/dist/daemon/api/handlers/feedback-comments.js +2 -2
  381. package/dist/daemon/api/handlers/health.js +10 -5
  382. package/dist/daemon/api/handlers/human-requests.js +168 -188
  383. package/dist/daemon/api/handlers/human.js +3 -148
  384. package/dist/daemon/api/handlers/inbox-page.d.ts +4 -0
  385. package/dist/daemon/api/handlers/inbox-page.js +89 -0
  386. package/dist/daemon/api/handlers/inbox.js +21 -120
  387. package/dist/daemon/api/handlers/messages.d.ts +1 -0
  388. package/dist/daemon/api/handlers/messages.js +73 -15
  389. package/dist/daemon/api/handlers/node-outcomes.js +58 -13
  390. package/dist/daemon/api/handlers/nodes.d.ts +1 -0
  391. package/dist/daemon/api/handlers/nodes.js +41 -42
  392. package/dist/daemon/api/handlers/reviews.js +4 -29
  393. package/dist/daemon/api/map.d.ts +25 -3
  394. package/dist/daemon/api/map.js +84 -14
  395. package/dist/daemon/api/server.js +68 -9
  396. package/dist/daemon/control.d.ts +18 -0
  397. package/dist/daemon/cron/disposition.d.ts +2 -0
  398. package/dist/daemon/cron/disposition.js +8 -5
  399. package/dist/daemon/cron/settle.js +37 -13
  400. package/dist/daemon/cron/sinks.d.ts +18 -1
  401. package/dist/daemon/cron/sinks.js +47 -93
  402. package/dist/daemon/crtrd-cli.js +4 -19
  403. package/dist/daemon/crtrd.d.ts +2 -0
  404. package/dist/daemon/crtrd.js +206 -81
  405. package/dist/daemon/fleet.js +5 -6
  406. package/dist/daemon/human/finish.d.ts +12 -24
  407. package/dist/daemon/human/finish.js +88 -285
  408. package/dist/daemon/human/settle.d.ts +40 -0
  409. package/dist/daemon/human/settle.js +89 -0
  410. package/dist/daemon/human/sweep.d.ts +20 -5
  411. package/dist/daemon/human/sweep.js +56 -60
  412. package/dist/daemon/manage.d.ts +21 -16
  413. package/dist/daemon/manage.js +85 -51
  414. package/dist/daemon/messaging/node-message.d.ts +1 -1
  415. package/dist/daemon/messaging/node-message.js +9 -12
  416. package/dist/daemon/park-activity.js +3 -3
  417. package/dist/daemon/reconcilers/bash-deadline.js +6 -7
  418. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  419. package/dist/daemon/reconcilers/broker-supervision.js +41 -19
  420. package/dist/daemon/reconcilers/controller-death.js +6 -18
  421. package/dist/daemon/reconcilers/delivery-lane.d.ts +9 -0
  422. package/dist/daemon/reconcilers/delivery-lane.js +130 -0
  423. package/dist/daemon/reconcilers/live-obligation.js +3 -3
  424. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  425. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -1
  426. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +10 -12
  427. package/dist/daemon/reconcilers/node-lifecycle/tick.js +5 -5
  428. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  429. package/dist/daemon/reconcilers/pending-review-submit.js +3 -3
  430. package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -8
  431. package/dist/daemon/reconcilers/storage-maintenance.js +13 -43
  432. package/dist/daemon/review/companion.js +5 -11
  433. package/dist/daemon/review/deliver.d.ts +1 -5
  434. package/dist/daemon/review/deliver.js +3 -52
  435. package/dist/daemon/review/finish.d.ts +2 -27
  436. package/dist/daemon/review/finish.js +79 -263
  437. package/dist/daemon/review/sweep.d.ts +3 -10
  438. package/dist/daemon/review/sweep.js +13 -131
  439. package/dist/daemon/startup-policy.d.ts +0 -5
  440. package/dist/daemon/startup-policy.js +0 -5
  441. package/dist/hook-authoring.d.ts +28 -2
  442. package/dist/hook-authoring.js +53 -1
  443. package/dist/index.d.ts +3 -2
  444. package/dist/index.js +1 -1
  445. package/dist/migrations/__tests__/activation-concurrency.test.js +3 -2
  446. package/dist/migrations/__tests__/activation.test.js +9 -6
  447. package/dist/migrations/activation.d.ts +3 -2
  448. package/dist/migrations/activation.js +2 -4
  449. package/dist/migrations/corpus.d.ts +2 -5
  450. package/dist/migrations/corpus.js +9 -20
  451. package/dist/migrations/runner.d.ts +3 -1
  452. package/dist/migrations/runner.js +6 -2
  453. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +21 -89
  454. package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +4 -2
  455. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +51 -33
  456. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +16 -2
  457. package/dist/pi-extensions/__tests__/pre-command-gate.test.js +13 -1
  458. package/dist/pi-extensions/canvas-inbox-watcher.js +98 -244
  459. package/dist/pi-extensions/canvas-passive-context.d.ts +4 -8
  460. package/dist/pi-extensions/canvas-passive-context.js +85 -37
  461. package/dist/pi-extensions/canvas-stophook.js +47 -31
  462. package/dist/shared/env.d.ts +1 -0
  463. package/dist/shared/env.js +3 -0
  464. package/package.json +1 -1
  465. package/runtime.lock.json +5 -5
  466. package/dist/clients/attach/__tests__/page-block.test.js +0 -54
  467. package/dist/clients/inbox/review-visibility.d.ts +0 -5
  468. package/dist/clients/inbox/review-visibility.js +0 -19
  469. package/dist/commands/canvas-rebuild-index.d.ts +0 -2
  470. package/dist/commands/canvas-rebuild-index.js +0 -46
  471. package/dist/core/__tests__/human-cancel-guard.test.js +0 -110
  472. package/dist/core/__tests__/human-deliver.test.d.ts +0 -1
  473. package/dist/core/__tests__/human-deliver.test.js +0 -256
  474. package/dist/core/__tests__/human-node-not-supervised.test.d.ts +0 -1
  475. package/dist/core/__tests__/human-node-not-supervised.test.js +0 -89
  476. package/dist/core/__tests__/integration/human-deliver-e2e.test.d.ts +0 -1
  477. package/dist/core/__tests__/integration/human-deliver-e2e.test.js +0 -131
  478. package/dist/core/__tests__/phase4-review-store.test.d.ts +0 -1
  479. package/dist/core/__tests__/phase4-review-store.test.js +0 -144
  480. package/dist/core/__tests__/watchdog-abort-arms-retry.test.d.ts +0 -1
  481. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +0 -110
  482. package/dist/core/canvas/human-deliveries.d.ts +0 -39
  483. package/dist/core/canvas/human-deliveries.js +0 -75
  484. package/dist/core/canvas/node-outcome-deliveries.d.ts +0 -64
  485. package/dist/core/canvas/node-outcome-deliveries.js +0 -159
  486. package/dist/core/feed/passive.d.ts +0 -3
  487. package/dist/core/feed/passive.js +0 -53
  488. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +0 -1
  489. package/dist/core/human/__tests__/inbox-cancel-worker.js +0 -7
  490. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +0 -1
  491. package/dist/core/human/__tests__/inbox-claim-worker.js +0 -17
  492. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +0 -1
  493. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +0 -8
  494. package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +0 -1
  495. package/dist/core/human/__tests__/integration/inbox-core.test.js +0 -145
  496. package/dist/core/human/__tests__/page-tickets.test.d.ts +0 -1
  497. package/dist/core/human/__tests__/page-tickets.test.js +0 -161
  498. package/dist/core/review/ticket-filter.d.ts +0 -17
  499. package/dist/core/review/ticket-filter.js +0 -21
  500. package/dist/core/runtime/broker/passive.d.ts +0 -17
  501. package/dist/core/runtime/broker/passive.js +0 -44
  502. package/dist/core/runtime/busy.d.ts +0 -46
  503. package/dist/core/runtime/busy.js +0 -150
  504. package/dist/daemon/__tests__/startup-block-marker.test.d.ts +0 -1
  505. package/dist/daemon/__tests__/startup-block-marker.test.js +0 -86
  506. package/dist/daemon/api/__tests__/review-terminal-conflict.test.d.ts +0 -1
  507. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +0 -98
  508. package/dist/daemon/human/deliver-action.d.ts +0 -3
  509. package/dist/daemon/human/deliver-action.js +0 -9
  510. package/dist/daemon/node-outcome/deliver-outcome.d.ts +0 -3
  511. package/dist/daemon/node-outcome/deliver-outcome.js +0 -9
  512. package/dist/daemon/reconcilers/human-delivery-lane.d.ts +0 -10
  513. package/dist/daemon/reconcilers/human-delivery-lane.js +0 -41
  514. package/dist/daemon/reconcilers/node-outcome-delivery-lane.d.ts +0 -10
  515. package/dist/daemon/reconcilers/node-outcome-delivery-lane.js +0 -41
  516. package/dist/daemon/startup-block-marker.d.ts +0 -25
  517. package/dist/daemon/startup-block-marker.js +0 -99
  518. /package/dist/{clients/attach/__tests__/page-block.test.d.ts → api/dto/mail.js} +0 -0
  519. /package/dist/{commands/sys/__tests__/migrate.test.d.ts → api/dto/recovery.js} +0 -0
  520. /package/dist/{core/__tests__/human-cancel-guard.test.d.ts → commands/__tests__/integration/migrate.test.d.ts} +0 -0
@@ -1,12 +1,7 @@
1
1
  import type { CanvasSource } from './source.js';
2
2
  import { type NodeRecap } from './node-recap.js';
3
- import { type Fault } from '../runtime/fault.js';
4
- import type { NodeStatus, Lifecycle, NodeMeta, NodeRow, TerminalReason } from './types.js';
5
- export declare function activeFaultForDisplay<T extends {
6
- status: NodeStatus;
7
- pi_pid?: number | null;
8
- }>(node: T, fault: Fault | null): Fault | null;
9
- export declare function hangingFor(node: NodeMeta): Fault | null;
3
+ import type { Fault } from '../runtime/fault.js';
4
+ import type { NodeStatus, Lifecycle, NodeRow, TerminalReason } from './types.js';
10
5
  export interface NodeTelemetry {
11
6
  tokens_in?: number;
12
7
  }
@@ -79,17 +74,17 @@ export interface DashboardRow {
79
74
  * updates as they work, so this is the last thing the node deliberately DELIVERED —
80
75
  * usually crisper than its last assistant message. */
81
76
  report?: NodeReportPreview;
82
- /** True when the node is GENUINELY mid-turn right now — its `busy` marker exists
83
- * AND its broker pid is alive (not merely an `active`, between-turns node). The
84
- * live "is it generating?" cue. Computed on the cheap boot path for LIVE nodes
85
- * only (dormant rows are always false). */
77
+ /** True when the node is GENUINELY mid-turn right now — the projected row's
78
+ * `streaming` (its live execution has an open turn AND its broker pid is alive),
79
+ * not merely an `active`, between-turns node. The live "is it generating?" cue,
80
+ * carried for LIVE nodes only (dormant rows are always false). */
86
81
  streaming?: boolean;
87
82
  /** Set when the node is parked on an active fault. The otherwise-invisible
88
83
  * "stuck, awaiting recovery" window. Mutually exclusive with `streaming`
89
- * (hanging means the turn ended, so `busy` is gone); when set,
90
- * dashboardRowsAll forces `streaming:false`. Computed on the cheap boot path
91
- * for every node, then suppressed only for stale daemon-owned provider faults
92
- * whose broker pid is gone. */
84
+ * (hanging means the turn ended, so no turn is open); when set,
85
+ * dashboardRowsAll forces `streaming:false`. The projected row field, already
86
+ * overlaid by the owning daemon (stale daemon-owned provider faults whose
87
+ * broker pid is gone are suppressed there). */
93
88
  hanging?: Fault | null;
94
89
  /** True when a viewer (focus row) is attached to the node — i.e. someone has it
95
90
  * open on screen. Set on the cheap boot path from one listFocuses() query. The
@@ -161,23 +156,17 @@ export declare function readTranscript(sessionFile: string | null | undefined):
161
156
  * — a tool-call-only turn (no final text) still counts. Drives reap-on-close/
162
157
  * detach. One file read with an early exit on the first substantive turn. */
163
158
  export declare function nodeHasAssistantMessage(sessionFile: string | null | undefined): boolean;
164
- /** Is the node GENUINELY mid-turn right now? The `busy` marker (touched on
165
- * agent_start, removed on agent_end) AND-ed with broker-pid liveness, so a stale
166
- * marker from a crashed pi reads false. This is the live "generating?" signal
167
- * — distinct from `status: 'active'`, which only means the engine never closed
168
- * (an active node is usually dormant between turns). Read directly off disk
169
- * (mirrors telemetry) to avoid inverting the canvas→runtime dependency. */
170
- export declare function isStreaming(nodeId: string, piPid: number | null | undefined): boolean;
171
159
  /** "Most recent activity" sort key (epoch ms) read CHEAPLY: a `statSync` (no file
172
160
  * read, no parse) of the node's job/telemetry.json — rewritten on every turn_end at
173
161
  * a deterministic canvas-home path, so it tracks last-message recency without a meta
174
162
  * read. Falls back to `created`'s epoch when a node never ran a turn (no telemetry).
175
163
  * Never throws. */
176
164
  export declare function sessionMtime(nodeId: string, created: string, remote?: boolean): number;
177
- /** Build one cheap-boot row from a raw db/source row. `remote` suppresses the
178
- * LOCAL disk reads (fault/streaming/telemetry-mtime/viewers) that are meaningless
179
- * for a truly remote canvas. A local row is viewed when either its tmux focus
180
- * row exists or its live broker reports a terminal/web viewer. */
165
+ /** Build one cheap-boot row from a raw db/source row. `fault`/`streaming` are
166
+ * projected row fields, so they hold for a remote row too; `remote` suppresses the
167
+ * LOCAL disk reads (telemetry-mtime/viewers) that are meaningless for a truly
168
+ * remote canvas. A local row is viewed when either its tmux focus row exists or
169
+ * its live broker reports a terminal/web viewer. */
181
170
  export declare function dashboardRowFromNodeRow(row: NodeRow, focusedNodeIds: ReadonlySet<string>, remote: boolean): DashboardRow;
182
171
  /** One row per node visible in the sub-DAG of `rootId` (including root), read
183
172
  * entirely through the source — the openDb-free sibling of `dashboardRows`.
@@ -188,7 +177,7 @@ export declare function dashboardRowsFromSource(source: CanvasSource, rootId: st
188
177
  * fields that need no per-node meta/session read. Local API callers may supply
189
178
  * the node ids from one `listFocuses()` query so `viewed` remains visible without
190
179
  * coupling the canvas source to local viewer state. Remote sources ignore that
191
- * set. Local disk telemetry/fault/streaming are likewise suppressed remotely. */
180
+ * set. Local disk telemetry is likewise suppressed remotely. */
192
181
  export declare function dashboardRowsAllFromSource(source: CanvasSource, localFocusedNodeIds?: ReadonlySet<string>, liveOnly?: boolean, snapshot?: readonly NodeRow[]): Promise<DashboardRow[]>;
193
182
  export declare function enrichRowsFromSource(_source: CanvasSource, rows: DashboardRow[], asks?: Record<string, number>): Promise<void>;
194
183
  /** goal (initial-prompt.md) and session parts are local disk reads — suppressed
@@ -8,8 +8,8 @@
8
8
  // in a separate `render.ts` re-export shim have been retired; their few real callers
9
9
  // migrated onto these `*FromSource` variants directly.
10
10
  //
11
- // ALLOWED imports (verified openDb-free): node:fs/path, ./pid.js, ./labels.js,
12
- // ./status-glyph.js, ./node-recap.js, ../runtime/fault.js, ../frontmatter.js,
11
+ // ALLOWED imports (verified openDb-free): node:fs/path, ./labels.js,
12
+ // ./status-glyph.js, ./node-recap.js, ../frontmatter.js,
13
13
  // ./paths.js, ./remote-canvas-source.js, and TYPE-ONLY ./source.js + ./types.js. Do NOT import ./canvas.js, ./attention.js,
14
14
  // ./focuses.js, or ./db.js here — that is the whole point of the split.
15
15
  import { existsSync, readFileSync, readdirSync, statSync, openSync, readSync, closeSync } from 'node:fs';
@@ -19,22 +19,8 @@ import { fullName } from './labels.js';
19
19
  import { jobDir, contextDir, reportsDir } from './paths.js';
20
20
  import { readNodeRecap } from './node-recap.js';
21
21
  import { parseFrontmatterGeneric } from '../frontmatter.js';
22
- import { isPidAlive, isPidPresent } from './pid.js';
23
22
  import { isFrozenRow, resolveNodeVisual, faultSummary } from './status-glyph.js';
24
- import { readFault } from '../runtime/fault.js';
25
23
  import { parseCard } from '../../shared/generated-context.js';
26
- // Active-fault overlay: stale daemon-owned provider faults are hidden once the
27
- // broker pid is gone; manual/client faults stay visible until cleared.
28
- export function activeFaultForDisplay(node, fault) {
29
- if (fault === null)
30
- return null;
31
- if (fault.link === 'pi→provider' && fault.retry.by === 'daemon' && fault.retry.disposition === 'auto' && !isPidAlive(node.pi_pid))
32
- return null;
33
- return fault;
34
- }
35
- export function hangingFor(node) {
36
- return activeFaultForDisplay(node, readFault(node.node_id));
37
- }
38
24
  export function readNodeTelemetry(nodeId) {
39
25
  const path = join(jobDir(nodeId), 'telemetry.json');
40
26
  if (!existsSync(path))
@@ -56,14 +42,14 @@ export function fmtCtx(tokensIn) {
56
42
  //
57
43
  // Ticket counts are threaded in as a `Record<node_id, count>` fetched ONCE per
58
44
  // render via `source.ticketCountsForView(root)` (the API/remote source's
59
- // attention projection) — never `countTickets()` (openDb). `ctx`/`hanging` are
60
- // LOCAL disk reads (telemetry.json / fault.json), valid for a same-host source
61
- // but meaningless for a truly remote canvas, so both are suppressed when the
62
- // source is a `RemoteCanvasSource`.
45
+ // attention projection) — never `countTickets()` (openDb). The active fault is a
46
+ // projected row field (the owning daemon already applied the stale-provider
47
+ // overlay), so it renders for a remote node too; `ctx` is a LOCAL telemetry.json
48
+ // read and stays suppressed when the source is a `RemoteCanvasSource`.
63
49
  function nodeLineFromSource(node, nodeId, indent, connector, remote, tickets) {
64
50
  if (node === undefined)
65
51
  return `${indent}${connector}? <missing meta: ${nodeId}>`;
66
- const hanging = remote ? null : hangingFor(node);
52
+ const hanging = node.fault ?? null;
67
53
  const glyph = resolveNodeVisual(node.status, { hanging, frozen: isFrozenRow(node) }).glyph;
68
54
  const ctx = remote ? '0k' : fmtCtx(readNodeTelemetry(nodeId).tokens_in);
69
55
  const asks = tickets[nodeId] ?? 0;
@@ -117,7 +103,7 @@ export async function renderTreeFromSource(source, rootId, snapshot, ticketSnaps
117
103
  const ctx = remote ? '0k' : fmtCtx(readNodeTelemetry(rootId).tokens_in);
118
104
  const asks = tickets[rootId] ?? 0;
119
105
  const askSuffix = asks > 0 ? ` ⚑${asks}` : '';
120
- const hanging = remote ? null : hangingFor(node);
106
+ const hanging = node.fault ?? null;
121
107
  const glyph = resolveNodeVisual(node.status, { hanging, frozen: isFrozenRow(node) }).glyph;
122
108
  const faultSuffix = hanging !== null ? ` · ${faultSummary(hanging)}` : '';
123
109
  const out = [];
@@ -467,22 +453,6 @@ function assistantContentIsSubstantive(content) {
467
453
  }
468
454
  return false;
469
455
  }
470
- /** Is the node GENUINELY mid-turn right now? The `busy` marker (touched on
471
- * agent_start, removed on agent_end) AND-ed with broker-pid liveness, so a stale
472
- * marker from a crashed pi reads false. This is the live "generating?" signal
473
- * — distinct from `status: 'active'`, which only means the engine never closed
474
- * (an active node is usually dormant between turns). Read directly off disk
475
- * (mirrors telemetry) to avoid inverting the canvas→runtime dependency. */
476
- export function isStreaming(nodeId, piPid) {
477
- if (!isPidPresent(piPid))
478
- return false;
479
- try {
480
- return existsSync(join(jobDir(nodeId), 'busy'));
481
- }
482
- catch {
483
- return false;
484
- }
485
- }
486
456
  /** Concatenate the `text` blocks of one pi user message's content. Content is
487
457
  * usually an array of `{type,text}` blocks but may be a bare string. */
488
458
  function extractUserText(content) {
@@ -530,13 +500,14 @@ function hasLiveBrokerViewer(row) {
530
500
  return false;
531
501
  }
532
502
  }
533
- /** Build one cheap-boot row from a raw db/source row. `remote` suppresses the
534
- * LOCAL disk reads (fault/streaming/telemetry-mtime/viewers) that are meaningless
535
- * for a truly remote canvas. A local row is viewed when either its tmux focus
536
- * row exists or its live broker reports a terminal/web viewer. */
503
+ /** Build one cheap-boot row from a raw db/source row. `fault`/`streaming` are
504
+ * projected row fields, so they hold for a remote row too; `remote` suppresses the
505
+ * LOCAL disk reads (telemetry-mtime/viewers) that are meaningless for a truly
506
+ * remote canvas. A local row is viewed when either its tmux focus row exists or
507
+ * its live broker reports a terminal/web viewer. */
537
508
  export function dashboardRowFromNodeRow(row, focusedNodeIds, remote) {
538
509
  const live = row.status === 'active' || row.status === 'idle';
539
- const hanging = remote ? null : activeFaultForDisplay(row, readFault(row.node_id));
510
+ const hanging = row.fault ?? null;
540
511
  return {
541
512
  node_id: row.node_id,
542
513
  name: fullName(row), // description is a row column (v38) — no meta read needed
@@ -555,7 +526,7 @@ export function dashboardRowFromNodeRow(row, focusedNodeIds, remote) {
555
526
  lifecycle: row.lifecycle,
556
527
  finalized: row.final_report != null,
557
528
  mtimeMs: sessionMtime(row.node_id, row.created, remote),
558
- streaming: !remote && hanging === null && live ? isStreaming(row.node_id, row.pi_pid) : false,
529
+ streaming: hanging === null && live && row.streaming === true,
559
530
  hanging,
560
531
  viewed: remote ? false : focusedNodeIds.has(row.node_id) || hasLiveBrokerViewer(row),
561
532
  srcRow: row,
@@ -597,7 +568,7 @@ export async function dashboardRowsFromSource(source, rootId, snapshot, ticketSn
597
568
  * fields that need no per-node meta/session read. Local API callers may supply
598
569
  * the node ids from one `listFocuses()` query so `viewed` remains visible without
599
570
  * coupling the canvas source to local viewer state. Remote sources ignore that
600
- * set. Local disk telemetry/fault/streaming are likewise suppressed remotely. */
571
+ * set. Local disk telemetry is likewise suppressed remotely. */
601
572
  export async function dashboardRowsAllFromSource(source, localFocusedNodeIds = new Set(), liveOnly = false, snapshot) {
602
573
  const remote = source instanceof RemoteCanvasSource;
603
574
  const focusedNodeIds = remote ? new Set() : localFocusedNodeIds;
@@ -0,0 +1,33 @@
1
+ export interface SessionBinding {
2
+ bindingId: string;
3
+ sessionId: string | null;
4
+ nodeId: string;
5
+ transcriptPath: string | null;
6
+ sourceSessionId: string | null;
7
+ forkEntryId: string | null;
8
+ createdAt: string;
9
+ boundAt: string;
10
+ unboundAt: string | null;
11
+ }
12
+ export declare function readLiveSession(nodeId: string): SessionBinding | null;
13
+ export declare function findNodeBySessionFileSql(path: string): string | null;
14
+ export declare function bindSession(nodeId: string, input: {
15
+ executionId: string;
16
+ sessionId: string | null;
17
+ transcriptPath: string | null;
18
+ sourceSessionId?: string | null;
19
+ }): 'bound' | 'shutdown';
20
+ export declare function resetSession(nodeId: string, input: {
21
+ sessionId: string;
22
+ transcriptPath: string | null;
23
+ }): void;
24
+ export declare function transferSession(input: {
25
+ fromNodeId: string;
26
+ fromBindingId: string;
27
+ toNodeId: string;
28
+ executionId: string;
29
+ sessionId: string | null;
30
+ transcriptPath: string | null;
31
+ }): 'transferred' | 'shutdown' | 'changed';
32
+ export declare function unbindSession(nodeId: string): void;
33
+ export declare function setCyclePending(nodeId: string, pending: boolean): void;
@@ -0,0 +1,78 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { openDb, withCanvasWrite } from './db.js';
3
+ import { canonicalSessionFile } from './canvas.js';
4
+ function now() {
5
+ return new Date().toISOString();
6
+ }
7
+ function liveExecution(db, nodeId, executionId) {
8
+ return db.prepare("SELECT 1 FROM executions WHERE execution_id = ? AND node_id = ? AND state != 'exited'").get(executionId, nodeId) !== undefined;
9
+ }
10
+ function hydrate(row) {
11
+ return {
12
+ bindingId: row['binding_id'],
13
+ sessionId: row['session_id'] ?? null,
14
+ nodeId: row['node_id'],
15
+ transcriptPath: row['transcript_path'] ?? null,
16
+ sourceSessionId: row['source_session_id'] ?? null,
17
+ forkEntryId: row['fork_entry_id'] ?? null,
18
+ createdAt: row['created_at'],
19
+ boundAt: row['bound_at'],
20
+ unboundAt: row['unbound_at'] ?? null,
21
+ };
22
+ }
23
+ export function readLiveSession(nodeId) {
24
+ const row = openDb().prepare('SELECT * FROM sessions WHERE node_id = ? AND unbound_at IS NULL').get(nodeId);
25
+ return row === undefined ? null : hydrate(row);
26
+ }
27
+ export function findNodeBySessionFileSql(path) {
28
+ const row = openDb().prepare('SELECT node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL').get(canonicalSessionFile(path));
29
+ return row?.node_id ?? null;
30
+ }
31
+ export function bindSession(nodeId, input) {
32
+ return withCanvasWrite((db) => {
33
+ if (!liveExecution(db, nodeId, input.executionId))
34
+ return 'shutdown';
35
+ const at = now();
36
+ const path = input.transcriptPath === null ? null : canonicalSessionFile(input.transcriptPath);
37
+ const current = db.prepare('SELECT binding_id, session_id FROM sessions WHERE node_id = ? AND unbound_at IS NULL').get(nodeId);
38
+ if (current !== undefined && current.session_id === input.sessionId) {
39
+ db.prepare('UPDATE sessions SET transcript_path = ?, source_session_id = ?, bound_at = ? WHERE binding_id = ?').run(path, input.sourceSessionId ?? null, at, current.binding_id);
40
+ }
41
+ else {
42
+ if (current !== undefined)
43
+ db.prepare('UPDATE sessions SET unbound_at = ? WHERE binding_id = ?').run(at, current.binding_id);
44
+ db.prepare('INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, ?, NULL, ?, ?)').run(randomUUID(), input.sessionId, nodeId, path, input.sourceSessionId ?? null, at, at);
45
+ }
46
+ db.prepare('UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?').run(nodeId);
47
+ return 'bound';
48
+ });
49
+ }
50
+ export function resetSession(nodeId, input) {
51
+ withCanvasWrite((db) => {
52
+ const at = now();
53
+ db.prepare('UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL').run(at, nodeId);
54
+ db.prepare('INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?)').run(randomUUID(), input.sessionId, nodeId, input.transcriptPath === null ? null : canonicalSessionFile(input.transcriptPath), at, at);
55
+ db.prepare('UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?').run(nodeId);
56
+ });
57
+ }
58
+ export function transferSession(input) {
59
+ return withCanvasWrite((db) => {
60
+ if (!liveExecution(db, input.toNodeId, input.executionId))
61
+ return 'shutdown';
62
+ const source = db.prepare('SELECT binding_id FROM sessions WHERE node_id = ? AND binding_id = ? AND unbound_at IS NULL').get(input.fromNodeId, input.fromBindingId);
63
+ if (source === undefined)
64
+ return 'changed';
65
+ const at = now();
66
+ db.prepare('UPDATE sessions SET unbound_at = ? WHERE binding_id = ?').run(at, input.fromBindingId);
67
+ db.prepare('UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL').run(at, input.toNodeId);
68
+ db.prepare('INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?)').run(randomUUID(), input.sessionId, input.toNodeId, input.transcriptPath === null ? null : canonicalSessionFile(input.transcriptPath), at, at);
69
+ db.prepare('UPDATE nodes SET cycle_pending = 0 WHERE node_id = ?').run(input.toNodeId);
70
+ return 'transferred';
71
+ });
72
+ }
73
+ export function unbindSession(nodeId) {
74
+ openDb().prepare('UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL').run(now(), nodeId);
75
+ }
76
+ export function setCyclePending(nodeId, pending) {
77
+ openDb().prepare('UPDATE nodes SET cycle_pending = ? WHERE node_id = ?').run(pending ? 1 : 0, nodeId);
78
+ }
@@ -166,11 +166,8 @@ export interface ReviewBinding {
166
166
  branch_file: string;
167
167
  target_file: string;
168
168
  }
169
- /** A node's DURABLE IDENTITY — the subset that `meta.json` persists on disk.
170
- * Written rarely (birth, polymorph, session-id capture, naming); never touched
171
- * by a status flip, an intent change, a focus swap, or a pid stamp. The db row
172
- * indexes the queryable identity columns; `rebuildIndex()` re-derives them from
173
- * here. (Live runtime state lives in NodeRuntime, authoritative in the row.) */
169
+ /** A node's durable configuration, stored in SQL node columns. Sessions and
170
+ * managed worktrees have their own SQL stores. */
174
171
  export interface NodeIdentity {
175
172
  node_id: string;
176
173
  name: string;
@@ -197,17 +194,13 @@ export interface NodeIdentity {
197
194
  /** The dir this node is pinned to — its cwd (where pi runs, bash executes). */
198
195
  cwd: string;
199
196
  /** Which HOST launches + supervises this node: 'tmux' (a pane) or 'broker' (the
200
- * headless in-process engine). Durable IDENTITY (mirrored to the row like
201
- * `cwd`, re-derived on index rebuild), NOT live runtime like `pane`.
202
- * NULL ⇒ 'tmux' (every pre-broker node). */
197
+ * headless in-process engine). NULL ⇒ 'tmux' (every pre-broker node). */
203
198
  host_kind?: 'tmux' | 'broker' | null;
204
199
  /** The profile this node runs under, a stable profile-directory id
205
- * (`<slug>-<id>`, see `core/profiles/manifest.ts`). Durable IDENTITY mirrored
206
- * to the row (like `cwd`/`host_kind`), NOT re-derived by `rebuildIndex()` —
207
- * it is chosen once at spawn (inherited from the spawner, or `--profile`) and
208
- * is the runtime→resolver seam (`CRTR_PROFILE_ID`) the memory/gate substrate
209
- * reads. NULL only for historical root/no-profile rows; new root conversations
210
- * use the stable root profile id. */
200
+ * (`<slug>-<id>`, see `core/profiles/manifest.ts`). It is chosen once at spawn
201
+ * (inherited from the spawner, or `--profile`) and is the runtime→resolver seam
202
+ * (`CRTR_PROFILE_ID`) the memory/gate substrate reads. NULL only for historical
203
+ * root/no-profile rows; new root conversations use the stable root profile id. */
211
204
  profile_id?: string | null;
212
205
  /** Role the node was born as: explore | developer | plan | review | general… */
213
206
  kind: string;
@@ -269,12 +262,10 @@ export interface NodeIdentity {
269
262
  /** Managed git worktree owned by this node (if any). */
270
263
  managed_worktree?: ManagedWorktree | null;
271
264
  }
272
- /** A node's LIVE RUNTIME state — authoritative in the WAL'd `nodes` row, each
273
- * field mutated by exactly one atomic single-statement `UPDATE` (setStatus /
274
- * setIntent / setPresence / recordPid+clearPid). NOT persisted to meta.json and
275
- * NOT re-derivable by `rebuildIndex()` — it describes live process/presence
276
- * state that is meaningless after the event that would lose the db; the daemon
277
- * reconciles it from tmux reality, not from a stale file. */
265
+ /** A node's live runtime state, stored in the WAL-backed `nodes` row. Each
266
+ * field is mutated by an atomic single-statement `UPDATE` (setStatus / setIntent /
267
+ * setPresence / recordPid+clearPid). The daemon reconciles process and presence
268
+ * state from tmux and broker reality. */
278
269
  export interface NodeRuntime {
279
270
  /** What the node is doing right now. */
280
271
  status: NodeStatus;
@@ -335,26 +326,31 @@ export interface NodeRuntime {
335
326
  * in the row exactly like `window`/`tmux_session` — a RUNTIME field, NOT meta
336
327
  * identity — written by the one atomic `setPresence` UPDATE. */
337
328
  pane?: string | null;
329
+ /** Active fault projected from SQL recovery state; stale daemon provider faults are suppressed. */
330
+ fault?: import('../fault-classifier.js').Fault | null;
331
+ /** True only while the live execution has an open turn and its PID is alive. */
332
+ streaming?: boolean;
338
333
  }
339
- /** The hydrated node view `getNode()` returns: durable identity (from meta.json)
340
- * ∪ live runtime (from the row). Keeps the historical `NodeMeta` name and field
341
- * set so every `meta.X` read across the codebase typechecks unchanged — but
342
- * `writeMeta` serializes only the NodeIdentity subset and the runtime fields are
343
- * hydrated from the authoritative row. */
334
+ /** The hydrated node view `getNode()` returns: durable configuration and live
335
+ * runtime from SQL, with session and worktree state from their named stores.
336
+ * It retains the historical `NodeMeta` name for existing callers. */
344
337
  export type NodeMeta = NodeIdentity & NodeRuntime;
345
- /** The queryable projection of a node stored as a canvas.db row: the indexed
346
- * identity columns PLUS the authoritative runtime columns. */
338
+ /** The queryable projection of a node's SQL configuration and runtime state. */
339
+ /** The SQL fields corpus discovery needs to resolve a node memory store. */
340
+ export interface NodeMemoryTarget {
341
+ nodeId: string;
342
+ cwd: string;
343
+ profileId: string | null;
344
+ }
347
345
  export interface NodeRow {
348
346
  node_id: string;
349
347
  name: string;
350
348
  /** The pi-generated first-task description; see NodeIdentity.description.
351
- * Durable IDENTITY mirrored to the row (like `cwd`/`host_kind`) so a roster
352
- * read can build the full display label without opening meta.json. Absent for
353
- * a node not yet named — the column's NULL is mapped to undefined at `rowFrom`
354
- * so identity, row, and DTO all spell "unnamed" the same way. */
349
+ * Absent for a node not yet named — the column's NULL is mapped to undefined
350
+ * at `rowFrom` so identity, row, and DTO all spell "unnamed" the same way. */
355
351
  description?: string;
356
- /** Relaunch count; see NodeIdentity.cycles. Mirrored to the row for the same
357
- * reason as `description`; absent on a row written before this column. */
352
+ /** Relaunch count; see NodeIdentity.cycles. Absent on a row written before
353
+ * this column. */
358
354
  cycles?: number;
359
355
  kind: string;
360
356
  mode: Mode;
@@ -392,6 +388,10 @@ export interface NodeRow {
392
388
  tmux_session: string | null;
393
389
  /** The durable LOCATION handle (the tmux `%pane_id`); see NodeRuntime.pane. */
394
390
  pane: string | null;
391
+ /** Active fault projected from SQL recovery state; stale daemon provider faults are suppressed. */
392
+ fault?: import('../fault-classifier.js').Fault | null;
393
+ /** True only while the live execution has an open turn and its PID is alive. */
394
+ streaming?: boolean;
395
395
  }
396
396
  /** An edge as stored. For `subscribes_to`, `from` is the subscriber and `to`
397
397
  * is the publisher (A subscribes_to B ⇒ A receives B's output). For
@@ -1,9 +1,6 @@
1
1
  // The canvas vocabulary — the node + edge model the whole runtime hangs on.
2
2
  //
3
- // One global canvas (`~/.crouter/canvas/canvas.db`) holds the topology (nodes +
4
- // edges); each node's flesh lives on disk under `~/.crouter/canvas/nodes/<id>/`. A node's
5
- // `meta.json` is the source of truth for its own row; the db is a queryable
6
- // index over those metas, plus the authoritative store for the mutable
7
- // `subscribes_to` edges (which no single meta owns).
3
+ // One global canvas (`~/.crouter/canvas/canvas.db`) holds the node graph and
4
+ // runtime state. Each node directory holds only its artifacts.
8
5
  /** Maximum serialized opaque action payload; enforced at registration in Phase 5. */
9
6
  export const OUTCOME_PAYLOAD_MAX_BYTES = 64 * 1024;
@@ -0,0 +1,18 @@
1
+ export interface ControllerWait {
2
+ waitId: string;
3
+ nodeId: string;
4
+ controllerId: string;
5
+ generation: number;
6
+ createdAt: number;
7
+ satisfiedAt: number | null;
8
+ }
9
+ /** Replace a node's live controller wait while retaining the prior row as history. */
10
+ export declare function armControllerWait(nodeId: string, controllerId: string, now?: number): ControllerWait;
11
+ export declare function readControllerWait(nodeId: string): ControllerWait | null;
12
+ /** Clear only the wait that was observed for this sender; a rearm wins a race. */
13
+ export declare function settleMatchingControllerWait(nodeId: string, senderId: string | null, now: number, db?: import("node:sqlite").DatabaseSync): boolean;
14
+ /** Clear a matching wait only if its controller is no longer active or idle. */
15
+ export declare function settleDeadControllerWait(nodeId: string, controllerId: string, now: number, db?: import("node:sqlite").DatabaseSync): boolean;
16
+ /** Live rows drive controller-death reconciliation without relying on the retired node columns. */
17
+ export declare function liveControllerWaits(): ControllerWait[];
18
+ export declare function hasLiveControllerWait(nodeId: string): boolean;
@@ -0,0 +1,70 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { openDb, withCanvasWrite } from './db.js';
3
+ function waitFrom(row) {
4
+ return {
5
+ waitId: row.wait_id,
6
+ nodeId: row.node_id,
7
+ controllerId: row.target_id,
8
+ generation: row.generation,
9
+ createdAt: row.created_at,
10
+ satisfiedAt: row.satisfied_at,
11
+ };
12
+ }
13
+ function newWaitId() {
14
+ let id;
15
+ do
16
+ id = randomBytes(16).toString('hex');
17
+ while (id === '00000000000000000000000000000000');
18
+ return id;
19
+ }
20
+ /** Replace a node's live controller wait while retaining the prior row as history. */
21
+ export function armControllerWait(nodeId, controllerId, now = Date.now()) {
22
+ return withCanvasWrite((db) => {
23
+ db.prepare('UPDATE waits SET satisfied_at = ? WHERE node_id = ? AND satisfied_at IS NULL').run(now, nodeId);
24
+ const generation = Number(db.prepare('SELECT COALESCE(MAX(generation), 0) AS generation FROM waits WHERE node_id = ?').get(nodeId).generation) + 1;
25
+ const wait = {
26
+ wait_id: newWaitId(),
27
+ node_id: nodeId,
28
+ kind: 'controller',
29
+ target_id: controllerId,
30
+ generation,
31
+ created_at: now,
32
+ satisfied_at: null,
33
+ };
34
+ db.prepare(`INSERT INTO waits (wait_id, node_id, kind, target_id, generation, created_at, satisfied_at)
35
+ VALUES (?, ?, 'controller', ?, ?, ?, NULL)`).run(wait.wait_id, wait.node_id, wait.target_id, wait.generation, wait.created_at);
36
+ return waitFrom(wait);
37
+ });
38
+ }
39
+ export function readControllerWait(nodeId) {
40
+ const row = openDb().prepare("SELECT * FROM waits WHERE node_id = ? AND kind = 'controller' AND satisfied_at IS NULL").get(nodeId);
41
+ return row === undefined ? null : waitFrom(row);
42
+ }
43
+ /** Clear only the wait that was observed for this sender; a rearm wins a race. */
44
+ export function settleMatchingControllerWait(nodeId, senderId, now, db = openDb()) {
45
+ if (senderId === null)
46
+ return false;
47
+ const row = db.prepare("SELECT wait_id, generation FROM waits WHERE node_id = ? AND kind = 'controller' AND target_id = ? AND satisfied_at IS NULL").get(nodeId, senderId);
48
+ if (row === undefined)
49
+ return false;
50
+ return Number(db.prepare('UPDATE waits SET satisfied_at = ? WHERE wait_id = ? AND generation = ? AND satisfied_at IS NULL').run(now, row.wait_id, row.generation).changes) === 1;
51
+ }
52
+ /** Clear a matching wait only if its controller is no longer active or idle. */
53
+ export function settleDeadControllerWait(nodeId, controllerId, now, db = openDb()) {
54
+ const row = db.prepare(`SELECT w.wait_id, w.generation, target.status AS controller_status
55
+ FROM waits w LEFT JOIN nodes target ON target.node_id = w.target_id
56
+ WHERE w.node_id = ? AND w.kind = 'controller' AND w.target_id = ? AND w.satisfied_at IS NULL`).get(nodeId, controllerId);
57
+ if (row === undefined || row.controller_status === 'active' || row.controller_status === 'idle')
58
+ return false;
59
+ return Number(db.prepare('UPDATE waits SET satisfied_at = ? WHERE wait_id = ? AND generation = ? AND satisfied_at IS NULL').run(now, row.wait_id, row.generation).changes) === 1;
60
+ }
61
+ /** Live rows drive controller-death reconciliation without relying on the retired node columns. */
62
+ export function liveControllerWaits() {
63
+ return openDb().prepare("SELECT * FROM waits WHERE kind = 'controller' AND satisfied_at IS NULL").all().map(waitFrom);
64
+ }
65
+ export function hasLiveControllerWait(nodeId) {
66
+ const row = openDb().prepare(`SELECT 1 FROM waits w JOIN nodes target ON target.node_id = w.target_id
67
+ WHERE w.node_id = ? AND w.kind = 'controller' AND w.satisfied_at IS NULL
68
+ AND target.status IN ('active', 'idle') LIMIT 1`).get(nodeId);
69
+ return row !== undefined;
70
+ }
@@ -0,0 +1,40 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import type { ManagedWorktree, ManagedWorktreeObservation } from './types.js';
3
+ export declare function readWorktree(nodeId: string): ManagedWorktree | null;
4
+ export declare function openWorktree(nodeId: string, worktree: ManagedWorktree, db?: DatabaseSync): void;
5
+ export declare function closeWorktree(nodeId: string, input: {
6
+ cleanup: 'pending' | 'complete';
7
+ closedAt: string;
8
+ }): void;
9
+ /** Complete a worktree close and repoint the node in the same SQL transaction.
10
+ * A close invalidates the active transcript because Pi remains in the old
11
+ * checkout; the next launch starts from the durable base checkout. */
12
+ export declare function closeWorktreeAndRepoint(nodeId: string, input: {
13
+ cwd: string;
14
+ cleanup: 'pending' | 'complete';
15
+ closedAt: string;
16
+ unbindSession: boolean;
17
+ }): void;
18
+ export declare function abandonWorktree(nodeId: string, abandoned: NonNullable<ManagedWorktree['abandoned']>): void;
19
+ export declare function abandonWorktreeAndRepoint(nodeId: string, input: {
20
+ cwd: string;
21
+ abandoned: NonNullable<ManagedWorktree['abandoned']>;
22
+ }): void;
23
+ export declare function recordLandIntent(nodeId: string, intent: NonNullable<ManagedWorktree['land_intent']>): void;
24
+ export declare function recordDisposalGrant(nodeId: string, disposal: NonNullable<ManagedWorktree['disposal']>): void;
25
+ export declare function recordSweepAttempt(nodeId: string, input: {
26
+ reason: string;
27
+ detail?: string;
28
+ observed: ManagedWorktreeObservation;
29
+ attempts: number;
30
+ lastAttemptAt: string;
31
+ nextAttemptAt: string;
32
+ quarantined: boolean;
33
+ }): void;
34
+ export declare function completeCleanup(nodeId: string): void;
35
+ export declare function hasUnreconciledWorktree(nodeId: string): boolean;
36
+ export declare function sweepCandidates(now: string): string[];
37
+ export declare function quarantinedWorktrees(): Array<{
38
+ nodeId: string;
39
+ worktree: ManagedWorktree;
40
+ }>;