@north-light/crouter 0.3.353 → 0.3.355

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 (626) hide show
  1. package/dist/api/client.d.ts +35 -25
  2. package/dist/api/client.js +2 -2
  3. package/dist/api/dto/broker-ops.d.ts +2 -36
  4. package/dist/api/dto/canvas.d.ts +8 -13
  5. package/dist/api/dto/config.d.ts +4 -0
  6. package/dist/api/dto/delivery.d.ts +61 -0
  7. package/dist/api/dto/docs.d.ts +135 -0
  8. package/dist/api/dto/docs.js +1 -0
  9. package/dist/api/dto/health.d.ts +26 -79
  10. package/dist/api/dto/node-outcomes.d.ts +1 -3
  11. package/dist/api/dto/nodes.d.ts +5 -26
  12. package/dist/api/dto/objects.d.ts +168 -0
  13. package/dist/api/dto/objects.js +1 -0
  14. package/dist/api/dto/profiles.d.ts +14 -8
  15. package/dist/api/dto/reports.d.ts +9 -7
  16. package/dist/api/dto/reviews.d.ts +11 -3
  17. package/dist/api/dto/worktree.d.ts +1 -1
  18. package/dist/api/index.d.ts +0 -1
  19. package/dist/api/index.js +1 -1
  20. package/dist/api/routes.d.ts +14 -12
  21. package/dist/api/routes.js +1 -1
  22. package/dist/build-root.js +1 -1
  23. package/dist/builtin-memory/00-runtime-base/00-authoring.md +10 -5
  24. package/dist/builtin-memory/02-turn-lifecycle/02-resident.md +1 -0
  25. package/dist/builtin-memory/04-orchestration-kernel.md +10 -31
  26. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +1 -1
  27. package/dist/builtin-memory/05-kinds/explore/00-base.md +2 -2
  28. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +2 -2
  29. package/dist/builtin-memory/crouter-concepts/INDEX.md +2 -2
  30. package/dist/builtin-memory/crouter-concepts/lifecycle-and-wakes.md +1 -1
  31. package/dist/builtin-memory/crouter-concepts/memory.md +15 -15
  32. package/dist/builtin-memory/crouter-concepts/nodes-and-the-canvas.md +1 -1
  33. package/dist/builtin-memory/crouter-concepts/profiles-kinds-and-modes.md +5 -5
  34. package/dist/builtin-memory/crouter-concepts/scopes-and-trust.md +1 -1
  35. package/dist/builtin-memory/crouter-concepts/why-a-daemon.md +1 -1
  36. package/dist/builtin-memory/crouter-sdk/INDEX.md +2 -2
  37. package/dist/builtin-memory/crouter-sdk/README.md +5 -6
  38. package/dist/builtin-memory/crouter-sdk/errors.md +0 -13
  39. package/dist/builtin-memory/crouter-sdk/guides/README.md +0 -1
  40. package/dist/builtin-memory/crouter-sdk/guides/event-driven-assistant.md +2 -2
  41. package/dist/builtin-memory/crouter-sdk/nodes.md +0 -2
  42. package/dist/builtin-memory/crouter-sdk/resources.md +0 -1
  43. package/dist/builtin-memory/explore/exploration-doc.md +4 -4
  44. package/dist/builtin-memory/insights/capture.md +6 -6
  45. package/dist/builtin-memory/insights/init.md +14 -14
  46. package/dist/builtin-memory/internal/INDEX.md +4 -4
  47. package/dist/builtin-memory/internal/agent-shaping.md +20 -20
  48. package/dist/builtin-memory/internal/examples/imessage-assistant.md +2 -2
  49. package/dist/builtin-memory/internal/marketplaces.md +2 -2
  50. package/dist/builtin-memory/internal/memory-loading.md +31 -30
  51. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  52. package/dist/builtin-memory/internal/plugins.md +16 -14
  53. package/dist/builtin-memory/internal/storage-tiers.md +4 -4
  54. package/dist/builtin-memory/memory-read-orientation.md +1 -1
  55. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +32 -40
  56. package/dist/clients/attach/input/controller.js +1 -1
  57. package/dist/clients/attach/input/ref-autocomplete.js +1 -1
  58. package/dist/clients/attach/input/titled-editor.js +1 -1
  59. package/dist/clients/attach/overlays/file-review.d.ts +1 -0
  60. package/dist/clients/attach/overlays/file-review.js +2 -2
  61. package/dist/clients/attach/render/chat-view.d.ts +6 -0
  62. package/dist/clients/attach/render/chat-view.js +2 -2
  63. package/dist/clients/attach/render/crtr-output.d.ts +1 -2
  64. package/dist/clients/attach/render/crtr-output.js +17 -17
  65. package/dist/clients/attach/render/doc-links.d.ts +34 -0
  66. package/dist/clients/attach/render/doc-links.js +1 -0
  67. package/dist/clients/attach/render/group-activity.d.ts +8 -8
  68. package/dist/clients/attach/render/group-activity.js +2 -2
  69. package/dist/clients/attach/render/group-recap.js +1 -1
  70. package/dist/clients/attach/render/markdown-source.js +5 -5
  71. package/dist/clients/attach/render/tool-calls.d.ts +1 -1
  72. package/dist/clients/attach/session/doc-materialize.d.ts +53 -0
  73. package/dist/clients/attach/session/doc-materialize.js +3 -0
  74. package/dist/clients/attach/session/document-links.d.ts +21 -0
  75. package/dist/clients/attach/session/document-links.js +1 -0
  76. package/dist/clients/attach/session/file-links.d.ts +2 -0
  77. package/dist/clients/attach/session/file-links.js +1 -1
  78. package/dist/clients/attach/session/profile-files.js +1 -1
  79. package/dist/clients/attach/slash/dispatch.js +1 -1
  80. package/dist/clients/attach/viewer.js +816 -1561
  81. package/dist/clients/inbox/review/review-client.d.ts +5 -1
  82. package/dist/clients/inbox/review/review-client.js +1 -1
  83. package/dist/commands/api-client.d.ts +2 -0
  84. package/dist/commands/api-client.js +3 -3
  85. package/dist/commands/canvas/edges.d.ts +2 -0
  86. package/dist/commands/canvas/edges.js +2 -0
  87. package/dist/commands/canvas/list.d.ts +4 -0
  88. package/dist/commands/canvas/list.js +3 -0
  89. package/dist/commands/canvas/read.d.ts +8 -0
  90. package/dist/commands/canvas/read.js +5 -0
  91. package/dist/commands/canvas/search.d.ts +2 -0
  92. package/dist/commands/canvas/search.js +3 -0
  93. package/dist/commands/canvas/unwatch.d.ts +2 -0
  94. package/dist/commands/canvas/unwatch.js +1 -0
  95. package/dist/commands/canvas/watch.d.ts +3 -0
  96. package/dist/commands/canvas/watch.js +1 -0
  97. package/dist/commands/canvas-analytics.js +1 -1
  98. package/dist/commands/canvas-history/grep.js +4 -4
  99. package/dist/commands/canvas-history/read.js +2 -2
  100. package/dist/commands/canvas-history/search.js +7 -7
  101. package/dist/commands/canvas-history/shared.d.ts +0 -1
  102. package/dist/commands/canvas-history/shared.js +1 -1
  103. package/dist/commands/canvas-history/stats.js +2 -2
  104. package/dist/commands/canvas-history.js +1 -1
  105. package/dist/commands/canvas.js +1 -1
  106. package/dist/commands/doc/delete.d.ts +2 -0
  107. package/dist/commands/doc/delete.js +1 -0
  108. package/dist/commands/doc/edit.d.ts +2 -0
  109. package/dist/commands/doc/edit.js +1 -0
  110. package/dist/commands/doc/history.d.ts +2 -0
  111. package/dist/commands/doc/history.js +2 -0
  112. package/dist/commands/doc/lint.d.ts +2 -0
  113. package/dist/commands/doc/lint.js +2 -0
  114. package/dist/commands/doc/list.d.ts +2 -0
  115. package/dist/commands/doc/list.js +1 -0
  116. package/dist/commands/doc/move.d.ts +2 -0
  117. package/dist/commands/doc/move.js +1 -0
  118. package/dist/commands/doc/read.d.ts +2 -0
  119. package/dist/commands/doc/read.js +1 -0
  120. package/dist/commands/doc/shared.d.ts +25 -0
  121. package/dist/commands/doc/shared.js +2 -0
  122. package/dist/commands/doc/write.d.ts +2 -0
  123. package/dist/commands/doc/write.js +1 -0
  124. package/dist/commands/{memory.d.ts → doc.d.ts} +1 -1
  125. package/dist/commands/doc.js +1 -0
  126. package/dist/commands/human/review.js +1 -1
  127. package/dist/commands/node/bash.js +2 -2
  128. package/dist/commands/node/create.js +1 -1
  129. package/dist/commands/node/inspect.js +10 -10
  130. package/dist/commands/node/lifecycle.js +2 -2
  131. package/dist/commands/node/outcome.js +1 -1
  132. package/dist/commands/node/subscription.js +1 -1
  133. package/dist/commands/node-context.js +2 -2
  134. package/dist/commands/pkg/browse/catalog.js +1 -1
  135. package/dist/commands/pkg/browse/doc-view.js +1 -1
  136. package/dist/commands/pkg/browse/model.d.ts +9 -17
  137. package/dist/commands/pkg/plugin-inspect.js +1 -1
  138. package/dist/commands/pkg/plugin-manage.d.ts +4 -8
  139. package/dist/commands/pkg/plugin-manage.js +15 -17
  140. package/dist/commands/profile/list.js +1 -1
  141. package/dist/commands/profile/new.js +1 -1
  142. package/dist/commands/profile/project.js +1 -1
  143. package/dist/commands/profile/show.js +1 -1
  144. package/dist/commands/push.js +3 -3
  145. package/dist/commands/sys/config.js +1 -1
  146. package/dist/commands/sys/context/admin/actions.d.ts +18 -43
  147. package/dist/commands/sys/context/admin/actions.js +1 -2
  148. package/dist/commands/sys/context/admin/detail-panel.d.ts +17 -25
  149. package/dist/commands/sys/context/admin/detail-panel.js +2 -1
  150. package/dist/commands/sys/context/admin/docs-panel.d.ts +7 -6
  151. package/dist/commands/sys/context/admin/docs-panel.js +1 -1
  152. package/dist/commands/sys/context/admin/list-view.d.ts +12 -12
  153. package/dist/commands/sys/context/admin/list-view.js +1 -1
  154. package/dist/commands/sys/context/admin/model.d.ts +96 -69
  155. package/dist/commands/sys/context/admin/model.js +1 -1
  156. package/dist/commands/sys/context/admin/rail-panel.d.ts +7 -5
  157. package/dist/commands/sys/context/admin/rail-panel.js +1 -1
  158. package/dist/commands/sys/context/admin/read-view.d.ts +10 -14
  159. package/dist/commands/sys/context/admin/read-view.js +1 -2
  160. package/dist/commands/sys/context/admin/shell.d.ts +26 -31
  161. package/dist/commands/sys/context/admin/shell.js +1 -1
  162. package/dist/commands/sys/context/admin.js +2 -2
  163. package/dist/commands/sys/context/doc.js +2 -3
  164. package/dist/commands/sys/context/expose.js +2 -2
  165. package/dist/commands/sys/context/prompt-review.js +4 -4
  166. package/dist/commands/sys/context/resolve.d.ts +92 -65
  167. package/dist/commands/sys/context/resolve.js +7 -9
  168. package/dist/commands/sys/context.js +1 -1
  169. package/dist/commands/sys/doctor.js +1 -1
  170. package/dist/commands/sys/migrate.js +1 -1
  171. package/dist/commands/sys/panels/profiles-panel.d.ts +3 -1
  172. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  173. package/dist/commands/sys/sync-deps.d.ts +6 -11
  174. package/dist/commands/sys/sync-deps.js +7 -8
  175. package/dist/commands/sys/sync-project-guidance.js +5 -4
  176. package/dist/commands/sys/sync-shared.d.ts +41 -4
  177. package/dist/commands/sys/sync-shared.js +1 -1
  178. package/dist/commands/sys/sync-skills.js +2 -2
  179. package/dist/commands/sys/sync.js +1 -1
  180. package/dist/core/bash-job-supervisor.d.ts +2 -3
  181. package/dist/core/bash-job-supervisor.js +3 -3
  182. package/dist/core/bash-jobs.d.ts +0 -5
  183. package/dist/core/bash-jobs.js +7 -7
  184. package/dist/core/bootstrap.js +2 -2
  185. package/dist/core/canvas/canvas.d.ts +6 -50
  186. package/dist/core/canvas/canvas.js +16 -21
  187. package/dist/core/canvas/db.d.ts +4 -1
  188. package/dist/core/canvas/db.js +2 -2
  189. package/dist/core/canvas/history.d.ts +11 -39
  190. package/dist/core/canvas/history.js +9 -20
  191. package/dist/core/canvas/install-id.d.ts +2 -2
  192. package/dist/core/canvas/install-id.js +1 -1
  193. package/dist/core/canvas/memory-reads.d.ts +5 -0
  194. package/dist/core/canvas/memory-reads.js +1 -1
  195. package/dist/core/canvas/migrations.js +215 -41
  196. package/dist/core/canvas/node-agent-paths.js +1 -1
  197. package/dist/core/canvas/node-tokens.js +1 -1
  198. package/dist/core/canvas/paths.d.ts +0 -4
  199. package/dist/core/canvas/paths.js +1 -1
  200. package/dist/core/canvas/remote-canvas-source.d.ts +0 -1
  201. package/dist/core/canvas/remote-canvas-source.js +1 -1
  202. package/dist/core/canvas/render-source.d.ts +9 -6
  203. package/dist/core/canvas/render-source.js +6 -6
  204. package/dist/core/canvas/sessions.js +2 -2
  205. package/dist/core/canvas/source.d.ts +6 -0
  206. package/dist/core/canvas/tree.d.ts +29 -0
  207. package/dist/core/canvas/tree.js +12 -0
  208. package/dist/core/canvas/types.d.ts +0 -20
  209. package/dist/core/command-plugins/bundle.js +1 -1
  210. package/dist/core/config.d.ts +1 -1
  211. package/dist/core/conversation-store/listener.js +4 -2
  212. package/dist/core/feed/feed.d.ts +9 -7
  213. package/dist/core/feed/feed.js +3 -7
  214. package/dist/core/feed/inbox.d.ts +3 -5
  215. package/dist/core/feed/inbox.js +1 -10
  216. package/dist/core/feed/messages.d.ts +33 -6
  217. package/dist/core/feed/messages.js +10 -7
  218. package/dist/core/feed/reports.d.ts +10 -0
  219. package/dist/core/feed/reports.js +2 -0
  220. package/dist/core/grants/remove.js +1 -1
  221. package/dist/core/graph/access.d.ts +24 -0
  222. package/dist/core/graph/access.js +8 -0
  223. package/dist/core/graph/bodies.d.ts +6 -0
  224. package/dist/core/graph/bodies.js +1 -0
  225. package/dist/core/graph/deletion.d.ts +10 -0
  226. package/dist/core/graph/deletion.js +5 -0
  227. package/dist/core/graph/diff.d.ts +4 -0
  228. package/dist/core/graph/diff.js +4 -0
  229. package/dist/core/graph/documents.d.ts +167 -0
  230. package/dist/core/graph/documents.js +10 -0
  231. package/dist/core/graph/edges.d.ts +25 -0
  232. package/dist/core/graph/edges.js +1 -0
  233. package/dist/core/graph/events.d.ts +26 -0
  234. package/dist/core/graph/events.js +7 -0
  235. package/dist/core/graph/exposures.d.ts +53 -0
  236. package/dist/core/graph/exposures.js +4 -0
  237. package/dist/core/graph/jobs.d.ts +31 -0
  238. package/dist/core/graph/jobs.js +2 -0
  239. package/dist/core/graph/names.d.ts +30 -0
  240. package/dist/core/graph/names.js +3 -0
  241. package/dist/core/graph/objects.d.ts +55 -0
  242. package/dist/core/graph/objects.js +9 -0
  243. package/dist/core/graph/package-docs.d.ts +31 -0
  244. package/dist/core/graph/package-docs.js +5 -0
  245. package/dist/core/graph/package-files.d.ts +20 -0
  246. package/dist/core/graph/package-files.js +2 -0
  247. package/dist/core/graph/reader.d.ts +21 -0
  248. package/dist/core/graph/reader.js +3 -0
  249. package/dist/core/graph/repo-sync/exchange.d.ts +34 -0
  250. package/dist/core/graph/repo-sync/exchange.js +2 -0
  251. package/dist/core/graph/repo-sync/identity.d.ts +30 -0
  252. package/dist/core/graph/repo-sync/identity.js +1 -0
  253. package/dist/core/graph/repo-sync/index.d.ts +4 -0
  254. package/dist/core/graph/repo-sync/index.js +1 -0
  255. package/dist/core/graph/repo-sync/mirror.d.ts +30 -0
  256. package/dist/core/graph/repo-sync/mirror.js +6 -0
  257. package/dist/core/graph/repo-sync/ref-format.d.ts +76 -0
  258. package/dist/core/graph/repo-sync/ref-format.js +2 -0
  259. package/dist/core/graph/repo-sync/repos.d.ts +17 -0
  260. package/dist/core/graph/repo-sync/repos.js +3 -0
  261. package/dist/core/graph/repo-sync/sync.d.ts +42 -0
  262. package/dist/core/graph/repo-sync/sync.js +2 -0
  263. package/dist/core/graph/rules.d.ts +26 -0
  264. package/dist/core/graph/rules.js +3 -0
  265. package/dist/core/graph/spaces/app.d.ts +3 -0
  266. package/dist/core/graph/spaces/app.js +1 -0
  267. package/dist/core/graph/spaces/index.d.ts +19 -0
  268. package/dist/core/graph/spaces/index.js +1 -0
  269. package/dist/core/graph/spaces/person.d.ts +5 -0
  270. package/dist/core/graph/spaces/person.js +2 -0
  271. package/dist/core/graph/spaces/repo.d.ts +4 -0
  272. package/dist/core/graph/spaces/repo.js +1 -0
  273. package/dist/core/graph/types.d.ts +75 -0
  274. package/dist/core/graph/types.js +1 -0
  275. package/dist/core/graph/watches.d.ts +62 -0
  276. package/dist/core/graph/watches.js +18 -0
  277. package/dist/core/human/feedback-companion.js +1 -1
  278. package/dist/core/human/requests.d.ts +3 -1
  279. package/dist/core/human/requests.js +6 -6
  280. package/dist/core/inspector/model.js +2 -2
  281. package/dist/core/io.js +5 -5
  282. package/dist/core/layout-migrate/index.d.ts +24 -1
  283. package/dist/core/layout-migrate/index.js +4 -4
  284. package/dist/core/layout-migrate/paths.d.ts +4 -0
  285. package/dist/core/layout-migrate/paths.js +1 -1
  286. package/dist/core/layout-migrate/stored-paths.d.ts +7 -0
  287. package/dist/core/layout-migrate/stored-paths.js +11 -11
  288. package/dist/core/layout-migrate/stores.d.ts +19 -6
  289. package/dist/core/layout-migrate/stores.js +3 -4
  290. package/dist/core/manifest.d.ts +0 -2
  291. package/dist/core/manifest.js +1 -1
  292. package/dist/core/{memory/extensions.d.ts → plugin-extensions.d.ts} +9 -10
  293. package/dist/core/plugin-extensions.js +1 -0
  294. package/dist/core/preview-registry.d.ts +1 -1
  295. package/dist/core/preview-registry.js +3 -2
  296. package/dist/core/profiles/manifest.d.ts +7 -7
  297. package/dist/core/profiles/manifest.js +1 -1
  298. package/dist/core/profiles/select.js +3 -3
  299. package/dist/core/review/birth.js +1 -1
  300. package/dist/core/review/companion.js +1 -1
  301. package/dist/core/review/stage.d.ts +12 -1
  302. package/dist/core/review/stage.js +1 -1
  303. package/dist/core/review/store.d.ts +2 -0
  304. package/dist/core/review/store.js +1 -1
  305. package/dist/core/review/types.d.ts +7 -1
  306. package/dist/core/runs/events.js +1 -1
  307. package/dist/core/runs/operations.js +5 -5
  308. package/dist/core/runs/questions.js +2 -2
  309. package/dist/core/runtime/bearings-render.d.ts +13 -7
  310. package/dist/core/runtime/bearings-render.js +12 -12
  311. package/dist/core/runtime/bearings.d.ts +8 -18
  312. package/dist/core/runtime/bearings.js +7 -7
  313. package/dist/core/runtime/broker/daemon-ops.d.ts +7 -12
  314. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  315. package/dist/core/runtime/broker/fault-retry.d.ts +2 -0
  316. package/dist/core/runtime/broker/fault-retry.js +1 -1
  317. package/dist/core/runtime/broker/frame-dispatch.d.ts +1 -1
  318. package/dist/core/runtime/broker/frame-memory-refs.d.ts +7 -2
  319. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  320. package/dist/core/runtime/broker/inbox.d.ts +1 -4
  321. package/dist/core/runtime/broker/inbox.js +1 -10
  322. package/dist/core/runtime/broker/rebind.js +1 -1
  323. package/dist/core/runtime/broker/retry-card-elision.d.ts +7 -0
  324. package/dist/core/runtime/broker/retry-card-elision.js +1 -0
  325. package/dist/core/runtime/broker-extension-render.d.ts +0 -13
  326. package/dist/core/runtime/broker-extension-render.js +2 -4
  327. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  328. package/dist/core/runtime/broker-protocol.d.ts +1 -1
  329. package/dist/core/runtime/broker.js +1 -1
  330. package/dist/core/runtime/close.d.ts +9 -4
  331. package/dist/core/runtime/close.js +1 -1
  332. package/dist/core/runtime/deliver-live.js +1 -1
  333. package/dist/core/runtime/kickoff.js +17 -19
  334. package/dist/core/runtime/launch-target.d.ts +7 -0
  335. package/dist/core/runtime/launch-target.js +1 -1
  336. package/dist/core/runtime/ledger.d.ts +10 -0
  337. package/dist/core/runtime/ledger.js +3 -0
  338. package/dist/core/runtime/lifecycle.js +2 -2
  339. package/dist/core/runtime/nodes.d.ts +10 -2
  340. package/dist/core/runtime/nodes.js +1 -1
  341. package/dist/core/runtime/outcome-document.d.ts +2 -2
  342. package/dist/core/runtime/outcome-document.js +1 -1
  343. package/dist/core/runtime/persona.js +2 -2
  344. package/dist/core/runtime/placement.js +1 -1
  345. package/dist/core/runtime/promote.d.ts +2 -2
  346. package/dist/core/runtime/promote.js +1 -1
  347. package/dist/core/runtime/prospective-inventory-cli.js +2 -2
  348. package/dist/core/runtime/recycle.js +1 -1
  349. package/dist/core/runtime/reopen.js +1 -1
  350. package/dist/core/runtime/revive.js +2 -2
  351. package/dist/core/runtime/roadmap.d.ts +20 -9
  352. package/dist/core/runtime/roadmap.js +10 -6
  353. package/dist/core/runtime/spawn-env.js +1 -1
  354. package/dist/core/runtime/spawn.d.ts +5 -3
  355. package/dist/core/runtime/spawn.js +2 -2
  356. package/dist/core/runtime/structured-output.d.ts +3 -1
  357. package/dist/core/runtime/structured-output.js +4 -4
  358. package/dist/core/scope.d.ts +1 -32
  359. package/dist/core/scope.js +1 -1
  360. package/dist/core/scoped-state/db.js +2 -1
  361. package/dist/core/scoped-state/migrate.js +2 -2
  362. package/dist/core/scoped-state/profiles.d.ts +11 -0
  363. package/dist/core/scoped-state/profiles.js +1 -1
  364. package/dist/core/scoped-state/schema.d.ts +1 -1
  365. package/dist/core/scoped-state/schema.js +7 -5
  366. package/dist/core/spaces/permissions.d.ts +0 -14
  367. package/dist/core/spaces/permissions.js +1 -1
  368. package/dist/core/spaces/stop.d.ts +13 -0
  369. package/dist/core/spaces/stop.js +2 -2
  370. package/dist/core/storage/tables.d.ts +1 -1
  371. package/dist/core/substrate/delivery/corpus.d.ts +21 -0
  372. package/dist/core/substrate/delivery/corpus.js +3 -0
  373. package/dist/core/substrate/delivery/deliver.d.ts +76 -0
  374. package/dist/core/substrate/delivery/deliver.js +6 -0
  375. package/dist/core/substrate/delivery/listings.d.ts +30 -0
  376. package/dist/core/substrate/delivery/listings.js +7 -0
  377. package/dist/core/substrate/delivery/match.d.ts +28 -0
  378. package/dist/core/substrate/delivery/match.js +1 -0
  379. package/dist/core/substrate/delivery/plan.d.ts +67 -0
  380. package/dist/core/substrate/delivery/plan.js +3 -0
  381. package/dist/core/substrate/delivery/render-boot.d.ts +20 -0
  382. package/dist/core/substrate/delivery/render-boot.js +54 -0
  383. package/dist/core/substrate/delivery/render-event.d.ts +54 -0
  384. package/dist/core/substrate/delivery/render-event.js +8 -0
  385. package/dist/core/substrate/delivery/sub-persona-menu.d.ts +2 -0
  386. package/dist/core/substrate/delivery/sub-persona-menu.js +6 -0
  387. package/dist/core/substrate/delivery/types.d.ts +30 -0
  388. package/dist/core/substrate/delivery/types.js +0 -0
  389. package/dist/core/substrate/gate-explain.d.ts +0 -13
  390. package/dist/core/substrate/gate-explain.js +1 -1
  391. package/dist/core/substrate/schema.d.ts +11 -139
  392. package/dist/core/substrate/schema.js +1 -1
  393. package/dist/core/substrate/subject-fields.d.ts +3 -0
  394. package/dist/core/substrate/subject.d.ts +2 -1
  395. package/dist/core/substrate/subject.js +1 -1
  396. package/dist/daemon/api/handlers/app-profiles.js +1 -1
  397. package/dist/daemon/api/handlers/bash-jobs.js +1 -2
  398. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  399. package/dist/daemon/api/handlers/canvas.js +5 -5
  400. package/dist/daemon/api/handlers/daemon.js +1 -1
  401. package/dist/daemon/api/handlers/delivery.d.ts +2 -0
  402. package/dist/daemon/api/handlers/delivery.js +1 -0
  403. package/dist/daemon/api/handlers/{memory.d.ts → docs.d.ts} +1 -1
  404. package/dist/daemon/api/handlers/docs.js +1 -0
  405. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  406. package/dist/daemon/api/handlers/messages.js +2 -2
  407. package/dist/daemon/api/handlers/node-records.js +2 -2
  408. package/dist/daemon/api/handlers/nodes.js +1 -1
  409. package/dist/daemon/api/handlers/objects.d.ts +2 -0
  410. package/dist/daemon/api/handlers/objects.js +5 -0
  411. package/dist/daemon/api/handlers/package-docs.d.ts +2 -0
  412. package/dist/daemon/api/handlers/package-docs.js +1 -0
  413. package/dist/daemon/api/handlers/profiles.js +1 -1
  414. package/dist/daemon/api/handlers/reports.d.ts +2 -2
  415. package/dist/daemon/api/handlers/reports.js +4 -4
  416. package/dist/daemon/api/handlers/reviews.d.ts +4 -1
  417. package/dist/daemon/api/handlers/reviews.js +1 -1
  418. package/dist/daemon/api/map.d.ts +2 -2
  419. package/dist/daemon/api/map.js +2 -2
  420. package/dist/daemon/api/operations.d.ts +1 -1
  421. package/dist/daemon/api/operations.js +1 -1
  422. package/dist/daemon/api/reader.d.ts +17 -0
  423. package/dist/daemon/api/reader.js +1 -0
  424. package/dist/daemon/api/server.js +1 -1
  425. package/dist/daemon/control.d.ts +2 -3
  426. package/dist/daemon/crtrd.js +8 -6
  427. package/dist/daemon/fleet.js +4 -4
  428. package/dist/daemon/reconcilers/bash-deadline.d.ts +11 -1
  429. package/dist/daemon/reconcilers/bash-deadline.js +2 -1
  430. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  431. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  432. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  433. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  434. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -0
  435. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  436. package/dist/daemon/review/deliver.js +2 -2
  437. package/dist/daemon/review/finish.js +1 -1
  438. package/dist/hook-authoring.d.ts +0 -1
  439. package/dist/hook-authoring.js +3 -3
  440. package/dist/migrations/004-canvas-documents/apply.d.ts +10 -0
  441. package/dist/migrations/004-canvas-documents/apply.js +1 -0
  442. package/dist/migrations/004-canvas-documents/fields.d.ts +24 -0
  443. package/dist/migrations/004-canvas-documents/fields.js +2 -0
  444. package/dist/migrations/004-canvas-documents/index.d.ts +16 -0
  445. package/dist/migrations/004-canvas-documents/index.js +2 -0
  446. package/dist/migrations/004-canvas-documents/legacy/discover.d.ts +16 -0
  447. package/dist/migrations/004-canvas-documents/legacy/discover.js +1 -0
  448. package/dist/migrations/004-canvas-documents/legacy/history.d.ts +5 -0
  449. package/dist/migrations/004-canvas-documents/legacy/history.js +2 -0
  450. package/dist/migrations/004-canvas-documents/legacy/nested.d.ts +7 -0
  451. package/dist/migrations/004-canvas-documents/legacy/nested.js +1 -0
  452. package/dist/migrations/004-canvas-documents/legacy/parse.d.ts +14 -0
  453. package/dist/migrations/004-canvas-documents/legacy/parse.js +1 -0
  454. package/dist/migrations/004-canvas-documents/legacy/types.d.ts +91 -0
  455. package/dist/migrations/004-canvas-documents/legacy/types.js +0 -0
  456. package/dist/migrations/004-canvas-documents/legacy-edges.d.ts +6 -0
  457. package/dist/migrations/004-canvas-documents/legacy-edges.js +18 -0
  458. package/dist/migrations/004-canvas-documents/plan.d.ts +102 -0
  459. package/dist/migrations/004-canvas-documents/plan.js +3 -0
  460. package/dist/migrations/004-canvas-documents/pointers.d.ts +23 -0
  461. package/dist/migrations/004-canvas-documents/pointers.js +4 -0
  462. package/dist/migrations/activation.d.ts +9 -18
  463. package/dist/migrations/activation.js +2 -2
  464. package/dist/pi-extensions/broker-local.d.ts +2 -2
  465. package/dist/pi-extensions/broker-local.js +2 -2
  466. package/dist/pi-extensions/canvas-bash-valve.js +5 -4
  467. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  468. package/dist/pi-extensions/canvas-doc-substrate.d.ts +0 -1
  469. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  470. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
  471. package/dist/pi-extensions/canvas-passive-context.js +1 -1
  472. package/dist/pi-extensions/canvas-recap.js +2 -2
  473. package/dist/pi-extensions/canvas-stophook.d.ts +1 -1
  474. package/dist/pi-extensions/canvas-stophook.js +1 -1
  475. package/dist/prompts/review.js +3 -3
  476. package/dist/shared/env.d.ts +5 -0
  477. package/dist/shared/env.js +1 -1
  478. package/dist/shared/generated-context.js +2 -10
  479. package/dist/shared/inbox-entry-body.d.ts +22 -0
  480. package/dist/shared/inbox-entry-body.js +10 -0
  481. package/dist/{core/memory → shared}/inline-ref-guidance.d.ts +2 -2
  482. package/dist/shared/inline-ref-guidance.js +2 -0
  483. package/dist/types.d.ts +3 -1
  484. package/docs/cli/memory-and-preferences.md +12 -14
  485. package/docs/concepts/README.md +1 -1
  486. package/docs/concepts/lifecycle-and-wakes.md +1 -1
  487. package/docs/concepts/memory.md +15 -15
  488. package/docs/concepts/nodes-and-the-canvas.md +1 -1
  489. package/docs/concepts/profiles-kinds-and-modes.md +5 -5
  490. package/docs/concepts/scopes-and-trust.md +1 -1
  491. package/docs/concepts/why-a-daemon.md +1 -1
  492. package/docs/sdk/README.md +5 -6
  493. package/docs/sdk/errors.md +0 -13
  494. package/docs/sdk/guides/README.md +0 -1
  495. package/docs/sdk/nodes.md +0 -2
  496. package/docs/sdk/resources.md +0 -1
  497. package/package.json +2 -2
  498. package/packages/crouter-identity/package.json +1 -1
  499. package/runtime.lock.json +11 -11
  500. package/scripts/lib/isolation-env.mjs +8 -2
  501. package/dist/api/dto/memory.d.ts +0 -171
  502. package/dist/api/dto/memory.js +0 -1
  503. package/dist/builtin-memory/crouter-sdk/guides/app-memory.md +0 -73
  504. package/dist/builtin-memory/crouter-sdk/memory.md +0 -87
  505. package/dist/commands/broker-permissions.d.ts +0 -2
  506. package/dist/commands/broker-permissions.js +0 -1
  507. package/dist/commands/memory/client.d.ts +0 -11
  508. package/dist/commands/memory/client.js +0 -1
  509. package/dist/commands/memory/delete.d.ts +0 -1
  510. package/dist/commands/memory/delete.js +0 -1
  511. package/dist/commands/memory/edit.d.ts +0 -1
  512. package/dist/commands/memory/edit.js +0 -21
  513. package/dist/commands/memory/find.d.ts +0 -1
  514. package/dist/commands/memory/find.js +0 -1
  515. package/dist/commands/memory/history.d.ts +0 -1
  516. package/dist/commands/memory/history.js +0 -5
  517. package/dist/commands/memory/lint.d.ts +0 -1
  518. package/dist/commands/memory/lint.js +0 -1
  519. package/dist/commands/memory/list.d.ts +0 -1
  520. package/dist/commands/memory/list.js +0 -1
  521. package/dist/commands/memory/move.d.ts +0 -1
  522. package/dist/commands/memory/move.js +0 -1
  523. package/dist/commands/memory/origin.d.ts +0 -1
  524. package/dist/commands/memory/origin.js +0 -1
  525. package/dist/commands/memory/read.d.ts +0 -1
  526. package/dist/commands/memory/read.js +0 -6
  527. package/dist/commands/memory/shared.d.ts +0 -22
  528. package/dist/commands/memory/shared.js +0 -1
  529. package/dist/commands/memory/write.d.ts +0 -1
  530. package/dist/commands/memory/write.js +0 -13
  531. package/dist/commands/memory.js +0 -1
  532. package/dist/commands/node-inspect-artifacts.d.ts +0 -1
  533. package/dist/commands/node-inspect-artifacts.js +0 -8
  534. package/dist/core/help/memory-extensions.d.ts +0 -3
  535. package/dist/core/help/memory-extensions.js +0 -2
  536. package/dist/core/memory/cli-selector.d.ts +0 -13
  537. package/dist/core/memory/cli-selector.js +0 -1
  538. package/dist/core/memory/doc-link-grammar.d.ts +0 -20
  539. package/dist/core/memory/doc-link-grammar.js +0 -2
  540. package/dist/core/memory/extensions.js +0 -1
  541. package/dist/core/memory/history.d.ts +0 -87
  542. package/dist/core/memory/history.js +0 -6
  543. package/dist/core/memory/identity.d.ts +0 -65
  544. package/dist/core/memory/identity.js +0 -1
  545. package/dist/core/memory/inline-ref-guidance.js +0 -2
  546. package/dist/core/memory/inline-ref-inventory.d.ts +0 -9
  547. package/dist/core/memory/inline-ref-inventory.js +0 -1
  548. package/dist/core/memory/lint.d.ts +0 -163
  549. package/dist/core/memory/lint.js +0 -2
  550. package/dist/core/memory/mutation-domain.d.ts +0 -113
  551. package/dist/core/memory/mutation-domain.js +0 -12
  552. package/dist/core/memory/mutations.d.ts +0 -74
  553. package/dist/core/memory/mutations.js +0 -1
  554. package/dist/core/memory/project-namespace.d.ts +0 -31
  555. package/dist/core/memory/project-namespace.js +0 -2
  556. package/dist/core/memory/repository-association.d.ts +0 -31
  557. package/dist/core/memory/repository-association.js +0 -1
  558. package/dist/core/memory/service.d.ts +0 -145
  559. package/dist/core/memory/service.js +0 -2
  560. package/dist/core/memory/tree.d.ts +0 -39
  561. package/dist/core/memory/tree.js +0 -1
  562. package/dist/core/memory-resolver.d.ts +0 -280
  563. package/dist/core/memory-resolver.js +0 -2
  564. package/dist/core/nested-stores.d.ts +0 -18
  565. package/dist/core/nested-stores.js +0 -1
  566. package/dist/core/runtime/memory.d.ts +0 -3
  567. package/dist/core/runtime/memory.js +0 -1
  568. package/dist/core/substrate/frontmatter-validation.d.ts +0 -11
  569. package/dist/core/substrate/frontmatter-validation.js +0 -1
  570. package/dist/core/substrate/gate.d.ts +0 -16
  571. package/dist/core/substrate/gate.js +0 -1
  572. package/dist/core/substrate/index.d.ts +0 -18
  573. package/dist/core/substrate/index.js +0 -1
  574. package/dist/core/substrate/injected-store.d.ts +0 -75
  575. package/dist/core/substrate/injected-store.js +0 -2
  576. package/dist/core/substrate/listings.d.ts +0 -28
  577. package/dist/core/substrate/listings.js +0 -1
  578. package/dist/core/substrate/memory-events.d.ts +0 -6
  579. package/dist/core/substrate/memory-events.js +0 -1
  580. package/dist/core/substrate/on-read-node.d.ts +0 -6
  581. package/dist/core/substrate/on-read-node.js +0 -1
  582. package/dist/core/substrate/on-read.d.ts +0 -101
  583. package/dist/core/substrate/on-read.js +0 -9
  584. package/dist/core/substrate/plan.d.ts +0 -94
  585. package/dist/core/substrate/plan.js +0 -1
  586. package/dist/core/substrate/render-node.d.ts +0 -12
  587. package/dist/core/substrate/render-node.js +0 -1
  588. package/dist/core/substrate/render.d.ts +0 -41
  589. package/dist/core/substrate/render.js +0 -65
  590. package/dist/core/substrate/session-cache.d.ts +0 -27
  591. package/dist/core/substrate/session-cache.js +0 -1
  592. package/dist/core/substrate/surface-match.d.ts +0 -73
  593. package/dist/core/substrate/surface-match.js +0 -1
  594. package/dist/daemon/api/handlers/memory.js +0 -5
  595. package/dist/migrations/001-surfaces-frontmatter.d.ts +0 -2
  596. package/dist/migrations/001-surfaces-frontmatter.js +0 -1
  597. package/dist/migrations/002-profile-project-memory.d.ts +0 -2
  598. package/dist/migrations/002-profile-project-memory.js +0 -1
  599. package/dist/migrations/003-repository-root-memory-identity/front-door.d.ts +0 -26
  600. package/dist/migrations/003-repository-root-memory-identity/front-door.js +0 -11
  601. package/dist/migrations/003-repository-root-memory-identity/index.d.ts +0 -2
  602. package/dist/migrations/003-repository-root-memory-identity/index.js +0 -5
  603. package/dist/migrations/003-repository-root-memory-identity/references.d.ts +0 -95
  604. package/dist/migrations/003-repository-root-memory-identity/references.js +0 -5
  605. package/dist/migrations/003-repository-root-memory-identity/repository-facts.d.ts +0 -39
  606. package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +0 -3
  607. package/dist/migrations/convergent.d.ts +0 -43
  608. package/dist/migrations/convergent.js +0 -2
  609. package/dist/migrations/corpus.d.ts +0 -75
  610. package/dist/migrations/corpus.js +0 -3
  611. package/dist/migrations/frontmatter-splice.d.ts +0 -15
  612. package/dist/migrations/frontmatter-splice.js +0 -8
  613. package/dist/migrations/profile-manifests.d.ts +0 -30
  614. package/dist/migrations/profile-manifests.js +0 -2
  615. package/dist/migrations/registry.d.ts +0 -7
  616. package/dist/migrations/registry.js +0 -1
  617. package/dist/migrations/runner.d.ts +0 -43
  618. package/dist/migrations/runner.js +0 -1
  619. package/dist/migrations/types.d.ts +0 -211
  620. package/dist/shared/birth-announcement.d.ts +0 -12
  621. package/dist/shared/birth-announcement.js +0 -1
  622. package/docs/sdk/guides/app-memory.md +0 -22
  623. package/docs/sdk/memory.md +0 -85
  624. /package/dist/{migrations/types.js → api/dto/delivery.js} +0 -0
  625. /package/dist/{core/memory → shared}/inline-ref-grammar.d.ts +0 -0
  626. /package/dist/{core/memory → shared}/inline-ref-grammar.js +0 -0
@@ -1,9 +1,11 @@
1
- var ve=Object.defineProperty;var a=(t,n)=>ve(t,"name",{value:n,configurable:!0});import{writeFileSync as ge,readFileSync as we,rmSync as ye,mkdirSync as V,existsSync as k,chmodSync as Se}from"node:fs";import{createServer as J}from"node:http";import{dirname as _e}from"node:path";import{envCrtrdTcp as ke}from"../shared/env.js";import{serveCanvasConversationStore as be}from"../core/canvas/sessions.js";import{pollRunObservers as Ee}from"./runs/observer.js";import{randomBytes as Pe}from"node:crypto";import{apiSocketPath as Ie,crtrHome as Te}from"../core/canvas/paths.js";import{activeAppUsers as Re}from"../core/spaces/users.js";import{ensureAppSpace as xe,ensureUserFiles as De}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as E}from"../launcher/spec.js";import{launcherRequest as T}from"../launcher/client.js";import{initializeEmptyLayout as Ce,layoutNeedsMigration as Me,socketDir as Q}from"../core/layout.js";import{listNodeMemoryTargets as Y,listNodesForSupervision as Ae}from"../core/canvas/index.js";import{createApiServer as Le}from"./api/server.js";import{createAppListener as Ne}from"./api/app-listener.js";import{installLocalTerminalGrant as Ge}from"../core/grants/local.js";import{createGrantSync as $e,GRANT_SYNC_INTERVAL_S as Oe}from"../core/grants/sync.js";import{runRemovalCascades as Fe}from"../core/grants/remove.js";import{sweepSandboxes as je}from"../core/grants/on-sync.js";import{hasSyncedGrants as He}from"../core/grants/mirror.js";import{readConfig as ze}from"../core/config.js";import{reconcileUndeliveredTickets as Be}from"./human/sweep.js";import{resetHandedOffDeliveries as We}from"../core/canvas/deliveries.js";import{sweepReviews as Ue}from"./review/sweep.js";import{pidfilePath as $}from"./pidfile.js";import{rendererWarning as qe}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as Ke}from"./supervise-cadence.js";import{BrokerSupervisionReconciler as Ve}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as Je}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as Qe}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as Ye}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as Xe}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as Ze}from"./reconcilers/delivery-lane.js";import{migrateLegacyExecutionIdentities as er}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as rr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as tr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as nr}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as or}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as ir}from"./reconcilers/bash-deadline.js";import{captureLivenessSnapshot as X,capturePidCommand as ar,captureTeardownSnapshot as Z,isPidAlive as sr,isAnyPidAlive as ee,killProcessTreePids as re}from"../core/canvas/pid.js";import{bindFleet as cr,boundFleet as lr}from"../core/runtime/fleet.js";import{bindDaemonControl as dr,clearDaemonControl as pr}from"./control.js";import{execDaemon as mr,spawnDaemon as fr}from"./manage.js";import{reconcileAndMigrateBoot as ur}from"../core/canvas/boot.js";import{resolveInstallId as hr}from"../core/canvas/install-id.js";import{setInstallId as vr}from"../core/runtime/nodes.js";import{claimDaemonOwnership as gr,releaseDaemonOwnership as te}from"../core/canvas/daemon-owner.js";import{migrate as wr,openDb as yr}from"../core/canvas/db.js";import{prewarmRecentRecipes as Sr,reapStaleSpares as _r}from"../core/runtime/warm-pool.js";import{DaemonFleet as kr}from"./fleet.js";import{BOOT_MIGRATIONS as br}from"./boot-migrations.js";import{applyJoinedOwner as Er}from"./joined-owner.js";import{emitEvent as h}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as Pr}from"../core/events/source.js";import{activateOnDiskMigrations as Ir,MigrationBlockedError as Tr,runForcedOnDiskMigrations as Rr}from"../migrations/activation.js";import{convertLegacyProviderStore as xr,convertLegacyScopedStore as Dr}from"../core/scoped-state/migrate.js";import{userScopeRoot as Cr}from"../core/scope.js";import{secretsDir as Mr}from"../core/layout.js";function O(t,n){return t.includes(` --canvas-home ${n} `)}a(O,"brokerCommandDeclaresCanvasHome");function F(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}a(F,"brokerCommandEpoch");const Ar=5e3,ne=150;async function Lr(t){const n=X();if(n===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const s=Te(),m=[];for(const[i,p]of n.processes){const g=p.command;if(p.zombie||!g.includes("broker-cli.js")||!O(g,s)||F(g)===t)continue;const y=g.trim().split(/\s+/).at(-1)??"";y===""||y.endsWith("broker-cli.js")||m.push({pid:i,nodeId:y})}let f=0;const o=[];for(const i of m){const p=ar(i.pid);if(p===null||!p.includes("broker-cli.js")||!O(p,s)||F(p)===t||p.trim().split(/\s+/).at(-1)!==i.nodeId)continue;const g=Z(i.pid,null);if(!g.reused){try{process.platform==="linux"&&k(E)?await T({operation:"stop",pid:i.pid}):process.kill(i.pid,"SIGTERM")}catch{continue}f++,o.push({pid:i.pid,snap:g})}}const w=Date.now()+Ar;for(;Date.now()<w&&o.some(i=>ee(i.snap.tree.length>0?i.snap.tree:[i.pid]));)await new Promise(i=>setTimeout(i,ne));let v=0;for(const i of o){const p=i.snap.tree.length>0?i.snap.tree:[i.pid];ee(p)&&(process.platform==="linux"&&k(E)?await T({operation:"stop",pid:i.pid}):re(p,"SIGKILL",i.snap.identities),v++)}v>0&&await new Promise(i=>setTimeout(i,ne));const c=X();if(c===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const d=[];for(const[i,p]of c.processes){const g=p.command;p.zombie||!g.includes("broker-cli.js")||O(g,s)&&F(g)!==t&&d.push(i)}if(d.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${d.join(", ")}`);h({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}a(Lr,"reapPriorEpochBrokers");const Nr=5e3;async function Gr(t){const n=Array.from(t.entries());if(n.length===0)return;const s=n.map(([,o])=>({pid:o.pid,snap:Z(o.pid,null),exited:o.handle.exited}));for(const o of s)if(!o.snap.reused)try{process.platform==="linux"&&k(E)?await T({operation:"stop",pid:o.pid}):process.kill(o.pid,"SIGTERM")}catch{}const m=new Promise(o=>{setTimeout(o,Nr).unref()});await Promise.allSettled(s.map(o=>Promise.race([o.exited.then(()=>{}),m])));const f=[];for(const o of s)sr(o.pid)&&(process.platform==="linux"&&k(E)?await T({operation:"stop",pid:o.pid}):re(o.snap.tree.length>0?o.snap.tree:[o.pid],"SIGKILL",o.snap.identities),f.push(o));await Promise.all(f.map(o=>o.exited)),h({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:s.length,sigkilled:f.length}})}a(Gr,"teardownFleet");function oe(){V(_e($()),{recursive:!0}),ge($(),String(process.pid),"utf8")}a(oe,"writePidfile");function ie(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}a(ie,"isMissingPathError");function ae(t){const n=$();let s;try{s=we(n,"utf8")}catch(m){if(ie(m))return;throw m}if(s.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{ye(n)}catch(m){if(ie(m))return;throw m}}a(ae,"removeOwnedPidfileMirror");const $r={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(t=>{t.catch(()=>{})},"registerDetached")},j=new Ve,Or=new Je,Fr=new Qe,jr=new Ye,Hr=new Xe,zr=new Ze,Br=new tr,Wr=new nr,Ur=new or,qr=new ir;async function Kr(t=Date.now(),n=$r){const s=lr(),m=await j.runFleetPreamble(s);let f,o;try{const v=Ae();f=v.filter(c=>c.status==="active"||c.status==="idle"),o=v.filter(c=>c.status==="done"||c.status==="canceled"||c.status==="dead")}catch(v){h({level:"error",event:"canvas.node_list.failed",error:v});return}await j.run(t,{rows:f,fleet:s,lifecycle:n}),Or.run(t,{rows:f});const w=await Fr.run(t,{rows:[...f,...o],fleet:s});jr.run(t),Hr.run(t,{lifecycle:n}),zr.run(t,{lifecycle:n}),Br.run(t,{lifecycle:n}),Wr.run(t,{lifecycle:n,fleet:s}),Ur.run(t,{lifecycle:n}),Ee(),await qr.run(t,{rows:f}),j.warnIfSaturated({fleet:s,lifecycle:n,thresholds:m,frozen:w})}a(Kr,"superviseTick");async function Vr(t){V(Q(),{recursive:!0,mode:493}),process.platform==="linux"&&Se(Q(),493);const n=Ie();if(k(n))throw new Error(`layout refusal cannot bind occupied socket: ${n}`);const s=J((c,d)=>{if(c.method==="GET"&&c.url==="/healthz"){d.writeHead(200,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}d.writeHead(503,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((c,d)=>{s.once("error",d),s.listen(n,()=>{s.off("error",d),c()})});let m;const f=t.tcp??ke();if(f){const c=/^(.*):(\d+)$/.exec(f);if(!c||Number(c[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const d=J(s.listeners("request")[0]);await new Promise((i,p)=>{d.once("error",p),d.listen(Number(c[2]),c[1],()=>{d.off("error",p),i()})}),m=d}oe();let o;const w=a(()=>(o??=(async()=>{s.closeAllConnections(),m?.closeAllConnections(),await Promise.all([s,m].filter(c=>c!==void 0).map(c=>new Promise((d,i)=>c.close(p=>p?i(p):d())))),ae(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),o),"cleanup"),v=a(()=>{w().then(()=>process.exit(0),c=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(c)}
2
- `),process.exit(1)})},"onSignal");return process.on("SIGINT",v),process.on("SIGTERM",v),w}a(Vr,"serveLayoutRefusal");async function Jr(t={}){if(Me())return Vr(t);Ce();const n=gr(Pe(16).toString("hex"));if(!n.claimed){if(n.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${n.incumbentPid??"?"})
1
+ var ve=Object.defineProperty;var a=(t,n)=>ve(t,"name",{value:n,configurable:!0});import{writeFileSync as ge,readFileSync as we,rmSync as ye,mkdirSync as V,existsSync as b,chmodSync as Se}from"node:fs";import{createServer as Q}from"node:http";import{dirname as _e}from"node:path";import{envCrtrdTcp as be}from"../shared/env.js";import{serveCanvasConversationStore as ke}from"../core/canvas/sessions.js";import{pollRunObservers as Ee}from"./runs/observer.js";import{randomBytes as Pe}from"node:crypto";import{apiSocketPath as Ie,crtrHome as Re}from"../core/canvas/paths.js";import{activeAppUsers as Te}from"../core/spaces/users.js";import{ensureAppSpace as xe,ensureUserFiles as De}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as E}from"../launcher/spec.js";import{launcherRequest as R}from"../launcher/client.js";import{initializeEmptyLayout as Ce,layoutNeedsMigration as Ae,socketDir as Y}from"../core/layout.js";import{listNodesForSupervision as Le}from"../core/canvas/index.js";import{createApiServer as $e}from"./api/server.js";import{createAppListener as Me}from"./api/app-listener.js";import{installLocalTerminalGrant as Ne}from"../core/grants/local.js";import{createGrantSync as Ge,GRANT_SYNC_INTERVAL_S as Oe}from"../core/grants/sync.js";import{runRemovalCascades as Fe}from"../core/grants/remove.js";import{sweepSandboxes as je}from"../core/grants/on-sync.js";import{hasSyncedGrants as He}from"../core/grants/mirror.js";import{readConfig as Be}from"../core/config.js";import{reconcileUndeliveredTickets as ze}from"./human/sweep.js";import{resetHandedOffDeliveries as We}from"../core/canvas/deliveries.js";import{sweepReviews as qe}from"./review/sweep.js";import{pidfilePath as G}from"./pidfile.js";import{rendererWarning as Ue}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as Ke}from"./supervise-cadence.js";import{BrokerSupervisionReconciler as Je}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as Ve}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as Qe}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as Ye}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as Xe}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as Ze}from"./reconcilers/delivery-lane.js";import{migrateLegacyExecutionIdentities as er}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as rr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as tr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as nr}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as or}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as ir}from"./reconcilers/bash-deadline.js";import{captureLivenessSnapshot as X,capturePidCommand as ar,captureTeardownSnapshot as Z,isPidAlive as sr,isAnyPidAlive as ee,killProcessTreePids as re}from"../core/canvas/pid.js";import{bindFleet as cr,boundFleet as lr}from"../core/runtime/fleet.js";import{bindDaemonControl as dr,clearDaemonControl as pr}from"./control.js";import{execDaemon as mr,spawnDaemon as fr}from"./manage.js";import{reconcileAndMigrateBoot as ur}from"../core/canvas/boot.js";import{resolveInstallId as hr}from"../core/canvas/install-id.js";import{setInstallId as vr}from"../core/runtime/nodes.js";import{claimDaemonOwnership as gr,releaseDaemonOwnership as te}from"../core/canvas/daemon-owner.js";import{migrate as wr,openDb as ne,withCanvasWrite as yr}from"../core/canvas/db.js";import{reconcilePackageDocuments as Sr}from"../core/graph/package-docs.js";import{startRepoSync as _r}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as br,reapStaleSpares as kr}from"../core/runtime/warm-pool.js";import{DaemonFleet as Er}from"./fleet.js";import{BOOT_MIGRATIONS as Pr}from"./boot-migrations.js";import{applyJoinedOwner as Ir}from"./joined-owner.js";import{emitEvent as h}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as Rr}from"../core/events/source.js";import{activateCanvasImport as Tr,MigrationBlockedError as xr,runForcedCanvasImport as Dr}from"../migrations/activation.js";import{convertLegacyProviderStore as Cr,convertLegacyScopedStore as Ar}from"../core/scoped-state/migrate.js";import{userScopeRoot as Lr}from"../core/scope.js";import{secretsDir as $r}from"../core/layout.js";function O(t,n){return t.includes(` --canvas-home ${n} `)}a(O,"brokerCommandDeclaresCanvasHome");function F(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}a(F,"brokerCommandEpoch");const Mr=5e3,oe=150;async function Nr(t){const n=X();if(n===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const s=Re(),m=[];for(const[i,p]of n.processes){const g=p.command;if(p.zombie||!g.includes("broker-cli.js")||!O(g,s)||F(g)===t)continue;const y=g.trim().split(/\s+/).at(-1)??"";y===""||y.endsWith("broker-cli.js")||m.push({pid:i,nodeId:y})}let f=0;const o=[];for(const i of m){const p=ar(i.pid);if(p===null||!p.includes("broker-cli.js")||!O(p,s)||F(p)===t||p.trim().split(/\s+/).at(-1)!==i.nodeId)continue;const g=Z(i.pid,null);if(!g.reused){try{process.platform==="linux"&&b(E)?await R({operation:"stop",pid:i.pid}):process.kill(i.pid,"SIGTERM")}catch{continue}f++,o.push({pid:i.pid,snap:g})}}const w=Date.now()+Mr;for(;Date.now()<w&&o.some(i=>ee(i.snap.tree.length>0?i.snap.tree:[i.pid]));)await new Promise(i=>setTimeout(i,oe));let v=0;for(const i of o){const p=i.snap.tree.length>0?i.snap.tree:[i.pid];ee(p)&&(process.platform==="linux"&&b(E)?await R({operation:"stop",pid:i.pid}):re(p,"SIGKILL",i.snap.identities),v++)}v>0&&await new Promise(i=>setTimeout(i,oe));const c=X();if(c===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const d=[];for(const[i,p]of c.processes){const g=p.command;p.zombie||!g.includes("broker-cli.js")||O(g,s)&&F(g)!==t&&d.push(i)}if(d.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${d.join(", ")}`);h({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}a(Nr,"reapPriorEpochBrokers");const Gr=5e3;async function Or(t){const n=Array.from(t.entries());if(n.length===0)return;const s=n.map(([,o])=>({pid:o.pid,snap:Z(o.pid,null),exited:o.handle.exited}));for(const o of s)if(!o.snap.reused)try{process.platform==="linux"&&b(E)?await R({operation:"stop",pid:o.pid}):process.kill(o.pid,"SIGTERM")}catch{}const m=new Promise(o=>{setTimeout(o,Gr).unref()});await Promise.allSettled(s.map(o=>Promise.race([o.exited.then(()=>{}),m])));const f=[];for(const o of s)sr(o.pid)&&(process.platform==="linux"&&b(E)?await R({operation:"stop",pid:o.pid}):re(o.snap.tree.length>0?o.snap.tree:[o.pid],"SIGKILL",o.snap.identities),f.push(o));await Promise.all(f.map(o=>o.exited)),h({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:s.length,sigkilled:f.length}})}a(Or,"teardownFleet");function ie(){V(_e(G()),{recursive:!0}),ge(G(),String(process.pid),"utf8")}a(ie,"writePidfile");function ae(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}a(ae,"isMissingPathError");function se(t){const n=G();let s;try{s=we(n,"utf8")}catch(m){if(ae(m))return;throw m}if(s.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{ye(n)}catch(m){if(ae(m))return;throw m}}a(se,"removeOwnedPidfileMirror");const Fr={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(t=>{t.catch(()=>{})},"registerDetached")},j=new Je,jr=new Ve,Hr=new Qe,Br=new Ye,zr=new Xe,Wr=new Ze,qr=new tr,Ur=new nr,Kr=new or,Jr=new ir;async function Vr(t=Date.now(),n=Fr){const s=lr(),m=await j.runFleetPreamble(s);let f,o;try{const v=Le();f=v.filter(c=>c.status==="active"||c.status==="idle"),o=v.filter(c=>c.status==="done"||c.status==="canceled"||c.status==="dead")}catch(v){h({level:"error",event:"canvas.node_list.failed",error:v});return}await j.run(t,{rows:f,fleet:s,lifecycle:n}),jr.run(t,{rows:f});const w=await Hr.run(t,{rows:[...f,...o],fleet:s});Br.run(t),zr.run(t,{lifecycle:n}),Wr.run(t,{lifecycle:n}),qr.run(t,{lifecycle:n}),Ur.run(t,{lifecycle:n,fleet:s}),Kr.run(t,{lifecycle:n}),Ee(),await Jr.run(t,{rows:f}),j.warnIfSaturated({fleet:s,lifecycle:n,thresholds:m,frozen:w})}a(Vr,"superviseTick");async function Qr(t){V(Y(),{recursive:!0,mode:493}),process.platform==="linux"&&Se(Y(),493);const n=Ie();if(b(n))throw new Error(`layout refusal cannot bind occupied socket: ${n}`);const s=Q((c,d)=>{if(c.method==="GET"&&c.url==="/healthz"){d.writeHead(200,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}d.writeHead(503,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((c,d)=>{s.once("error",d),s.listen(n,()=>{s.off("error",d),c()})});let m;const f=t.tcp??be();if(f){const c=/^(.*):(\d+)$/.exec(f);if(!c||Number(c[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const d=Q(s.listeners("request")[0]);await new Promise((i,p)=>{d.once("error",p),d.listen(Number(c[2]),c[1],()=>{d.off("error",p),i()})}),m=d}ie();let o;const w=a(()=>(o??=(async()=>{s.closeAllConnections(),m?.closeAllConnections(),await Promise.all([s,m].filter(c=>c!==void 0).map(c=>new Promise((d,i)=>c.close(p=>p?i(p):d())))),se(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),o),"cleanup"),v=a(()=>{w().then(()=>process.exit(0),c=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(c)}
2
+ `),process.exit(1)})},"onSignal");return process.on("SIGINT",v),process.on("SIGTERM",v),w}a(Qr,"serveLayoutRefusal");async function Yr(t={}){if(Ae())return Qr(t);Ce();const n=gr(Pe(16).toString("hex"));if(!n.claimed){if(n.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${n.incumbentPid??"?"})
3
3
  `);else{const e=[n.incumbentPid!==void 0?`pid ${n.incumbentPid}`:void 0,n.verdict!==void 0?`verdict ${n.verdict}`:void 0].filter(l=>l!==void 0),r=e.length>0?` (${e.join(", ")})`:"";process.stderr.write(`[crtrd] claim lost: ${n.reason}${r}
4
- `)}return async()=>{}}const s=n.claim;let m=null;try{await Lr(s.token),Dr({kind:"user",root:Cr()}),await xr(Mr()),wr(yr()),m=Er(),process.platform==="linux"&&k(E)&&await T({operation:"users.sync",users:Re()}),rr(s.token)}catch(e){try{const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released")}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}let f=!0,o,w=Promise.resolve(),v=!1,c,d;const i=new Set;let p=!1,g=!1,y,C,H=!1,M,R,x,A,u={phase:"initializing",message:"daemon startup is initializing its on-disk memory migration and normal services are unavailable",blockerPaths:[]},P="initial startup activation",se=null;function ce(){return u.phase==="ready"?null:{phase:u.phase,message:u.message,blockerPaths:u.blockerPaths}}a(ce,"startupBlock");function I(e){i.add(e),e.finally(()=>{i.delete(e)}).catch(()=>{})}a(I,"registerDetached");const le={acceptsDetachedWork:a(()=>f,"acceptsDetachedWork"),registerDetached:I};async function de(){try{f=!1,c!==void 0&&(clearInterval(c),c=void 0),x!==void 0&&(clearInterval(x),x=void 0);let e;do e=w,await e;while(e!==w);for(;i.size>0;)await Promise.allSettled([...i]);if(d!==void 0&&(await Gr(d),d.dispose()),C!==void 0&&!H&&(H=!0,await C.close()),R!==void 0){const r=R;R=void 0,await r.close()}if(M!==void 0){const r=M;M=void 0,await r.close()}if(p||(ae(process.pid),p=!0),p&&!g){const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released");g=!0}}finally{pr(),process.off("SIGINT",W),process.off("SIGTERM",U),process.off("exit",q)}}a(de,"cleanupAttempt");const L=1e3;let z=!1;function pe(){return z?{graceMs:L}:(z=!0,_.fresh(()=>{h({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:L}})}),setTimeout(()=>{me()},L),{graceMs:L})}a(pe,"requestHandover");async function me(){try{await b()}catch(e){const r=e instanceof Error?e.stack??e.message:String(e);process.stderr.write(`[crtrd] handover cleanup failed:
4
+ `)}return async()=>{}}const s=n.claim;let m=null;try{await Nr(s.token),Ar({kind:"user",root:Lr()}),await Cr($r()),wr(ne());const e=yr(r=>Sr(r));for(const r of e.conflicts)process.stderr.write(`[crtrd] plugin documents not reconciled: ${r.message}
5
+ `);for(const r of e.invalid)process.stderr.write(`[crtrd] package file is not a document: ${r.path}: ${r.error}
6
+ `);m=Ir(),process.platform==="linux"&&b(E)&&await R({operation:"users.sync",users:Te()}),rr(s.token)}catch(e){try{const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released")}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}let f=!0,o,w=Promise.resolve(),v=!1,c,d;const i=new Set;let p=!1,g=!1,y,C,H=!1,A,T,x,L,u={phase:"initializing",message:"daemon startup is running the canvas import and normal services are unavailable",blockerPaths:[]},P="initial startup activation",ce=null;function le(){return u.phase==="ready"?null:{phase:u.phase,message:u.message,blockerPaths:u.blockerPaths}}a(le,"startupBlock");function I(e){i.add(e),e.finally(()=>{i.delete(e)}).catch(()=>{})}a(I,"registerDetached");const B={acceptsDetachedWork:a(()=>f,"acceptsDetachedWork"),registerDetached:I};_r(B,ne);async function de(){try{f=!1,c!==void 0&&(clearInterval(c),c=void 0),x!==void 0&&(clearInterval(x),x=void 0);let e;do e=w,await e;while(e!==w);for(;i.size>0;)await Promise.allSettled([...i]);if(d!==void 0&&(await Or(d),d.dispose()),C!==void 0&&!H&&(H=!0,await C.close()),T!==void 0){const r=T;T=void 0,await r.close()}if(A!==void 0){const r=A;A=void 0,await r.close()}if(p||(se(process.pid),p=!0),p&&!g){const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released");g=!0}}finally{pr(),process.off("SIGINT",q),process.off("SIGTERM",U),process.off("exit",K)}}a(de,"cleanupAttempt");const $=1e3;let z=!1;function pe(){return z?{graceMs:$}:(z=!0,_.fresh(()=>{h({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:$}})}),setTimeout(()=>{me()},$),{graceMs:$})}a(pe,"requestHandover");async function me(){try{await k()}catch(e){const r=e instanceof Error?e.stack??e.message:String(e);process.stderr.write(`[crtrd] handover cleanup failed:
5
7
  ${r}
6
- `),process.exit(1)}try{process.platform==="linux"&&k(E)&&(await T({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await mr();const e=await fr();_.fresh(()=>{h({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:e.pid??e.existing_pid??null,spawned:e.started}})})}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.handover.successor_failed",error:e})});const r=e instanceof Error?e.message:String(e);process.stderr.write(`[crtrd] handover successor failed to start: ${r}
7
- `),process.exit(1)}process.exit(0)}a(me,"performHandover");function b(){if(y!==void 0)return y;const e=de();return y=e,e.then(()=>{y===e&&(y=void 0)},()=>{y===e&&(y=void 0)}),e}a(b,"requestCleanup");async function B(e){try{await b(),process.exit(0)}catch(r){process.exitCode=1;const l=r instanceof Error?r.stack??`${r.name}: ${r.message}`:String(r);process.stderr.write(`[crtrd] ${e} cleanup failed:
8
+ `),process.exit(1)}try{process.platform==="linux"&&b(E)&&(await R({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await mr();const e=await fr();_.fresh(()=>{h({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:e.pid??e.existing_pid??null,spawned:e.started}})})}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.handover.successor_failed",error:e})});const r=e instanceof Error?e.message:String(e);process.stderr.write(`[crtrd] handover successor failed to start: ${r}
9
+ `),process.exit(1)}process.exit(0)}a(me,"performHandover");function k(){if(y!==void 0)return y;const e=de();return y=e,e.then(()=>{y===e&&(y=void 0)},()=>{y===e&&(y=void 0)}),e}a(k,"requestCleanup");async function W(e){try{await k(),process.exit(0)}catch(r){process.exitCode=1;const l=r instanceof Error?r.stack??`${r.name}: ${r.message}`:String(r);process.stderr.write(`[crtrd] ${e} cleanup failed:
8
10
  ${l}
9
- `),process.exit(1)}}a(B,"handleSignal");function W(){B("SIGINT")}a(W,"onSigint");function U(){B("SIGTERM")}a(U,"onSigterm");function q(){b().catch(()=>{})}a(q,"onExit");function N(e){f&&(w=w.then(e).then(()=>{},r=>{_.fresh(()=>{h({level:"error",event:"daemon.lane_job.failed",error:r})})}))}a(N,"enqueue");function K(){!f||v||(v=!0,N(async()=>{if(v=!1,!!f)try{await Kr(Date.now(),le)}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.tick.failed",error:e})})}}))}a(K,"enqueueTick");let D=null;async function fe(){if(D!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${D instanceof Error?D.message:String(D)}`};if(u.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(u.phase!=="prepared"&&u.phase!=="recovering")throw{status:409,code:"not_prepared",message:u.message};const e=u.phase==="prepared";try{return await G(),u={phase:"ready",message:"",blockerPaths:[]},e?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(r){throw D=r,{status:500,code:"admission_failed",message:`daemon admission failed: ${r instanceof Error?r.message:String(r)}`}}}a(fe,"admitStartup");async function ue(e){if(P!==null)throw{status:409,code:"migration_in_progress",message:`on-disk migration is already running (${P})`};P="repair";try{const r=await Rr({dryRun:e.dryRun,explicitDirs:e.dirs,nodes:Y()});if(e.dryRun||!r.finalVerificationSucceeded||u.phase!=="blocked")return{result:r,resumed:!1};if(t.prepare)return u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:r,resumed:!1};try{return await G(),u={phase:"ready",message:"",blockerPaths:[]},{result:r,resumed:!0}}catch(l){const S=l instanceof Error?l.message:String(l);return setTimeout(()=>{b().catch(()=>{})},1e3),{result:r,resumed:!1,resumeError:S}}}finally{P=null}}a(ue,"repairMigrations");async function he(){o=t.intervalMs??Ke;const e=s.token;d=new kr({epoch:e,enqueue:N}),cr(d),u={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{h({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:o}})});const r=hr();if(vr(r),_.fresh(()=>{h({level:"info",event:"daemon.install_id.resolved",fields:{install_id:r}})}),_.fresh(()=>{let l;try{l=qe()}catch{return}l!==null&&h({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:l.slice(0,2048)}})}),await _.fresh(async()=>{await Ue(),await Be(),We(Date.now())}),_.fresh(()=>{const{reconcile:l,migrated:S}=ur(er);l.changed&&h({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:l.cleared.length,same_boot_proven:l.sameBootProven}}),S.length>0&&h({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:S.length}})}),_.fresh(()=>{for(const l of br){const S=l.apply();S.changed&&h({level:"info",event:"daemon.boot_migration.applied",fields:{migration:l.id,...S.summary}})}}),A){const l=a(()=>{I(A().catch(()=>{}))},"refresh");I(Fe().catch(()=>{})),I(je().then(({completion:S})=>S).catch(S=>{h({level:"error",event:"daemon.grants.sweep_failed",error:S})})),l(),x=setInterval(l,Oe*1e3),x.unref()}N(()=>{_r(),Sr()}),c=setInterval(K,o),K()}a(he,"completeStartup");function G(){return se??=he().catch(e=>{throw u={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},e})}a(G,"resumeStartup");try{process.on("SIGINT",W),process.on("SIGTERM",U),process.on("exit",q),Pr(),m!==null&&h({level:"info",event:"daemon.joined_owner.applied",fields:{owner:m.owner,rows:m.rows}}),M=await be();const e=s.token;dr({epoch:e,requestHandover:pe,registerDetached:I,startupBlock:ce,admitStartup:fe,repairMigrations:ue}),oe(),C=Le({tcp:t.tcp}),await C.ready;const r=ze("user").runtime;r?.issuer?A=$e(r.issuer,I):Ge(),r!==void 0&&(R=Ne(r,()=>He(r.issuer.replace(/\/$/,"")),A),await R.ready);try{await Ir({nodes:Y()})}catch(l){if(P=null,l instanceof Tr)return u={phase:"blocked",message:l.message,blockerPaths:l.blockerPaths},b;throw l}process.platform==="linux"&&k(E)&&(De(),await xe("app:terminal"));try{t.prepare?u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await G(),u={phase:"ready",message:"",blockerPaths:[]})}finally{P=null}return b}catch(e){try{await b()}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}}a(Jr,"runDaemon");var nn=Jr;export{O as brokerCommandDeclaresCanvasHome,F as brokerCommandEpoch,nn as default,Jr as runDaemon,Kr as superviseTick};
11
+ `),process.exit(1)}}a(W,"handleSignal");function q(){W("SIGINT")}a(q,"onSigint");function U(){W("SIGTERM")}a(U,"onSigterm");function K(){k().catch(()=>{})}a(K,"onExit");function M(e){f&&(w=w.then(e).then(()=>{},r=>{_.fresh(()=>{h({level:"error",event:"daemon.lane_job.failed",error:r})})}))}a(M,"enqueue");function J(){!f||v||(v=!0,M(async()=>{if(v=!1,!!f)try{await Vr(Date.now(),B)}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.tick.failed",error:e})})}}))}a(J,"enqueueTick");let D=null;async function fe(){if(D!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${D instanceof Error?D.message:String(D)}`};if(u.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(u.phase!=="prepared"&&u.phase!=="recovering")throw{status:409,code:"not_prepared",message:u.message};const e=u.phase==="prepared";try{return await N(),u={phase:"ready",message:"",blockerPaths:[]},e?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(r){throw D=r,{status:500,code:"admission_failed",message:`daemon admission failed: ${r instanceof Error?r.message:String(r)}`}}}a(fe,"admitStartup");async function ue(e){if(P!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${P})`};P="repair";try{const r=await Dr({dryRun:e.dryRun});if(e.dryRun||r.pending||u.phase!=="blocked")return{result:r,resumed:!1};if(t.prepare)return u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:r,resumed:!1};try{return await N(),u={phase:"ready",message:"",blockerPaths:[]},{result:r,resumed:!0}}catch(l){const S=l instanceof Error?l.message:String(l);return setTimeout(()=>{k().catch(()=>{})},1e3),{result:r,resumed:!1,resumeError:S}}}finally{P=null}}a(ue,"repairMigrations");async function he(){o=t.intervalMs??Ke;const e=s.token;d=new Er({epoch:e,enqueue:M}),cr(d),u={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{h({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:o}})});const r=hr();if(vr(r),_.fresh(()=>{h({level:"info",event:"daemon.install_id.resolved",fields:{install_id:r}})}),_.fresh(()=>{let l;try{l=Ue()}catch{return}l!==null&&h({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:l.slice(0,2048)}})}),await _.fresh(async()=>{await qe(),await ze(),We(Date.now())}),_.fresh(()=>{const{reconcile:l,migrated:S}=ur(er);l.changed&&h({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:l.cleared.length,same_boot_proven:l.sameBootProven}}),S.length>0&&h({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:S.length}})}),_.fresh(()=>{for(const l of Pr){const S=l.apply();S.changed&&h({level:"info",event:"daemon.boot_migration.applied",fields:{migration:l.id,...S.summary}})}}),L){const l=a(()=>{I(L().catch(()=>{}))},"refresh");I(Fe().catch(()=>{})),I(je().then(({completion:S})=>S).catch(S=>{h({level:"error",event:"daemon.grants.sweep_failed",error:S})})),l(),x=setInterval(l,Oe*1e3),x.unref()}M(()=>{kr(),br()}),c=setInterval(J,o),J()}a(he,"completeStartup");function N(){return ce??=he().catch(e=>{throw u={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},e})}a(N,"resumeStartup");try{process.on("SIGINT",q),process.on("SIGTERM",U),process.on("exit",K),Rr(),m!==null&&h({level:"info",event:"daemon.joined_owner.applied",fields:{owner:m.owner,rows:m.rows}}),A=await ke();const e=s.token;dr({epoch:e,requestHandover:pe,registerDetached:I,startupBlock:le,admitStartup:fe,repairMigrations:ue}),ie(),C=$e({tcp:t.tcp}),await C.ready;const r=Be("user").runtime;r?.issuer?L=Ge(r.issuer,I):Ne(),r!==void 0&&(T=Me(r,()=>He(r.issuer.replace(/\/$/,"")),L),await T.ready);try{await Tr()}catch(l){if(P=null,l instanceof xr)return u={phase:"blocked",message:l.message,blockerPaths:l.blockerPaths},k;throw l}process.platform==="linux"&&b(E)&&(De(),await xe("app:terminal"));try{t.prepare?u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await N(),u={phase:"ready",message:"",blockerPaths:[]})}finally{P=null}return k}catch(e){try{await k()}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}}a(Yr,"runDaemon");var cn=Yr;export{O as brokerCommandDeclaresCanvasHome,F as brokerCommandEpoch,cn as default,Yr as runDaemon,Vr as superviseTick};
@@ -1,17 +1,17 @@
1
- var b=Object.defineProperty;var l=(t,e)=>b(t,"name",{value:e,configurable:!0});import{getNode as p,getRow as g,subscribersOf as k}from"../core/canvas/index.js";import{revokeExitedNodeToken as $}from"../core/canvas/node-tokens.js";import{isProfilePaused as T}from"../core/profiles/manifest.js";import{fullName as v}from"../core/canvas/labels.js";import{isSafeNodeId as o}from"../core/canvas/paths.js";import{transition as _}from"../core/runtime/lifecycle.js";import{fanDoctrineWake as P}from"../core/runtime/close.js";import{readInterruptedTurn as E,readTransportPoisonVerdict as x}from"../core/canvas/recovery.js";import{hasPendingWake as N}from"./reconcilers/live-obligation.js";import{clearRespawnPolicy as h,deferRespawnWhileOffline as R,MAX_RESPAWN_ATTEMPTS as C,OFFLINE_RESPAWN_RETRY_MS as F,recordRespawnPolicy as S,respawnBackoffMs as M}from"./reconcilers/node-lifecycle/respawn-policy.js";import{probeOnline as O}from"../core/runtime/connectivity.js";import{reviveNode as A}from"../core/runtime/revive.js";import{pushUrgent as m}from"../core/feed/feed.js";import{emitEvent as c}from"../core/events/emit.js";import{brokerThresholdsForDaemon as z}from"../core/runtime/fleet.js";import{isRecoveryHeld as D}from"../core/runtime/recovery-hold.js";function w(t,e){const r=e===void 0?"The daemon did not observe an exit status.":`The observed exit status was code ${e.code??"null"}, signal ${e.signal??"null"}.`;return`\u26A0 Spawn failed \u2014 \`${t.name}\` (${t.kind}) never started.
1
+ var b=Object.defineProperty;var l=(t,e)=>b(t,"name",{value:e,configurable:!0});import{getNode as p,getRow as g}from"../core/canvas/index.js";import{revokeExitedNodeToken as k}from"../core/canvas/node-tokens.js";import{isProfilePaused as $}from"../core/profiles/manifest.js";import{fullName as v}from"../core/canvas/labels.js";import{isSafeNodeId as o}from"../core/canvas/paths.js";import{transition as _}from"../core/runtime/lifecycle.js";import{publishNotice as T}from"../core/runtime/close.js";import{readInterruptedTurn as P,readTransportPoisonVerdict as E}from"../core/canvas/recovery.js";import{hasPendingWake as N}from"./reconcilers/live-obligation.js";import{clearRespawnPolicy as h,deferRespawnWhileOffline as x,MAX_RESPAWN_ATTEMPTS as R,OFFLINE_RESPAWN_RETRY_MS as C,recordRespawnPolicy as F,respawnBackoffMs as S}from"./reconcilers/node-lifecycle/respawn-policy.js";import{probeOnline as M}from"../core/runtime/connectivity.js";import{reviveNode as A}from"../core/runtime/revive.js";import{pushUrgent as m}from"../core/feed/feed.js";import{emitEvent as c}from"../core/events/emit.js";import{brokerThresholdsForDaemon as O}from"../core/runtime/fleet.js";import{isRecoveryHeld as z}from"../core/runtime/recovery-hold.js";function w(t,e){const r=e===void 0?"The daemon did not observe an exit status.":`The observed exit status was code ${e.code??"null"}, signal ${e.signal??"null"}.`;return`\u26A0 Spawn failed \u2014 \`${t.name}\` (${t.kind}) never started.
2
2
 
3
3
  Its pi vehicle exited before the session came up (no pi_session_id was ever recorded), so the node produced no output. ${r}
4
4
 
5
5
  Inspect canonical event diagnostics with \`crtr sys logs --node ${t.node_id}\`.
6
6
 
7
- If the work still needs doing, re-spawn it.`}l(w,"bootFailureBody");async function y(t,e){await m(t.node_id,w(t,e),{from:t.node_id})}l(y,"surfaceBootFailure");async function B(t){const e=x(t.node_id),r=e===null?"":`
7
+ If the work still needs doing, re-spawn it.`}l(w,"bootFailureBody");async function y(t,e){await m(t.node_id,w(t,e),{from:t.node_id})}l(y,"surfaceBootFailure");async function D(t){const e=E(t.node_id),r=e===null?"":`
8
8
 
9
9
  Provider rotation observed ${e.consecutivePasses} consecutive route-queue passes with no HTTP response (tried ${e.routes.join(", ")}). Check network and provider transport before reviving.`,i=`\u26A0 Crash loop \u2014 \`${t.name}\` (${t.kind}) kept dying without settling a turn.
10
10
 
11
11
  Its session started successfully, but six consecutive relaunches made no progress, so the daemon stopped retrying.`+r+`
12
12
 
13
- Fix the crash cause, then revive the node if the work still needs doing.`;await m(t.node_id,i,{from:t.node_id})}l(B,"surfaceCrashLoop");async function L(t,e){const r=e instanceof Error?e.message:String(e),i=`\u26A0 Recovery failed \u2014 \`${t.name}\` (${t.kind}) could not be relaunched.
13
+ Fix the crash cause, then revive the node if the work still needs doing.`;await m(t.node_id,i,{from:t.node_id})}l(D,"surfaceCrashLoop");async function B(t,e){const r=e instanceof Error?e.message:String(e),i=`\u26A0 Recovery failed \u2014 \`${t.name}\` (${t.kind}) could not be relaunched.
14
14
 
15
15
  The daemon refused this recovery before starting a broker: ${r}
16
16
 
17
- The node is now dead. Fix the recorded launch configuration, then revive it if the work still needs doing.`;await m(t.node_id,i,{from:t.node_id})}l(L,"surfaceRecoveryFailure");function W(t){return t?.cycle_pending!==!0}l(W,"retryResumeMode");function q(t,e,r=!0){return t===null||t.status==="done"||t.status==="canceled"||t.status==="dead"?"forget":t.intent==="refresh"?"respawn-fresh":t.intent==="idle-release"?"dormant":t.lifecycle==="resident"&&!e&&!r&&t.pi_session_id!=null?"release-idle":t.pi_session_id!=null?W(t)?"respawn-resume":"respawn-cycle":e||t.fork_from!=null?"respawn-fresh":"boot-failure"}l(q,"classifyDeadNode");const G=3e4;class ne{static{l(this,"DaemonFleet")}#n;#o;#i;#l;#e=new Map;#r=new Set;#s=new Set;#t=new Map;#c=Number.NEGATIVE_INFINITY;constructor(e){this.#n=e.epoch,this.#o=e.enqueue,this.#i=e.now??Date.now,this.#l=e.probeOnline??(()=>O())}epoch(){return this.#n}register(e,r){if(this.#e.has(e))throw new Error(`fleet: ${e} already has a live broker entry \u2014 refusing a second launch (programming error)`);if(r.pid===null)throw new Error(`fleet: refusing to register ${e} with no pid`);this.#r.delete(e),this.#t.delete(e),this.#e.set(e,{pid:r.pid,handle:r})}has(e){return this.#e.has(e)}isClaimed(e){return this.#e.has(e)||this.#r.has(e)}get(e){return this.#e.get(e)}size(){return this.#e.size}occupancy(){return this.#e.size+this.#r.size}reserveSlot(e){if(this.#r.has(e)||this.#e.has(e))return!0;const{automaticReviveCap:r}=z();if(this.occupancy()<r)return this.#r.add(e),!0;const i=this.#i();return i-this.#c>=G&&(this.#c=i,c({level:"warn",event:"broker.capacity.revive_deferred",fields:{live_count:this.occupancy(),hard_cap:r}})),!1}releaseReservation(e){this.#r.delete(e)}entries(){return this.#e.entries()}interruptForProfilePause(e,r=this.#e.get(e)?.pid){if(r!==void 0){this.#s.add(e);try{process.kill(r,"SIGTERM")}catch{}}}hasProfilePauseInterruption(e){return this.#s.has(e)}forget(e){this.#e.delete(e),this.#r.delete(e),this.#t.delete(e)}onChildExit(e,r,i){i&&$(i),this.#e.delete(e),this.#o(()=>{const s=p(e),a=s?.launched_at==null?Number.NaN:Date.parse(s.launched_at),n=Number.isFinite(a)?Math.max(0,this.#i()-a):null,d=s?.respawn_failures??0;s?.status==="done"||s?.status==="canceled"||s?.status==="dead"?this.#t.delete(e):this.#t.set(e,r),this.#u(e,r,n,d)})}deliverExit(e,r){this.onChildExit(e,r)}async applyDeadRowPolicy(e){const r=this.#t.get(e);try{await this.#f(e,r)}finally{this.#t.get(e)===r&&this.#t.delete(e)}}async terminalizeIfStillNonTerminal(e,r,i,s,a){const n=p(e);return n===null||n.status==="done"||n.status==="canceled"||n.status==="dead"?!1:(await this.#a(e,n,{event:r,reason:s,detail:a,wake:`Child crashed \u2014 ${v(n)} (${e}) could not be relaunched and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,surface:l(()=>L(n,i),"surface")}),!0)}dispose(){}#u(e,r,i,s){c({level:"info",event:"broker.exit.observed",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},code:r.code,signal:r.signal,uptime_ms:i,consecutive_failures:s}})}async#f(e,r){return this.#h(e,r)}async#h(e,r){const i=p(e);if(i!==null&&T(i.profile_id))return h(e),"forget";if(this.#s.delete(e))return h(e),"forget";if(D(e))return"dormant";const s=E(e)?.interrupted===!0,a=q(i,s,N(e));switch(a){case"forget":h(e);break;case"dormant":h(e);break;case"release-idle":h(e),_(e,"release"),c({level:"info",event:"broker.recovery.released",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e}}});break;case"boot-failure":await this.#a(e,i,{event:"broker.boot.failed",reason:"boot_failed",detail:{schema:"crtr.node-outcome-detail/v1",message:w(i,r)},wake:`Child crashed \u2014 ${v(i)} (${e}) exited before its session ever came up and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,surface:l(()=>y(i,r),"surface")});break;case"respawn-fresh":case"respawn-cycle":case"respawn-resume":await this.#d(e,i,a,s);break}return a}async#d(e,r,i,s){const a=g(e);if(a===null)return;const n=a.respawn_failures??0;if(!await this.#l()){R(e,n,this.#i()),c({level:"info",event:"broker.respawn.offline_deferred",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,retry_in_ms:F,consecutive_failures:n}});return}const d=a.respawn_not_before==null,f=d?S(a,this.#i()):{failures:n,notBefore:a.respawn_not_before,exhausted:n>=C};if(f.exhausted){const u=`Child crashed \u2014 ${v(r)} (${e}) kept dying without settling a turn (${f.failures} consecutive launches) and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`;await this.#a(e,r,{event:"broker.respawn.exhausted",reason:"crash_looped",detail:{schema:"crtr.node-outcome-detail/v1",message:u,respawn_failures:f.failures},wake:u,...r.pi_session_id!=null?{surface:l(()=>B(r),"surface")}:{}});return}if(d&&f.notBefore!==null){c({level:"info",event:"broker.respawn.deferred",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,backoff_ms:M(f.failures),consecutive_failures:f.failures}});return}c({level:"info",event:"broker.respawn.started",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,consecutive_failures:f.failures}});try{await A(e,{capacity:"freeze",resume:i==="respawn-resume",wakeReason:i==="respawn-resume"&&s?"runtime-restart-abort":void 0,recovery:!0})}catch(u){c({level:"error",event:"broker.respawn.failed",...o(e)?{node_id:e}:{},error:u,fields:{...o(e)?{}:{affected_node_id:e},action:i}}),await this.terminalizeIfStillNonTerminal(e,"broker.respawn.refused",u,"launch_failed",{schema:"crtr.node-outcome-detail/v1",message:u instanceof Error?u.message:String(u)})}}async#a(e,r,i){c({level:"error",event:i.event,...o(e)?{node_id:e}:{fields:{affected_node_id:e}}}),_(e,"crash",{reason:i.reason,outcome:{detail:i.detail}});try{await(i.surface??(()=>y(r)))()}catch(s){c({level:"error",event:"broker.boot_failure_surface.failed",...o(e)?{node_id:e}:{fields:{affected_node_id:e}},error:s})}P(e,k(e),i.wake,{reason:"child-crashed",child:e})}}export{ne as DaemonFleet,q as classifyDeadNode,W as retryResumeMode,y as surfaceBootFailure};
17
+ The node is now dead. Fix the recorded launch configuration, then revive it if the work still needs doing.`;await m(t.node_id,i,{from:t.node_id})}l(B,"surfaceRecoveryFailure");function L(t){return t?.cycle_pending!==!0}l(L,"retryResumeMode");function W(t,e,r=!0){return t===null||t.status==="done"||t.status==="canceled"||t.status==="dead"?"forget":t.intent==="refresh"?"respawn-fresh":t.intent==="idle-release"?"dormant":t.lifecycle==="resident"&&!e&&!r&&t.pi_session_id!=null?"release-idle":t.pi_session_id!=null?L(t)?"respawn-resume":"respawn-cycle":e||t.fork_from!=null?"respawn-fresh":"boot-failure"}l(W,"classifyDeadNode");const q=3e4;class ne{static{l(this,"DaemonFleet")}#a;#o;#i;#l;#e=new Map;#r=new Set;#s=new Set;#t=new Map;#c=Number.NEGATIVE_INFINITY;constructor(e){this.#a=e.epoch,this.#o=e.enqueue,this.#i=e.now??Date.now,this.#l=e.probeOnline??(()=>M())}epoch(){return this.#a}register(e,r){if(this.#e.has(e))throw new Error(`fleet: ${e} already has a live broker entry \u2014 refusing a second launch (programming error)`);if(r.pid===null)throw new Error(`fleet: refusing to register ${e} with no pid`);this.#r.delete(e),this.#t.delete(e),this.#e.set(e,{pid:r.pid,handle:r})}has(e){return this.#e.has(e)}isClaimed(e){return this.#e.has(e)||this.#r.has(e)}get(e){return this.#e.get(e)}size(){return this.#e.size}occupancy(){return this.#e.size+this.#r.size}reserveSlot(e){if(this.#r.has(e)||this.#e.has(e))return!0;const{automaticReviveCap:r}=O();if(this.occupancy()<r)return this.#r.add(e),!0;const i=this.#i();return i-this.#c>=q&&(this.#c=i,c({level:"warn",event:"broker.capacity.revive_deferred",fields:{live_count:this.occupancy(),hard_cap:r}})),!1}releaseReservation(e){this.#r.delete(e)}entries(){return this.#e.entries()}interruptForProfilePause(e,r=this.#e.get(e)?.pid){if(r!==void 0){this.#s.add(e);try{process.kill(r,"SIGTERM")}catch{}}}hasProfilePauseInterruption(e){return this.#s.has(e)}forget(e){this.#e.delete(e),this.#r.delete(e),this.#t.delete(e)}onChildExit(e,r,i){i&&k(i),this.#e.delete(e),this.#o(()=>{const s=p(e),n=s?.launched_at==null?Number.NaN:Date.parse(s.launched_at),a=Number.isFinite(n)?Math.max(0,this.#i()-n):null,d=s?.respawn_failures??0;s?.status==="done"||s?.status==="canceled"||s?.status==="dead"?this.#t.delete(e):this.#t.set(e,r),this.#u(e,r,a,d)})}deliverExit(e,r){this.onChildExit(e,r)}async applyDeadRowPolicy(e){const r=this.#t.get(e);try{await this.#f(e,r)}finally{this.#t.get(e)===r&&this.#t.delete(e)}}async terminalizeIfStillNonTerminal(e,r,i,s,n){const a=p(e);return a===null||a.status==="done"||a.status==="canceled"||a.status==="dead"?!1:(await this.#n(e,a,{event:r,reason:s,detail:n,wake:`Child crashed \u2014 ${v(a)} (${e}) could not be relaunched and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,surface:l(()=>B(a,i),"surface")}),!0)}dispose(){}#u(e,r,i,s){c({level:"info",event:"broker.exit.observed",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},code:r.code,signal:r.signal,uptime_ms:i,consecutive_failures:s}})}async#f(e,r){return this.#h(e,r)}async#h(e,r){const i=p(e);if(i!==null&&$(i.profile_id))return h(e),"forget";if(this.#s.delete(e))return h(e),"forget";if(z(e))return"dormant";const s=P(e)?.interrupted===!0,n=W(i,s,N(e));switch(n){case"forget":h(e);break;case"dormant":h(e);break;case"release-idle":h(e),_(e,"release"),c({level:"info",event:"broker.recovery.released",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e}}});break;case"boot-failure":await this.#n(e,i,{event:"broker.boot.failed",reason:"boot_failed",detail:{schema:"crtr.node-outcome-detail/v1",message:w(i,r)},wake:`Child crashed \u2014 ${v(i)} (${e}) exited before its session ever came up and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,surface:l(()=>y(i,r),"surface")});break;case"respawn-fresh":case"respawn-cycle":case"respawn-resume":await this.#d(e,i,n,s);break}return n}async#d(e,r,i,s){const n=g(e);if(n===null)return;const a=n.respawn_failures??0;if(!await this.#l()){x(e,a,this.#i()),c({level:"info",event:"broker.respawn.offline_deferred",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,retry_in_ms:C,consecutive_failures:a}});return}const d=n.respawn_not_before==null,f=d?F(n,this.#i()):{failures:a,notBefore:n.respawn_not_before,exhausted:a>=R};if(f.exhausted){const u=`Child crashed \u2014 ${v(r)} (${e}) kept dying without settling a turn (${f.failures} consecutive launches) and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`;await this.#n(e,r,{event:"broker.respawn.exhausted",reason:"crash_looped",detail:{schema:"crtr.node-outcome-detail/v1",message:u,respawn_failures:f.failures},wake:u,...r.pi_session_id!=null?{surface:l(()=>D(r),"surface")}:{}});return}if(d&&f.notBefore!==null){c({level:"info",event:"broker.respawn.deferred",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,backoff_ms:S(f.failures),consecutive_failures:f.failures}});return}c({level:"info",event:"broker.respawn.started",...o(e)?{node_id:e}:{},fields:{...o(e)?{}:{affected_node_id:e},action:i,consecutive_failures:f.failures}});try{await A(e,{capacity:"freeze",resume:i==="respawn-resume",wakeReason:i==="respawn-resume"&&s?"runtime-restart-abort":void 0,recovery:!0})}catch(u){c({level:"error",event:"broker.respawn.failed",...o(e)?{node_id:e}:{},error:u,fields:{...o(e)?{}:{affected_node_id:e},action:i}}),await this.terminalizeIfStillNonTerminal(e,"broker.respawn.refused",u,"launch_failed",{schema:"crtr.node-outcome-detail/v1",message:u instanceof Error?u.message:String(u)})}}async#n(e,r,i){c({level:"error",event:i.event,...o(e)?{node_id:e}:{fields:{affected_node_id:e}}}),_(e,"crash",{reason:i.reason,outcome:{detail:i.detail}});try{await(i.surface??(()=>y(r)))()}catch(s){c({level:"error",event:"broker.boot_failure_surface.failed",...o(e)?{node_id:e}:{fields:{affected_node_id:e}},error:s})}T(e,"notice.crash",i.wake,{reason:"child-crashed",child:e})}}export{ne as DaemonFleet,W as classifyDeadNode,L as retryResumeMode,y as surfaceBootFailure};
@@ -9,9 +9,19 @@ export interface BashDeadlineContext {
9
9
  * alive. This lane is the enforcer: it survives a broker restart and fires while
10
10
  * the node is idle, so a runaway command cannot outlive its window just because
11
11
  * the agent moved on. A deliberately backgrounded job carries no deadline and is
12
- * never touched here. */
12
+ * never canceled here. It also publishes every backgrounded job's exit, and adopts
13
+ * a job the broker backgrounded while exiting (SIGTERM/SIGHUP), which could not
14
+ * record its own job object. */
13
15
  export declare class BashDeadlineReconciler {
14
16
  private lastScanAt;
17
+ /** An exit written before this daemon started is history, not a job to adopt. */
18
+ private readonly startedAt;
15
19
  run(now: number, ctx: BashDeadlineContext): Promise<void>;
20
+ /** A running job whose supervisor wrote job.exit has exited: `finishJob` publishes `exited`
21
+ * once (the row leaves `running`). A job being stopped (job.stop) is ended by its killer. */
22
+ private publishExits;
23
+ /** Give every backgrounded job dir (job.bg) that has no job object one; the next tick's
24
+ * `publishExits` then ends it like any other job. */
25
+ private adoptUnrecorded;
16
26
  private cancel;
17
27
  }
@@ -1 +1,2 @@
1
- var p=Object.defineProperty;var m=(l,t)=>p(l,"name",{value:t,configurable:!0});import{bashJobPaths as b,completedBackgroundBashJobs as _,expiredAutoBackgroundBashJobs as g,formatBashElapsed as h,stopBackgroundBashJob as y}from"../../core/bash-jobs.js";import{isSafeNodeId as n}from"../../core/canvas/paths.js";import{contextDir as k}from"../../core/canvas/node-agent-paths.js";import{enqueueNodeMail as u}from"../../core/feed/messages.js";import{emitEvent as i}from"../../core/events/emit.js";import{operationIdContext as c}from"../../core/events/operation-id.js";import{isProfilePaused as $}from"../../core/profiles/manifest.js";const v=5*1e3;class E{static{m(this,"BashDeadlineReconciler")}lastScanAt=Number.NEGATIVE_INFINITY;async run(t,a){if(!(t-this.lastScanAt<v)){this.lastScanAt=t;for(const e of a.rows){if(e.status==="dead"||$(e.profile_id))continue;const r=k(e.node_id);let s;try{s=g(r,t)}catch(o){c.fresh(()=>{i({level:"error",event:"bash_deadline.scan_failed",...n(e.node_id)?{node_id:e.node_id}:{},error:o})});continue}if(process.platform==="linux")try{for(const o of _(r)){const d=b(r,o.jobId),f=`Background bash job ${o.jobId} finished (exit ${o.exitCode}) after ${h(t-o.startedAtMs)}. Log: ${d.jobLog} Command: ${d.cmdSh}`;u(e.node_id,{senderNodeId:null,urgency:"urgent",wake:1,kind:"message",label:f.slice(0,120),bodyJson:{body:f},idempotencyKey:`bash-completed:${e.node_id}:${o.jobId}`})}}catch(o){c.fresh(()=>i({level:"error",event:"bash_completion.delivery_failed",...n(e.node_id)?{node_id:e.node_id}:{},error:o}))}for(const o of s)await this.cancel(e.node_id,r,o.jobId,t-o.startedAtMs)}}}async cancel(t,a,e,r){if((await y(a,e,!1,t)).kind!=="stopped")return;const o=b(a,e);c.fresh(()=>{try{i({level:"info",event:"bash_deadline.canceled",...n(t)?{node_id:t}:{},fields:{job_id:e}}),u(t,{senderNodeId:null,urgency:"urgent",wake:1,kind:"urgent",label:"background bash job canceled at its deadline",bodyJson:{body:`Background bash job ${e} was canceled after ${h(r)} because its background deadline passed and you did not claim it. Next time, give a long command more room up front (a larger inline timeout), or claim the job with \`crtr node bash extend ${e} --for <duration>\` before the deadline. Log: ${o.jobLog} Command: ${o.cmdSh}`}})}catch(d){i({level:"error",event:"bash_deadline.notice_failed",...n(t)?{node_id:t}:{},error:d,fields:{job_id:e}})}})}}export{E as BashDeadlineReconciler};
1
+ var p=Object.defineProperty;var f=(l,e)=>p(l,"name",{value:e,configurable:!0});import{existsSync as s,readFileSync as m,readdirSync as u,statSync as j}from"node:fs";import{join as b}from"node:path";import{bashJobPaths as _,bashJobsDir as S,expiredAutoBackgroundBashJobs as x,stopBackgroundBashJob as y}from"../../core/bash-jobs.js";import{killBashJobObject as N,recordBashJobObject as E}from"../../core/spaces/stop.js";import{withCanvasWrite as h}from"../../core/canvas/db.js";import{finishJob as v}from"../../core/graph/jobs.js";import{getById as g,getByRowid as A}from"../../core/graph/objects.js";import{isSafeNodeId as c}from"../../core/canvas/paths.js";import{contextDir as B}from"../../core/canvas/node-agent-paths.js";import{emitEvent as a}from"../../core/events/emit.js";import{operationIdContext as d}from"../../core/events/operation-id.js";import{isProfilePaused as J}from"../../core/profiles/manifest.js";const w=5*1e3;class W{static{f(this,"BashDeadlineReconciler")}lastScanAt=Number.NEGATIVE_INFINITY;startedAt=Date.now();async run(e,n){if(this.publishExits(),!(e-this.lastScanAt<w)){this.lastScanAt=e;for(const t of n.rows){if(t.status==="dead"||J(t.profile_id))continue;const i=B(t.node_id);let r;try{this.adoptUnrecorded(t.node_id,i),r=x(i,e)}catch(o){d.fresh(()=>{a({level:"error",event:"bash_deadline.scan_failed",...c(t.node_id)?{node_id:t.node_id}:{},error:o})});continue}for(const o of r)await this.cancel(t.node_id,i,o.jobId)}}}publishExits(){try{h(e=>{const n=e.prepare(`SELECT j.object, j.job_dir FROM jobs j JOIN objects o ON o.rowid = j.object
2
+ WHERE j.status = 'running' AND o.deleted_at IS NULL`).all();for(const{object:t,job_dir:i}of n){const r=b(i,"job.exit");if(!s(r)||s(b(i,"job.stop")))continue;const o=Number(m(r,"utf8").trim());Number.isSafeInteger(o)&&v(e,A(e,t),{exitCode:o})}})}catch(e){d.fresh(()=>a({level:"error",event:"bash_completion.delivery_failed",error:e}))}}adoptUnrecorded(e,n){let t;try{t=u(S(n))}catch{return}const i=h(r=>t.filter(o=>g(r,o)===null));for(const r of i){const o=_(n,r);!s(o.jobBg)||!s(o.cmdSh)||s(o.jobExit)&&j(o.jobExit).mtimeMs<this.startedAt||E(e,r,{command:m(o.cmdSh,"utf8"),jobDir:o.dir,logPath:o.jobLog})}}async cancel(e,n,t){(await y(n,t,!1,e)).kind==="stopped"&&d.fresh(()=>{try{a({level:"info",event:"bash_deadline.canceled",...c(e)?{node_id:e}:{},fields:{job_id:t}}),N(t,()=>null,"deadline")}catch(r){a({level:"error",event:"bash_deadline.notice_failed",...c(e)?{node_id:e}:{},error:r,fields:{job_id:t}})}})}}export{W as BashDeadlineReconciler};
@@ -1,4 +1,4 @@
1
- var H=Object.defineProperty;var m=(o,e)=>H(o,"name",{value:e,configurable:!0});import{existsSync as j,statSync as K}from"node:fs";import{join as $}from"node:path";import{LAUNCHER_SOCKET as V}from"../../launcher/spec.js";import{launcherRequest as z}from"../../launcher/client.js";import{secretsDir as J}from"../../core/layout.js";import{execFile as Q}from"node:child_process";import{promisify as X}from"node:util";import{getNode as A,isWarmSpare as Z,subscribersOf as D}from"../../core/canvas/index.js";import{isSafeNodeId as u}from"../../core/canvas/paths.js";import{contextDir as ee}from"../../core/canvas/node-agent-paths.js";import{fullName as I}from"../../core/canvas/labels.js";import{recordedPidLiveness as O}from"../../core/canvas/pid.js";import{transition as te}from"../../core/runtime/lifecycle.js";import{readFault as L,readLiveTurn as C,recordFault as ne}from"../../core/canvas/recovery.js";import{errorClassFromFault as re}from"../../core/fault-classifier.js";import{nextFaultRetry as ie}from"../../core/runtime/fault-recovery.js";import{fanDoctrineWake as G}from"../../core/runtime/close.js";import{headlessBrokerHost as v}from"../../core/runtime/host.js";import{reloadAuthLive as ae}from"../../core/runtime/auth-reload.js";import{emitEvent as f}from"../../core/events/emit.js";import{operationIdContext as R}from"../../core/events/operation-id.js";import{hasUnseenWakeMail as se,resetStaleExecutionMail as oe}from"../../core/canvas/deliveries.js";import{activeBackgroundBashJobs as le}from"../../core/bash-jobs.js";import{focusOf as de}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as ce}from"../api/viewer-presence.js";import{deliverLive as ue}from"../../core/runtime/interactive-deliver.js";import{BrokerUnreachableError as fe}from"../../core/runtime/broker-request.js";import{formatCard as pe,PARK_SUMMARY_PROMPT as me}from"../../shared/generated-context.js";import{brokerThresholdsForDaemon as he}from"../../core/runtime/fleet.js";import{readConfig as _e}from"../../core/config.js";import{scopedStoreExists as ge}from"../../core/scoped-state/db.js";import{providerStore as ve}from"../../core/scoped-state/paths.js";import{providerRevision as ke}from"../../core/scoped-state/providers.js";import{beginPendingPark as ye,consumePendingPark as y,pendingParkIds as we,pendingParkStartedAt as be}from"../park-pending.js";import{shouldParkAfterSummary as Se}from"../park-activity.js";import{applyParkEvent as w,parkEvent as Ae}from"./live-obligation.js";import{envNoDaemonAutostart as Ne,envTestUnattendedParkMs as Pe,parkSummaryGraceMs as Me,envUnattendedParkMs as Te}from"../../shared/env.js";const N=X(Q);function Ee(o){return C(o)?.busy===!0}m(Ee,"liveBusy");function bt(o){const e=C(o)?.progressAt;if(e==null)return null;const t=Date.parse(e);return Number.isNaN(t)?null:t}m(bt,"liveTurnProgressMs");function W(o,e){return e===null?null:`${o}:${e}`}m(W,"incarnationOf");function F(o){const e=C(o.node_id),t=e?.busy===!0&&e.progressAt!==null?Date.parse(e.progressAt):Number.NaN,i=o.launched_at===null||o.launched_at===void 0?Number.NaN:Date.parse(o.launched_at);return!Number.isFinite(t)||!Number.isFinite(i)||t<i?null:t}m(F,"busySinceForIncarnation");const U=3*6e4,B=2e4,x=20*6e4,$e=2,Ce=5*6e4;function Re(){const o=Te();if(o!==void 0)return o;const e=_e("user").lifecycle.unattendedParkMs;return Ne()?Pe()??e:e}m(Re,"unattendedParkMsForDaemon");function q(){return Me()}m(q,"parkSummaryGraceMsForDaemon");function Fe(o,e,t,i){return o!==!0||e!=="refresh"||t?"leave":i===null||i<U?"pending":"kill"}m(Fe,"yieldStallVerdict");function xe(o){return!o.busy||o.quietForMs===null||o.quietForMs<x?"leave":o.cpuPercent===null||o.hasDescendants!==!1&&o.cpuPercent>$e?"pending":"wedged"}m(xe,"wedgeVerdict");function Y(o){const e=new Map,t=new Map;for(const i of o.split(`
2
- `)){const a=i.trim();if(a==="")continue;const n=a.split(/\s+/);if(n.length<3)continue;const s=Number(n[0]),r=Number(n[1]),d=Number(n[2]);if(!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(d))continue;e.set(s,d);const c=t.get(r);c===void 0?t.set(r,[s]):c.push(s)}return{byPid:e,childrenOf:t}}m(Y,"parsePsTree");function De(o,e){const{byPid:t,childrenOf:i}=Y(o);if(!t.has(e))return null;let a=0;const n=[e],s=new Set;for(;n.length>0;){const r=n.pop();if(s.has(r))continue;s.add(r),a+=t.get(r)??0;const d=i.get(r);d!==void 0&&n.push(...d)}return a}m(De,"sumTreeCpu");function Ie(o,e){const{byPid:t,childrenOf:i}=Y(o);return t.has(e)?(i.get(e)??[]).length>0:null}m(Ie,"treeHasDescendants");function Oe(o){return[$(o,"auth.json"),$(o,"anthropic-credentials.json"),$(o,"openai-codex-credentials.json")]}m(Oe,"piCredentialPaths");class St{static{m(this,"BrokerSupervisionReconciler")}yieldStalls=new Map;wedgeNotifiedAt=new Map;fatalFaultNotifiedAt=new Map;unattendedSince=new Map;sampleTree;signal;knownCredentialRevision=null;lastOverCapWarnAt=Number.NEGATIVE_INFINITY;constructor(e={}){this.sampleTree=e.readTreeSample??(t=>this.readTreeSample(t)),this.signal=e.signal??((t,i)=>{if(process.platform==="linux"&&j(V)){if(i!=="SIGTERM"&&i!=="SIGKILL")throw new Error(`unsupported launcher signal ${i}`);return z({operation:"stop",pid:t,signal:i}).then(()=>{})}process.kill(t,i)})}async runFleetPreamble(e){return await this.handleAuthReload(e),he()}warnIfSaturated(e){if(e.fleet.size()<e.thresholds.warning||!e.lifecycle.acceptsDetachedWork())return;const t=R.fresh(()=>this.warnOverCapInTmux(e.fleet.size(),e.thresholds,e.frozen));e.lifecycle.registerDetached(t)}async run(e,t){const i=Re();for(const a of t.rows){const n=a.node_id,s=t.fleet.get(n);if(s===void 0||a.status!=="active"&&a.status!=="idle"){this.unattendedSince.delete(n);continue}await R.fresh(async()=>{try{await this.handleYieldStall(a,s,t.fleet,e),await this.handleWedgeDetection(a,s,t.fleet,e),this.handleFatalFault(n),this.handleUnattendedParking(n,A(n),s.pid,e,t,i)}catch(r){this.unattendedSince.delete(n),f({level:"error",event:"broker.supervision.failed",...u(n)?{node_id:n}:{fields:{affected_node_id:n}},error:r})}})}for(const a of this.unattendedSince.keys())t.fleet.has(a)||this.unattendedSince.delete(a);for(const a of we())t.fleet.has(a)||y(a);oe(e)}parkResetCondition(e,t,i,a){if(t.pi_session_id==null||t.pi_pid!==i||t.status==="done"||t.status==="canceled"||t.status==="dead"||t.intent!==null||le(ee(e)).length>0||de(e)!==null||ce(e))return!0;const n=L(e);return n!==null&&n.retry.disposition==="auto"&&n.retry.by==="daemon"&&(n.kind==="connection"||n.kind==="rate-limit"||n.kind==="overloaded")&&(n.retry.nextAt!==void 0||ie(n,a)!==null)?!0:se(e)}handleUnattendedParking(e,t,i,a,n,s){if(Z(e)){this.unattendedSince.delete(e),y(e);return}if(t===null){this.unattendedSince.delete(e),y(e);return}const r=this.parkResetCondition(e,t,i,a),d=be(e);if(d!==void 0){if(a-d<q())return;const p=y(e);if(p===void 0||(this.unattendedSince.delete(e),!Se(e,t,p)))return;f({level:"warn",event:"broker.park.summary_expired",...u(e)?{node_id:e}:{},fields:{...u(e)?{}:{affected_node_id:e},grace_ms:q()}}),w(e,"park"),v.teardown(e);return}if(r||Ee(e)){this.unattendedSince.delete(e);return}const c=this.unattendedSince.get(e);if(c===void 0){this.unattendedSince.set(e,a);return}if(a-c<s)return;this.unattendedSince.delete(e);const l=Ae(e,t.lifecycle);if(l==="release"){w(e,l),v.teardown(e);return}if(l==="cancel"){w(e,l),v.teardown(e);return}if(t.grantee!==void 0&&t.grantee!=="app:terminal"){w(e,"park"),v.teardown(e);return}n.lifecycle.acceptsDetachedWork()&&(ye(e,a),n.lifecycle.registerDetached(this.requestParkSummary(e)))}async requestParkSummary(e){try{const t=await ue(e,pe("park",{},me),{origin:{type:"runtime",kind:"park"}});f({level:"info",event:"broker.park.summary_requested",...u(e)?{node_id:e}:{},fields:{...u(e)?{}:{affected_node_id:e},route:t}})}catch(t){if(y(e)===void 0)return;if(t instanceof fe){w(e,"park"),v.teardown(e);return}f({level:"error",event:"broker.park.summary_failed",...u(e)?{node_id:e}:{fields:{affected_node_id:e}},error:t})}}async warnOverCapInTmux(e,t,i){const a=Date.now();if(a-this.lastOverCapWarnAt<Ce)return;this.lastOverCapWarnAt=a;const{warning:n,automaticReviveCap:s}=t,r=i.stalled+i.waitingOnMail;f({level:"warn",event:"broker.capacity.warning",fields:{live_count:e,warning_threshold:n,hard_cap:s,frozen_stalled:i.stalled,frozen_waiting_on_mail:i.waitingOnMail}});const d=r===0?"":` \u2014 ${r} frozen (${i.stalled} stalled, ${i.waitingOnMail} waiting on mail)`,c=`\u26A0 crtrd: ${e} live brokers (warning ${n}; hard cap ${s})${d} \u2014 possible broker leak. ps -ax | grep broker-cli.js`;try{const l=await N("tmux",["list-clients","-F","#{client_name}"],{encoding:"utf8",timeout:2e3});if(typeof l.stdout!="string")return;await Promise.allSettled(l.stdout.split(`
3
- `).map(async p=>{if(p!=="")try{await N("tmux",["display-message","-C","-d","10000","-c",p,c],{encoding:"utf8",timeout:2e3})}catch{try{await N("tmux",["display-message","-c",p,c],{encoding:"utf8",timeout:2e3})}catch(h){f({level:"error",event:"broker.capacity.tmux_display_failed",error:h,fields:{client:p}})}}}))}catch(l){f({level:"error",event:"broker.capacity.tmux_list_clients_failed",error:l})}}async handleYieldStall(e,t,i,a){const n=e.node_id,s=W(t.pid,e.pi_pid_identity);if(e.intent!=="refresh"||F(e)!==null||s===null){s!==null&&this.yieldStalls.delete(s);return}let r=this.yieldStalls.get(s);if(r===void 0){r={since:a},this.yieldStalls.set(s,r);return}if(Fe(!0,e.intent,!1,a-r.since)!=="kill")return;const d=A(n);if(!(i.get(n)!==t||d?.pi_pid!==t.pid||d.pi_pid_identity!==e.pi_pid_identity||O(t.pid,e.pi_pid_identity)!=="alive"))if(r.termedAt===void 0){if(!await this.signalYieldStall(n,t.pid,"SIGTERM"))return;r.termedAt=a,f({level:"warn",event:"broker.yield_stall.sigterm",...u(n)?{node_id:n}:{},fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:a-r.since,grace_ms:U}})}else a-r.termedAt>=B&&await this.signalYieldStall(n,t.pid,"SIGKILL")&&f({level:"warn",event:"broker.yield_stall.sigkill",...u(n)?{node_id:n}:{},fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:a-r.termedAt,grace_ms:B,stall_elapsed_ms:a-r.since}})}async signalYieldStall(e,t,i){try{return await this.signal(t,i),!0}catch(a){return f({level:"error",event:"broker.yield_stall.signal_failed",...u(e)?{node_id:e}:{},error:a,fields:{...u(e)?{}:{affected_node_id:e},pid:t,signal:i}}),!1}}async readTreeSample(e){try{const{stdout:t}=await N("ps",["-ax","-o","pid=,ppid=,pcpu="],{encoding:"utf8",timeout:2e3});if(typeof t!="string")return null;const i=De(t,e),a=Ie(t,e);return i===null||a===null?null:{cpuPercent:i,hasDescendants:a}}catch{return null}}async handleWedgeDetection(e,t,i,a){const n=e.node_id,s=W(t.pid,e.pi_pid_identity),r=F(e);if(r===null||s===null){s!==null&&this.wedgeNotifiedAt.delete(s);return}const d=a-r,c=d>=x?await this.sampleTree(t.pid):null,l=A(n),p=l===null?null:F(l);if(i.get(n)!==t||l===null||l.pi_pid!==t.pid||l.pi_pid_identity!==e.pi_pid_identity||p!==r)return;const h=c?.cpuPercent??null,_=c?.hasDescendants??null;if(xe({busy:!0,quietForMs:d,cpuPercent:h,hasDescendants:_})!=="wedged"||this.wedgeNotifiedAt.get(s)===r)return;this.wedgeNotifiedAt.set(s,r);const b=I(l),S=Math.round((d??x)/6e4),P=_??!0,k=!P&&O(t.pid,e.pi_pid_identity)!=="alive"?"pid_identity_unproven":null;let M=!1,T=!1,g;if(P)g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and its process is near-idle. It will NOT recover on its own \u2014 read \`crtr memory read wedged-child-on-runaway-bash\` and kill the runaway SUBPROCESS (not this node) so its turn can resume with no lost context.`;else if(k!==null)g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon did not SIGTERM the broker because its PID identity cannot be confirmed alive.`;else{M=!0;try{await this.signal(t.pid,"SIGTERM"),T=!0,g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon sent SIGTERM to the broker and will resume a cleanly aborted session with a continuation, or start a recovery cycle if the abort cannot settle.`}catch(E){f({level:"error",event:"broker.wedge.signal_failed",...u(n)?{node_id:n}:{},error:E,fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,signal:"SIGTERM"}}),g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon attempted SIGTERM to the broker, but the signal call failed.`}}f({level:"error",event:"broker.wedge.detected",...u(n)?{node_id:n}:{},fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,quiet_ms:d,cpu_percent:h,has_descendants:P,kick_attempted:M,kicked:T,...k===null?{}:{kick_suppression_reason:k}}});try{ne(n,{link:"daemon\u2192node",op:"engine wedge",kind:"wedged",retry:{disposition:"manual"},message:g})}catch(E){f({level:"error",event:"broker.wedge.fault_record_failed",...u(n)?{node_id:n}:{fields:{affected_node_id:n}},error:E})}G(n,D(n),g,{reason:"child-wedged",child:n,quiet_ms:d,cpu_percent:h,kick_attempted:M,kicked:T,...k===null?{}:{kick_suppression_reason:k}})}handleFatalFault(e){const t=L(e);if(t===null){this.fatalFaultNotifiedAt.delete(e);return}if(t.retry.disposition!=="fatal"||t.link!=="pi\u2192provider"||this.fatalFaultNotifiedAt.get(e)===t.since)return;const i=A(e),a=i!==null?I(i):e,n=t.kind==="auth",s=(t.message.split(`
4
- `)[0]??"").slice(0,200),r=t.providerError,d=r===void 0?"":` Provider: ${r.provider}/${r.model}.`+(r.status===void 0?"":` HTTP status: ${r.status}.`)+(r.errno===void 0?"":` Errno: ${r.errno}.`)+(r.code===void 0?"":` Code: ${r.code}.`)+(r.body===void 0?"":` Body: ${r.body.slice(0,200)}.`),c=t.kind==="context-overflow",l=i?.parent==null&&i?.lifecycle==="terminal",p=c||l,h=c?`Child failed \u2014 ${a} (${e}) exceeded its model context window and is now dead. Shrink the task or loaded context, or choose a larger-context model before spawning it again. Error: ${s}`:`Child hit a fatal provider fault \u2014 ${a} (${e}) got a non-retryable ${t.kind} error and will NOT recover on its own; `+(l?"its terminal run has failed. ":"it stays alive, and waking it clears the fault as soon as one turn completes \u2014 a wake that hits the same cause fails again. "+(n?"Its provider credential is dead \u2014 re-authenticate (`/login`, or re-auth crtr); the child recovers on its next wake once the auth reloads. ":""))+`Error: ${s}.${d}`;p&&(te(e,"crash",{reason:c?"context_overflow":"provider_fatal",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:t.message,fault_kind:t.kind,error_class:re(t).class}}}),v.teardown(e).then(_=>{_.confirmed||f({level:"error",event:"fault.fatal.teardown_failed",node_id:e,error:_.error??new Error("Broker teardown not confirmed")})},_=>f({level:"error",event:"fault.fatal.teardown_failed",node_id:e,error:_}))),this.fatalFaultNotifiedAt.set(e,t.since),f({level:"error",event:"fault.fatal.fanout",...u(e)?{node_id:e}:{},fields:{...u(e)?{}:{affected_node_id:e},kind:t.kind,link:t.link,terminal_overflow:c,terminal_provider_fault:l}}),G(e,D(e),h,{reason:c?"child-context-overflow":"child-fault-fatal",child:e,kind:t.kind,message:s,...r===void 0?{}:{provider_error:r}})}async handleAuthReload(e){const t=J();let i=0;for(const r of Oe(t))try{i=Math.max(i,K(r).mtimeMs)}catch{}let a=0;const n=ve(t);ge(n)&&(a=ke(t));const s=`${i}:${a}`;if(this.knownCredentialRevision===null){this.knownCredentialRevision=s;return}s!==this.knownCredentialRevision&&(this.knownCredentialRevision=s,await R.fresh(async()=>{try{const r=Array.from(e.entries(),([l])=>l);if(r.length===0)return;const c=(await Promise.allSettled(r.map(async l=>{try{await ae(l)}catch(p){throw f({level:"error",event:"auth.reload.broker_failed",...u(l)?{node_id:l}:{fields:{broker_id:l}},error:p}),p}}))).filter(l=>l.status==="fulfilled").length;f({level:"info",event:"auth.reload.completed",outcome:c===r.length?"succeeded":"failed",fields:{broker_count:r.length,succeeded_count:c,failed_count:r.length-c}})}catch(r){f({level:"error",event:"auth.reload.failed",error:r})}}))}}export{St as BrokerSupervisionReconciler,$e as WEDGE_CPU_MAX_PERCENT,x as WEDGE_QUIET_MS,U as YIELD_STALL_GRACE_MS,q as parkSummaryGraceMsForDaemon,De as sumTreeCpu,Ie as treeHasDescendants,Re as unattendedParkMsForDaemon,xe as wedgeVerdict,Fe as yieldStallVerdict};
1
+ var Y=Object.defineProperty;var m=(o,e)=>Y(o,"name",{value:e,configurable:!0});import{existsSync as H,statSync as j}from"node:fs";import{join as $}from"node:path";import{LAUNCHER_SOCKET as K}from"../../launcher/spec.js";import{launcherRequest as V}from"../../launcher/client.js";import{secretsDir as z}from"../../core/layout.js";import{execFile as J}from"node:child_process";import{promisify as Q}from"node:util";import{getNode as A,isWarmSpare as X}from"../../core/canvas/index.js";import{isSafeNodeId as u}from"../../core/canvas/paths.js";import{contextDir as Z}from"../../core/canvas/node-agent-paths.js";import{fullName as I}from"../../core/canvas/labels.js";import{recordedPidLiveness as D}from"../../core/canvas/pid.js";import{transition as ee}from"../../core/runtime/lifecycle.js";import{readFault as O,readLiveTurn as C,recordFault as te}from"../../core/canvas/recovery.js";import{errorClassFromFault as ne}from"../../core/fault-classifier.js";import{nextFaultRetry as re}from"../../core/runtime/fault-recovery.js";import{publishNotice as L}from"../../core/runtime/close.js";import{headlessBrokerHost as v}from"../../core/runtime/host.js";import{reloadAuthLive as ie}from"../../core/runtime/auth-reload.js";import{emitEvent as f}from"../../core/events/emit.js";import{operationIdContext as R}from"../../core/events/operation-id.js";import{hasUnseenWakeMail as ae,resetStaleExecutionMail as se}from"../../core/canvas/deliveries.js";import{activeBackgroundBashJobs as oe}from"../../core/bash-jobs.js";import{focusOf as le}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as de}from"../api/viewer-presence.js";import{deliverLive as ce}from"../../core/runtime/interactive-deliver.js";import{BrokerUnreachableError as ue}from"../../core/runtime/broker-request.js";import{formatCard as fe,PARK_SUMMARY_PROMPT as pe}from"../../shared/generated-context.js";import{brokerThresholdsForDaemon as me}from"../../core/runtime/fleet.js";import{readConfig as he}from"../../core/config.js";import{scopedStoreExists as _e}from"../../core/scoped-state/db.js";import{providerStore as ge}from"../../core/scoped-state/paths.js";import{providerRevision as ve}from"../../core/scoped-state/providers.js";import{beginPendingPark as ke,consumePendingPark as y,pendingParkIds as ye,pendingParkStartedAt as we}from"../park-pending.js";import{shouldParkAfterSummary as be}from"../park-activity.js";import{applyParkEvent as w,parkEvent as Se}from"./live-obligation.js";import{envNoDaemonAutostart as Ae,envTestUnattendedParkMs as Ne,parkSummaryGraceMs as Pe,envUnattendedParkMs as Me}from"../../shared/env.js";const N=Q(J);function Te(o){return C(o)?.busy===!0}m(Te,"liveBusy");function wt(o){const e=C(o)?.progressAt;if(e==null)return null;const t=Date.parse(e);return Number.isNaN(t)?null:t}m(wt,"liveTurnProgressMs");function G(o,e){return e===null?null:`${o}:${e}`}m(G,"incarnationOf");function F(o){const e=C(o.node_id),t=e?.busy===!0&&e.progressAt!==null?Date.parse(e.progressAt):Number.NaN,i=o.launched_at===null||o.launched_at===void 0?Number.NaN:Date.parse(o.launched_at);return!Number.isFinite(t)||!Number.isFinite(i)||t<i?null:t}m(F,"busySinceForIncarnation");const W=3*6e4,U=2e4,x=20*6e4,Ee=2,$e=5*6e4;function Ce(){const o=Me();if(o!==void 0)return o;const e=he("user").lifecycle.unattendedParkMs;return Ae()?Ne()??e:e}m(Ce,"unattendedParkMsForDaemon");function B(){return Pe()}m(B,"parkSummaryGraceMsForDaemon");function Re(o,e,t,i){return o!==!0||e!=="refresh"||t?"leave":i===null||i<W?"pending":"kill"}m(Re,"yieldStallVerdict");function Fe(o){return!o.busy||o.quietForMs===null||o.quietForMs<x?"leave":o.cpuPercent===null||o.hasDescendants!==!1&&o.cpuPercent>Ee?"pending":"wedged"}m(Fe,"wedgeVerdict");function q(o){const e=new Map,t=new Map;for(const i of o.split(`
2
+ `)){const a=i.trim();if(a==="")continue;const n=a.split(/\s+/);if(n.length<3)continue;const s=Number(n[0]),r=Number(n[1]),d=Number(n[2]);if(!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(d))continue;e.set(s,d);const c=t.get(r);c===void 0?t.set(r,[s]):c.push(s)}return{byPid:e,childrenOf:t}}m(q,"parsePsTree");function xe(o,e){const{byPid:t,childrenOf:i}=q(o);if(!t.has(e))return null;let a=0;const n=[e],s=new Set;for(;n.length>0;){const r=n.pop();if(s.has(r))continue;s.add(r),a+=t.get(r)??0;const d=i.get(r);d!==void 0&&n.push(...d)}return a}m(xe,"sumTreeCpu");function Ie(o,e){const{byPid:t,childrenOf:i}=q(o);return t.has(e)?(i.get(e)??[]).length>0:null}m(Ie,"treeHasDescendants");function De(o){return[$(o,"auth.json"),$(o,"anthropic-credentials.json"),$(o,"openai-codex-credentials.json")]}m(De,"piCredentialPaths");class bt{static{m(this,"BrokerSupervisionReconciler")}yieldStalls=new Map;wedgeNotifiedAt=new Map;fatalFaultNotifiedAt=new Map;unattendedSince=new Map;sampleTree;signal;knownCredentialRevision=null;lastOverCapWarnAt=Number.NEGATIVE_INFINITY;constructor(e={}){this.sampleTree=e.readTreeSample??(t=>this.readTreeSample(t)),this.signal=e.signal??((t,i)=>{if(process.platform==="linux"&&H(K)){if(i!=="SIGTERM"&&i!=="SIGKILL")throw new Error(`unsupported launcher signal ${i}`);return V({operation:"stop",pid:t,signal:i}).then(()=>{})}process.kill(t,i)})}async runFleetPreamble(e){return await this.handleAuthReload(e),me()}warnIfSaturated(e){if(e.fleet.size()<e.thresholds.warning||!e.lifecycle.acceptsDetachedWork())return;const t=R.fresh(()=>this.warnOverCapInTmux(e.fleet.size(),e.thresholds,e.frozen));e.lifecycle.registerDetached(t)}async run(e,t){const i=Ce();for(const a of t.rows){const n=a.node_id,s=t.fleet.get(n);if(s===void 0||a.status!=="active"&&a.status!=="idle"){this.unattendedSince.delete(n);continue}await R.fresh(async()=>{try{await this.handleYieldStall(a,s,t.fleet,e),await this.handleWedgeDetection(a,s,t.fleet,e),this.handleFatalFault(n),this.handleUnattendedParking(n,A(n),s.pid,e,t,i)}catch(r){this.unattendedSince.delete(n),f({level:"error",event:"broker.supervision.failed",...u(n)?{node_id:n}:{fields:{affected_node_id:n}},error:r})}})}for(const a of this.unattendedSince.keys())t.fleet.has(a)||this.unattendedSince.delete(a);for(const a of ye())t.fleet.has(a)||y(a);se(e)}parkResetCondition(e,t,i,a){if(t.pi_session_id==null||t.pi_pid!==i||t.status==="done"||t.status==="canceled"||t.status==="dead"||t.intent!==null||oe(Z(e)).length>0||le(e)!==null||de(e))return!0;const n=O(e);return n!==null&&n.retry.disposition==="auto"&&n.retry.by==="daemon"&&(n.kind==="connection"||n.kind==="rate-limit"||n.kind==="overloaded")&&(n.retry.nextAt!==void 0||re(n,a)!==null)?!0:ae(e)}handleUnattendedParking(e,t,i,a,n,s){if(X(e)){this.unattendedSince.delete(e),y(e);return}if(t===null){this.unattendedSince.delete(e),y(e);return}const r=this.parkResetCondition(e,t,i,a),d=we(e);if(d!==void 0){if(a-d<B())return;const p=y(e);if(p===void 0||(this.unattendedSince.delete(e),!be(e,t,p)))return;f({level:"warn",event:"broker.park.summary_expired",...u(e)?{node_id:e}:{},fields:{...u(e)?{}:{affected_node_id:e},grace_ms:B()}}),w(e,"park"),v.teardown(e);return}if(r||Te(e)){this.unattendedSince.delete(e);return}const c=this.unattendedSince.get(e);if(c===void 0){this.unattendedSince.set(e,a);return}if(a-c<s)return;this.unattendedSince.delete(e);const l=Se(e,t.lifecycle);if(l==="release"){w(e,l),v.teardown(e);return}if(l==="cancel"){w(e,l),v.teardown(e);return}if(t.grantee!==void 0&&t.grantee!=="app:terminal"){w(e,"park"),v.teardown(e);return}n.lifecycle.acceptsDetachedWork()&&(ke(e,a),n.lifecycle.registerDetached(this.requestParkSummary(e)))}async requestParkSummary(e){try{const t=await ce(e,fe("park",{},pe),{origin:{type:"runtime",kind:"park"}});f({level:"info",event:"broker.park.summary_requested",...u(e)?{node_id:e}:{},fields:{...u(e)?{}:{affected_node_id:e},route:t}})}catch(t){if(y(e)===void 0)return;if(t instanceof ue){w(e,"park"),v.teardown(e);return}f({level:"error",event:"broker.park.summary_failed",...u(e)?{node_id:e}:{fields:{affected_node_id:e}},error:t})}}async warnOverCapInTmux(e,t,i){const a=Date.now();if(a-this.lastOverCapWarnAt<$e)return;this.lastOverCapWarnAt=a;const{warning:n,automaticReviveCap:s}=t,r=i.stalled+i.waitingOnMail;f({level:"warn",event:"broker.capacity.warning",fields:{live_count:e,warning_threshold:n,hard_cap:s,frozen_stalled:i.stalled,frozen_waiting_on_mail:i.waitingOnMail}});const d=r===0?"":` \u2014 ${r} frozen (${i.stalled} stalled, ${i.waitingOnMail} waiting on mail)`,c=`\u26A0 crtrd: ${e} live brokers (warning ${n}; hard cap ${s})${d} \u2014 possible broker leak. ps -ax | grep broker-cli.js`;try{const l=await N("tmux",["list-clients","-F","#{client_name}"],{encoding:"utf8",timeout:2e3});if(typeof l.stdout!="string")return;await Promise.allSettled(l.stdout.split(`
3
+ `).map(async p=>{if(p!=="")try{await N("tmux",["display-message","-C","-d","10000","-c",p,c],{encoding:"utf8",timeout:2e3})}catch{try{await N("tmux",["display-message","-c",p,c],{encoding:"utf8",timeout:2e3})}catch(h){f({level:"error",event:"broker.capacity.tmux_display_failed",error:h,fields:{client:p}})}}}))}catch(l){f({level:"error",event:"broker.capacity.tmux_list_clients_failed",error:l})}}async handleYieldStall(e,t,i,a){const n=e.node_id,s=G(t.pid,e.pi_pid_identity);if(e.intent!=="refresh"||F(e)!==null||s===null){s!==null&&this.yieldStalls.delete(s);return}let r=this.yieldStalls.get(s);if(r===void 0){r={since:a},this.yieldStalls.set(s,r);return}if(Re(!0,e.intent,!1,a-r.since)!=="kill")return;const d=A(n);if(!(i.get(n)!==t||d?.pi_pid!==t.pid||d.pi_pid_identity!==e.pi_pid_identity||D(t.pid,e.pi_pid_identity)!=="alive"))if(r.termedAt===void 0){if(!await this.signalYieldStall(n,t.pid,"SIGTERM"))return;r.termedAt=a,f({level:"warn",event:"broker.yield_stall.sigterm",...u(n)?{node_id:n}:{},fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:a-r.since,grace_ms:W}})}else a-r.termedAt>=U&&await this.signalYieldStall(n,t.pid,"SIGKILL")&&f({level:"warn",event:"broker.yield_stall.sigkill",...u(n)?{node_id:n}:{},fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,elapsed_ms:a-r.termedAt,grace_ms:U,stall_elapsed_ms:a-r.since}})}async signalYieldStall(e,t,i){try{return await this.signal(t,i),!0}catch(a){return f({level:"error",event:"broker.yield_stall.signal_failed",...u(e)?{node_id:e}:{},error:a,fields:{...u(e)?{}:{affected_node_id:e},pid:t,signal:i}}),!1}}async readTreeSample(e){try{const{stdout:t}=await N("ps",["-ax","-o","pid=,ppid=,pcpu="],{encoding:"utf8",timeout:2e3});if(typeof t!="string")return null;const i=xe(t,e),a=Ie(t,e);return i===null||a===null?null:{cpuPercent:i,hasDescendants:a}}catch{return null}}async handleWedgeDetection(e,t,i,a){const n=e.node_id,s=G(t.pid,e.pi_pid_identity),r=F(e);if(r===null||s===null){s!==null&&this.wedgeNotifiedAt.delete(s);return}const d=a-r,c=d>=x?await this.sampleTree(t.pid):null,l=A(n),p=l===null?null:F(l);if(i.get(n)!==t||l===null||l.pi_pid!==t.pid||l.pi_pid_identity!==e.pi_pid_identity||p!==r)return;const h=c?.cpuPercent??null,_=c?.hasDescendants??null;if(Fe({busy:!0,quietForMs:d,cpuPercent:h,hasDescendants:_})!=="wedged"||this.wedgeNotifiedAt.get(s)===r)return;this.wedgeNotifiedAt.set(s,r);const b=I(l),S=Math.round((d??x)/6e4),P=_??!0,k=!P&&D(t.pid,e.pi_pid_identity)!=="alive"?"pid_identity_unproven":null;let M=!1,T=!1,g;if(P)g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and its process is near-idle. It will NOT recover on its own \u2014 read \`crtr canvas read wedged-child-on-runaway-bash\` and kill the runaway SUBPROCESS (not this node) so its turn can resume with no lost context.`;else if(k!==null)g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon did not SIGTERM the broker because its PID identity cannot be confirmed alive.`;else{M=!0;try{await this.signal(t.pid,"SIGTERM"),T=!0,g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon sent SIGTERM to the broker and will resume a cleanly aborted session with a continuation, or start a recovery cycle if the abort cannot settle.`}catch(E){f({level:"error",event:"broker.wedge.signal_failed",...u(n)?{node_id:n}:{},error:E,fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,signal:"SIGTERM"}}),g=`Child wedged \u2014 ${b} (${n}) is alive and mid-turn but has shown NO engine progress for ${S}+ minutes and it has no subprocess to kill (the engine itself stalled). The daemon attempted SIGTERM to the broker, but the signal call failed.`}}f({level:"error",event:"broker.wedge.detected",...u(n)?{node_id:n}:{},fields:{...u(n)?{}:{affected_node_id:n},pid:t.pid,quiet_ms:d,cpu_percent:h,has_descendants:P,kick_attempted:M,kicked:T,...k===null?{}:{kick_suppression_reason:k}}});try{te(n,{link:"daemon\u2192node",op:"engine wedge",kind:"wedged",retry:{disposition:"manual"},message:g})}catch(E){f({level:"error",event:"broker.wedge.fault_record_failed",...u(n)?{node_id:n}:{fields:{affected_node_id:n}},error:E})}L(n,"notice.crash",g,{reason:"child-wedged",child:n,quiet_ms:d,cpu_percent:h,kick_attempted:M,kicked:T,...k===null?{}:{kick_suppression_reason:k}})}handleFatalFault(e){const t=O(e);if(t===null){this.fatalFaultNotifiedAt.delete(e);return}if(t.retry.disposition!=="fatal"||t.link!=="pi\u2192provider"||this.fatalFaultNotifiedAt.get(e)===t.since)return;const i=A(e),a=i!==null?I(i):e,n=t.kind==="auth",s=(t.message.split(`
4
+ `)[0]??"").slice(0,200),r=t.providerError,d=r===void 0?"":` Provider: ${r.provider}/${r.model}.`+(r.status===void 0?"":` HTTP status: ${r.status}.`)+(r.errno===void 0?"":` Errno: ${r.errno}.`)+(r.code===void 0?"":` Code: ${r.code}.`)+(r.body===void 0?"":` Body: ${r.body.slice(0,200)}.`),c=t.kind==="context-overflow",l=i?.parent==null&&i?.lifecycle==="terminal",p=c||l,h=c?`Child failed \u2014 ${a} (${e}) exceeded its model context window and is now dead. Shrink the task or loaded context, or choose a larger-context model before spawning it again. Error: ${s}`:`Child hit a fatal provider fault \u2014 ${a} (${e}) got a non-retryable ${t.kind} error and will NOT recover on its own; `+(l?"its terminal run has failed. ":"it stays alive, and waking it clears the fault as soon as one turn completes \u2014 a wake that hits the same cause fails again. "+(n?"Its provider credential is dead \u2014 re-authenticate (`/login`, or re-auth crtr); the child recovers on its next wake once the auth reloads. ":""))+`Error: ${s}.${d}`;p&&(ee(e,"crash",{reason:c?"context_overflow":"provider_fatal",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:t.message,fault_kind:t.kind,error_class:ne(t).class}}}),v.teardown(e).then(_=>{_.confirmed||f({level:"error",event:"fault.fatal.teardown_failed",node_id:e,error:_.error??new Error("Broker teardown not confirmed")})},_=>f({level:"error",event:"fault.fatal.teardown_failed",node_id:e,error:_}))),this.fatalFaultNotifiedAt.set(e,t.since),f({level:"error",event:"fault.fatal.fanout",...u(e)?{node_id:e}:{},fields:{...u(e)?{}:{affected_node_id:e},kind:t.kind,link:t.link,terminal_overflow:c,terminal_provider_fault:l}}),L(e,"notice.crash",h,{reason:c?"child-context-overflow":"child-fault-fatal",child:e,kind:t.kind,message:s,...r===void 0?{}:{provider_error:r}})}async handleAuthReload(e){const t=z();let i=0;for(const r of De(t))try{i=Math.max(i,j(r).mtimeMs)}catch{}let a=0;const n=ge(t);_e(n)&&(a=ve(t));const s=`${i}:${a}`;if(this.knownCredentialRevision===null){this.knownCredentialRevision=s;return}s!==this.knownCredentialRevision&&(this.knownCredentialRevision=s,await R.fresh(async()=>{try{const r=Array.from(e.entries(),([l])=>l);if(r.length===0)return;const c=(await Promise.allSettled(r.map(async l=>{try{await ie(l)}catch(p){throw f({level:"error",event:"auth.reload.broker_failed",...u(l)?{node_id:l}:{fields:{broker_id:l}},error:p}),p}}))).filter(l=>l.status==="fulfilled").length;f({level:"info",event:"auth.reload.completed",outcome:c===r.length?"succeeded":"failed",fields:{broker_count:r.length,succeeded_count:c,failed_count:r.length-c}})}catch(r){f({level:"error",event:"auth.reload.failed",error:r})}}))}}export{bt as BrokerSupervisionReconciler,Ee as WEDGE_CPU_MAX_PERCENT,x as WEDGE_QUIET_MS,W as YIELD_STALL_GRACE_MS,B as parkSummaryGraceMsForDaemon,xe as sumTreeCpu,Ie as treeHasDescendants,Ce as unattendedParkMsForDaemon,Fe as wedgeVerdict,Re as yieldStallVerdict};
@@ -1 +1 @@
1
- var c=Object.defineProperty;var e=(r,t)=>c(r,"name",{value:t,configurable:!0});import{newestReportRef as l,hasActiveLiveSubscription as p,hasLiveMessageWait as m,hasLiveSubscriber as h,hasPendingCronWake as k,subscribersOf as b}from"../../core/canvas/index.js";import{fullName as g}from"../../core/canvas/labels.js";import{countTickets as w}from"../../core/canvas/attention.js";import{hasUnseenWakeMail as s}from"../../core/canvas/deliveries.js";import{readOutputRequest as v}from"../../core/runtime/structured-output.js";import{focusOf as x}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as W}from"../api/viewer-presence.js";import{fanDoctrineWake as $}from"../../core/runtime/close.js";import{readFault as y}from"../../core/canvas/recovery.js";import{transition as u}from"../../core/runtime/lifecycle.js";function a(r){return p(r)||m(r)||k(r)||w(r)>0||v(r).state!=="absent"}e(a,"hasLiveObligation");function q(r){return a(r)||s(r)?!0:n(r)}e(q,"hasPendingWake");function B(r){return t=>r.isClaimed(t)||a(t)||n(t)}e(B,"retentionHold");function n(r){return x(r)!==null||W(r)}e(n,"hasHumanViewer");function D(r,t){if(n(r)||a(r))return"release";const i=y(r);return i?.link==="pi\u2192provider"&&i.retry.disposition==="fatal"?"release":t==="resident"?s(r)?"release":"park":s(r)||h(r)?"release":"cancel"}e(D,"parkEvent");function F(r,t){const i=t==="cancel"?u(r,t,{reason:"stranded"}):u(r,t);if(t!=="park")return;const o=l(r),f=o===null?`It left no report behind; \`crtr node inspect show ${r}\` shows where it stands.`:`Its latest report is where it left things: \`crtr canvas history read ${o}\`.`;$(r,b(r),`Resident concluded \u2014 ${g(i)} (${r}) had nothing left to wake it through its unattended grace, so its conversation was concluded. It submitted no final report. ${f} A message to it reopens it on a fresh cycle.`,{reason:"child-auto-done",child:r},"deferred")}e(F,"applyParkEvent");export{F as applyParkEvent,n as hasHumanViewer,a as hasLiveObligation,q as hasPendingWake,D as parkEvent,B as retentionHold};
1
+ var f=Object.defineProperty;var e=(r,t)=>f(r,"name",{value:t,configurable:!0});import{hasActiveLiveSubscription as l,hasLiveMessageWait as p,hasLiveSubscriber as m,hasPendingCronWake as h}from"../../core/canvas/index.js";import{fullName as k}from"../../core/canvas/labels.js";import{newestReportName as g}from"../../core/feed/reports.js";import{countTickets as w}from"../../core/canvas/attention.js";import{hasUnseenWakeMail as s}from"../../core/canvas/deliveries.js";import{readOutputRequest as b}from"../../core/runtime/structured-output.js";import{focusOf as v}from"../../core/runtime/placement.js";import{hasAttachedBrokerViewers as x}from"../api/viewer-presence.js";import{publishNotice as $}from"../../core/runtime/close.js";import{readFault as L}from"../../core/canvas/recovery.js";import{transition as u}from"../../core/runtime/lifecycle.js";function a(r){return l(r)||p(r)||h(r)||w(r)>0||b(r).state!=="absent"}e(a,"hasLiveObligation");function V(r){return a(r)||s(r)?!0:n(r)}e(V,"hasPendingWake");function q(r){return t=>r.isClaimed(t)||a(t)||n(t)}e(q,"retentionHold");function n(r){return v(r)!==null||x(r)}e(n,"hasHumanViewer");function B(r,t){if(n(r)||a(r))return"release";const i=L(r);return i?.link==="pi\u2192provider"&&i.retry.disposition==="fatal"?"release":t==="resident"?s(r)?"release":"park":s(r)||m(r)?"release":"cancel"}e(B,"parkEvent");function F(r,t){const i=t==="cancel"?u(r,t,{reason:"stranded"}):u(r,t);if(t!=="park")return;const o=g(r),c=o===null?`It left no report behind; \`crtr node inspect show ${r}\` shows where it stands.`:`Its latest report is where it left things: \`crtr canvas read ${o}\`.`;$(r,"notice.close",`Resident concluded \u2014 ${k(i)} (${r}) had nothing left to wake it through its unattended grace, so its conversation was concluded. It submitted no final report. ${c} A message to it reopens it on a fresh cycle.`,{reason:"child-auto-done",child:r},"deferred")}e(F,"applyParkEvent");export{F as applyParkEvent,n as hasHumanViewer,a as hasLiveObligation,V as hasPendingWake,B as parkEvent,q as retentionHold};
@@ -1 +1 @@
1
- var c=Object.defineProperty;var s=(o,e)=>c(o,"name",{value:e,configurable:!0});import{dueNodeDeadlines as _,subscribersOf as f}from"../../core/canvas/index.js";import{emitEvent as n}from"../../core/events/emit.js";import{isProfilePaused as m}from"../../core/profiles/manifest.js";import{operationIdContext as u}from"../../core/events/operation-id.js";import{errorClassFromFault as p}from"../../core/fault-classifier.js";import{fanDoctrineWake as v}from"../../core/runtime/close.js";import{readFault as h}from"../../core/canvas/recovery.js";import{requestBrokerTeardown as x}from"../../core/runtime/host.js";import{transition as y}from"../../core/runtime/lifecycle.js";class S{static{s(this,"NodeDeadlineReconciler")}run(e){let r;try{r=_(new Date(e).toISOString())}catch(d){n({level:"error",event:"node_deadline.scan_failed",error:d});return}for(const d of r)m(d.profile_id)||u.fresh(()=>this.expire(d,e))}expire(e,r){const d=e.deadline_at;if(d==null)return;const l=h(e.node_id),t=l?.retry.disposition==="fatal"?l:null;let a;try{a=y(e.node_id,"cancel",{reason:"deadline_exceeded",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",deadline:{deadline_at:d,elapsed_ms:r-Date.parse(d)},...t===null?{}:{message:t.message,fault_kind:t.kind,error_class:p(t).class}}}})}catch(i){n({level:"error",event:"node_deadline.terminalize_failed",node_id:e.node_id,error:i,fields:{deadline_at:d}});return}if(!(a.status!=="canceled"||a.outcome_reason!=="deadline_exceeded")){try{x(e.node_id)}catch(i){n({level:"error",event:"node_deadline.teardown_failed",node_id:e.node_id,error:i,fields:{deadline_at:d}})}try{v(e.node_id,f(e.node_id),"child-deadline-exceeded",{reason:"child-deadline-exceeded",child:e.node_id})}catch(i){n({level:"error",event:"node_deadline.notify_failed",node_id:e.node_id,error:i,fields:{deadline_at:d}})}try{n({level:"error",event:"node_deadline.expired",node_id:e.node_id,fields:{deadline_at:d,elapsed_ms:r-Date.parse(d)}})}catch{}}}}export{S as NodeDeadlineReconciler};
1
+ var c=Object.defineProperty;var s=(o,e)=>c(o,"name",{value:e,configurable:!0});import{dueNodeDeadlines as _}from"../../core/canvas/index.js";import{emitEvent as n}from"../../core/events/emit.js";import{isProfilePaused as f}from"../../core/profiles/manifest.js";import{operationIdContext as m}from"../../core/events/operation-id.js";import{errorClassFromFault as u}from"../../core/fault-classifier.js";import{publishNotice as p}from"../../core/runtime/close.js";import{readFault as h}from"../../core/canvas/recovery.js";import{requestBrokerTeardown as v}from"../../core/runtime/host.js";import{transition as x}from"../../core/runtime/lifecycle.js";class b{static{s(this,"NodeDeadlineReconciler")}run(e){let r;try{r=_(new Date(e).toISOString())}catch(d){n({level:"error",event:"node_deadline.scan_failed",error:d});return}for(const d of r)f(d.profile_id)||m.fresh(()=>this.expire(d,e))}expire(e,r){const d=e.deadline_at;if(d==null)return;const l=h(e.node_id),t=l?.retry.disposition==="fatal"?l:null;let a;try{a=x(e.node_id,"cancel",{reason:"deadline_exceeded",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",deadline:{deadline_at:d,elapsed_ms:r-Date.parse(d)},...t===null?{}:{message:t.message,fault_kind:t.kind,error_class:u(t).class}}}})}catch(i){n({level:"error",event:"node_deadline.terminalize_failed",node_id:e.node_id,error:i,fields:{deadline_at:d}});return}if(!(a.status!=="canceled"||a.outcome_reason!=="deadline_exceeded")){try{v(e.node_id)}catch(i){n({level:"error",event:"node_deadline.teardown_failed",node_id:e.node_id,error:i,fields:{deadline_at:d}})}try{p(e.node_id,"notice.deadline","child-deadline-exceeded",{reason:"child-deadline-exceeded",child:e.node_id})}catch(i){n({level:"error",event:"node_deadline.notify_failed",node_id:e.node_id,error:i,fields:{deadline_at:d}})}try{n({level:"error",event:"node_deadline.expired",node_id:e.node_id,fields:{deadline_at:d,elapsed_ms:r-Date.parse(d)}})}catch{}}}}export{b as NodeDeadlineReconciler};
@@ -1 +1 @@
1
- var w=Object.defineProperty;var d=(i,t)=>w(i,"name",{value:t,configurable:!0});import{clearFrozen as v,getNode as E,getRow as y,subscribersOf as g}from"../../../core/canvas/index.js";import{fullName as A}from"../../../core/canvas/labels.js";import{isSafeNodeId as s}from"../../../core/canvas/paths.js";import{emitEvent as c}from"../../../core/events/emit.js";import{operationIdContext as k}from"../../../core/events/operation-id.js";import{acknowledgedNodeMailCount as z}from"../../../core/canvas/deliveries.js";import{fanDoctrineWake as S}from"../../../core/runtime/close.js";import{transition as p}from"../../../core/runtime/lifecycle.js";import{reviveNode as m}from"../../../core/runtime/revive.js";import{hasPendingWake as _}from"../live-obligation.js";const f=6,R=10*6e4,L=2e4;function M(i,t){if(t)return 2;const r=i.launched_at;if(r==null)return 1;const e=i.last_settled_at;return e==null?2:Date.parse(e)>Date.parse(r)?1:2}d(M,"thawTier");function C(i,t){if(i.tier!==t.tier)return i.tier-t.tier;const r=i.row.frozen_at,e=t.row.frozen_at;return r==null?e==null?0:1:e==null?-1:Date.parse(r)-Date.parse(e)}d(C,"compareThaw");class U{static{d(this,"FreezeLaneReconciler")}relaunchState=new Map;endEpisode(t){this.relaunchState.delete(t)}async run(t,r){const e=r.candidates.map(a=>({...a,tier:M(a.row,_(a.row.node_id))}));e.sort(C);const n={stalled:0,waitingOnMail:0};for(const a of e)await k.fresh(()=>this.enact(t,a,r.fleet))==="frozen"&&(a.tier===1?n.stalled+=1:n.waitingOnMail+=1);return n}async enact(t,r,e){const n=r.row.node_id;try{return r.enact==="thaw"?await this.enactThaw(r.row):r.enact==="idle-release"?await this.enactIdleRelease(t,r.row):(await e.applyDeadRowPolicy(n),e.has(n)?"launched":y(n)?.frozen_at!=null?"frozen":"skipped")}catch(a){return c({level:"error",event:"node.lifecycle.enact_failed",...s(n)?{node_id:n}:{},error:a,fields:{...s(n)?{}:{affected_node_id:n},enact:r.enact}}),"skipped"}}async enactThaw(t){return t.lifecycle==="resident"&&E(t.node_id)?.pi_session_id!=null&&!_(t.node_id)?(p(t.node_id,"release"),v(t.node_id),"skipped"):(await m(t.node_id,{resume:!0,capacity:"freeze",recovery:!0})).outcome==="frozen"?"frozen":"launched"}async enactIdleRelease(t,r){const e=r.node_id,n=z(e),a=this.relaunchState.get(e),l=a===void 0||a.acknowledgedCount!==n,o=l?0:a.attempts;if(o>=f)return this.relaunchState.delete(e),c({level:"warn",event:"broker.idle_release.exhausted",...s(e)?{node_id:e}:{},fields:{...s(e)?{}:{affected_node_id:e},attempts:o,max_attempts:f}}),p(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",respawn_failures:o}}}),S(e,g(e),`Child crashed \u2014 ${A(r)} (${e}) failed to relaunch after ${o} attempts while trying to deliver a pending inbox message (no delivery progress across any attempt), and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e}),"skipped";const u=l?void 0:a?.lastAttempt,h=Math.min(L*2**o,R);return u!==void 0&&t-u<h?"skipped":(await m(e,{resume:!0,capacity:"freeze"})).outcome==="frozen"?"frozen":(this.relaunchState.set(e,{acknowledgedCount:n,attempts:o+1,lastAttempt:t}),c({level:"info",event:"broker.revive.idle_release",...s(e)?{node_id:e}:{},attempt:o+1,fields:{...s(e)?{}:{affected_node_id:e},attempts:o+1,max_attempts:f}}),"launched")}}export{U as FreezeLaneReconciler,C as compareThaw,M as thawTier};
1
+ var w=Object.defineProperty;var d=(i,t)=>w(i,"name",{value:t,configurable:!0});import{clearFrozen as v,getNode as E,getRow as y}from"../../../core/canvas/index.js";import{fullName as g}from"../../../core/canvas/labels.js";import{isSafeNodeId as s}from"../../../core/canvas/paths.js";import{emitEvent as c}from"../../../core/events/emit.js";import{operationIdContext as A}from"../../../core/events/operation-id.js";import{acknowledgedNodeMailCount as z}from"../../../core/canvas/deliveries.js";import{publishNotice as S}from"../../../core/runtime/close.js";import{transition as p}from"../../../core/runtime/lifecycle.js";import{reviveNode as m}from"../../../core/runtime/revive.js";import{hasPendingWake as _}from"../live-obligation.js";const f=6,k=10*6e4,R=2e4;function L(i,t){if(t)return 2;const r=i.launched_at;if(r==null)return 1;const e=i.last_settled_at;return e==null?2:Date.parse(e)>Date.parse(r)?1:2}d(L,"thawTier");function M(i,t){if(i.tier!==t.tier)return i.tier-t.tier;const r=i.row.frozen_at,e=t.row.frozen_at;return r==null?e==null?0:1:e==null?-1:Date.parse(r)-Date.parse(e)}d(M,"compareThaw");class O{static{d(this,"FreezeLaneReconciler")}relaunchState=new Map;endEpisode(t){this.relaunchState.delete(t)}async run(t,r){const e=r.candidates.map(a=>({...a,tier:L(a.row,_(a.row.node_id))}));e.sort(M);const n={stalled:0,waitingOnMail:0};for(const a of e)await A.fresh(()=>this.enact(t,a,r.fleet))==="frozen"&&(a.tier===1?n.stalled+=1:n.waitingOnMail+=1);return n}async enact(t,r,e){const n=r.row.node_id;try{return r.enact==="thaw"?await this.enactThaw(r.row):r.enact==="idle-release"?await this.enactIdleRelease(t,r.row):(await e.applyDeadRowPolicy(n),e.has(n)?"launched":y(n)?.frozen_at!=null?"frozen":"skipped")}catch(a){return c({level:"error",event:"node.lifecycle.enact_failed",...s(n)?{node_id:n}:{},error:a,fields:{...s(n)?{}:{affected_node_id:n},enact:r.enact}}),"skipped"}}async enactThaw(t){return t.lifecycle==="resident"&&E(t.node_id)?.pi_session_id!=null&&!_(t.node_id)?(p(t.node_id,"release"),v(t.node_id),"skipped"):(await m(t.node_id,{resume:!0,capacity:"freeze",recovery:!0})).outcome==="frozen"?"frozen":"launched"}async enactIdleRelease(t,r){const e=r.node_id,n=z(e),a=this.relaunchState.get(e),l=a===void 0||a.acknowledgedCount!==n,o=l?0:a.attempts;if(o>=f)return this.relaunchState.delete(e),c({level:"warn",event:"broker.idle_release.exhausted",...s(e)?{node_id:e}:{},fields:{...s(e)?{}:{affected_node_id:e},attempts:o,max_attempts:f}}),p(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",respawn_failures:o}}}),S(e,"notice.crash",`Child crashed \u2014 ${g(r)} (${e}) failed to relaunch after ${o} attempts while trying to deliver a pending inbox message (no delivery progress across any attempt), and is now dead. It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e}),"skipped";const u=l?void 0:a?.lastAttempt,h=Math.min(R*2**o,k);return u!==void 0&&t-u<h?"skipped":(await m(e,{resume:!0,capacity:"freeze"})).outcome==="frozen"?"frozen":(this.relaunchState.set(e,{acknowledgedCount:n,attempts:o+1,lastAttempt:t}),c({level:"info",event:"broker.revive.idle_release",...s(e)?{node_id:e}:{},attempt:o+1,fields:{...s(e)?{}:{affected_node_id:e},attempts:o+1,max_attempts:f}}),"launched")}}export{O as FreezeLaneReconciler,M as compareThaw,L as thawTier};
@@ -16,6 +16,7 @@ export interface StorageMaintenanceContext {
16
16
  export declare class StorageMaintenanceReconciler {
17
17
  private lastSpareSweepAt;
18
18
  private lastRunExpiryAt;
19
+ private lastAnalyzeAt;
19
20
  private lastRetentionSweepAt;
20
21
  private lastContextStripAt;
21
22
  private contextStripInFlight;
@@ -1 +1 @@
1
- var I=Object.defineProperty;var c=(f,t)=>I(f,"name",{value:t,configurable:!0});import{rm as y}from"node:fs/promises";import{closeFocusRow as g,getFocusById as N,listFocuses as E,listNodes as h}from"../../core/canvas/index.js";import{getNode as A,lastActivityMs as u,pruneNodes as x}from"../../core/canvas/canvas.js";import{lastContextStripMs as R,stripContextDir as T}from"../../core/canvas/context-strip.js";import{isSafeNodeId as d}from"../../core/canvas/paths.js";import{emitEvent as i}from"../../core/events/emit.js";import{operationIdContext as o}from"../../core/events/operation-id.js";import{listLivePanesAsync as w,tearDownNode as F}from"../../core/runtime/placement.js";import{reapStaleSpares as D}from"../../core/runtime/warm-pool.js";import{ManagedWorktreeSweepReconciler as C}from"./managed-worktree-sweep.js";import{expireRunEvents as G}from"../../core/runs/events.js";import{retentionHold as m}from"./live-obligation.js";import{pruneMemoryReads as P}from"../../core/canvas/memory-reads.js";const M=10*6e4,b=60*1e3,v=5*6e4,W=14,V=1440*6e4;class U{static{c(this,"StorageMaintenanceReconciler")}lastSpareSweepAt=Number.NEGATIVE_INFINITY;lastRunExpiryAt=Number.NEGATIVE_INFINITY;lastRetentionSweepAt=Number.NEGATIVE_INFINITY;lastContextStripAt=Number.NEGATIVE_INFINITY;contextStripInFlight=!1;focusGcInFlight=!1;worktreeSweep=new C;run(t,r){if(this.reapDeadResidue(t),this.scheduleFocusGc(r),this.gcWarmPool(t),t-this.lastRunExpiryAt>=60*6e4){G(t);try{P(t)}catch(e){console.warn(`memory-read log prune failed: ${String(e)}`)}this.lastRunExpiryAt=t}this.sweepRetention(t,r),this.scheduleContextStrip(t,r),this.worktreeSweep.run(t,r)}msSinceTerminalActivity(t,r){const e=u(t);return e===0?Number.POSITIVE_INFINITY:r-e}sweepRetention(t,r){t-this.lastRetentionSweepAt<v||r.lifecycle.acceptsDetachedWork()&&(this.lastRetentionSweepAt=t,o.fresh(()=>{try{const e=x({ttlDays:W,held:m(r.fleet),removeDirs:c(s=>{r.lifecycle.registerDetached(Promise.all(s.map(l=>y(l,{recursive:!0,force:!0}))).then(()=>{}).catch(l=>{o.fresh(()=>{i({level:"error",event:"canvas.retention.failed",error:l})})}))},"removeDirs")});e.pruned.length>0&&i({level:"info",event:"canvas.retention.pruned",outcome:"succeeded",fields:{pruned_count:e.pruned.length}})}catch(e){i({level:"error",event:"canvas.retention.failed",error:e})}}))}scheduleContextStrip(t,r){if(this.contextStripInFlight||t-this.lastContextStripAt<v||!r.lifecycle.acceptsDetachedWork())return;this.lastContextStripAt=t,this.contextStripInFlight=!0;const e=this.stripFinishedContexts(t,r).finally(()=>{this.contextStripInFlight=!1});r.lifecycle.registerDetached(e)}async stripFinishedContexts(t,r){const e=m(r.fleet),s=c(n=>n!==null&&["done","canceled","dead"].includes(n.status)&&(n.pi_pid??null)===null&&(n.frozen_at??null)===null&&(n.run_id??null)===null&&u(n)<t-V&&!e(n.node_id),"eligible");let l=0,p=0;try{for(const n of h({status:["done","canceled","dead"]})){if(!d(n.node_id)||!s(n))continue;const _=await R(n.node_id);if(_!==null&&_>=u(n)||!s(A(n.node_id)))continue;let a;try{a=await T(n.node_id)}catch(S){o.fresh(()=>{i({level:"warn",event:"canvas.context_strip.node_failed",error:S,fields:{node_id:n.node_id}})});continue}a.removed.length>0&&(l+=1,p+=a.bytes)}}catch(n){o.fresh(()=>{i({level:"error",event:"canvas.context_strip.failed",error:n})})}l>0&&o.fresh(()=>{i({level:"info",event:"canvas.context_strip.completed",outcome:"succeeded",fields:{node_count:l,bytes:p}})})}reapDeadResidue(t){let r;try{r=h({status:["done","canceled","dead"]})}catch(e){o.fresh(()=>{i({level:"error",event:"residue.reap_scan.failed",error:e})});return}for(const e of r)if(!(e.pane==null&&e.window==null&&e.tmux_session==null)){try{if(this.msSinceTerminalActivity(e,t)<M)continue}catch(s){o.fresh(()=>{i({level:"error",event:"residue.reap.failed",...d(e.node_id)?{node_id:e.node_id}:{},error:s,fields:{...d(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})});continue}o.fresh(()=>{try{i({level:"info",event:"residue.reaped",...d(e.node_id)?{node_id:e.node_id}:{},fields:{...d(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}}),F(e.node_id)}catch(s){i({level:"error",event:"residue.reap.failed",...d(e.node_id)?{node_id:e.node_id}:{},error:s,fields:{...d(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})}})}}scheduleFocusGc(t){if(this.focusGcInFlight||!t.lifecycle.acceptsDetachedWork())return;this.focusGcInFlight=!0;const r=this.gcStaleFocuses().finally(()=>{this.focusGcInFlight=!1});t.lifecycle.registerDetached(r)}async gcStaleFocuses(){let t;try{t=E()}catch(e){o.fresh(()=>{i({level:"error",event:"focus.gc.failed",error:e})});return}if(t.length===0)return;let r;try{r=await w()}catch(e){o.fresh(()=>{i({level:"error",event:"focus.gc.failed",error:e})});return}if(r!==null)for(const e of t){if(e.pane===null||r.has(e.pane))continue;if(!o.fresh(()=>{try{return N(e.focus_id)?.pane!==e.pane||(i({level:"info",event:"focus.gc.removed",...d(e.node_id)?{node_id:e.node_id}:{},fields:{focus_id:e.focus_id,focus_node_id:e.node_id,pane:e.pane}}),g(e.focus_id)),!0}catch(l){return i({level:"error",event:"focus.gc.failed",error:l}),!1}}))return}}gcWarmPool(t){t-this.lastSpareSweepAt<b||(this.lastSpareSweepAt=t,o.fresh(()=>{const r=D();r.length>0&&i({level:"info",event:"warm_pool.spares_reaped",outcome:"succeeded",fields:{reaped_count:r.length}})}))}}export{V as CONTEXT_STRIP_GRACE_MS,M as DEAD_REAP_GRACE_MS,v as RETENTION_SWEEP_INTERVAL_MS,W as RETENTION_TTL_DAYS,U as StorageMaintenanceReconciler};
1
+ var S=Object.defineProperty;var c=(f,t)=>S(f,"name",{value:t,configurable:!0});import{rm as A}from"node:fs/promises";import{closeFocusRow as y,getFocusById as N,listFocuses as E,listNodes as h}from"../../core/canvas/index.js";import{getNode as g,lastActivityMs as u,pruneNodes as x}from"../../core/canvas/canvas.js";import{lastContextStripMs as T,stripContextDir as R}from"../../core/canvas/context-strip.js";import{isSafeNodeId as d}from"../../core/canvas/paths.js";import{emitEvent as i}from"../../core/events/emit.js";import{operationIdContext as o}from"../../core/events/operation-id.js";import{listLivePanesAsync as F,tearDownNode as w}from"../../core/runtime/placement.js";import{reapStaleSpares as D}from"../../core/runtime/warm-pool.js";import{ManagedWorktreeSweepReconciler as C}from"./managed-worktree-sweep.js";import{expireRunEvents as G}from"../../core/runs/events.js";import{openDb as b}from"../../core/canvas/db.js";import{retentionHold as m}from"./live-obligation.js";import{pruneMemoryReads as P}from"../../core/canvas/memory-reads.js";const M=10*6e4,V=60*1e3,v=5*6e4,W=14,Y=1440*6e4;class ee{static{c(this,"StorageMaintenanceReconciler")}lastSpareSweepAt=Number.NEGATIVE_INFINITY;lastRunExpiryAt=Number.NEGATIVE_INFINITY;lastAnalyzeAt=Number.NEGATIVE_INFINITY;lastRetentionSweepAt=Number.NEGATIVE_INFINITY;lastContextStripAt=Number.NEGATIVE_INFINITY;contextStripInFlight=!1;focusGcInFlight=!1;worktreeSweep=new C;run(t,r){if(this.reapDeadResidue(t),this.scheduleFocusGc(r),this.gcWarmPool(t),t-this.lastRunExpiryAt>=60*6e4){G(t);try{P(t)}catch(e){console.warn(`memory-read log prune failed: ${String(e)}`)}this.lastRunExpiryAt=t}t-this.lastAnalyzeAt>=1440*6e4&&(b().exec("ANALYZE"),this.lastAnalyzeAt=t),this.sweepRetention(t,r),this.scheduleContextStrip(t,r),this.worktreeSweep.run(t,r)}msSinceTerminalActivity(t,r){const e=u(t);return e===0?Number.POSITIVE_INFINITY:r-e}sweepRetention(t,r){t-this.lastRetentionSweepAt<v||r.lifecycle.acceptsDetachedWork()&&(this.lastRetentionSweepAt=t,o.fresh(()=>{try{const e=x({ttlDays:W,held:m(r.fleet),removeDirs:c(s=>{r.lifecycle.registerDetached(Promise.all(s.map(l=>A(l,{recursive:!0,force:!0}))).then(()=>{}).catch(l=>{o.fresh(()=>{i({level:"error",event:"canvas.retention.failed",error:l})})}))},"removeDirs")});e.pruned.length>0&&i({level:"info",event:"canvas.retention.pruned",outcome:"succeeded",fields:{pruned_count:e.pruned.length}})}catch(e){i({level:"error",event:"canvas.retention.failed",error:e})}}))}scheduleContextStrip(t,r){if(this.contextStripInFlight||t-this.lastContextStripAt<v||!r.lifecycle.acceptsDetachedWork())return;this.lastContextStripAt=t,this.contextStripInFlight=!0;const e=this.stripFinishedContexts(t,r).finally(()=>{this.contextStripInFlight=!1});r.lifecycle.registerDetached(e)}async stripFinishedContexts(t,r){const e=m(r.fleet),s=c(n=>n!==null&&["done","canceled","dead"].includes(n.status)&&(n.pi_pid??null)===null&&(n.frozen_at??null)===null&&(n.run_id??null)===null&&u(n)<t-Y&&!e(n.node_id),"eligible");let l=0,p=0;try{for(const n of h({status:["done","canceled","dead"]})){if(!d(n.node_id)||!s(n))continue;const _=await T(n.node_id);if(_!==null&&_>=u(n)||!s(g(n.node_id)))continue;let a;try{a=await R(n.node_id)}catch(I){o.fresh(()=>{i({level:"warn",event:"canvas.context_strip.node_failed",error:I,fields:{node_id:n.node_id}})});continue}a.removed.length>0&&(l+=1,p+=a.bytes)}}catch(n){o.fresh(()=>{i({level:"error",event:"canvas.context_strip.failed",error:n})})}l>0&&o.fresh(()=>{i({level:"info",event:"canvas.context_strip.completed",outcome:"succeeded",fields:{node_count:l,bytes:p}})})}reapDeadResidue(t){let r;try{r=h({status:["done","canceled","dead"]})}catch(e){o.fresh(()=>{i({level:"error",event:"residue.reap_scan.failed",error:e})});return}for(const e of r)if(!(e.pane==null&&e.window==null&&e.tmux_session==null)){try{if(this.msSinceTerminalActivity(e,t)<M)continue}catch(s){o.fresh(()=>{i({level:"error",event:"residue.reap.failed",...d(e.node_id)?{node_id:e.node_id}:{},error:s,fields:{...d(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})});continue}o.fresh(()=>{try{i({level:"info",event:"residue.reaped",...d(e.node_id)?{node_id:e.node_id}:{},fields:{...d(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}}),w(e.node_id)}catch(s){i({level:"error",event:"residue.reap.failed",...d(e.node_id)?{node_id:e.node_id}:{},error:s,fields:{...d(e.node_id)?{}:{affected_node_id:e.node_id},pane:e.pane,window:e.window,tmux_session:e.tmux_session}})}})}}scheduleFocusGc(t){if(this.focusGcInFlight||!t.lifecycle.acceptsDetachedWork())return;this.focusGcInFlight=!0;const r=this.gcStaleFocuses().finally(()=>{this.focusGcInFlight=!1});t.lifecycle.registerDetached(r)}async gcStaleFocuses(){let t;try{t=E()}catch(e){o.fresh(()=>{i({level:"error",event:"focus.gc.failed",error:e})});return}if(t.length===0)return;let r;try{r=await F()}catch(e){o.fresh(()=>{i({level:"error",event:"focus.gc.failed",error:e})});return}if(r!==null)for(const e of t){if(e.pane===null||r.has(e.pane))continue;if(!o.fresh(()=>{try{return N(e.focus_id)?.pane!==e.pane||(i({level:"info",event:"focus.gc.removed",...d(e.node_id)?{node_id:e.node_id}:{},fields:{focus_id:e.focus_id,focus_node_id:e.node_id,pane:e.pane}}),y(e.focus_id)),!0}catch(l){return i({level:"error",event:"focus.gc.failed",error:l}),!1}}))return}}gcWarmPool(t){t-this.lastSpareSweepAt<V||(this.lastSpareSweepAt=t,o.fresh(()=>{const r=D();r.length>0&&i({level:"info",event:"warm_pool.spares_reaped",outcome:"succeeded",fields:{reaped_count:r.length}})}))}}export{Y as CONTEXT_STRIP_GRACE_MS,M as DEAD_REAP_GRACE_MS,v as RETENTION_SWEEP_INTERVAL_MS,W as RETENTION_TTL_DAYS,ee as StorageMaintenanceReconciler};
@@ -1,3 +1,3 @@
1
- var d=Object.defineProperty;var n=(e,r)=>d(e,"name",{value:r,configurable:!0});import{formatCard as a}from"../../shared/generated-context.js";function p(e,r){const o=e.changed?`The user reviewed and approved \`${e.file}\`. The document changed during review; re-read it before continuing. Review conversation: node \`${e.companion_node_id}\`.`:`The user reviewed and approved \`${e.file}\`. The document was not modified.`;return a("review-approval",{},`${o}
1
+ var a=Object.defineProperty;var d=(e,n)=>a(e,"name",{value:n,configurable:!0});import{formatCard as r}from"../../shared/generated-context.js";function c(e,n){const o=e.document_name!==null?e.changed?`The user reviewed and approved \`${e.document_name}\`. Their edits are saved as a new revision; re-read it with \`crtr canvas read ${e.document_name}\` before continuing. Review conversation: node \`${e.companion_node_id}\`.`:`The user reviewed and approved \`${e.document_name}\`. The document was not modified.`:e.changed?`The user reviewed and approved \`${e.file}\`. The document changed during review; re-read it before continuing. Review conversation: node \`${e.companion_node_id}\`.`:`The user reviewed and approved \`${e.file}\`. The document was not modified.`;return r("review-approval",{},`${o}
2
2
 
3
- Durable review result: ${r}`)}n(p,"renderApprovalMessage");export{p as renderApprovalMessage};
3
+ Durable review result: ${n}`)}d(c,"renderApprovalMessage");export{c as renderApprovalMessage};
@@ -1 +1 @@
1
- var R=Object.defineProperty;var r=(e,t)=>R(e,"name",{value:t,configurable:!0});import{withCanvasWrite as j}from"../../core/canvas/db.js";import{snapshotCommentsLocked as S}from"../../core/review/comments.js";import{readReviewSource as q}from"../../core/review/document.js";import{projectReviewCancellation as C,projectReviewResult as g,buildReviewResult as J}from"../../core/review/project.js";import{signalReviewActivity as p}from"../../core/review/signal.js";import{getReview as N,getReviewByCompanion as O,requestReviewSubmit as $,requireVisibleReview as c}from"../../core/review/store.js";import{ReviewOperationError as k}from"../../core/review/types.js";import{settleHumanRequest as w}from"../human/settle.js";import{retireCompanion as _}from"../companion-retire.js";import{companionHasQueuedWork as T,companionMidTurn as x,companionStillWorking as A}from"./companion.js";import{renderApprovalMessage as E}from"./deliver.js";function f(){return new Date().toISOString()}r(f,"now");function d(e,t){throw new k("review_terminal","review already has a terminal outcome",{state:e.state,requested:t,review:e})}r(d,"terminalConflict");function v(e){if(e.result_json===null)throw new Error(`approved review lacks its immutable result: ${e.review_id}`);return JSON.parse(e.result_json)}r(v,"approvedResult");function b(e){return`${e.review_dir}/result.json`}r(b,"resultPath");function W(e){return{project:r(t=>{g(c(t.request_id),e)},"project"),retire:r(async(t,o)=>{await _(t,o)},"retire")}}r(W,"effects");function H(e){return{label:"review approved by the user",disposition:"human-answer",body_json:{review_id:e.review_id,result_path:b(e),body:E(e,b(e))}}}r(H,"approvalNotification");function M(e,t,o){const a=o==="dismissed";return{label:a?"review dismissed":"review canceled",disposition:"human-canceled",body_json:{review_id:e.review_id,disposition:o,body:a?`The review of \`${e.file}\` was dismissed without approval.`:`The review of \`${e.file}\` was canceled${t===""?"":` \u2014 ${t}`}.`}}}r(M,"cancellationNotification");async function y(e){if(e.state==="canceled")return d(e,"submit");if(e.state==="approved")return{outcome:"already_settled",record:e,result:v(e)};const t=q(e.file,"submit"),{result:o,resultJson:a}=j(m=>{const n=c(e.review_id);if(n.state==="canceled")return d(n,"submit");if(n.state==="approved")return{result:v(n),resultJson:n.result_json};const l=S(m,n.review_id),u=J(n,l,t.sha256,f());return{result:u,resultJson:JSON.stringify(u)}}),s=await w({request_id:e.review_id,outcome:"approved",result_json:a,notification:H({...e,changed:o.changed}),post_commit:W(o)});s.outcome==="settled"&&p();const i=c(e.review_id);return s.outcome==="already_settled"&&i.state!=="approved"?d(i,"submit"):{outcome:s.outcome,record:i,result:s.outcome==="settled"?o:v(i)}}r(y,"approveReview");async function Z(e){const t=c(e);return t.state==="canceled"?d(t,"submit"):t.state==="open"&&A(t.companion_node_id)?($(e,f())&&p(),{outcome:"awaiting_companion",record:c(e)}):y(t)}r(Z,"submitReviewApproval");async function B(e,t){const o=N(e);return o===null||o.state!=="open"||o.submit_requested_at===null||T(o.companion_node_id)||!t.atCompanionTurnEnd&&x(o.companion_node_id)?null:y(o)}r(B,"completeRequestedSubmit");async function I(e){const t=O(e);return t===null?null:B(t.review_id,{atCompanionTurnEnd:!0})}r(I,"completeCompanionRequestedSubmit");async function ee(e,t={}){const o=c(e);if(o.state==="approved")return d(o,"cancel");const a=f(),s=t.reason??"",i=t.disposition??"canceled",m=JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:a,...s===""?{}:{reason:s},...t.actor===void 0?{}:{actor:t.actor},...i==="dismissed"?{disposition:i}:{}}),n=await w({request_id:e,outcome:i==="dismissed"?"dismissed":"canceled",result_json:m,notification:M(o,s,i),post_commit:{project:r(u=>{C(c(u.request_id),JSON.parse(m))},"project"),retire:r(async(u,h)=>{await _(u,h)},"retire")}});n.outcome==="settled"&&p();const l=c(e);return n.outcome==="already_settled"&&l.state==="approved"?d(l,"cancel"):{outcome:n.outcome,record:l}}r(ee,"cancelReview");export{ee as cancelReview,I as completeCompanionRequestedSubmit,B as completeRequestedSubmit,Z as submitReviewApproval};
1
+ var g=Object.defineProperty;var n=(e,t)=>g(e,"name",{value:t,configurable:!0});import{withCanvasWrite as j}from"../../core/canvas/db.js";import{get as S}from"../../core/graph/bodies.js";import{documentById as q,editDocument as C,heads as $}from"../../core/graph/documents.js";import{readerFor as J}from"../../core/graph/reader.js";import{reposForCwd as k}from"../../core/graph/repo-sync/repos.js";import{snapshotCommentsLocked as x}from"../../core/review/comments.js";import{readReviewSource as N}from"../../core/review/document.js";import{projectReviewCancellation as O,projectReviewResult as T,buildReviewResult as A}from"../../core/review/project.js";import{signalReviewActivity as p}from"../../core/review/signal.js";import{clearReviewSubmit as D,getReview as E,getReviewByCompanion as B,requestReviewSubmit as F,requireVisibleReview as u}from"../../core/review/store.js";import{ReviewOperationError as f}from"../../core/review/types.js";import{settleHumanRequest as w}from"../human/settle.js";import{retireCompanion as h}from"../companion-retire.js";import{companionHasQueuedWork as W,companionMidTurn as H,companionStillWorking as M}from"./companion.js";import{renderApprovalMessage as L}from"./deliver.js";function _(){return new Date().toISOString()}n(_,"now");function l(e,t){throw new f("review_terminal","review already has a terminal outcome",{state:e.state,requested:t,review:e})}n(l,"terminalConflict");function v(e){if(e.result_json===null)throw new Error(`approved review lacks its immutable result: ${e.review_id}`);return JSON.parse(e.result_json)}n(v,"approvedResult");function y(e){return`${e.review_dir}/result.json`}n(y,"resultPath");function P(e){return{project:n(t=>{T(u(t.request_id),e)},"project"),retire:n(async(t,o)=>{await h(t,o)},"retire")}}n(P,"effects");function Q(e){return{label:"review approved by the user",disposition:"human-answer",body_json:{review_id:e.review_id,result_path:y(e),body:L(e,y(e))}}}n(Q,"approvalNotification");function V(e,t,o){const s=o==="dismissed";return{label:s?"review dismissed":"review canceled",disposition:"human-canceled",body_json:{review_id:e.review_id,disposition:o,body:s?`The review of \`${e.document_name??e.file}\` was dismissed without approval.`:`The review of \`${e.document_name??e.file}\` was canceled${t===""?"":` \u2014 ${t}`}.`}}}n(V,"cancellationNotification");function z(e,t,o){if(t.document_id===null||t.document_base===null)return;const s=n(d=>k(e,d),"reposFn"),i=q(e,t.document_id),a=J(e,{class:"person"},s),c=C(e,a,i,{body:o},`edited in review ${t.review_id}`,t.document_base,{},s);if(!("stale"in c))return;const r=$(e,i);if(!(r.length===1&&S(r[0].body_hash)===o))throw new f("stale_revision",`${t.document_name??i.name} changed since the review began; the reviewed text was not saved`,{review_id:t.review_id,document:t.document_name??i.name,base:t.document_base,heads_key:c.stale.heads_key,revision:c.stale.revision,next:`Read the current revision with \`crtr canvas read ${i.id}\`, then start a new review of it.`})}n(z,"saveReviewedDocument");async function b(e){if(e.state==="canceled")return l(e,"submit");if(e.state==="approved")return{outcome:"already_settled",record:e,result:v(e)};const t=N(e.file,"submit"),{result:o,resultJson:s}=j(c=>{const r=u(e.review_id);if(r.state==="canceled")return l(r,"submit");if(r.state==="approved")return{result:v(r),resultJson:r.result_json};const d=x(c,r.review_id),m=A(r,d,t.sha256,_());return m.changed&&z(c,r,new TextDecoder("utf-8").decode(t.bytes)),{result:m,resultJson:JSON.stringify(m)}}),i=await w({request_id:e.review_id,outcome:"approved",result_json:s,notification:Q({...e,changed:o.changed}),post_commit:P(o)});i.outcome==="settled"&&p();const a=u(e.review_id);return i.outcome==="already_settled"&&a.state!=="approved"?l(a,"submit"):{outcome:i.outcome,record:a,result:i.outcome==="settled"?o:v(a)}}n(b,"approveReview");async function de(e){const t=u(e);return t.state==="canceled"?l(t,"submit"):t.state==="open"&&M(t.companion_node_id)?(F(e,_())&&p(),{outcome:"awaiting_companion",record:u(e)}):b(t)}n(de,"submitReviewApproval");async function G(e,t){const o=E(e);if(o===null||o.state!=="open"||o.submit_requested_at===null||W(o.companion_node_id)||!t.atCompanionTurnEnd&&H(o.companion_node_id))return null;try{return await b(o)}catch(s){throw s instanceof f&&s.code==="stale_revision"&&(D(e),p()),s}}n(G,"completeRequestedSubmit");async function me(e){const t=B(e);return t===null?null:G(t.review_id,{atCompanionTurnEnd:!0})}n(me,"completeCompanionRequestedSubmit");async function le(e,t={}){const o=u(e);if(o.state==="approved")return l(o,"cancel");const s=_(),i=t.reason??"",a=t.disposition??"canceled",c=JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:s,...i===""?{}:{reason:i},...t.actor===void 0?{}:{actor:t.actor},...a==="dismissed"?{disposition:a}:{}}),r=await w({request_id:e,outcome:a==="dismissed"?"dismissed":"canceled",result_json:c,notification:V(o,i,a),post_commit:{project:n(m=>{O(u(m.request_id),JSON.parse(c))},"project"),retire:n(async(m,R)=>{await h(m,R)},"retire")}});r.outcome==="settled"&&p();const d=u(e);return r.outcome==="already_settled"&&d.state==="approved"?l(d,"cancel"):{outcome:r.outcome,record:d}}n(le,"cancelReview");export{le as cancelReview,me as completeCompanionRequestedSubmit,G as completeRequestedSubmit,de as submitReviewApproval};
@@ -16,7 +16,6 @@ export interface LifecycleHookNode {
16
16
  nodeDir: string;
17
17
  contextDir: string;
18
18
  jobDir: string;
19
- reportsDir: string;
20
19
  }
21
20
  export interface LifecycleHookRuntime {
22
21
  isBirth: boolean;
@@ -1,5 +1,5 @@
1
- var B=Object.defineProperty;var o=(e,r)=>B(e,"name",{value:r,configurable:!0});import{spawn as R}from"node:child_process";import{Console as T}from"node:console";import{posixProcessGroupSpawnOptions as M,terminateProcessGroup as j}from"./hook-process.js";function d(e,r,t={}){return{protocolVersion:1,ok:!1,error:{code:e,message:r,...t}}}o(d,"hookError");async function X(e,r={}){const t=r.stdin??process.stdin,s=r.stdout??process.stdout,i=r.stderr??process.stderr;let c;try{const m=await D(t);let p;try{p=JSON.parse(m)}catch{c=d("invalid_hook_request","stdin must contain one JSON hook request"),_(s,c);return}const f=P(p);if(!f.valid){c=d("invalid_hook_request",f.message),_(s,c);return}const g=e[f.value.op];if(g===void 0){c=d("unsupported_hook_op",`no handler is registered for ${f.value.op}`),_(s,c);return}try{c=await H(i,()=>g(f.value))}catch(h){i.write(`hook handler ${f.value.op} failed: ${b(h)}
1
+ var B=Object.defineProperty;var o=(e,r)=>B(e,"name",{value:r,configurable:!0});import{spawn as R}from"node:child_process";import{Console as T}from"node:console";import{posixProcessGroupSpawnOptions as M,terminateProcessGroup as j}from"./hook-process.js";function d(e,r,t={}){return{protocolVersion:1,ok:!1,error:{code:e,message:r,...t}}}o(d,"hookError");async function X(e,r={}){const t=r.stdin??process.stdin,s=r.stdout??process.stdout,i=r.stderr??process.stderr;let c;try{const m=await C(t);let p;try{p=JSON.parse(m)}catch{c=d("invalid_hook_request","stdin must contain one JSON hook request"),_(s,c);return}const f=A(p);if(!f.valid){c=d("invalid_hook_request",f.message),_(s,c);return}const g=e[f.value.op];if(g===void 0){c=d("unsupported_hook_op",`no handler is registered for ${f.value.op}`),_(s,c);return}try{c=await H(i,()=>g(f.value))}catch(h){i.write(`hook handler ${f.value.op} failed: ${b(h)}
2
2
  `),c=d("hook_handler_failed",`handler failed for ${f.value.op}`)}const a=I(c,f.value);a.valid||(i.write(`hook handler ${f.value.op} returned an invalid response: ${a.message}
3
3
  `),c=d("invalid_hook_response",a.message))}catch(m){i.write(`hook executable failed: ${b(m)}
4
- `),c=d("hook_executable_failed","hook executable could not read its request")}_(s,c)}o(X,"runHookExecutable");async function Y(e,r){const t=e[0];return t===void 0||t===""?d("local_process_invalid","local process argv[0] must not be empty"):!Number.isFinite(r.timeoutMs)||r.timeoutMs<=0?d("local_process_invalid_options","timeoutMs must be greater than zero"):new Promise(s=>{let i=!1,c=!1,m=!1,p=!1,f;const g=[],a=o(u=>{i||(i=!0,f!==void 0&&clearTimeout(f),s(u))},"settle");let h;try{h=R(t,e.slice(1),{cwd:r.cwd,env:r.env,shell:!1,stdio:[r.input===void 0?"ignore":"pipe","pipe","inherit"],...M()})}catch(u){a(d("local_process_spawn_failed",`could not start ${t}: ${b(u)}`));return}const x=o(()=>{c&&m&&p&&a(d("local_process_timeout",`${t} did not finish within ${r.timeoutMs}ms`))},"settleTimeout");f=setTimeout(()=>{c=!0,j(h).then(()=>{p=!0,x()},u=>{p=!0,a(d("local_process_cleanup_failed",`could not stop ${t}: ${b(u)}`))})},r.timeoutMs),h.stdout.on("data",u=>g.push(u)),h.once("error",u=>{h.pid===void 0&&a(d("local_process_spawn_failed",`could not start ${t}: ${b(u)}`))}),h.once("close",(u,$)=>{if(m=!0,c){x();return}if(u===0){a({ok:!0,stdout:Buffer.concat(g).toString("utf8")});return}const V=$===null?`exit code ${u??"unknown"}`:`signal ${$}`;a(d("local_process_failed",`${t} exited with ${V}`))}),r.input!==void 0&&h.stdin!==null&&h.stdin.end(r.input)})}o(Y,"runLocalHookProcess");async function Z(e,r,t){if(!Number.isFinite(t.timeoutMs)||t.timeoutMs<=0)return d("hook_forward_invalid_options","timeoutMs must be greater than zero");if(!Number.isSafeInteger(t.maxResponseBytes)||t.maxResponseBytes<=0)return d("hook_forward_invalid_options","maxResponseBytes must be a positive integer");const s=new Headers(t.headers);s.has("content-type")||s.set("content-type","application/json"),t.bearer!==void 0&&s.set("authorization",`Bearer ${t.bearer}`);const i=new AbortController;let c=!1;const m=setTimeout(()=>{c=!0,i.abort()},t.timeoutMs);try{const p=await fetch(e,{method:"POST",headers:s,body:JSON.stringify(r),signal:i.signal}),f=await C(p,t.maxResponseBytes);let g;try{g=JSON.parse(f)}catch{return d("hook_forward_invalid_response",`hook endpoint returned invalid JSON (HTTP ${p.status})`)}const a=I(g,r);return a.valid?a.value:d("hook_forward_invalid_response",`${a.message} (HTTP ${p.status})`)}catch(p){return c?d("hook_forward_timeout",`hook endpoint did not respond within ${t.timeoutMs}ms`):p instanceof N?d("hook_forward_response_too_large",`hook endpoint exceeded ${t.maxResponseBytes} response bytes`):d("hook_forward_failed",`hook endpoint request failed: ${b(p)}`)}finally{clearTimeout(m)}}o(Z,"forwardHook");const O=["log","info","debug","dir","table","group","groupCollapsed"];async function H(e,r){const t=new T({stdout:e,stderr:e,colorMode:!1}),s=new Map;for(const i of O)s.set(i,console[i]),console[i]=t[i].bind(t);try{return await r()}finally{for(const i of O)console[i]=s.get(i)}}o(H,"withConsoleStdoutOnStderr");function _(e,r){e.write(`${JSON.stringify(r)}
5
- `)}o(_,"writeResponse");async function D(e){const r=[];for await(const t of e)r.push(Buffer.isBuffer(t)?t:Buffer.from(t));return Buffer.concat(r).toString("utf8")}o(D,"readStream");async function C(e,r){if(e.body===null)return"";const t=e.body.getReader(),s=[];let i=0;try{for(;;){const{done:c,value:m}=await t.read();if(c)break;if(i+=m.byteLength,i>r)throw await t.cancel(),new N;s.push(m)}}finally{t.releaseLock()}return new TextDecoder().decode(J(s,i))}o(C,"readResponseBody");function J(e,r){const t=new Uint8Array(r);let s=0;for(const i of e)t.set(i,s),s+=i.byteLength;return t}o(J,"concatBytes");function P(e){return y(e)?e.protocolVersion!==1?n("unsupported hook protocol version"):typeof e.op!="string"||e.op===""?n("op must be a non-empty string"):typeof e.operationId!="string"||!/^[0-9a-f]{32}$/.test(e.operationId)?n("operationId must be a 32-character lowercase hexadecimal string"):e.event==="node:create"?l(e,["protocolVersion","op","event","phase","operationId","create","runtime","context"])?e.phase!=="before"?n("node:create phase must be before"):E(e.create)?L(e.runtime)?q(e.context)?w({protocolVersion:1,op:e.op,event:"node:create",phase:"before",operationId:e.operationId,create:e.create,runtime:e.runtime,context:e.context}):n("node:create request context must contain cwd"):n("node:create request runtime contains invalid fields"):n("node:create request create contains invalid fields"):n("node:create request contains unknown fields"):e.phase==="on"?l(e,["protocolVersion","op","event","phase","operationId","node","runtime","context"])?e.event!=="node:start"&&e.event!=="node:close"?n("unsupported lifecycle event"):z(e.node)?F(e.runtime)?q(e.context)?w({protocolVersion:1,op:e.op,event:e.event,phase:"on",operationId:e.operationId,node:e.node,runtime:e.runtime,context:e.context}):n("lifecycle request context must contain cwd"):n("lifecycle request runtime contains invalid fields"):n("lifecycle request node contains invalid fields"):n("lifecycle request contains unknown fields"):l(e,["protocolVersion","op","phase","command","operationId","input","context","result"])?!S(e.command)||e.command.length===0?n("command must be a non-empty string array"):!y(e.input)||!k(e.input)?n("input must be a JSON object"):A(e.context)?e.phase==="after"?!Object.hasOwn(e,"result")||!k(e.result)?n("after requests require a JSON result"):w({protocolVersion:1,op:e.op,phase:"after",command:e.command,operationId:e.operationId,input:e.input,context:e.context,result:e.result}):e.phase!=="before"&&e.phase!=="replace"?n("phase must be before, after, or replace"):Object.hasOwn(e,"result")?n("only after requests may contain result"):e.phase==="before"?w({protocolVersion:1,op:e.op,phase:"before",command:e.command,operationId:e.operationId,input:e.input,context:e.context}):w({protocolVersion:1,op:e.op,phase:"replace",command:e.command,operationId:e.operationId,input:e.input,context:e.context}):n("context must contain cwd and providedParams"):n("request contains unknown fields"):n("request must be an object")}o(P,"validateRequest");function I(e,r){if(!y(e))return n("response must be an object");if(e.protocolVersion!==1)return n("response has an unsupported hook protocol version");if(e.ok===!0){if(!l(e,["protocolVersion","ok","result"]))return n("successful response contains unknown fields");const t=Object.hasOwn(e,"result");if(r.phase==="replace"&&!t)return n("replace response requires result");if(r.phase!=="replace"&&t)return n("only replace responses may contain result");if(t){const s=e.result;return k(s)?w({protocolVersion:1,ok:!0,result:s}):n("response result must be JSON")}return w({protocolVersion:1,ok:!0})}return e.ok!==!1||!l(e,["protocolVersion","ok","error"])?n("response must contain protocolVersion, ok, and error or result"):G(e.error)?w({protocolVersion:1,ok:!1,error:e.error}):n("response error must contain code and message strings")}o(I,"validateResponse");function A(e){return y(e)&&l(e,["cwd","providedParams"])&&typeof e.cwd=="string"&&S(e.providedParams)}o(A,"isContext");function q(e){return y(e)&&l(e,["cwd"])&&typeof e.cwd=="string"}o(q,"isLifecycleContext");function E(e){return y(e)&&l(e,["kind","mode","cwd","profile","root","parentId","requestingNodeId","lifecycle","replaces"])&&typeof e.kind=="string"&&typeof e.mode=="string"&&typeof e.cwd=="string"&&(typeof e.profile=="string"||e.profile===null)&&typeof e.root=="boolean"&&(typeof e.parentId=="string"||e.parentId===null)&&(typeof e.requestingNodeId=="string"||e.requestingNodeId===null)&&(e.lifecycle==="resident"||e.lifecycle==="terminal")&&(typeof e.replaces=="string"||e.replaces===null)}o(E,"isNodeCreate");function L(e){return y(e)&&l(e,["canvasHome","profile"])&&typeof e.canvasHome=="string"&&(typeof e.profile=="string"||e.profile===null)}o(L,"isCreateRuntime");function z(e){return y(e)&&l(e,["id","name","kind","mode","lifecycle","cwd","nodeDir","contextDir","jobDir","reportsDir"])&&["id","name","kind","mode","lifecycle","cwd","nodeDir","contextDir","jobDir","reportsDir"].every(r=>typeof e[r]=="string")}o(z,"isLifecycleNode");function F(e){return y(e)&&l(e,["isBirth","canvasHome","profile"])&&typeof e.isBirth=="boolean"&&typeof e.canvasHome=="string"&&(typeof e.profile=="string"||e.profile===null)}o(F,"isLifecycleRuntime");function G(e){return y(e)&&l(e,["code","message","field","next"])&&typeof e.code=="string"&&e.code!==""&&typeof e.message=="string"&&e.message!==""&&(e.field===void 0||typeof e.field=="string")&&(e.next===void 0||typeof e.next=="string")}o(G,"isHookError");function y(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(y,"isRecord");function S(e){return Array.isArray(e)&&e.every(r=>typeof r=="string")}o(S,"isStringArray");function k(e){return e===null||typeof e=="boolean"||typeof e=="string"?!0:typeof e=="number"?Number.isFinite(e):Array.isArray(e)?e.every(k):y(e)&&Object.values(e).every(k)}o(k,"isJson");function l(e,r){return Object.keys(e).every(t=>r.includes(t))}o(l,"hasOnlyKeys");function w(e){return{valid:!0,value:e}}o(w,"valid");function n(e){return{valid:!1,message:e}}o(n,"invalid");function b(e){return e instanceof Error?e.message:String(e)}o(b,"describeError");class N extends Error{static{o(this,"ResponseTooLargeError")}}export{Z as forwardHook,d as hookError,X as runHookExecutable,Y as runLocalHookProcess};
4
+ `),c=d("hook_executable_failed","hook executable could not read its request")}_(s,c)}o(X,"runHookExecutable");async function Y(e,r){const t=e[0];return t===void 0||t===""?d("local_process_invalid","local process argv[0] must not be empty"):!Number.isFinite(r.timeoutMs)||r.timeoutMs<=0?d("local_process_invalid_options","timeoutMs must be greater than zero"):new Promise(s=>{let i=!1,c=!1,m=!1,p=!1,f;const g=[],a=o(u=>{i||(i=!0,f!==void 0&&clearTimeout(f),s(u))},"settle");let h;try{h=R(t,e.slice(1),{cwd:r.cwd,env:r.env,shell:!1,stdio:[r.input===void 0?"ignore":"pipe","pipe","inherit"],...M()})}catch(u){a(d("local_process_spawn_failed",`could not start ${t}: ${b(u)}`));return}const x=o(()=>{c&&m&&p&&a(d("local_process_timeout",`${t} did not finish within ${r.timeoutMs}ms`))},"settleTimeout");f=setTimeout(()=>{c=!0,j(h).then(()=>{p=!0,x()},u=>{p=!0,a(d("local_process_cleanup_failed",`could not stop ${t}: ${b(u)}`))})},r.timeoutMs),h.stdout.on("data",u=>g.push(u)),h.once("error",u=>{h.pid===void 0&&a(d("local_process_spawn_failed",`could not start ${t}: ${b(u)}`))}),h.once("close",(u,$)=>{if(m=!0,c){x();return}if(u===0){a({ok:!0,stdout:Buffer.concat(g).toString("utf8")});return}const V=$===null?`exit code ${u??"unknown"}`:`signal ${$}`;a(d("local_process_failed",`${t} exited with ${V}`))}),r.input!==void 0&&h.stdin!==null&&h.stdin.end(r.input)})}o(Y,"runLocalHookProcess");async function Z(e,r,t){if(!Number.isFinite(t.timeoutMs)||t.timeoutMs<=0)return d("hook_forward_invalid_options","timeoutMs must be greater than zero");if(!Number.isSafeInteger(t.maxResponseBytes)||t.maxResponseBytes<=0)return d("hook_forward_invalid_options","maxResponseBytes must be a positive integer");const s=new Headers(t.headers);s.has("content-type")||s.set("content-type","application/json"),t.bearer!==void 0&&s.set("authorization",`Bearer ${t.bearer}`);const i=new AbortController;let c=!1;const m=setTimeout(()=>{c=!0,i.abort()},t.timeoutMs);try{const p=await fetch(e,{method:"POST",headers:s,body:JSON.stringify(r),signal:i.signal}),f=await J(p,t.maxResponseBytes);let g;try{g=JSON.parse(f)}catch{return d("hook_forward_invalid_response",`hook endpoint returned invalid JSON (HTTP ${p.status})`)}const a=I(g,r);return a.valid?a.value:d("hook_forward_invalid_response",`${a.message} (HTTP ${p.status})`)}catch(p){return c?d("hook_forward_timeout",`hook endpoint did not respond within ${t.timeoutMs}ms`):p instanceof N?d("hook_forward_response_too_large",`hook endpoint exceeded ${t.maxResponseBytes} response bytes`):d("hook_forward_failed",`hook endpoint request failed: ${b(p)}`)}finally{clearTimeout(m)}}o(Z,"forwardHook");const O=["log","info","debug","dir","table","group","groupCollapsed"];async function H(e,r){const t=new T({stdout:e,stderr:e,colorMode:!1}),s=new Map;for(const i of O)s.set(i,console[i]),console[i]=t[i].bind(t);try{return await r()}finally{for(const i of O)console[i]=s.get(i)}}o(H,"withConsoleStdoutOnStderr");function _(e,r){e.write(`${JSON.stringify(r)}
5
+ `)}o(_,"writeResponse");async function C(e){const r=[];for await(const t of e)r.push(Buffer.isBuffer(t)?t:Buffer.from(t));return Buffer.concat(r).toString("utf8")}o(C,"readStream");async function J(e,r){if(e.body===null)return"";const t=e.body.getReader(),s=[];let i=0;try{for(;;){const{done:c,value:m}=await t.read();if(c)break;if(i+=m.byteLength,i>r)throw await t.cancel(),new N;s.push(m)}}finally{t.releaseLock()}return new TextDecoder().decode(P(s,i))}o(J,"readResponseBody");function P(e,r){const t=new Uint8Array(r);let s=0;for(const i of e)t.set(i,s),s+=i.byteLength;return t}o(P,"concatBytes");function A(e){return y(e)?e.protocolVersion!==1?n("unsupported hook protocol version"):typeof e.op!="string"||e.op===""?n("op must be a non-empty string"):typeof e.operationId!="string"||!/^[0-9a-f]{32}$/.test(e.operationId)?n("operationId must be a 32-character lowercase hexadecimal string"):e.event==="node:create"?l(e,["protocolVersion","op","event","phase","operationId","create","runtime","context"])?e.phase!=="before"?n("node:create phase must be before"):E(e.create)?L(e.runtime)?q(e.context)?w({protocolVersion:1,op:e.op,event:"node:create",phase:"before",operationId:e.operationId,create:e.create,runtime:e.runtime,context:e.context}):n("node:create request context must contain cwd"):n("node:create request runtime contains invalid fields"):n("node:create request create contains invalid fields"):n("node:create request contains unknown fields"):e.phase==="on"?l(e,["protocolVersion","op","event","phase","operationId","node","runtime","context"])?e.event!=="node:start"&&e.event!=="node:close"?n("unsupported lifecycle event"):z(e.node)?F(e.runtime)?q(e.context)?w({protocolVersion:1,op:e.op,event:e.event,phase:"on",operationId:e.operationId,node:e.node,runtime:e.runtime,context:e.context}):n("lifecycle request context must contain cwd"):n("lifecycle request runtime contains invalid fields"):n("lifecycle request node contains invalid fields"):n("lifecycle request contains unknown fields"):l(e,["protocolVersion","op","phase","command","operationId","input","context","result"])?!S(e.command)||e.command.length===0?n("command must be a non-empty string array"):!y(e.input)||!k(e.input)?n("input must be a JSON object"):D(e.context)?e.phase==="after"?!Object.hasOwn(e,"result")||!k(e.result)?n("after requests require a JSON result"):w({protocolVersion:1,op:e.op,phase:"after",command:e.command,operationId:e.operationId,input:e.input,context:e.context,result:e.result}):e.phase!=="before"&&e.phase!=="replace"?n("phase must be before, after, or replace"):Object.hasOwn(e,"result")?n("only after requests may contain result"):e.phase==="before"?w({protocolVersion:1,op:e.op,phase:"before",command:e.command,operationId:e.operationId,input:e.input,context:e.context}):w({protocolVersion:1,op:e.op,phase:"replace",command:e.command,operationId:e.operationId,input:e.input,context:e.context}):n("context must contain cwd and providedParams"):n("request contains unknown fields"):n("request must be an object")}o(A,"validateRequest");function I(e,r){if(!y(e))return n("response must be an object");if(e.protocolVersion!==1)return n("response has an unsupported hook protocol version");if(e.ok===!0){if(!l(e,["protocolVersion","ok","result"]))return n("successful response contains unknown fields");const t=Object.hasOwn(e,"result");if(r.phase==="replace"&&!t)return n("replace response requires result");if(r.phase!=="replace"&&t)return n("only replace responses may contain result");if(t){const s=e.result;return k(s)?w({protocolVersion:1,ok:!0,result:s}):n("response result must be JSON")}return w({protocolVersion:1,ok:!0})}return e.ok!==!1||!l(e,["protocolVersion","ok","error"])?n("response must contain protocolVersion, ok, and error or result"):G(e.error)?w({protocolVersion:1,ok:!1,error:e.error}):n("response error must contain code and message strings")}o(I,"validateResponse");function D(e){return y(e)&&l(e,["cwd","providedParams"])&&typeof e.cwd=="string"&&S(e.providedParams)}o(D,"isContext");function q(e){return y(e)&&l(e,["cwd"])&&typeof e.cwd=="string"}o(q,"isLifecycleContext");function E(e){return y(e)&&l(e,["kind","mode","cwd","profile","root","parentId","requestingNodeId","lifecycle","replaces"])&&typeof e.kind=="string"&&typeof e.mode=="string"&&typeof e.cwd=="string"&&(typeof e.profile=="string"||e.profile===null)&&typeof e.root=="boolean"&&(typeof e.parentId=="string"||e.parentId===null)&&(typeof e.requestingNodeId=="string"||e.requestingNodeId===null)&&(e.lifecycle==="resident"||e.lifecycle==="terminal")&&(typeof e.replaces=="string"||e.replaces===null)}o(E,"isNodeCreate");function L(e){return y(e)&&l(e,["canvasHome","profile"])&&typeof e.canvasHome=="string"&&(typeof e.profile=="string"||e.profile===null)}o(L,"isCreateRuntime");function z(e){return y(e)&&l(e,["id","name","kind","mode","lifecycle","cwd","nodeDir","contextDir","jobDir"])&&["id","name","kind","mode","lifecycle","cwd","nodeDir","contextDir","jobDir"].every(r=>typeof e[r]=="string")}o(z,"isLifecycleNode");function F(e){return y(e)&&l(e,["isBirth","canvasHome","profile"])&&typeof e.isBirth=="boolean"&&typeof e.canvasHome=="string"&&(typeof e.profile=="string"||e.profile===null)}o(F,"isLifecycleRuntime");function G(e){return y(e)&&l(e,["code","message","field","next"])&&typeof e.code=="string"&&e.code!==""&&typeof e.message=="string"&&e.message!==""&&(e.field===void 0||typeof e.field=="string")&&(e.next===void 0||typeof e.next=="string")}o(G,"isHookError");function y(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(y,"isRecord");function S(e){return Array.isArray(e)&&e.every(r=>typeof r=="string")}o(S,"isStringArray");function k(e){return e===null||typeof e=="boolean"||typeof e=="string"?!0:typeof e=="number"?Number.isFinite(e):Array.isArray(e)?e.every(k):y(e)&&Object.values(e).every(k)}o(k,"isJson");function l(e,r){return Object.keys(e).every(t=>r.includes(t))}o(l,"hasOnlyKeys");function w(e){return{valid:!0,value:e}}o(w,"valid");function n(e){return{valid:!1,message:e}}o(n,"invalid");function b(e){return e instanceof Error?e.message:String(e)}o(b,"describeError");class N extends Error{static{o(this,"ResponseTooLargeError")}}export{Z as forwardHook,d as hookError,X as runHookExecutable,Y as runLocalHookProcess};
@@ -0,0 +1,10 @@
1
+ import type { DatabaseSync } from 'node:sqlite';
2
+ import type { ImportPlan, ImportReport } from './plan.js';
3
+ /** The canvas_meta key whose presence means this home's legacy stores were imported. */
4
+ export declare const IMPORT_DONE_KEY = "canvas-import";
5
+ export declare const IMPORT_ID = "004-canvas-documents";
6
+ export declare function readImportRecord(db: DatabaseSync): ImportReport | null;
7
+ /** Store every revision body. Call before `applyPlan`, outside its transaction. */
8
+ export declare function storePlanBodies(plan: ImportPlan): Map<string, string>;
9
+ /** Run inside the caller's write transaction. Throws on any divergence from the plan. */
10
+ export declare function applyPlan(db: DatabaseSync, plan: ImportPlan, hashes: ReadonlyMap<string, string>): void;
@@ -0,0 +1 @@
1
+ var x=Object.defineProperty;var d=(n,t)=>x(n,"name",{value:t,configurable:!0});import{put as N}from"../../core/graph/bodies.js";import{importDocument as O}from"../../core/graph/documents.js";import{linksIn as _}from"../../core/graph/documents.js";import{recordActedOn as M,setLinks as R}from"../../core/graph/edges.js";import{resolveName as $}from"../../core/graph/names.js";import{ensureOwner as y,nodeObject as k,ownerForGrantee as b}from"../../core/graph/objects.js";import{ensureRepo as S}from"../../core/graph/repo-sync/repos.js";import{recordWatch as T}from"../../core/graph/watches.js";const v="canvas-import",K="004-canvas-documents";function C(n){const t=n.prepare("SELECT value FROM canvas_meta WHERE key = ?").get(v);if(t===void 0)return null;const p=JSON.parse(t.value).report;return{...p,resolutions:p.resolutions??[]}}d(C,"readImportRecord");function G(n){const t=new Map;for(const p of n.documents)for(const i of p.revisions)t.has(i.body)||t.set(i.body,N(i.body));return t}d(G,"storePlanBodies");function U(n,t,p){const i=new Map(t.owners.map(e=>[e.key,e])),f=new Map,u=d(e=>{const o=f.get(e.key);if(o)return o;let r;switch(e.type){case"person":r=b(n,"user:local");break;case"app":r=y(n,"app","app",`app:${e.handle}`,e.handle);break;case"profile":{const c=i.get(e.ownerKey);if(!c)throw new Error(`import: profile ${e.key} names unplanned app ${e.ownerKey}`);r=y(n,"profile","profile",e.key.slice(8),e.handle,u(c));break}case"repo":r=S(n,{scheme:e.scheme,externalId:e.externalId,handleHint:e.handle},e.handle);break;case"node":r=k(n,e.handle);break}if(e.type!=="node"&&r.name!==e.handle)throw new Error(`import: owner ${e.key} holds handle ${r.name}, planned ${e.handle}`);return f.set(e.key,r),r},"ownerRow"),I={class:"person",person:u(i.get("person")??{key:"person",type:"person",handle:"user"})},h=new Map,m=d(e=>{let o=h.get(e);return o||h.set(e,o=k(n,e)),o},"node"),w=[];for(const e of t.documents){const o=u(i.get(e.ownerKey)),r=O(n,{owner:o,name:e.name,kind:e.kind,preview:e.preview,privacy:e.privacy,summary:e.summary,whyItExists:e.whyItExists,unlisted:e.unlisted,rules:e.rules,lintIgnore:e.lintIgnore,extensions:e.extensions,revisions:e.revisions.map(s=>({body_hash:p.get(s.body),author:s.authorNodeId===null?null:m(s.authorNodeId),rationale:s.rationale,created_at:s.createdAt}))}),c=new Set(e.revisions.flatMap(s=>s.authorNodeId===null?[]:[s.authorNodeId]));w.push({doc:r,owner:o,body:e.revisions[e.revisions.length-1].body,authors:c})}for(const{doc:e,owner:o,body:r,authors:c}of w){const s=[];for(const a of _(r)){const g=a.includes("/")?[a]:[`${o.type==="node"?o.id:o.name}/${a}`,a];for(const E of g){const l=$(n,I,E);if("object"in l){s.push({written_as:a,dst:l.object});break}if("deleted"in l){s.push({written_as:a,dst:l.deleted});break}}}R(n,e,s);for(const a of c)M(n,m(a),e),T(n,m(a),e,"write")}n.prepare("INSERT INTO canvas_meta (key, value) VALUES (?, ?)").run(v,JSON.stringify({id:K,report:t.report}))}d(U,"applyPlan");export{v as IMPORT_DONE_KEY,K as IMPORT_ID,U as applyPlan,C as readImportRecord,G as storePlanBodies};