@atolis-hq/wake 0.2.97 → 0.3.0

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 (442) hide show
  1. package/dist/src/activities/agent/agent-activity-definition.js +26 -0
  2. package/dist/src/activities/agent/agent-activity.js +171 -0
  3. package/dist/src/activities/agent/agent-result.js +149 -0
  4. package/dist/src/activities/contracts/activity.js +10 -0
  5. package/dist/src/activities/contracts/config.js +2 -0
  6. package/dist/src/activities/contracts/event-schema.js +302 -0
  7. package/dist/src/activities/contracts/events.js +42 -0
  8. package/dist/src/activities/contracts/identifiers.js +29 -0
  9. package/dist/src/activities/contracts/registry.js +71 -0
  10. package/dist/src/activities/contracts/streams.js +17 -0
  11. package/dist/src/activities/contracts/vocabulary.js +58 -0
  12. package/dist/src/activities/index.js +21 -0
  13. package/dist/src/activities/pr/activity-support.js +111 -0
  14. package/dist/src/activities/pr/application.js +158 -0
  15. package/dist/src/activities/pr/approve.js +85 -0
  16. package/dist/src/activities/pr/capability.js +11 -0
  17. package/dist/src/activities/pr/decision-claim.js +76 -0
  18. package/dist/src/activities/pr/event-drafts.js +66 -0
  19. package/dist/src/activities/pr/intent.js +37 -0
  20. package/dist/src/activities/pr/merge-authority-gate.js +14 -0
  21. package/dist/src/activities/pr/merge.js +110 -0
  22. package/dist/src/activities/pr/policy.js +135 -0
  23. package/dist/src/activities/pr/projection.js +130 -0
  24. package/dist/src/activities/pr/vocabulary.js +30 -0
  25. package/dist/src/activities/review/authorization.js +22 -0
  26. package/dist/src/activities/review/contracts.js +22 -0
  27. package/dist/src/activities/review/signals.js +3 -0
  28. package/dist/src/bootstrap/analytics-projection.js +26 -0
  29. package/dist/src/bootstrap/board-projection.js +337 -0
  30. package/dist/src/bootstrap/composition-root.js +382 -0
  31. package/dist/src/bootstrap/config/load-config.js +51 -0
  32. package/dist/src/bootstrap/config/root-schema.js +134 -0
  33. package/dist/src/bootstrap/external-ref.js +12 -0
  34. package/dist/src/bootstrap/fake-provider-files.js +44 -0
  35. package/dist/src/bootstrap/fake-scenarios.js +22 -0
  36. package/dist/src/bootstrap/index.js +48 -0
  37. package/dist/src/bootstrap/initialise.js +434 -0
  38. package/dist/src/bootstrap/paths.js +15 -0
  39. package/dist/src/bootstrap/projection-runtime.js +27 -0
  40. package/dist/src/bootstrap/runner-quota-reporter.js +21 -0
  41. package/dist/src/bootstrap/runner-registry.js +30 -0
  42. package/dist/src/bootstrap/schedule-checkpoint-store.js +49 -0
  43. package/dist/src/bootstrap/self-update-application.js +195 -0
  44. package/dist/src/bootstrap/self-update-failure-log.js +33 -0
  45. package/dist/src/bootstrap/source-update-port.js +47 -0
  46. package/dist/src/bootstrap/status-publish-activity.js +42 -0
  47. package/dist/src/bootstrap/surface-api-applications.js +325 -0
  48. package/dist/src/bootstrap/surface-api-execution-applications.js +95 -0
  49. package/dist/src/bootstrap/surface-api-metadata.js +12 -0
  50. package/dist/src/bootstrap/surface-api-projection-pages.js +22 -0
  51. package/dist/src/bootstrap/surface-api-run-context.js +5 -0
  52. package/dist/src/bootstrap/surface-api-transcripts.js +57 -0
  53. package/dist/src/bootstrap/surface-api-work-applications.js +199 -0
  54. package/dist/src/bootstrap/surface-applications.js +7 -0
  55. package/dist/src/bootstrap/surface-cli-applications.js +701 -0
  56. package/dist/src/bootstrap/update-ledger.js +61 -0
  57. package/dist/src/bootstrap/update-maintenance-lease.js +176 -0
  58. package/dist/src/{version.js → bootstrap/version.js} +35 -51
  59. package/dist/src/control-plane/application/advance-once.js +184 -0
  60. package/dist/src/control-plane/application/control-plane-projection.js +42 -0
  61. package/dist/src/control-plane/application/control-plane-service.js +42 -0
  62. package/dist/src/control-plane/application/intake-pipeline.js +29 -0
  63. package/dist/src/control-plane/application/runner-control-service.js +66 -0
  64. package/dist/src/control-plane/application/runner-pipeline.js +57 -0
  65. package/dist/src/control-plane/application/schedule-service.js +47 -0
  66. package/dist/src/control-plane/application/work-cancellation-policy.js +31 -0
  67. package/dist/src/control-plane/contracts/commands.js +10 -0
  68. package/dist/src/control-plane/contracts/config.js +22 -0
  69. package/dist/src/control-plane/contracts/events.js +81 -0
  70. package/dist/src/control-plane/contracts/streams.js +5 -0
  71. package/dist/src/control-plane/domain/dispatch-policy.js +15 -0
  72. package/dist/src/control-plane/domain/quota-policy.js +26 -0
  73. package/dist/src/control-plane/domain/runner-quota.js +35 -0
  74. package/dist/src/control-plane/domain/schedule-policy.js +46 -0
  75. package/dist/src/control-plane/index.js +20 -0
  76. package/dist/src/control-plane/infrastructure/intake-host.js +24 -0
  77. package/dist/src/control-plane/infrastructure/resident-host.js +45 -0
  78. package/dist/src/control-plane/infrastructure/tick-host.js +35 -0
  79. package/dist/src/execution/application/activation-claim.js +50 -0
  80. package/dist/src/execution/application/active-run-cancellation.js +14 -0
  81. package/dist/src/execution/application/execution-activity.js +97 -0
  82. package/dist/src/execution/application/execution-projection.js +17 -0
  83. package/dist/src/execution/application/execution-service.js +372 -0
  84. package/dist/src/execution/application/execution-validation.js +26 -0
  85. package/dist/src/execution/application/recovery-service.js +212 -0
  86. package/dist/src/execution/application/run-lifecycle.js +115 -0
  87. package/dist/src/execution/application/run-liveness-service.js +80 -0
  88. package/dist/src/execution/application/run-repository.js +27 -0
  89. package/dist/src/execution/contracts/commands.js +1 -0
  90. package/dist/src/execution/contracts/config.js +35 -0
  91. package/dist/src/execution/contracts/control-plane.js +1 -0
  92. package/dist/src/execution/contracts/event-factory.js +53 -0
  93. package/dist/src/execution/contracts/events.js +274 -0
  94. package/dist/src/execution/contracts/identifiers.js +5 -0
  95. package/dist/src/execution/contracts/liveness.js +1 -0
  96. package/dist/src/execution/contracts/results.js +1 -0
  97. package/dist/src/execution/contracts/runner.js +15 -0
  98. package/dist/src/execution/contracts/streams.js +10 -0
  99. package/dist/src/execution/contracts/views.js +1 -0
  100. package/dist/src/execution/contracts/vocabulary.js +43 -0
  101. package/dist/src/execution/contracts/workspace.js +1 -0
  102. package/dist/src/execution/domain/run-result.js +34 -0
  103. package/dist/src/execution/domain/run.js +142 -0
  104. package/dist/src/execution/index.js +31 -0
  105. package/dist/src/execution/infrastructure/agent-runner-adapter.js +114 -0
  106. package/dist/src/execution/infrastructure/process-execution.js +29 -0
  107. package/dist/src/execution/infrastructure/prompt-templates.js +42 -0
  108. package/dist/src/execution/infrastructure/runners/claude.js +120 -0
  109. package/dist/src/execution/infrastructure/runners/codex.js +143 -0
  110. package/dist/src/execution/infrastructure/runners/command.js +4 -0
  111. package/dist/src/execution/infrastructure/runners/cursor.js +69 -0
  112. package/dist/src/execution/infrastructure/runners/fake-scenarios.js +99 -0
  113. package/dist/src/execution/infrastructure/runners/fake.js +65 -0
  114. package/dist/src/execution/infrastructure/runners/registry.js +26 -0
  115. package/dist/src/execution/infrastructure/transcript-store.js +223 -0
  116. package/dist/src/execution/infrastructure/transcripts.js +11 -0
  117. package/dist/src/execution/infrastructure/workspace/fake-workspace.js +19 -0
  118. package/dist/src/execution/infrastructure/workspace/git-workspace.js +241 -0
  119. package/dist/src/integrations/application/agent-run-publication-reactor.js +111 -0
  120. package/dist/src/integrations/application/artifact-registration-reactor.js +159 -0
  121. package/dist/src/integrations/application/poll-service.js +25 -0
  122. package/dist/src/integrations/application/terminal-agent-run-report.js +40 -0
  123. package/dist/src/integrations/application/work-admission.js +31 -0
  124. package/dist/src/integrations/application/work-conclusion.js +19 -0
  125. package/dist/src/integrations/contracts/artifact-events.js +60 -0
  126. package/dist/src/integrations/contracts/artifact-vocabulary.js +9 -0
  127. package/dist/src/integrations/contracts/config.js +14 -0
  128. package/dist/src/integrations/contracts/identifiers.js +5 -0
  129. package/dist/src/integrations/contracts/intake-rules.js +14 -0
  130. package/dist/src/integrations/contracts/intake.js +1 -0
  131. package/dist/src/integrations/contracts/outcome-vocabulary.js +7 -0
  132. package/dist/src/integrations/contracts/provider.js +37 -0
  133. package/dist/src/integrations/contracts/streams.js +10 -0
  134. package/dist/src/integrations/delivery/application/delivery-outcome-reactor.js +75 -0
  135. package/dist/src/integrations/delivery/application/delivery-projector.js +165 -0
  136. package/dist/src/integrations/delivery/application/delivery-service.js +173 -0
  137. package/dist/src/integrations/delivery/contracts/commands.js +1 -0
  138. package/dist/src/integrations/delivery/contracts/config.js +1 -0
  139. package/dist/src/integrations/delivery/contracts/event-factory.js +18 -0
  140. package/dist/src/integrations/delivery/contracts/events.js +86 -0
  141. package/dist/src/integrations/delivery/contracts/intents.js +89 -0
  142. package/dist/src/integrations/delivery/contracts/views.js +1 -0
  143. package/dist/src/integrations/delivery/contracts/vocabulary.js +22 -0
  144. package/dist/src/integrations/fake/durable-delivery-provider.js +48 -0
  145. package/dist/src/integrations/fake/external-sink.js +9 -0
  146. package/dist/src/integrations/fake/external-source.js +44 -0
  147. package/dist/src/integrations/fake/inbound-translator.js +130 -0
  148. package/dist/src/integrations/fake/provider.js +95 -0
  149. package/dist/src/integrations/github/application/agent-context-reader.js +54 -0
  150. package/dist/src/integrations/github/application/agent-run-comment.js +94 -0
  151. package/dist/src/integrations/github/application/comment-history-reader.js +43 -0
  152. package/dist/src/integrations/github/application/inbound-context.js +10 -0
  153. package/dist/src/integrations/github/application/inbound-review-signals.js +159 -0
  154. package/dist/src/integrations/github/application/inbound-translator.js +231 -0
  155. package/dist/src/integrations/github/application/inbound-watch-gate-signals.js +84 -0
  156. package/dist/src/integrations/github/application/intake-policy.js +23 -0
  157. package/dist/src/integrations/github/application/outbound-translator.js +47 -0
  158. package/dist/src/integrations/github/application/poll-service.js +29 -0
  159. package/dist/src/integrations/github/application/pull-request-translation.js +10 -0
  160. package/dist/src/integrations/github/application/resource-links.js +8 -0
  161. package/dist/src/integrations/github/application/review-command-translator.js +16 -0
  162. package/dist/src/integrations/github/application/wake-labels.js +95 -0
  163. package/dist/src/integrations/github/contracts/config.js +47 -0
  164. package/dist/src/integrations/github/contracts/events.js +127 -0
  165. package/dist/src/integrations/github/contracts/external-key.js +19 -0
  166. package/dist/src/integrations/github/contracts/payloads.js +9 -0
  167. package/dist/src/integrations/github/contracts/vocabulary.js +55 -0
  168. package/dist/src/integrations/github/index.js +31 -0
  169. package/dist/src/integrations/github/infrastructure/client-reads.js +214 -0
  170. package/dist/src/integrations/github/infrastructure/client.js +132 -0
  171. package/dist/src/integrations/github/infrastructure/content-fingerprint.js +10 -0
  172. package/dist/src/integrations/github/infrastructure/delivery.js +31 -0
  173. package/dist/src/integrations/github/infrastructure/etag-cache.js +56 -0
  174. package/dist/src/integrations/github/infrastructure/gh-auth.js +19 -0
  175. package/dist/src/integrations/github/infrastructure/issue-source.js +109 -0
  176. package/dist/src/integrations/github/infrastructure/pr-source.js +186 -0
  177. package/dist/src/integrations/github/infrastructure/review-source.js +70 -0
  178. package/dist/src/integrations/github/infrastructure/source.js +108 -0
  179. package/dist/src/integrations/github/provider.js +96 -0
  180. package/dist/src/integrations/index.js +30 -0
  181. package/dist/src/kernel/contracts/checkpoint-store.js +1 -0
  182. package/dist/src/kernel/contracts/clock.js +1 -0
  183. package/dist/src/kernel/contracts/commands.js +1 -0
  184. package/dist/src/kernel/contracts/event-journal.js +2 -0
  185. package/dist/src/kernel/contracts/event-schema.js +54 -0
  186. package/dist/src/kernel/contracts/events.js +11 -0
  187. package/dist/src/kernel/contracts/id-generator.js +1 -0
  188. package/dist/src/kernel/contracts/identifiers.js +8 -0
  189. package/dist/src/kernel/contracts/projection-store.js +1 -0
  190. package/dist/src/kernel/contracts/relations.js +1 -0
  191. package/dist/src/kernel/contracts/schema.js +17 -0
  192. package/dist/src/kernel/contracts/vocabulary.js +6 -0
  193. package/dist/src/kernel/domain/event-envelope.js +29 -0
  194. package/dist/src/kernel/domain/match-mode.js +11 -0
  195. package/dist/src/kernel/domain/relation.js +10 -0
  196. package/dist/src/kernel/index.js +17 -0
  197. package/dist/src/{lib/clock.js → kernel/infrastructure/system-clock.js} +3 -3
  198. package/dist/src/kernel/infrastructure/ulid-id-generator.js +9 -0
  199. package/dist/src/main.js +137 -1030
  200. package/dist/src/orchestration/application/accept-activity-outcome.js +25 -0
  201. package/dist/src/orchestration/application/accept-signal.js +35 -0
  202. package/dist/src/orchestration/application/advance-workflow.js +160 -0
  203. package/dist/src/orchestration/application/coordination-claims.js +107 -0
  204. package/dist/src/orchestration/application/group-budget-recorder.js +43 -0
  205. package/dist/src/orchestration/application/orchestration-projection.js +20 -0
  206. package/dist/src/orchestration/application/orchestration-repository.js +36 -0
  207. package/dist/src/orchestration/application/orchestration-service.js +82 -0
  208. package/dist/src/orchestration/application/request-child.js +118 -0
  209. package/dist/src/orchestration/application/signal-reactor.js +17 -0
  210. package/dist/src/orchestration/application/start-workflow.js +51 -0
  211. package/dist/src/orchestration/application/watch-reactor.js +82 -0
  212. package/dist/src/orchestration/contracts/activity-outcome.js +18 -0
  213. package/dist/src/orchestration/contracts/commands.js +1 -0
  214. package/dist/src/orchestration/contracts/config.js +128 -0
  215. package/dist/src/orchestration/contracts/event-decoder.js +263 -0
  216. package/dist/src/orchestration/contracts/events.js +41 -0
  217. package/dist/src/orchestration/contracts/identifiers.js +35 -0
  218. package/dist/src/orchestration/contracts/streams.js +38 -0
  219. package/dist/src/orchestration/contracts/views.js +1 -0
  220. package/dist/src/orchestration/contracts/vocabulary.js +30 -0
  221. package/dist/src/orchestration/domain/activation-policy.js +55 -0
  222. package/dist/src/orchestration/domain/approval-defaults.js +17 -0
  223. package/dist/src/orchestration/domain/child-policy.js +63 -0
  224. package/dist/src/orchestration/domain/compiler.js +162 -0
  225. package/dist/src/orchestration/domain/coordination-events.js +25 -0
  226. package/dist/src/orchestration/domain/decision-events.js +47 -0
  227. package/dist/src/orchestration/domain/interpreter.js +49 -0
  228. package/dist/src/orchestration/domain/operator-retry-policy.js +34 -0
  229. package/dist/src/orchestration/domain/retry-policy.js +26 -0
  230. package/dist/src/orchestration/domain/signal-policy.js +120 -0
  231. package/dist/src/orchestration/domain/supplemental-policy.js +61 -0
  232. package/dist/src/orchestration/domain/transition.js +55 -0
  233. package/dist/src/orchestration/domain/workflow-graph.js +41 -0
  234. package/dist/src/orchestration/domain/workflow-instance-events.js +236 -0
  235. package/dist/src/orchestration/domain/workflow-instance.js +41 -0
  236. package/dist/src/orchestration/domain/workflow-selector.js +21 -0
  237. package/dist/src/orchestration/index.js +19 -0
  238. package/dist/src/persistence/application/projection-runner.js +79 -0
  239. package/dist/src/persistence/filesystem/file-checkpoint-store.js +35 -0
  240. package/dist/src/persistence/filesystem/file-event-journal.js +143 -0
  241. package/dist/src/persistence/filesystem/file-lock.js +91 -0
  242. package/dist/src/persistence/filesystem/file-projection-store.js +64 -0
  243. package/dist/src/persistence/index.js +8 -0
  244. package/dist/src/persistence/memory/in-memory-checkpoint-store.js +14 -0
  245. package/dist/src/persistence/memory/in-memory-event-journal.js +88 -0
  246. package/dist/src/persistence/memory/in-memory-projection-store.js +17 -0
  247. package/dist/src/resources/application/lookup-projections.js +48 -0
  248. package/dist/src/resources/application/resource-lookup.js +16 -0
  249. package/dist/src/resources/application/resource-projections.js +81 -0
  250. package/dist/src/resources/application/resource-repository.js +18 -0
  251. package/dist/src/resources/application/resource-service.js +83 -0
  252. package/dist/src/resources/contracts/commands.js +1 -0
  253. package/dist/src/resources/contracts/config.js +2 -0
  254. package/dist/src/resources/contracts/events.js +83 -0
  255. package/dist/src/resources/contracts/identifiers.js +15 -0
  256. package/dist/src/resources/contracts/streams.js +6 -0
  257. package/dist/src/resources/contracts/views.js +1 -0
  258. package/dist/src/resources/contracts/vocabulary.js +67 -0
  259. package/dist/src/resources/domain/correlation.js +8 -0
  260. package/dist/src/resources/domain/resource.js +58 -0
  261. package/dist/src/resources/index.js +14 -0
  262. package/dist/src/surfaces/api/contracts/activities.js +1 -0
  263. package/dist/src/surfaces/api/contracts/board.js +2 -0
  264. package/dist/src/surfaces/api/contracts/common.js +46 -0
  265. package/dist/src/surfaces/api/contracts/control-plane.js +5 -0
  266. package/dist/src/surfaces/api/contracts/events.js +1 -0
  267. package/dist/src/surfaces/api/contracts/execution.js +1 -0
  268. package/dist/src/surfaces/api/contracts/index.js +13 -0
  269. package/dist/src/surfaces/api/contracts/observability.js +1 -0
  270. package/dist/src/surfaces/api/contracts/orchestration.js +1 -0
  271. package/dist/src/surfaces/api/contracts/resources.js +1 -0
  272. package/dist/src/surfaces/api/contracts/status.js +1 -0
  273. package/dist/src/surfaces/api/contracts/system.js +1 -0
  274. package/dist/src/surfaces/api/contracts/transport-values.js +39 -0
  275. package/dist/src/surfaces/api/contracts/work.js +17 -0
  276. package/dist/src/surfaces/api/http-server.js +121 -0
  277. package/dist/src/surfaces/api/presenters/activities.js +1 -0
  278. package/dist/src/surfaces/api/presenters/board.js +3 -0
  279. package/dist/src/surfaces/api/presenters/control-plane.js +1 -0
  280. package/dist/src/surfaces/api/presenters/events.js +1 -0
  281. package/dist/src/surfaces/api/presenters/execution.js +59 -0
  282. package/dist/src/surfaces/api/presenters/observability.js +1 -0
  283. package/dist/src/surfaces/api/presenters/orchestration.js +19 -0
  284. package/dist/src/surfaces/api/presenters/resources.js +15 -0
  285. package/dist/src/surfaces/api/presenters/status.js +3 -0
  286. package/dist/src/surfaces/api/presenters/system.js +14 -0
  287. package/dist/src/surfaces/api/presenters/work.js +16 -0
  288. package/dist/src/surfaces/api/problem-details.js +9 -0
  289. package/dist/src/surfaces/api/router.js +13 -0
  290. package/dist/src/surfaces/api/routes/activities.js +1 -0
  291. package/dist/src/surfaces/api/routes/applications.js +1 -0
  292. package/dist/src/surfaces/api/routes/commands.js +82 -0
  293. package/dist/src/surfaces/api/routes/control-plane.js +6 -0
  294. package/dist/src/surfaces/api/routes/events.js +1 -0
  295. package/dist/src/surfaces/api/routes/execution.js +8 -0
  296. package/dist/src/surfaces/api/routes/index.js +18 -0
  297. package/dist/src/surfaces/api/routes/observability.js +1 -0
  298. package/dist/src/surfaces/api/routes/orchestration.js +1 -0
  299. package/dist/src/surfaces/api/routes/pagination.js +78 -0
  300. package/dist/src/surfaces/api/routes/read.js +135 -0
  301. package/dist/src/surfaces/api/routes/resources.js +1 -0
  302. package/dist/src/surfaces/api/routes/responses.js +67 -0
  303. package/dist/src/surfaces/api/routes/system.js +1 -0
  304. package/dist/src/surfaces/api/routes/work.js +9 -0
  305. package/dist/src/surfaces/cli/commands/api.js +1 -0
  306. package/dist/src/surfaces/cli/commands/audit.js +10 -0
  307. package/dist/src/surfaces/cli/commands/correlate.js +2 -0
  308. package/dist/src/surfaces/cli/commands/doctor.js +6 -0
  309. package/dist/src/surfaces/cli/commands/init.js +39 -0
  310. package/dist/src/surfaces/cli/commands/sandbox-entrypoint.js +33 -0
  311. package/dist/src/surfaces/cli/commands/sandbox-setup.js +29 -0
  312. package/dist/src/surfaces/cli/commands/sandbox.js +105 -0
  313. package/dist/src/surfaces/cli/commands/self-update.js +38 -0
  314. package/dist/src/surfaces/cli/commands/smoke.js +16 -0
  315. package/dist/src/surfaces/cli/commands/start.js +1 -0
  316. package/dist/src/surfaces/cli/commands/stop.js +13 -0
  317. package/dist/src/surfaces/cli/commands/tick.js +1 -0
  318. package/dist/src/surfaces/cli/commands/ui.js +2 -0
  319. package/dist/src/surfaces/cli/commands/validate-state.js +5 -0
  320. package/dist/src/surfaces/cli/infrastructure/docker-cli.js +221 -0
  321. package/dist/src/surfaces/cli/infrastructure/process-log.js +86 -0
  322. package/dist/src/surfaces/cli/main.js +140 -0
  323. package/dist/src/surfaces/cli/usage.js +33 -0
  324. package/dist/src/surfaces/contracts/config.js +34 -0
  325. package/dist/src/surfaces/index.js +47 -0
  326. package/dist/src/surfaces/web-assets/assets/index-Bfn4FwZG.css +1 -0
  327. package/dist/src/surfaces/web-assets/assets/index-ipB6JPGU.js +1090 -0
  328. package/dist/src/surfaces/web-assets/index.html +13 -0
  329. package/dist/src/surfaces/web-host/asset-source.js +1 -0
  330. package/dist/src/surfaces/web-host/packaged-assets.js +44 -0
  331. package/dist/src/work/application/work-projection.js +59 -0
  332. package/dist/src/work/application/work-repository.js +18 -0
  333. package/dist/src/work/application/work-service.js +117 -0
  334. package/dist/src/work/contracts/commands.js +1 -0
  335. package/dist/src/work/contracts/config.js +2 -0
  336. package/dist/src/work/contracts/events.js +103 -0
  337. package/dist/src/work/contracts/identifiers.js +5 -0
  338. package/dist/src/work/contracts/streams.js +6 -0
  339. package/dist/src/work/contracts/views.js +1 -0
  340. package/dist/src/work/contracts/vocabulary.js +6 -0
  341. package/dist/src/work/domain/work-item.js +89 -0
  342. package/dist/src/work/index.js +11 -0
  343. package/docker/Dockerfile +10 -6
  344. package/docker/Dockerfile.packaged +3 -3
  345. package/package.json +29 -4
  346. package/prompts/implement.md +2 -2
  347. package/templates/SETUP.md +7 -7
  348. package/dist/src/adapters/claude/claude-runner.js +0 -529
  349. package/dist/src/adapters/codex/codex-runner.js +0 -503
  350. package/dist/src/adapters/cursor/cursor-runner.js +0 -418
  351. package/dist/src/adapters/docker/docker-cli.js +0 -150
  352. package/dist/src/adapters/fake/fake-artifact-verifier.js +0 -14
  353. package/dist/src/adapters/fake/fake-github-pull-request-activity-source.js +0 -77
  354. package/dist/src/adapters/fake/fake-resource-index.js +0 -21
  355. package/dist/src/adapters/fake/fake-runner.js +0 -77
  356. package/dist/src/adapters/fake/fake-ticketing-system.js +0 -185
  357. package/dist/src/adapters/fake/fake-workspace-manager.js +0 -81
  358. package/dist/src/adapters/fs/resource-index.js +0 -126
  359. package/dist/src/adapters/fs/self-update-ledger.js +0 -17
  360. package/dist/src/adapters/fs/state-store.js +0 -775
  361. package/dist/src/adapters/git/git-workspace-manager.js +0 -289
  362. package/dist/src/adapters/github/github-artifact-verifier.js +0 -38
  363. package/dist/src/adapters/github/github-auth.js +0 -16
  364. package/dist/src/adapters/github/github-client.js +0 -249
  365. package/dist/src/adapters/github/github-etag-cache.js +0 -57
  366. package/dist/src/adapters/github/github-issues-work-source.js +0 -692
  367. package/dist/src/adapters/github/github-pull-request-activity-source.js +0 -584
  368. package/dist/src/adapters/github/github-pull-request-merge-actor.js +0 -45
  369. package/dist/src/adapters/http/ui-assets.js +0 -1188
  370. package/dist/src/adapters/http/ui-data.js +0 -1107
  371. package/dist/src/adapters/http/ui-server.js +0 -458
  372. package/dist/src/adapters/runner/cli-command.js +0 -73
  373. package/dist/src/adapters/runner/prompt-templates.js +0 -76
  374. package/dist/src/adapters/runner/runner-cli-adapter.js +0 -112
  375. package/dist/src/adapters/runner/runner-registry.js +0 -139
  376. package/dist/src/adapters/runner/runtime-events.js +0 -32
  377. package/dist/src/adapters/runner/stage-prompt.js +0 -268
  378. package/dist/src/adapters/runner/transcripts.js +0 -25
  379. package/dist/src/cli/audit-command.js +0 -36
  380. package/dist/src/cli/correlate-command.js +0 -62
  381. package/dist/src/cli/doctor-command.js +0 -48
  382. package/dist/src/cli/init-command.js +0 -18
  383. package/dist/src/cli/sandbox-command.js +0 -258
  384. package/dist/src/cli/sandbox-entrypoint-command.js +0 -88
  385. package/dist/src/cli/sandbox-exec-logging.js +0 -7
  386. package/dist/src/cli/sandbox-resume.js +0 -79
  387. package/dist/src/cli/sandbox-setup-command.js +0 -31
  388. package/dist/src/cli/scaffold-assets.js +0 -100
  389. package/dist/src/cli/self-update-command.js +0 -198
  390. package/dist/src/cli/startup-preflight.js +0 -134
  391. package/dist/src/cli/stop-command.js +0 -46
  392. package/dist/src/cli/ui-command.js +0 -27
  393. package/dist/src/config/defaults.js +0 -10
  394. package/dist/src/config/discover-config-files.js +0 -11
  395. package/dist/src/config/load-config.js +0 -69
  396. package/dist/src/config/split-config.js +0 -14
  397. package/dist/src/core/active-run-recovery.js +0 -44
  398. package/dist/src/core/approval-intents.js +0 -16
  399. package/dist/src/core/audit-events.js +0 -82
  400. package/dist/src/core/control-plane.js +0 -192
  401. package/dist/src/core/event-builders.js +0 -153
  402. package/dist/src/core/event-resolver.js +0 -249
  403. package/dist/src/core/lifecycle-service.js +0 -8
  404. package/dist/src/core/live-execution.js +0 -81
  405. package/dist/src/core/outbox.js +0 -198
  406. package/dist/src/core/policy-engine.js +0 -389
  407. package/dist/src/core/projection-updater.js +0 -693
  408. package/dist/src/core/quota-backoff.js +0 -69
  409. package/dist/src/core/run-lease.js +0 -38
  410. package/dist/src/core/scheduled-workflow-source.js +0 -199
  411. package/dist/src/core/sink-router.js +0 -107
  412. package/dist/src/core/stale-run-reconciler.js +0 -352
  413. package/dist/src/core/tick-runner.js +0 -2442
  414. package/dist/src/core/workspace-cleanup.js +0 -117
  415. package/dist/src/domain/branch-naming.js +0 -14
  416. package/dist/src/domain/custom-commands.js +0 -58
  417. package/dist/src/domain/event-types.js +0 -158
  418. package/dist/src/domain/manual-labels.js +0 -1
  419. package/dist/src/domain/resource-uri.js +0 -38
  420. package/dist/src/domain/runner-routing.js +0 -127
  421. package/dist/src/domain/runtime-events.js +0 -36
  422. package/dist/src/domain/schema.js +0 -1233
  423. package/dist/src/domain/sources.js +0 -16
  424. package/dist/src/domain/stages.js +0 -36
  425. package/dist/src/domain/work-item-labels.js +0 -48
  426. package/dist/src/domain/work-item-lifecycle.js +0 -10
  427. package/dist/src/domain/work-item-status.js +0 -33
  428. package/dist/src/domain/workflows.js +0 -159
  429. package/dist/src/lib/deep-merge.js +0 -14
  430. package/dist/src/lib/detached-process-logging.js +0 -46
  431. package/dist/src/lib/event-log.js +0 -21
  432. package/dist/src/lib/format.js +0 -41
  433. package/dist/src/lib/json-file.js +0 -23
  434. package/dist/src/lib/lock.js +0 -181
  435. package/dist/src/lib/log-rotation.js +0 -42
  436. package/dist/src/lib/paths.js +0 -52
  437. package/dist/src/lib/process-identity.js +0 -54
  438. package/dist/src/lib/state-health.js +0 -30
  439. package/dist/src/lib/work-id.js +0 -19
  440. package/dist/src/lib/yaml-file.js +0 -20
  441. /package/dist/src/{core → activities/pr}/contracts.js +0 -0
  442. /package/dist/src/{domain/types.js → control-plane/contracts/views.js} +0 -0
@@ -1,775 +0,0 @@
1
- import { setTimeout as delay } from 'node:timers/promises';
2
- import { access, appendFile, mkdir, readFile, readdir, rename } from 'node:fs/promises';
3
- import { dirname, join } from 'node:path';
4
- import { validateResourceIndex } from './resource-index.js';
5
- import { parseEventEnvelope, parseIssueStateRecord, parseLedger, parseRunInputSnapshot, parseRunRecord, parseSourceStateRecord, } from '../../domain/schema.js';
6
- import { isTerminalStage } from '../../domain/stages.js';
7
- import { appendJsonLine, readJsonFile, writeJsonFile } from '../../lib/json-file.js';
8
- import { acquireFileLock } from '../../lib/lock.js';
9
- import { createWakePaths } from '../../lib/paths.js';
10
- import { isMissingPathError, stateHealthIssue, StateHealthError, throwIfUnhealthy, } from '../../lib/state-health.js';
11
- const runSummaryIndexLockTimeoutMs = 5_000;
12
- const runSummaryIndexLockPollMs = 10;
13
- async function readIssueStateFile(file) {
14
- try {
15
- return parseIssueStateRecord(await readJsonFile(file));
16
- }
17
- catch (error) {
18
- if (isMissingPathError(error)) {
19
- return null;
20
- }
21
- throw new StateHealthError([
22
- stateHealthIssue({
23
- surface: 'state',
24
- kind: 'corrupted',
25
- path: file,
26
- message: error instanceof Error ? error.message : String(error),
27
- }),
28
- ]);
29
- }
30
- }
31
- // The board/runs/metrics UI list many run records at once purely for their
32
- // small fields (status, timing, routing) - metadata.stdout/stderr/raw and
33
- // runtimeEvents are captured agent output that can run into single-digit MB
34
- // per run, and holding all of them in memory for a full-history listing is
35
- // what took the UI process OOM. Stripped only for bulk-list reads; single-run
36
- // reads (readRunRecord) keep the full record since reconciliation code
37
- // spreads a record's metadata back into a rewrite (see stale-run-reconciler).
38
- function stripHeavyRunRecordFields(record) {
39
- if (record.metadata === undefined && record.runtimeEvents === undefined) {
40
- return record;
41
- }
42
- const { runtimeEvents: _runtimeEvents, metadata, ...rest } = record;
43
- if (metadata === undefined) {
44
- return rest;
45
- }
46
- const { stdout: _stdout, stderr: _stderr, raw: _raw, ...restMetadata } = metadata;
47
- return { ...rest, metadata: restMetadata };
48
- }
49
- function compareIssueStatesForListing(left, right) {
50
- return left.workItemKey.localeCompare(right.workItemKey);
51
- }
52
- function parseRunRecordSummaryIndex(input, date) {
53
- if (input === null || typeof input !== 'object') {
54
- throw new Error('Run summary index must be an object');
55
- }
56
- const record = input;
57
- if (record.schemaVersion !== 1) {
58
- throw new Error('Run summary index schemaVersion must be 1');
59
- }
60
- if (record.date !== date) {
61
- throw new Error(`Run summary index date must be ${date}`);
62
- }
63
- if (!Array.isArray(record.entries)) {
64
- throw new Error('Run summary index entries must be an array');
65
- }
66
- return {
67
- schemaVersion: 1,
68
- date,
69
- entries: record.entries.map((entry) => parseRunRecord(entry)),
70
- };
71
- }
72
- async function withRunSummaryIndexLock(paths, date, operation) {
73
- const deadline = Date.now() + runSummaryIndexLockTimeoutMs;
74
- while (true) {
75
- const lock = await acquireFileLock(paths.runDateIndexLockFile(date), {
76
- staleAfterMs: runSummaryIndexLockTimeoutMs,
77
- });
78
- if (lock.acquired) {
79
- try {
80
- return await operation();
81
- }
82
- finally {
83
- await lock.release();
84
- }
85
- }
86
- if (Date.now() >= deadline) {
87
- throw new Error(`Timed out acquiring run summary index lock for ${date}`);
88
- }
89
- await delay(runSummaryIndexLockPollMs);
90
- }
91
- }
92
- async function readRunSummaryIndex(paths, date) {
93
- return parseRunRecordSummaryIndex(await readJsonFile(paths.runDateIndexFile(date)), date);
94
- }
95
- async function writeRunSummaryIndex(paths, date, entries) {
96
- await writeJsonFile(paths.runDateIndexFile(date), {
97
- schemaVersion: 1,
98
- date,
99
- entries: entries.sort((left, right) => left.startedAt.localeCompare(right.startedAt)),
100
- });
101
- }
102
- async function countRunDateBucketFiles(paths, date) {
103
- return (await readdir(join(paths.dataRoot, 'runs', 'by-date', date), { withFileTypes: true }).catch((error) => {
104
- if (isMissingPathError(error)) {
105
- return [];
106
- }
107
- throw error;
108
- })).filter((file) => file.isFile() && file.name.endsWith('.json') && file.name !== 'index.json')
109
- .length;
110
- }
111
- async function rebuildRunSummaryIndexForDate(paths, date) {
112
- const recordsById = new Map();
113
- const bucketFiles = (await readdir(join(paths.dataRoot, 'runs', 'by-date', date)).catch(() => []))
114
- .filter((file) => file.endsWith('.json') && file !== 'index.json')
115
- .sort();
116
- for (const file of bucketFiles) {
117
- const record = await readRunRecordFile(join(paths.dataRoot, 'runs', 'by-date', date, file), {
118
- summarize: true,
119
- });
120
- if (record !== null) {
121
- recordsById.set(record.runId, record);
122
- }
123
- }
124
- const entries = [...recordsById.values()].sort((left, right) => left.startedAt.localeCompare(right.startedAt));
125
- await writeRunSummaryIndex(paths, date, entries);
126
- return entries;
127
- }
128
- async function upsertRunSummaryIndexEntry(paths, record) {
129
- const date = record.startedAt.slice(0, 10);
130
- const summary = stripHeavyRunRecordFields(record);
131
- await withRunSummaryIndexLock(paths, date, async () => {
132
- const entries = await readRunSummaryIndex(paths, date)
133
- .then((index) => index.entries)
134
- .catch(() => []);
135
- const nextById = new Map(entries.map((entry) => [entry.runId, entry]));
136
- nextById.set(summary.runId, summary);
137
- await writeRunSummaryIndex(paths, date, [...nextById.values()]);
138
- });
139
- }
140
- async function readRunRecordFile(file, options) {
141
- try {
142
- const record = parseRunRecord(await readJsonFile(file));
143
- return options?.summarize === true ? stripHeavyRunRecordFields(record) : record;
144
- }
145
- catch {
146
- return null;
147
- }
148
- }
149
- async function readEventFile(file) {
150
- try {
151
- const raw = await readFile(file, 'utf8');
152
- const envelopes = [];
153
- let lineNumber = 0;
154
- for (const line of raw.split('\n')) {
155
- lineNumber += 1;
156
- const trimmed = line.trim();
157
- if (trimmed.length === 0) {
158
- continue;
159
- }
160
- try {
161
- const parsed = JSON.parse(trimmed);
162
- envelopes.push(parseEventEnvelope(parsed));
163
- }
164
- catch (error) {
165
- throw new StateHealthError([
166
- stateHealthIssue({
167
- surface: 'events',
168
- kind: 'corrupted',
169
- path: `${file}:${lineNumber}`,
170
- message: error instanceof Error ? error.message : String(error),
171
- }),
172
- ]);
173
- }
174
- }
175
- return envelopes;
176
- }
177
- catch (error) {
178
- if (isMissingPathError(error)) {
179
- return [];
180
- }
181
- if (error instanceof StateHealthError) {
182
- throw error;
183
- }
184
- throw new StateHealthError([
185
- stateHealthIssue({
186
- surface: 'events',
187
- kind: 'corrupted',
188
- path: file,
189
- message: error instanceof Error ? error.message : String(error),
190
- }),
191
- ]);
192
- }
193
- }
194
- async function collectIssueStateIssues(paths) {
195
- const issues = [];
196
- const visit = async (dir) => {
197
- const entries = await readdir(dir, { withFileTypes: true }).catch((error) => {
198
- if (isMissingPathError(error)) {
199
- return [];
200
- }
201
- throw error;
202
- });
203
- for (const entry of entries) {
204
- if (entry.isDirectory()) {
205
- if (entry.name === 'index') {
206
- continue;
207
- }
208
- await visit(join(dir, entry.name));
209
- continue;
210
- }
211
- if (!entry.isFile() || !entry.name.endsWith('.json')) {
212
- continue;
213
- }
214
- const file = join(dir, entry.name);
215
- try {
216
- parseIssueStateRecord(await readJsonFile(file));
217
- }
218
- catch (error) {
219
- issues.push(stateHealthIssue({
220
- surface: 'state',
221
- kind: 'corrupted',
222
- path: file,
223
- message: error instanceof Error ? error.message : String(error),
224
- }));
225
- }
226
- }
227
- };
228
- await visit(join(paths.dataRoot, 'state'));
229
- return issues;
230
- }
231
- async function collectEventIssues(paths) {
232
- const issues = [];
233
- const eventLogFiles = await readdir(join(paths.dataRoot, 'events'), {
234
- withFileTypes: true,
235
- }).catch((error) => {
236
- if (isMissingPathError(error)) {
237
- return [];
238
- }
239
- throw error;
240
- });
241
- for (const entry of eventLogFiles) {
242
- if (!entry.isFile() || !entry.name.endsWith('.jsonl')) {
243
- continue;
244
- }
245
- try {
246
- await readEventFile(join(paths.dataRoot, 'events', entry.name));
247
- }
248
- catch (error) {
249
- if (error instanceof StateHealthError) {
250
- issues.push(...error.issues);
251
- }
252
- else {
253
- throw error;
254
- }
255
- }
256
- }
257
- const eventEnvelopeFiles = await readdir(join(paths.dataRoot, 'events-by-id'), {
258
- withFileTypes: true,
259
- }).catch((error) => {
260
- if (isMissingPathError(error)) {
261
- return [];
262
- }
263
- throw error;
264
- });
265
- for (const entry of eventEnvelopeFiles) {
266
- if (!entry.isFile() || !entry.name.endsWith('.json')) {
267
- continue;
268
- }
269
- const file = join(paths.dataRoot, 'events-by-id', entry.name);
270
- try {
271
- parseEventEnvelope(await readJsonFile(file));
272
- }
273
- catch (error) {
274
- issues.push(stateHealthIssue({
275
- surface: 'events',
276
- kind: 'corrupted',
277
- path: file,
278
- message: error instanceof Error ? error.message : String(error),
279
- }));
280
- }
281
- }
282
- return issues;
283
- }
284
- async function collectRunSummaryIndexIssues(paths) {
285
- const issues = [];
286
- const byDateRoot = join(paths.dataRoot, 'runs', 'by-date');
287
- const dateDirs = await readdir(byDateRoot, { withFileTypes: true }).catch((error) => {
288
- if (isMissingPathError(error)) {
289
- return [];
290
- }
291
- throw error;
292
- });
293
- for (const entry of dateDirs) {
294
- if (!entry.isDirectory()) {
295
- continue;
296
- }
297
- const date = entry.name;
298
- const runFileCount = await countRunDateBucketFiles(paths, date);
299
- const indexFile = paths.runDateIndexFile(date);
300
- try {
301
- const index = await readRunSummaryIndex(paths, date);
302
- if (index.entries.length !== runFileCount) {
303
- issues.push(stateHealthIssue({
304
- surface: 'runs',
305
- kind: 'incomplete',
306
- path: indexFile,
307
- message: `Run summary index has ${index.entries.length} entries but ${runFileCount} run files exist for ${date}`,
308
- }));
309
- }
310
- }
311
- catch (error) {
312
- issues.push(stateHealthIssue({
313
- surface: 'runs',
314
- kind: isMissingPathError(error) ? 'incomplete' : 'corrupted',
315
- path: indexFile,
316
- message: error instanceof Error ? error.message : String(error),
317
- }));
318
- }
319
- }
320
- return issues;
321
- }
322
- function issueArchiveAgeDate(item) {
323
- const stageChangedAt = item.wake.stageHistory.at(-1)?.changedAt;
324
- return ([stageChangedAt, item.wake.syncedAt, item.issue.updatedAt]
325
- .filter((value) => value !== undefined)
326
- .sort()
327
- .at(-1) ?? item.wake.syncedAt);
328
- }
329
- function shouldArchiveIssueState(item, options) {
330
- if (!isTerminalStage(item.wake.stage) && item.issue.state !== 'closed') {
331
- return false;
332
- }
333
- const ageMs = options.now.getTime() - Date.parse(issueArchiveAgeDate(item));
334
- return Number.isFinite(ageMs) && ageMs > options.archiveFreshnessDays * 24 * 60 * 60 * 1000;
335
- }
336
- async function listRunRecordsImpl(wakeRoot, options) {
337
- const runsRoot = join(createWakePaths(wakeRoot).dataRoot, 'runs');
338
- const recordsById = new Map();
339
- try {
340
- const files = (await readdir(runsRoot)).filter((file) => file.endsWith('.json')).sort();
341
- for (const file of files) {
342
- const record = await readRunRecordFile(join(runsRoot, file), options);
343
- if (record !== null) {
344
- recordsById.set(record.runId, record);
345
- }
346
- }
347
- }
348
- catch {
349
- // The date-bucketed layout below may still exist.
350
- }
351
- try {
352
- const byDateRoot = join(runsRoot, 'by-date');
353
- const dateDirs = (await readdir(byDateRoot)).sort();
354
- for (const dateDir of dateDirs) {
355
- const files = (await readdir(join(byDateRoot, dateDir)).catch(() => []))
356
- .filter((file) => file.endsWith('.json'))
357
- .sort();
358
- for (const file of files) {
359
- const record = await readRunRecordFile(join(byDateRoot, dateDir, file), options);
360
- if (record !== null) {
361
- recordsById.set(record.runId, record);
362
- }
363
- }
364
- }
365
- }
366
- catch {
367
- // Old wake homes only have root-level run files.
368
- }
369
- return [...recordsById.values()].sort((left, right) => left.startedAt.localeCompare(right.startedAt));
370
- }
371
- export async function listRunRecords(wakeRoot) {
372
- return listRunRecordsImpl(wakeRoot);
373
- }
374
- // Same records as listRunRecords, but with metadata.stdout/stderr/raw and
375
- // runtimeEvents stripped per-file as they're read - for callers (board/runs/
376
- // metrics UI) that list every run and only need the small fields. See
377
- // stripHeavyRunRecordFields for why this can't just be a post-hoc .map() over
378
- // listRunRecords: that would still hold every full record in memory at once.
379
- export async function listRunRecordSummaries(wakeRoot) {
380
- const paths = createWakePaths(wakeRoot);
381
- const byDateRoot = join(paths.dataRoot, 'runs', 'by-date');
382
- const dateDirs = (await readdir(byDateRoot).catch(() => [])).sort();
383
- if (dateDirs.length === 0) {
384
- return listRunRecordsImpl(wakeRoot, { summarize: true });
385
- }
386
- const recordsById = new Map();
387
- for (const dateDir of dateDirs) {
388
- const records = await listRunRecordSummariesForDate(wakeRoot, dateDir);
389
- for (const record of records) {
390
- recordsById.set(record.runId, record);
391
- }
392
- }
393
- return [...recordsById.values()].sort((left, right) => left.startedAt.localeCompare(right.startedAt));
394
- }
395
- async function listRunRecordsForDateImpl(wakeRoot, date, options) {
396
- const runsRoot = join(createWakePaths(wakeRoot).dataRoot, 'runs');
397
- const recordsById = new Map();
398
- const bucketFiles = (await readdir(join(runsRoot, 'by-date', date)).catch(() => []))
399
- .filter((file) => file.endsWith('.json'))
400
- .sort();
401
- for (const file of bucketFiles) {
402
- const record = await readRunRecordFile(join(runsRoot, 'by-date', date, file), options);
403
- if (record !== null) {
404
- recordsById.set(record.runId, record);
405
- }
406
- }
407
- if (recordsById.size === 0) {
408
- const legacyFiles = (await readdir(runsRoot).catch(() => []))
409
- .filter((file) => file.endsWith('.json'))
410
- .sort();
411
- for (const file of legacyFiles) {
412
- const record = await readRunRecordFile(join(runsRoot, file), options);
413
- if (record?.startedAt.slice(0, 10) === date) {
414
- recordsById.set(record.runId, record);
415
- }
416
- }
417
- }
418
- return [...recordsById.values()].sort((left, right) => left.startedAt.localeCompare(right.startedAt));
419
- }
420
- async function listRunRecordsForDate(wakeRoot, date) {
421
- return listRunRecordsForDateImpl(wakeRoot, date);
422
- }
423
- async function listRunRecordSummariesForDate(wakeRoot, date) {
424
- const paths = createWakePaths(wakeRoot);
425
- try {
426
- const index = await readRunSummaryIndex(paths, date);
427
- const runFileCount = await countRunDateBucketFiles(paths, date);
428
- if (index.entries.length === runFileCount && (index.entries.length > 0 || runFileCount > 0)) {
429
- return index.entries;
430
- }
431
- }
432
- catch {
433
- // Rebuild below under the per-date lock.
434
- }
435
- const rebuilt = await withRunSummaryIndexLock(paths, date, async () => {
436
- const runFileCount = await countRunDateBucketFiles(paths, date);
437
- if (runFileCount === 0) {
438
- return null;
439
- }
440
- try {
441
- const index = await readRunSummaryIndex(paths, date);
442
- if (index.entries.length === runFileCount) {
443
- return index.entries;
444
- }
445
- }
446
- catch {
447
- // Rebuild below.
448
- }
449
- return rebuildRunSummaryIndexForDate(paths, date);
450
- });
451
- if (rebuilt !== null) {
452
- return rebuilt;
453
- }
454
- return listRunRecordsForDateImpl(wakeRoot, date, { summarize: true });
455
- }
456
- async function listRecentRunRecords(wakeRoot, limit) {
457
- const runsRoot = join(createWakePaths(wakeRoot).dataRoot, 'runs');
458
- const recordsById = new Map();
459
- const dateDirs = (await readdir(join(runsRoot, 'by-date')).catch(() => [])).sort().reverse();
460
- for (const dateDir of dateDirs) {
461
- const records = await listRunRecordsForDate(wakeRoot, dateDir);
462
- for (const record of records.reverse()) {
463
- recordsById.set(record.runId, record);
464
- if (recordsById.size >= limit) {
465
- return [...recordsById.values()].sort((left, right) => right.startedAt.localeCompare(left.startedAt));
466
- }
467
- }
468
- }
469
- if (recordsById.size === 0) {
470
- return (await listRunRecords(wakeRoot))
471
- .sort((left, right) => right.startedAt.localeCompare(left.startedAt))
472
- .slice(0, limit);
473
- }
474
- return [...recordsById.values()].sort((left, right) => right.startedAt.localeCompare(left.startedAt));
475
- }
476
- export function createStateStore({ wakeRoot }) {
477
- const paths = createWakePaths(wakeRoot);
478
- return {
479
- paths,
480
- async ensureWakeRoot() {
481
- await mkdir(wakeRoot, { recursive: true });
482
- },
483
- async writeLedger(record) {
484
- const parsed = parseLedger(record);
485
- await writeJsonFile(paths.ledgerFile, parsed);
486
- return parsed;
487
- },
488
- async readLedger() {
489
- try {
490
- return parseLedger(await readJsonFile(paths.ledgerFile));
491
- }
492
- catch (error) {
493
- if (isMissingPathError(error)) {
494
- return null;
495
- }
496
- throw error;
497
- }
498
- },
499
- async writeIssueState(record) {
500
- const parsed = parseIssueStateRecord(record);
501
- await writeJsonFile(paths.workItemStateFile(parsed.workItemKey), parsed);
502
- return parsed;
503
- },
504
- async readIssueState(workId) {
505
- return ((await readIssueStateFile(paths.workItemStateFile(workId))) ??
506
- (await readIssueStateFile(paths.archivedWorkItemStateFile(workId))));
507
- },
508
- async writeRunRecord(record) {
509
- const parsed = parseRunRecord(record);
510
- await writeJsonFile(paths.runFile(parsed.runId), parsed);
511
- await writeJsonFile(paths.runDateFile(parsed.startedAt.slice(0, 10), parsed.runId), parsed);
512
- await upsertRunSummaryIndexEntry(paths, parsed);
513
- return parsed;
514
- },
515
- async writeRunInputSnapshot(record) {
516
- const parsed = parseRunInputSnapshot(record);
517
- await writeJsonFile(paths.runInputSnapshotFile(parsed.snapshotId), parsed);
518
- return parsed;
519
- },
520
- async readRunInputSnapshot(snapshotId) {
521
- try {
522
- return parseRunInputSnapshot(await readJsonFile(paths.runInputSnapshotFile(snapshotId)));
523
- }
524
- catch (error) {
525
- if (isMissingPathError(error)) {
526
- return null;
527
- }
528
- throw error;
529
- }
530
- },
531
- async updateRunRecordIf(runId, input) {
532
- const current = await this.readRunRecord(runId);
533
- if (current === null || !input.expect(current)) {
534
- return null;
535
- }
536
- return this.writeRunRecord(input.update(current));
537
- },
538
- async writeSourceState(record) {
539
- const parsed = parseSourceStateRecord(record);
540
- await writeJsonFile(paths.sourceStateFile(parsed.source, parsed.key), parsed);
541
- return parsed;
542
- },
543
- async readRunRecord(runId) {
544
- try {
545
- return parseRunRecord(await readJsonFile(paths.runFile(runId)));
546
- }
547
- catch {
548
- // buildBoard calls this once per work item (readRunRecord per
549
- // lastRunId), so a missing flat file used to mean a full,
550
- // unstripped listRecentRunRecords(500) scan - every heavy
551
- // stdout/raw payload in the 500 most recent runs, parsed again for
552
- // every item on the board. Scan summaries to locate the record's
553
- // date bucket instead, then do one targeted full read of just that
554
- // file so the caller still gets full fidelity.
555
- const summaries = await listRunRecordSummaries(wakeRoot);
556
- const match = summaries.find((record) => record.runId === runId);
557
- if (match === undefined) {
558
- return null;
559
- }
560
- try {
561
- return parseRunRecord(await readJsonFile(paths.runDateFile(match.startedAt.slice(0, 10), runId)));
562
- }
563
- catch {
564
- return match;
565
- }
566
- }
567
- },
568
- async listRunRecords() {
569
- return listRunRecords(wakeRoot);
570
- },
571
- async listRunRecordSummaries() {
572
- return listRunRecordSummaries(wakeRoot);
573
- },
574
- async listRunRecordsForDate(date) {
575
- return listRunRecordsForDate(wakeRoot, date);
576
- },
577
- async listRunRecordSummariesForDate(date) {
578
- return listRunRecordSummariesForDate(wakeRoot, date);
579
- },
580
- async listRecentRunRecords(limit = 10) {
581
- return listRecentRunRecords(wakeRoot, limit);
582
- },
583
- async readSourceState(source, key) {
584
- try {
585
- return parseSourceStateRecord(await readJsonFile(paths.sourceStateFile(source, key)));
586
- }
587
- catch (error) {
588
- if (isMissingPathError(error)) {
589
- return null;
590
- }
591
- throw error;
592
- }
593
- },
594
- async appendEventEnvelope(record) {
595
- const parsed = parseEventEnvelope(record);
596
- const existing = await this.readEventEnvelope(parsed.eventId);
597
- if (existing !== null) {
598
- return existing;
599
- }
600
- await appendJsonLine(paths.eventFile(parsed.ingestedAt.slice(0, 10)), parsed);
601
- await writeJsonFile(paths.eventEnvelopeFile(parsed.eventId), parsed);
602
- return parsed;
603
- },
604
- async readEventEnvelope(eventId) {
605
- try {
606
- return parseEventEnvelope(await readJsonFile(paths.eventEnvelopeFile(eventId)));
607
- }
608
- catch (error) {
609
- if (isMissingPathError(error)) {
610
- return null;
611
- }
612
- throw new StateHealthError([
613
- stateHealthIssue({
614
- surface: 'events',
615
- kind: 'corrupted',
616
- path: paths.eventEnvelopeFile(eventId),
617
- message: error instanceof Error ? error.message : String(error),
618
- }),
619
- ]);
620
- }
621
- },
622
- async listIssueStates(options = {}) {
623
- const stateRoot = join(paths.dataRoot, 'state');
624
- const items = [];
625
- const includeArchived = options.includeArchived ?? false;
626
- const archiveOptions = options.archiveFreshnessDays === undefined
627
- ? null
628
- : {
629
- archiveFreshnessDays: options.archiveFreshnessDays,
630
- now: options.now ?? new Date(),
631
- };
632
- // state/ is flat: state/<workId>.json, plus state/archive/ and the
633
- // reverse index's own state/index/ shards. Only those two subdirectories
634
- // exist, and index/ holds `{ resourceUri: workItemKey }` maps that are
635
- // not projections at all — skip it rather than parse-and-discard.
636
- const visit = async (dir, isArchive) => {
637
- const entries = await readdir(dir, { withFileTypes: true }).catch((error) => {
638
- if (isMissingPathError(error)) {
639
- return [];
640
- }
641
- throw error;
642
- });
643
- for (const entry of entries) {
644
- if (entry.isDirectory()) {
645
- if (entry.name === 'index') {
646
- continue;
647
- }
648
- if (entry.name === 'archive' && includeArchived) {
649
- await visit(join(dir, entry.name), true);
650
- }
651
- continue;
652
- }
653
- if (!entry.isFile() || !entry.name.endsWith('.json')) {
654
- continue;
655
- }
656
- const file = join(dir, entry.name);
657
- const record = await readIssueStateFile(file);
658
- if (record === null)
659
- continue;
660
- if (archiveOptions !== null &&
661
- !isArchive &&
662
- shouldArchiveIssueState(record, archiveOptions)) {
663
- const archivePath = paths.archivedWorkItemStateFile(record.workItemKey);
664
- await mkdir(dirname(archivePath), { recursive: true });
665
- await rename(file, archivePath).catch(() => undefined);
666
- continue;
667
- }
668
- items.push(record);
669
- }
670
- };
671
- await visit(stateRoot, false);
672
- const byWorkItemKey = new Map();
673
- for (const item of items) {
674
- byWorkItemKey.set(item.workItemKey, item);
675
- }
676
- return [...byWorkItemKey.values()].sort(compareIssueStatesForListing);
677
- },
678
- async listEventEnvelopes() {
679
- const eventsRoot = join(paths.dataRoot, 'events');
680
- try {
681
- const files = (await readdir(eventsRoot)).sort();
682
- const envelopes = [];
683
- for (const file of files) {
684
- envelopes.push(...(await readEventFile(join(eventsRoot, file))));
685
- }
686
- return envelopes;
687
- }
688
- catch (error) {
689
- if (isMissingPathError(error)) {
690
- return [];
691
- }
692
- throw error;
693
- }
694
- },
695
- async listRecentEventEnvelopes(filter = {}) {
696
- const limit = filter.limit ?? 200;
697
- const eventsRoot = join(paths.dataRoot, 'events');
698
- const files = (await readdir(eventsRoot).catch((error) => {
699
- if (isMissingPathError(error)) {
700
- return [];
701
- }
702
- throw error;
703
- }))
704
- .filter((file) => file.endsWith('.jsonl'))
705
- .sort()
706
- .reverse();
707
- const results = [];
708
- for (const file of files) {
709
- const events = await readEventFile(join(eventsRoot, file));
710
- for (const event of events.reverse()) {
711
- if (filter.workItemKey !== undefined && event.workItemKey !== filter.workItemKey) {
712
- continue;
713
- }
714
- if (filter.direction !== undefined && event.direction !== filter.direction) {
715
- continue;
716
- }
717
- if (filter.type !== undefined && event.sourceEventType !== filter.type) {
718
- continue;
719
- }
720
- results.push(event);
721
- if (results.length >= limit) {
722
- return results;
723
- }
724
- }
725
- }
726
- return results;
727
- },
728
- async listEventEnvelopesForWorkItem(workItemKey, limit = 10) {
729
- const projection = await this.readIssueState(workItemKey);
730
- const recentEventIds = projection?.wake.recentEventIds.slice(-limit) ?? [];
731
- const envelopes = [];
732
- for (const eventId of recentEventIds) {
733
- const envelope = await this.readEventEnvelope(eventId);
734
- if (envelope?.workItemKey === workItemKey) {
735
- envelopes.push(envelope);
736
- }
737
- }
738
- return envelopes;
739
- },
740
- async appendLog(date, line) {
741
- await mkdir(wakeRoot, { recursive: true });
742
- await appendFile(paths.logFile(date), `${line}\n`, 'utf8');
743
- },
744
- // Only the manual pause file is a hard stop on the whole loop. Quota
745
- // pauses are now per-runner (ledger.runners, #67): a paused runner skips
746
- // itself via routing fallback inside a tick, but the tick loop itself must
747
- // keep running so polling, delivery retries, and other tiers still make
748
- // progress while one runner is paused.
749
- async isPaused(_now = new Date()) {
750
- try {
751
- await access(paths.pauseFile);
752
- return true;
753
- }
754
- catch {
755
- return false;
756
- }
757
- },
758
- async readEventLog(date) {
759
- return readFile(paths.eventFile(date), 'utf8');
760
- },
761
- async validateStateHealth() {
762
- const issues = [
763
- ...(await collectEventIssues(paths)),
764
- ...(await collectIssueStateIssues(paths)),
765
- ...(await collectRunSummaryIndexIssues(paths)),
766
- ...(await validateResourceIndex(paths)),
767
- ];
768
- return { healthy: issues.length === 0, issues };
769
- },
770
- async assertStateHealthy() {
771
- const report = await this.validateStateHealth();
772
- throwIfUnhealthy(report.issues);
773
- },
774
- };
775
- }