@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
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Runs the externally-rate-limited half of a Wake tick: poll and translate
3
+ * inbound. Kept separate from RunnerPipeline so its host can back off when
4
+ * idle without slowing down dispatch/delivery, which never touch a
5
+ * rate-limited external API.
6
+ */
7
+ export function createIntakePipeline(stages) {
8
+ const isPaused = async () => (await stages.isPaused?.()) ?? false;
9
+ return {
10
+ async run(signal) {
11
+ if (await isPaused())
12
+ return { processed: false };
13
+ await stages.catchUpProjections();
14
+ try {
15
+ if (await isPaused())
16
+ return { processed: false };
17
+ const polled = await stages.poll(signal);
18
+ if (await isPaused())
19
+ return { processed: false };
20
+ const translated = await stages.translateInbound();
21
+ return { processed: polled > 0 || translated > 0 };
22
+ }
23
+ finally {
24
+ if (!(await isPaused()))
25
+ await stages.catchUpProjections();
26
+ }
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,66 @@
1
+ import { EventActorKind, WrongExpectedSequenceError, correlationId, } from '../../kernel/index.js';
2
+ import { ControlEventType, createControlEventDraft, selectControlEvent, } from '../contracts/events.js';
3
+ import { controlPlaneStream } from '../contracts/streams.js';
4
+ export function createRunnerControlService(input) {
5
+ const commands = new Map();
6
+ const once = (key, operation) => {
7
+ const existing = commands.get(key);
8
+ if (existing !== undefined)
9
+ return existing;
10
+ const pending = operation().finally(() => commands.set(key, pending));
11
+ commands.set(key, pending);
12
+ return pending;
13
+ };
14
+ return {
15
+ pause: (runnerName, idempotencyKey) => once(`pause:${runnerName}:${idempotencyKey}`, () => append(input, runnerName, idempotencyKey, 'pause')),
16
+ unpause: (runnerName, idempotencyKey) => once(`unpause:${runnerName}:${idempotencyKey}`, () => append(input, runnerName, idempotencyKey, 'unpause')),
17
+ };
18
+ }
19
+ async function append(input, runnerName, idempotencyKey, operation) {
20
+ if (!input.runners.has(runnerName))
21
+ throw new Error(`Unknown runner: ${runnerName}`);
22
+ const stream = controlPlaneStream();
23
+ const events = await input.journal.readStream(stream);
24
+ const expectedType = operation === 'pause' ? ControlEventType.RunnerPaused : ControlEventType.RunnerResumed;
25
+ const correlation = correlationId(`runner:${runnerName}:${idempotencyKey}`);
26
+ if (events.some((event) => event.eventType === expectedType && event.correlationId === correlation))
27
+ return;
28
+ if (operation === 'unpause' &&
29
+ !runnerIsPaused(events, runnerName, input.clock.now().toISOString()))
30
+ throw new Error(`Runner ${runnerName} is not paused`);
31
+ const occurredAt = input.clock.now().toISOString();
32
+ const context = {
33
+ commandId: input.ids.next('command'),
34
+ correlationId: correlation,
35
+ occurredAt,
36
+ actor: { kind: EventActorKind.Operator, id: 'web' },
37
+ };
38
+ const event = operation === 'pause'
39
+ ? createControlEventDraft(ControlEventType.RunnerPaused, { runnerName, cause: 'manual', reason: 'paused by operator' }, context)
40
+ : createControlEventDraft(ControlEventType.RunnerResumed, { runnerName, resumedAt: occurredAt }, context);
41
+ try {
42
+ await input.journal.append(stream, events.length, [event]);
43
+ }
44
+ catch (error) {
45
+ if (!(error instanceof WrongExpectedSequenceError))
46
+ throw error;
47
+ const latest = await input.journal.readStream(stream);
48
+ if (latest.some((entry) => entry.eventType === expectedType && entry.correlationId === correlation))
49
+ return;
50
+ throw error;
51
+ }
52
+ }
53
+ function runnerIsPaused(events, runnerName, now) {
54
+ let pause;
55
+ for (const envelope of events) {
56
+ const event = selectControlEvent(envelope);
57
+ if (event?.eventType === ControlEventType.RunnerPaused &&
58
+ event.payload.runnerName === runnerName)
59
+ pause = event.payload.resumeAt === undefined ? {} : { resumeAt: event.payload.resumeAt };
60
+ if (event?.eventType === ControlEventType.RunnerResumed &&
61
+ event.payload.runnerName === runnerName)
62
+ pause = undefined;
63
+ }
64
+ return (pause !== undefined &&
65
+ (pause.resumeAt === undefined || Date.parse(pause.resumeAt) > Date.parse(now)));
66
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Runs the internal half of a Wake tick: schedules, reactors, Advancement,
3
+ * and delivery. None of this touches a rate-limited external poll, so its
4
+ * host runs on a fast, un-backed-off cadence — see IntakePipeline for the
5
+ * half that does need backoff.
6
+ */
7
+ export function createRunnerPipeline(stages) {
8
+ const isPaused = async () => (await stages.isPaused?.()) ?? false;
9
+ const runOnce = async (options, signal) => {
10
+ if (await isPaused())
11
+ return { kind: 'paused' };
12
+ await stages.catchUpProjections();
13
+ try {
14
+ if (await isPaused())
15
+ return { kind: 'paused' };
16
+ await stages.runSchedules();
17
+ if (await isPaused())
18
+ return { kind: 'paused' };
19
+ await stages.react();
20
+ if (await isPaused())
21
+ return { kind: 'paused' };
22
+ const result = await stages.advance(options);
23
+ if (await isPaused())
24
+ return { kind: 'paused' };
25
+ await stages.publishAgentRuns?.();
26
+ if (await isPaused())
27
+ return { kind: 'paused' };
28
+ await stages.catchUpProjections();
29
+ if (await isPaused())
30
+ return { kind: 'paused' };
31
+ await stages.deliver(signal);
32
+ if (await isPaused())
33
+ return { kind: 'paused' };
34
+ await stages.catchUpProjections();
35
+ if (await isPaused())
36
+ return { kind: 'paused' };
37
+ await stages.react();
38
+ return result;
39
+ }
40
+ finally {
41
+ if (!(await isPaused()))
42
+ await stages.catchUpProjections();
43
+ }
44
+ };
45
+ // The API's manual Tick Now endpoint and the resident tick host share this
46
+ // pipeline. Serializing all callers prevents them from racing the same run
47
+ // claim, checkpoint, and workspace lifecycle within one Wake process.
48
+ let queue = Promise.resolve();
49
+ return {
50
+ run(options, signal = new AbortController().signal) {
51
+ const result = queue.then(() => runOnce(options, signal));
52
+ // A rejected tick must not prevent the next requested tick from running.
53
+ queue = result.catch(() => { });
54
+ return result;
55
+ },
56
+ };
57
+ }
@@ -0,0 +1,47 @@
1
+ import { correlationId } from '../../kernel/index.js';
2
+ import { orchestrationGroupId, workflowInstanceId, workflowName, } from '../../orchestration/index.js';
3
+ import { workItemId } from '../../work/index.js';
4
+ import { SchedulePolicy } from '../domain/schedule-policy.js';
5
+ export class ScheduleService {
6
+ dependencies;
7
+ policy = new SchedulePolicy();
8
+ constructor(dependencies) {
9
+ this.dependencies = dependencies;
10
+ }
11
+ async run(config, context) {
12
+ const checkpoint = await this.dependencies.checkpoint.load(config.id);
13
+ const slots = this.policy.elapsedSlots(config, this.dependencies.now(), checkpoint);
14
+ const accepted = [];
15
+ for (const slot of slots) {
16
+ const workflow = workflowInstanceId(`workflow-${safe(slot.at)}`);
17
+ const slotContext = slotCommandContext(context, slot.identity);
18
+ const existing = await this.dependencies.orchestration.get(workflow);
19
+ const item = existing?.workItemId ?? workItemId(this.dependencies.ids.next('work'));
20
+ if (existing === null) {
21
+ const workCommand = { workItemId: item, objective: config.objective };
22
+ await this.dependencies.work.create(workCommand, slotContext);
23
+ }
24
+ const start = {
25
+ workflowInstanceId: workflow,
26
+ workItemId: item,
27
+ workflowName: workflowName(config.workflow),
28
+ orchestrationGroupId: orchestrationGroupId(`primary:${item}`),
29
+ };
30
+ await this.dependencies.orchestration.start(start, slotContext);
31
+ await this.dependencies.checkpoint.save(config.id, slot.at);
32
+ accepted.push(slot.identity);
33
+ }
34
+ return accepted;
35
+ }
36
+ }
37
+ function slotCommandContext(context, identity) {
38
+ const suffix = safe(identity);
39
+ return {
40
+ ...context,
41
+ commandId: `${context.commandId}:${suffix}`,
42
+ correlationId: correlationId(`${context.correlationId}:${suffix}`),
43
+ };
44
+ }
45
+ function safe(value) {
46
+ return value.toLowerCase().replace(/[^a-z0-9-]/g, '-');
47
+ }
@@ -0,0 +1,31 @@
1
+ import { ExecutionCancellationReason } from '../../execution/index.js';
2
+ import { EventActorKind, correlationId, } from '../../kernel/index.js';
3
+ import { ControlStreamKind } from '../contracts/streams.js';
4
+ /** Applies a Work conclusion (close or cancel) consistently to active workflows and their Runs. */
5
+ export function createWorkCancellationPolicy(work, orchestration, execution, clock, ids) {
6
+ async function conclude(workItemId, reason, workAction, executionReason, blockReasonPrefix) {
7
+ const context = commandContext(clock, ids, workItemId);
8
+ const concluded = await workAction(context);
9
+ const workflows = (await orchestration.listAll()).filter((workflow) => workflow.workItemId === workItemId);
10
+ await execution.cancelActive(workflows.map((workflow) => workflow.workflowInstanceId), executionReason);
11
+ for (const workflow of workflows)
12
+ await orchestration.block(workflow.workflowInstanceId, `${blockReasonPrefix}: ${reason}`, context);
13
+ return concluded;
14
+ }
15
+ return {
16
+ cancelWork(workItemId, reason) {
17
+ return conclude(workItemId, reason, (context) => work.cancel(workItemId, reason, context), ExecutionCancellationReason.WorkCancelled, 'work cancelled');
18
+ },
19
+ closeWork(workItemId, reason) {
20
+ return conclude(workItemId, reason, (context) => work.close(workItemId, reason, context), ExecutionCancellationReason.WorkClosed, 'work closed');
21
+ },
22
+ };
23
+ }
24
+ function commandContext(clock, ids, cause) {
25
+ return {
26
+ commandId: ids.next('command'),
27
+ correlationId: correlationId(cause),
28
+ occurredAt: clock.now().toISOString(),
29
+ actor: { kind: EventActorKind.System, id: ControlStreamKind.Global },
30
+ };
31
+ }
@@ -0,0 +1,10 @@
1
+ import { ExecutionCancellationReason } from '../../execution/index.js';
2
+ import { WorkflowStatus } from '../../orchestration/index.js';
3
+ export const HostStopReason = {
4
+ Idle: 'idle',
5
+ Waiting: WorkflowStatus.Waiting,
6
+ Blocked: WorkflowStatus.Blocked,
7
+ Budget: 'budget',
8
+ Paused: 'paused',
9
+ Shutdown: ExecutionCancellationReason.Shutdown,
10
+ };
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ const scheduleSchema = z
3
+ .object({
4
+ id: z.string().trim().min(1),
5
+ workflow: z.string().trim().min(1),
6
+ cron: z.string().trim().min(1),
7
+ objective: z.string().trim().min(1),
8
+ })
9
+ .strict();
10
+ export const controlPlaneConfigSchema = z
11
+ .object({
12
+ maxDispatches: z.number().int().positive().default(1),
13
+ schedules: z.array(scheduleSchema).default([]),
14
+ resident: z
15
+ .object({
16
+ idleBackoffMs: z.number().int().positive().default(1000),
17
+ maxIdleBackoffMs: z.number().int().positive().optional(),
18
+ })
19
+ .strict()
20
+ .default({ idleBackoffMs: 1000 }),
21
+ })
22
+ .strict();
@@ -0,0 +1,81 @@
1
+ import { z } from 'zod';
2
+ import { EventSourceKind, createEventDraft, eventEnvelopeSchema, } from '../../kernel/index.js';
3
+ import { ControlStreamKind, controlPlaneStream } from './streams.js';
4
+ export const ControlEventType = {
5
+ DispatchPaused: 'control-plane.dispatch-paused',
6
+ DispatchResumed: 'control-plane.dispatch-resumed',
7
+ RunnerPaused: 'control-plane.runner-paused',
8
+ RunnerResumed: 'control-plane.runner-resumed',
9
+ };
10
+ export const RunnerPauseCause = { Manual: 'manual', Quota: 'quota' };
11
+ export const ControlEventNamespace = 'control-plane.';
12
+ const streamSchema = z
13
+ .object({ kind: z.literal(ControlStreamKind.Global), id: z.literal('global') })
14
+ .strict();
15
+ const eventSchema = z.discriminatedUnion('eventType', [
16
+ eventEnvelopeSchema.extend({
17
+ eventType: z.literal(ControlEventType.DispatchPaused),
18
+ stream: streamSchema,
19
+ payload: z
20
+ .object({ resumeAt: z.string().datetime({ offset: true }), reason: z.string().min(1) })
21
+ .strict(),
22
+ }),
23
+ eventEnvelopeSchema.extend({
24
+ eventType: z.literal(ControlEventType.DispatchResumed),
25
+ stream: streamSchema,
26
+ payload: z.object({ resumedAt: z.string().datetime({ offset: true }) }).strict(),
27
+ }),
28
+ eventEnvelopeSchema.extend({
29
+ eventType: z.literal(ControlEventType.RunnerPaused),
30
+ stream: streamSchema,
31
+ payload: z
32
+ .object({
33
+ runnerName: z.string().trim().min(1),
34
+ cause: z.enum(RunnerPauseCause),
35
+ reason: z.string().min(1),
36
+ resumeAt: z.string().datetime({ offset: true }).optional(),
37
+ })
38
+ .strict()
39
+ .superRefine((value, context) => {
40
+ if (value.cause === RunnerPauseCause.Quota && value.resumeAt === undefined)
41
+ context.addIssue({
42
+ code: z.ZodIssueCode.custom,
43
+ message: 'Quota runner pauses require resumeAt',
44
+ });
45
+ }),
46
+ }),
47
+ eventEnvelopeSchema.extend({
48
+ eventType: z.literal(ControlEventType.RunnerResumed),
49
+ stream: streamSchema,
50
+ payload: z
51
+ .object({
52
+ runnerName: z.string().trim().min(1),
53
+ resumedAt: z.string().datetime({ offset: true }),
54
+ })
55
+ .strict(),
56
+ }),
57
+ ]);
58
+ export function decodeControlEvent(event) {
59
+ const result = eventSchema.safeParse(event);
60
+ if (!result.success)
61
+ throw new Error(`Invalid Control Plane event ${event.eventId}: ${result.error.message}`, {
62
+ cause: result.error,
63
+ });
64
+ return result.data;
65
+ }
66
+ export function selectControlEvent(event) {
67
+ return event.eventType.startsWith(ControlEventNamespace) ? decodeControlEvent(event) : null;
68
+ }
69
+ export function createControlEventDraft(eventType, payload, context) {
70
+ return createEventDraft({
71
+ eventId: `${context.commandId}:${eventType}`,
72
+ eventType,
73
+ occurredAt: context.occurredAt,
74
+ correlationId: context.correlationId,
75
+ causationId: context.commandId,
76
+ actor: context.actor,
77
+ source: { kind: EventSourceKind.Internal, id: ControlStreamKind.Global },
78
+ stream: controlPlaneStream(),
79
+ payload,
80
+ });
81
+ }
@@ -0,0 +1,5 @@
1
+ export const ControlStreamKind = { Global: 'control-plane' };
2
+ export const controlPlaneStream = () => ({
3
+ kind: ControlStreamKind.Global,
4
+ id: 'global',
5
+ });
@@ -0,0 +1,15 @@
1
+ export class DispatchPolicy {
2
+ options;
3
+ constructor(options) {
4
+ this.options = options;
5
+ }
6
+ select(candidates, state = {}) {
7
+ if (state.blocked === true || this.options.maxDispatches <= 0)
8
+ return [];
9
+ return [...candidates]
10
+ .filter((candidate) => !candidate.cancelled && !candidate.hasActiveRun)
11
+ .sort((left, right) => left.requestedPosition - right.requestedPosition ||
12
+ left.activationId.localeCompare(right.activationId))
13
+ .slice(0, this.options.maxDispatches);
14
+ }
15
+ }
@@ -0,0 +1,26 @@
1
+ export class QuotaPolicy {
2
+ options;
3
+ constructor(options) {
4
+ this.options = options;
5
+ }
6
+ decide(now, dispatches, pausedUntil) {
7
+ const current = parse(now);
8
+ if (pausedUntil !== null) {
9
+ const deadline = parse(pausedUntil);
10
+ return current >= deadline ? { kind: 'resume' } : { kind: 'paused', resumeAt: pausedUntil };
11
+ }
12
+ if (dispatches < this.options.maxDispatches)
13
+ return { kind: 'dispatch' };
14
+ return {
15
+ kind: 'pause',
16
+ resumeAt: new Date(current + this.options.pauseDurationMs).toISOString(),
17
+ reason: 'dispatch quota exhausted',
18
+ };
19
+ }
20
+ }
21
+ function parse(value) {
22
+ const result = Date.parse(value);
23
+ if (Number.isNaN(result))
24
+ throw new Error(`Invalid quota timestamp: ${value}`);
25
+ return result;
26
+ }
@@ -0,0 +1,35 @@
1
+ const reportedUtcReset = /(?:resets?|try again at)\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*(?:\(utc\)|utc)/i;
2
+ const reportedLocalReset = /(?:resets?|try again at)\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)\b/i;
3
+ const fallbackPauseMs = 30 * 60_000;
4
+ /** Produces a durable deadline; an unlabelled provider clock is not trusted as UTC. */
5
+ export function resolveRunnerQuotaResumeAt(message, now) {
6
+ const current = new Date(now);
7
+ const match = reportedUtcReset.exec(message);
8
+ if (match === null)
9
+ return localReset(message, current);
10
+ let hour = Number(match[1]);
11
+ if (hour === 12)
12
+ hour = 0;
13
+ if (match[3]?.toLowerCase() === 'pm')
14
+ hour += 12;
15
+ const reset = new Date(current);
16
+ reset.setUTCHours(hour, Number(match[2] ?? 0), 0, 0);
17
+ if (reset.getTime() <= current.getTime())
18
+ reset.setUTCDate(reset.getUTCDate() + 1);
19
+ return reset.toISOString();
20
+ }
21
+ function localReset(message, current) {
22
+ const match = reportedLocalReset.exec(message);
23
+ if (match === null)
24
+ return new Date(current.getTime() + fallbackPauseMs).toISOString();
25
+ let hour = Number(match[1]);
26
+ if (hour === 12)
27
+ hour = 0;
28
+ if (match[3]?.toLowerCase() === 'pm')
29
+ hour += 12;
30
+ const reset = new Date(current);
31
+ reset.setHours(hour, Number(match[2] ?? 0), 0, 0);
32
+ if (reset.getTime() <= current.getTime())
33
+ reset.setDate(reset.getDate() + 1);
34
+ return reset.toISOString();
35
+ }
@@ -0,0 +1,46 @@
1
+ export class SchedulePolicy {
2
+ elapsedSlots(config, now, checkpoint) {
3
+ const end = minute(new Date(now));
4
+ const start = checkpoint === null ? end : minute(new Date(new Date(checkpoint).getTime() + 60_000));
5
+ if (start > end)
6
+ return [];
7
+ const fields = config.cron.trim().split(/\s+/);
8
+ if (fields.length !== 5)
9
+ throw new Error(`Schedule ${config.id} must use a five-field cron expression`);
10
+ const slots = [];
11
+ for (let cursor = start; cursor <= end; cursor += 60_000) {
12
+ const date = new Date(cursor);
13
+ if (matches(fields, date)) {
14
+ const at = date.toISOString();
15
+ slots.push({ identity: `schedule:${config.id}:${at}`, at });
16
+ }
17
+ }
18
+ return slots;
19
+ }
20
+ }
21
+ function minute(value) {
22
+ if (Number.isNaN(value.getTime()))
23
+ throw new Error('Schedule timestamps must be valid dates');
24
+ return Math.floor(value.getTime() / 60_000) * 60_000;
25
+ }
26
+ function matches(fields, date) {
27
+ return (matchesField(fields[0], date.getUTCMinutes(), 0, 59) &&
28
+ matchesField(fields[1], date.getUTCHours(), 0, 23) &&
29
+ matchesField(fields[2], date.getUTCDate(), 1, 31) &&
30
+ matchesField(fields[3], date.getUTCMonth() + 1, 1, 12) &&
31
+ matchesField(fields[4], date.getUTCDay(), 0, 6));
32
+ }
33
+ function matchesField(expression, value, minimum, maximum) {
34
+ return expression.split(',').some((part) => {
35
+ const [base, stepText] = part.split('/');
36
+ const step = stepText === undefined ? 1 : Number(stepText);
37
+ if (!Number.isInteger(step) || step < 1)
38
+ throw new Error(`Invalid cron step: ${part}`);
39
+ if (base === '*')
40
+ return (value - minimum) % step === 0;
41
+ const number = Number(base);
42
+ if (!Number.isInteger(number) || number < minimum || number > maximum)
43
+ throw new Error(`Invalid cron field: ${part}`);
44
+ return value === number;
45
+ });
46
+ }
@@ -0,0 +1,20 @@
1
+ export * from './application/advance-once.js';
2
+ export * from './application/control-plane-projection.js';
3
+ export * from './application/control-plane-service.js';
4
+ export * from './application/runner-control-service.js';
5
+ export * from './application/schedule-service.js';
6
+ export * from './application/intake-pipeline.js';
7
+ export * from './application/runner-pipeline.js';
8
+ export * from './application/work-cancellation-policy.js';
9
+ export * from './contracts/commands.js';
10
+ export * from './contracts/config.js';
11
+ export * from './contracts/events.js';
12
+ export * from './contracts/streams.js';
13
+ export * from './contracts/views.js';
14
+ export * from './domain/dispatch-policy.js';
15
+ export * from './domain/quota-policy.js';
16
+ export * from './domain/runner-quota.js';
17
+ export * from './domain/schedule-policy.js';
18
+ export * from './infrastructure/intake-host.js';
19
+ export * from './infrastructure/resident-host.js';
20
+ export * from './infrastructure/tick-host.js';
@@ -0,0 +1,24 @@
1
+ import { HostStopReason } from '../contracts/commands.js';
2
+ /**
3
+ * Bounded host for IntakePipeline. Unlike TickHost, one cycle is always
4
+ * exactly one poll-and-translate pass — there's no Advancement to loop
5
+ * within a budget, and AdvanceResult's `progressed` variant requires an
6
+ * activationId/runId that intake has no honest value for. ResidentHost
7
+ * only needs `advances > 0` to decide whether its next sleep resets to the
8
+ * fast end of backoff, which `processed` maps onto directly.
9
+ */
10
+ export class IntakeHost {
11
+ cycle;
12
+ constructor(cycle) {
13
+ this.cycle = cycle;
14
+ }
15
+ async run(_budget) {
16
+ const controller = new AbortController();
17
+ const { processed } = await this.cycle(controller.signal);
18
+ return {
19
+ advances: processed ? 1 : 0,
20
+ runs: 0,
21
+ stoppedBecause: processed ? HostStopReason.Budget : HostStopReason.Idle,
22
+ };
23
+ }
24
+ }
@@ -0,0 +1,45 @@
1
+ import { HostStopReason } from '../contracts/commands.js';
2
+ export class ResidentHost {
3
+ tick;
4
+ sleep;
5
+ reportError;
6
+ constructor(tick, sleep = async (signal) => {
7
+ await new Promise((resolve) => {
8
+ if (signal.aborted)
9
+ return resolve();
10
+ signal.addEventListener('abort', () => resolve(), { once: true });
11
+ });
12
+ }, reportError = async () => { }) {
13
+ this.tick = tick;
14
+ this.sleep = sleep;
15
+ this.reportError = reportError;
16
+ }
17
+ async run(signal, budget) {
18
+ let total = { advances: 0, runs: 0, stoppedBecause: HostStopReason.Shutdown };
19
+ let consecutiveIdleTicks = 0;
20
+ let consecutiveErrorTicks = 0;
21
+ while (!signal.aborted) {
22
+ let madeProgress = false;
23
+ let errored = false;
24
+ try {
25
+ const result = await this.tick.run(budget);
26
+ madeProgress = result.advances > 0;
27
+ total = {
28
+ advances: total.advances + result.advances,
29
+ runs: total.runs + result.runs,
30
+ stoppedBecause: result.stoppedBecause,
31
+ };
32
+ }
33
+ catch (error) {
34
+ errored = true;
35
+ await this.reportError(error);
36
+ }
37
+ consecutiveIdleTicks = madeProgress ? 0 : consecutiveIdleTicks + 1;
38
+ consecutiveErrorTicks = errored ? consecutiveErrorTicks + 1 : 0;
39
+ if (signal.aborted)
40
+ break;
41
+ await this.sleep(signal, { consecutiveIdleTicks, consecutiveErrorTicks });
42
+ }
43
+ return { ...total, stoppedBecause: HostStopReason.Shutdown };
44
+ }
45
+ }
@@ -0,0 +1,35 @@
1
+ import { WorkflowStatus } from '../../orchestration/index.js';
2
+ import { HostStopReason, } from '../contracts/commands.js';
3
+ export class TickHost {
4
+ advance;
5
+ constructor(advance) {
6
+ this.advance = advance;
7
+ }
8
+ async run(budget) {
9
+ const started = Date.now();
10
+ let advances = 0;
11
+ let runs = 0;
12
+ while (advances < budget.maxAdvances && runs < budget.maxRuns) {
13
+ if (Date.now() - started >= budget.maxDurationMs)
14
+ return { advances, runs, stoppedBecause: HostStopReason.Budget };
15
+ const result = await this.advance({ maxProgress: 1 });
16
+ if (result.kind === 'progressed') {
17
+ advances += 1;
18
+ runs += 1;
19
+ continue;
20
+ }
21
+ return {
22
+ advances,
23
+ runs,
24
+ stoppedBecause: result.kind === 'no-work'
25
+ ? HostStopReason.Idle
26
+ : result.kind === WorkflowStatus.Waiting
27
+ ? HostStopReason.Waiting
28
+ : result.kind === WorkflowStatus.Blocked
29
+ ? HostStopReason.Blocked
30
+ : HostStopReason.Budget,
31
+ };
32
+ }
33
+ return { advances, runs, stoppedBecause: HostStopReason.Budget };
34
+ }
35
+ }
@@ -0,0 +1,50 @@
1
+ import { EventActorKind, EventSourceKind, } from '../../kernel/index.js';
2
+ import { createActivationExecutionEventDraft } from '../contracts/event-factory.js';
3
+ import { decodeActivationExecutionEvent, ExecutionEventType, } from '../contracts/events.js';
4
+ import { activationStream } from '../contracts/streams.js';
5
+ export async function claimActivation(input) {
6
+ const { journal, clock, config, activationId, runId, owner, occurredAt } = input;
7
+ const stream = activationStream(activationId);
8
+ const events = (await journal.readStream(stream)).map(decodeActivationExecutionEvent);
9
+ const last = events.at(-1);
10
+ if (last?.eventType === ExecutionEventType.ActivationClaimed && claimIsUnexpired(last, clock))
11
+ throw new Error(`Activation ${activationId} already has an active Run claim`);
12
+ await journal.append(stream, events.length, [
13
+ createActivationExecutionEventDraft({
14
+ eventId: `${activationId}:claim:${runId}`,
15
+ eventType: ExecutionEventType.ActivationClaimed,
16
+ occurredAt,
17
+ correlationId: activationId,
18
+ causationId: runId,
19
+ actor: { kind: EventActorKind.System, id: owner },
20
+ source: { kind: EventSourceKind.Internal, id: 'execution' },
21
+ stream,
22
+ payload: {
23
+ runId,
24
+ owner,
25
+ expiresAt: new Date(clock.now().getTime() + (config.leaseDurationMs ?? 60_000)).toISOString(),
26
+ },
27
+ }),
28
+ ]);
29
+ }
30
+ export async function releaseActivation(input) {
31
+ const { journal, clock, activationId, runId } = input;
32
+ const stream = activationStream(activationId);
33
+ const events = (await journal.readStream(stream)).map(decodeActivationExecutionEvent);
34
+ await journal.append(stream, events.length, [
35
+ createActivationExecutionEventDraft({
36
+ eventId: `${activationId}:released:${runId}`,
37
+ eventType: ExecutionEventType.ActivationReleased,
38
+ occurredAt: clock.now().toISOString(),
39
+ correlationId: activationId,
40
+ causationId: runId,
41
+ actor: { kind: EventActorKind.System, id: 'execution' },
42
+ source: { kind: EventSourceKind.Internal, id: 'execution' },
43
+ stream,
44
+ payload: { runId },
45
+ }),
46
+ ]);
47
+ }
48
+ function claimIsUnexpired(event, clock) {
49
+ return new Date(event.payload.expiresAt) > clock.now();
50
+ }