@atolis-hq/wake 0.2.97 → 0.3.1

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 (443) hide show
  1. package/README.md +5 -5
  2. package/dist/src/activities/agent/agent-activity-definition.js +26 -0
  3. package/dist/src/activities/agent/agent-activity.js +171 -0
  4. package/dist/src/activities/agent/agent-result.js +149 -0
  5. package/dist/src/activities/contracts/activity.js +10 -0
  6. package/dist/src/activities/contracts/config.js +2 -0
  7. package/dist/src/activities/contracts/event-schema.js +302 -0
  8. package/dist/src/activities/contracts/events.js +42 -0
  9. package/dist/src/activities/contracts/identifiers.js +29 -0
  10. package/dist/src/activities/contracts/registry.js +71 -0
  11. package/dist/src/activities/contracts/streams.js +17 -0
  12. package/dist/src/activities/contracts/vocabulary.js +58 -0
  13. package/dist/src/activities/index.js +21 -0
  14. package/dist/src/activities/pr/activity-support.js +111 -0
  15. package/dist/src/activities/pr/application.js +158 -0
  16. package/dist/src/activities/pr/approve.js +85 -0
  17. package/dist/src/activities/pr/capability.js +11 -0
  18. package/dist/src/activities/pr/decision-claim.js +76 -0
  19. package/dist/src/activities/pr/event-drafts.js +66 -0
  20. package/dist/src/activities/pr/intent.js +37 -0
  21. package/dist/src/activities/pr/merge-authority-gate.js +14 -0
  22. package/dist/src/activities/pr/merge.js +110 -0
  23. package/dist/src/activities/pr/policy.js +135 -0
  24. package/dist/src/activities/pr/projection.js +130 -0
  25. package/dist/src/activities/pr/vocabulary.js +30 -0
  26. package/dist/src/activities/review/authorization.js +22 -0
  27. package/dist/src/activities/review/contracts.js +22 -0
  28. package/dist/src/activities/review/signals.js +3 -0
  29. package/dist/src/bootstrap/analytics-projection.js +26 -0
  30. package/dist/src/bootstrap/board-projection.js +337 -0
  31. package/dist/src/bootstrap/composition-root.js +382 -0
  32. package/dist/src/bootstrap/config/load-config.js +51 -0
  33. package/dist/src/bootstrap/config/root-schema.js +134 -0
  34. package/dist/src/bootstrap/external-ref.js +12 -0
  35. package/dist/src/bootstrap/fake-provider-files.js +44 -0
  36. package/dist/src/bootstrap/fake-scenarios.js +22 -0
  37. package/dist/src/bootstrap/index.js +48 -0
  38. package/dist/src/bootstrap/initialise.js +436 -0
  39. package/dist/src/bootstrap/paths.js +15 -0
  40. package/dist/src/bootstrap/projection-runtime.js +27 -0
  41. package/dist/src/bootstrap/runner-quota-reporter.js +21 -0
  42. package/dist/src/bootstrap/runner-registry.js +30 -0
  43. package/dist/src/bootstrap/schedule-checkpoint-store.js +49 -0
  44. package/dist/src/bootstrap/self-update-application.js +195 -0
  45. package/dist/src/bootstrap/self-update-failure-log.js +33 -0
  46. package/dist/src/bootstrap/source-update-port.js +47 -0
  47. package/dist/src/bootstrap/status-publish-activity.js +42 -0
  48. package/dist/src/bootstrap/surface-api-applications.js +325 -0
  49. package/dist/src/bootstrap/surface-api-execution-applications.js +95 -0
  50. package/dist/src/bootstrap/surface-api-metadata.js +12 -0
  51. package/dist/src/bootstrap/surface-api-projection-pages.js +22 -0
  52. package/dist/src/bootstrap/surface-api-run-context.js +5 -0
  53. package/dist/src/bootstrap/surface-api-transcripts.js +57 -0
  54. package/dist/src/bootstrap/surface-api-work-applications.js +199 -0
  55. package/dist/src/bootstrap/surface-applications.js +7 -0
  56. package/dist/src/bootstrap/surface-cli-applications.js +701 -0
  57. package/dist/src/bootstrap/update-ledger.js +61 -0
  58. package/dist/src/bootstrap/update-maintenance-lease.js +176 -0
  59. package/dist/src/{version.js → bootstrap/version.js} +35 -51
  60. package/dist/src/control-plane/application/advance-once.js +184 -0
  61. package/dist/src/control-plane/application/control-plane-projection.js +42 -0
  62. package/dist/src/control-plane/application/control-plane-service.js +42 -0
  63. package/dist/src/control-plane/application/intake-pipeline.js +29 -0
  64. package/dist/src/control-plane/application/runner-control-service.js +66 -0
  65. package/dist/src/control-plane/application/runner-pipeline.js +57 -0
  66. package/dist/src/control-plane/application/schedule-service.js +47 -0
  67. package/dist/src/control-plane/application/work-cancellation-policy.js +31 -0
  68. package/dist/src/control-plane/contracts/commands.js +10 -0
  69. package/dist/src/control-plane/contracts/config.js +22 -0
  70. package/dist/src/control-plane/contracts/events.js +81 -0
  71. package/dist/src/control-plane/contracts/streams.js +5 -0
  72. package/dist/src/control-plane/domain/dispatch-policy.js +15 -0
  73. package/dist/src/control-plane/domain/quota-policy.js +26 -0
  74. package/dist/src/control-plane/domain/runner-quota.js +35 -0
  75. package/dist/src/control-plane/domain/schedule-policy.js +46 -0
  76. package/dist/src/control-plane/index.js +20 -0
  77. package/dist/src/control-plane/infrastructure/intake-host.js +24 -0
  78. package/dist/src/control-plane/infrastructure/resident-host.js +45 -0
  79. package/dist/src/control-plane/infrastructure/tick-host.js +35 -0
  80. package/dist/src/execution/application/activation-claim.js +50 -0
  81. package/dist/src/execution/application/active-run-cancellation.js +14 -0
  82. package/dist/src/execution/application/execution-activity.js +97 -0
  83. package/dist/src/execution/application/execution-projection.js +17 -0
  84. package/dist/src/execution/application/execution-service.js +372 -0
  85. package/dist/src/execution/application/execution-validation.js +26 -0
  86. package/dist/src/execution/application/recovery-service.js +212 -0
  87. package/dist/src/execution/application/run-lifecycle.js +115 -0
  88. package/dist/src/execution/application/run-liveness-service.js +80 -0
  89. package/dist/src/execution/application/run-repository.js +27 -0
  90. package/dist/src/execution/contracts/commands.js +1 -0
  91. package/dist/src/execution/contracts/config.js +35 -0
  92. package/dist/src/execution/contracts/control-plane.js +1 -0
  93. package/dist/src/execution/contracts/event-factory.js +53 -0
  94. package/dist/src/execution/contracts/events.js +274 -0
  95. package/dist/src/execution/contracts/identifiers.js +5 -0
  96. package/dist/src/execution/contracts/liveness.js +1 -0
  97. package/dist/src/execution/contracts/results.js +1 -0
  98. package/dist/src/execution/contracts/runner.js +15 -0
  99. package/dist/src/execution/contracts/streams.js +10 -0
  100. package/dist/src/execution/contracts/views.js +1 -0
  101. package/dist/src/execution/contracts/vocabulary.js +43 -0
  102. package/dist/src/execution/contracts/workspace.js +1 -0
  103. package/dist/src/execution/domain/run-result.js +34 -0
  104. package/dist/src/execution/domain/run.js +142 -0
  105. package/dist/src/execution/index.js +31 -0
  106. package/dist/src/execution/infrastructure/agent-runner-adapter.js +114 -0
  107. package/dist/src/execution/infrastructure/process-execution.js +29 -0
  108. package/dist/src/execution/infrastructure/prompt-templates.js +42 -0
  109. package/dist/src/execution/infrastructure/runners/claude.js +120 -0
  110. package/dist/src/execution/infrastructure/runners/codex.js +143 -0
  111. package/dist/src/execution/infrastructure/runners/command.js +4 -0
  112. package/dist/src/execution/infrastructure/runners/cursor.js +69 -0
  113. package/dist/src/execution/infrastructure/runners/fake-scenarios.js +99 -0
  114. package/dist/src/execution/infrastructure/runners/fake.js +65 -0
  115. package/dist/src/execution/infrastructure/runners/registry.js +26 -0
  116. package/dist/src/execution/infrastructure/transcript-store.js +223 -0
  117. package/dist/src/execution/infrastructure/transcripts.js +11 -0
  118. package/dist/src/execution/infrastructure/workspace/fake-workspace.js +19 -0
  119. package/dist/src/execution/infrastructure/workspace/git-workspace.js +241 -0
  120. package/dist/src/integrations/application/agent-run-publication-reactor.js +111 -0
  121. package/dist/src/integrations/application/artifact-registration-reactor.js +159 -0
  122. package/dist/src/integrations/application/poll-service.js +25 -0
  123. package/dist/src/integrations/application/terminal-agent-run-report.js +40 -0
  124. package/dist/src/integrations/application/work-admission.js +31 -0
  125. package/dist/src/integrations/application/work-conclusion.js +19 -0
  126. package/dist/src/integrations/contracts/artifact-events.js +60 -0
  127. package/dist/src/integrations/contracts/artifact-vocabulary.js +9 -0
  128. package/dist/src/integrations/contracts/config.js +14 -0
  129. package/dist/src/integrations/contracts/identifiers.js +5 -0
  130. package/dist/src/integrations/contracts/intake-rules.js +14 -0
  131. package/dist/src/integrations/contracts/intake.js +1 -0
  132. package/dist/src/integrations/contracts/outcome-vocabulary.js +7 -0
  133. package/dist/src/integrations/contracts/provider.js +37 -0
  134. package/dist/src/integrations/contracts/streams.js +10 -0
  135. package/dist/src/integrations/delivery/application/delivery-outcome-reactor.js +75 -0
  136. package/dist/src/integrations/delivery/application/delivery-projector.js +165 -0
  137. package/dist/src/integrations/delivery/application/delivery-service.js +173 -0
  138. package/dist/src/integrations/delivery/contracts/commands.js +1 -0
  139. package/dist/src/integrations/delivery/contracts/config.js +1 -0
  140. package/dist/src/integrations/delivery/contracts/event-factory.js +18 -0
  141. package/dist/src/integrations/delivery/contracts/events.js +86 -0
  142. package/dist/src/integrations/delivery/contracts/intents.js +89 -0
  143. package/dist/src/integrations/delivery/contracts/views.js +1 -0
  144. package/dist/src/integrations/delivery/contracts/vocabulary.js +22 -0
  145. package/dist/src/integrations/fake/durable-delivery-provider.js +48 -0
  146. package/dist/src/integrations/fake/external-sink.js +9 -0
  147. package/dist/src/integrations/fake/external-source.js +44 -0
  148. package/dist/src/integrations/fake/inbound-translator.js +130 -0
  149. package/dist/src/integrations/fake/provider.js +95 -0
  150. package/dist/src/integrations/github/application/agent-context-reader.js +54 -0
  151. package/dist/src/integrations/github/application/agent-run-comment.js +94 -0
  152. package/dist/src/integrations/github/application/comment-history-reader.js +43 -0
  153. package/dist/src/integrations/github/application/inbound-context.js +10 -0
  154. package/dist/src/integrations/github/application/inbound-review-signals.js +159 -0
  155. package/dist/src/integrations/github/application/inbound-translator.js +231 -0
  156. package/dist/src/integrations/github/application/inbound-watch-gate-signals.js +84 -0
  157. package/dist/src/integrations/github/application/intake-policy.js +23 -0
  158. package/dist/src/integrations/github/application/outbound-translator.js +47 -0
  159. package/dist/src/integrations/github/application/poll-service.js +29 -0
  160. package/dist/src/integrations/github/application/pull-request-translation.js +10 -0
  161. package/dist/src/integrations/github/application/resource-links.js +8 -0
  162. package/dist/src/integrations/github/application/review-command-translator.js +16 -0
  163. package/dist/src/integrations/github/application/wake-labels.js +95 -0
  164. package/dist/src/integrations/github/contracts/config.js +47 -0
  165. package/dist/src/integrations/github/contracts/events.js +127 -0
  166. package/dist/src/integrations/github/contracts/external-key.js +19 -0
  167. package/dist/src/integrations/github/contracts/payloads.js +9 -0
  168. package/dist/src/integrations/github/contracts/vocabulary.js +55 -0
  169. package/dist/src/integrations/github/index.js +31 -0
  170. package/dist/src/integrations/github/infrastructure/client-reads.js +214 -0
  171. package/dist/src/integrations/github/infrastructure/client.js +132 -0
  172. package/dist/src/integrations/github/infrastructure/content-fingerprint.js +10 -0
  173. package/dist/src/integrations/github/infrastructure/delivery.js +31 -0
  174. package/dist/src/integrations/github/infrastructure/etag-cache.js +56 -0
  175. package/dist/src/integrations/github/infrastructure/gh-auth.js +19 -0
  176. package/dist/src/integrations/github/infrastructure/issue-source.js +109 -0
  177. package/dist/src/integrations/github/infrastructure/pr-source.js +186 -0
  178. package/dist/src/integrations/github/infrastructure/review-source.js +70 -0
  179. package/dist/src/integrations/github/infrastructure/source.js +108 -0
  180. package/dist/src/integrations/github/provider.js +96 -0
  181. package/dist/src/integrations/index.js +30 -0
  182. package/dist/src/kernel/contracts/checkpoint-store.js +1 -0
  183. package/dist/src/kernel/contracts/clock.js +1 -0
  184. package/dist/src/kernel/contracts/commands.js +1 -0
  185. package/dist/src/kernel/contracts/event-journal.js +2 -0
  186. package/dist/src/kernel/contracts/event-schema.js +54 -0
  187. package/dist/src/kernel/contracts/events.js +11 -0
  188. package/dist/src/kernel/contracts/id-generator.js +1 -0
  189. package/dist/src/kernel/contracts/identifiers.js +8 -0
  190. package/dist/src/kernel/contracts/projection-store.js +1 -0
  191. package/dist/src/kernel/contracts/relations.js +1 -0
  192. package/dist/src/kernel/contracts/schema.js +17 -0
  193. package/dist/src/kernel/contracts/vocabulary.js +6 -0
  194. package/dist/src/kernel/domain/event-envelope.js +29 -0
  195. package/dist/src/kernel/domain/match-mode.js +11 -0
  196. package/dist/src/kernel/domain/relation.js +10 -0
  197. package/dist/src/kernel/index.js +17 -0
  198. package/dist/src/{lib/clock.js → kernel/infrastructure/system-clock.js} +3 -3
  199. package/dist/src/kernel/infrastructure/ulid-id-generator.js +9 -0
  200. package/dist/src/main.js +137 -1030
  201. package/dist/src/orchestration/application/accept-activity-outcome.js +25 -0
  202. package/dist/src/orchestration/application/accept-signal.js +35 -0
  203. package/dist/src/orchestration/application/advance-workflow.js +160 -0
  204. package/dist/src/orchestration/application/coordination-claims.js +107 -0
  205. package/dist/src/orchestration/application/group-budget-recorder.js +43 -0
  206. package/dist/src/orchestration/application/orchestration-projection.js +20 -0
  207. package/dist/src/orchestration/application/orchestration-repository.js +36 -0
  208. package/dist/src/orchestration/application/orchestration-service.js +82 -0
  209. package/dist/src/orchestration/application/request-child.js +118 -0
  210. package/dist/src/orchestration/application/signal-reactor.js +17 -0
  211. package/dist/src/orchestration/application/start-workflow.js +51 -0
  212. package/dist/src/orchestration/application/watch-reactor.js +82 -0
  213. package/dist/src/orchestration/contracts/activity-outcome.js +18 -0
  214. package/dist/src/orchestration/contracts/commands.js +1 -0
  215. package/dist/src/orchestration/contracts/config.js +128 -0
  216. package/dist/src/orchestration/contracts/event-decoder.js +263 -0
  217. package/dist/src/orchestration/contracts/events.js +41 -0
  218. package/dist/src/orchestration/contracts/identifiers.js +35 -0
  219. package/dist/src/orchestration/contracts/streams.js +38 -0
  220. package/dist/src/orchestration/contracts/views.js +1 -0
  221. package/dist/src/orchestration/contracts/vocabulary.js +30 -0
  222. package/dist/src/orchestration/domain/activation-policy.js +55 -0
  223. package/dist/src/orchestration/domain/approval-defaults.js +17 -0
  224. package/dist/src/orchestration/domain/child-policy.js +63 -0
  225. package/dist/src/orchestration/domain/compiler.js +162 -0
  226. package/dist/src/orchestration/domain/coordination-events.js +25 -0
  227. package/dist/src/orchestration/domain/decision-events.js +47 -0
  228. package/dist/src/orchestration/domain/interpreter.js +49 -0
  229. package/dist/src/orchestration/domain/operator-retry-policy.js +34 -0
  230. package/dist/src/orchestration/domain/retry-policy.js +26 -0
  231. package/dist/src/orchestration/domain/signal-policy.js +120 -0
  232. package/dist/src/orchestration/domain/supplemental-policy.js +61 -0
  233. package/dist/src/orchestration/domain/transition.js +55 -0
  234. package/dist/src/orchestration/domain/workflow-graph.js +41 -0
  235. package/dist/src/orchestration/domain/workflow-instance-events.js +236 -0
  236. package/dist/src/orchestration/domain/workflow-instance.js +41 -0
  237. package/dist/src/orchestration/domain/workflow-selector.js +21 -0
  238. package/dist/src/orchestration/index.js +19 -0
  239. package/dist/src/persistence/application/projection-runner.js +79 -0
  240. package/dist/src/persistence/filesystem/file-checkpoint-store.js +35 -0
  241. package/dist/src/persistence/filesystem/file-event-journal.js +143 -0
  242. package/dist/src/persistence/filesystem/file-lock.js +91 -0
  243. package/dist/src/persistence/filesystem/file-projection-store.js +64 -0
  244. package/dist/src/persistence/index.js +8 -0
  245. package/dist/src/persistence/memory/in-memory-checkpoint-store.js +14 -0
  246. package/dist/src/persistence/memory/in-memory-event-journal.js +88 -0
  247. package/dist/src/persistence/memory/in-memory-projection-store.js +17 -0
  248. package/dist/src/resources/application/lookup-projections.js +48 -0
  249. package/dist/src/resources/application/resource-lookup.js +16 -0
  250. package/dist/src/resources/application/resource-projections.js +81 -0
  251. package/dist/src/resources/application/resource-repository.js +18 -0
  252. package/dist/src/resources/application/resource-service.js +83 -0
  253. package/dist/src/resources/contracts/commands.js +1 -0
  254. package/dist/src/resources/contracts/config.js +2 -0
  255. package/dist/src/resources/contracts/events.js +83 -0
  256. package/dist/src/resources/contracts/identifiers.js +15 -0
  257. package/dist/src/resources/contracts/streams.js +6 -0
  258. package/dist/src/resources/contracts/views.js +1 -0
  259. package/dist/src/resources/contracts/vocabulary.js +67 -0
  260. package/dist/src/resources/domain/correlation.js +8 -0
  261. package/dist/src/resources/domain/resource.js +58 -0
  262. package/dist/src/resources/index.js +14 -0
  263. package/dist/src/surfaces/api/contracts/activities.js +1 -0
  264. package/dist/src/surfaces/api/contracts/board.js +2 -0
  265. package/dist/src/surfaces/api/contracts/common.js +46 -0
  266. package/dist/src/surfaces/api/contracts/control-plane.js +5 -0
  267. package/dist/src/surfaces/api/contracts/events.js +1 -0
  268. package/dist/src/surfaces/api/contracts/execution.js +1 -0
  269. package/dist/src/surfaces/api/contracts/index.js +13 -0
  270. package/dist/src/surfaces/api/contracts/observability.js +1 -0
  271. package/dist/src/surfaces/api/contracts/orchestration.js +1 -0
  272. package/dist/src/surfaces/api/contracts/resources.js +1 -0
  273. package/dist/src/surfaces/api/contracts/status.js +1 -0
  274. package/dist/src/surfaces/api/contracts/system.js +1 -0
  275. package/dist/src/surfaces/api/contracts/transport-values.js +39 -0
  276. package/dist/src/surfaces/api/contracts/work.js +17 -0
  277. package/dist/src/surfaces/api/http-server.js +121 -0
  278. package/dist/src/surfaces/api/presenters/activities.js +1 -0
  279. package/dist/src/surfaces/api/presenters/board.js +3 -0
  280. package/dist/src/surfaces/api/presenters/control-plane.js +1 -0
  281. package/dist/src/surfaces/api/presenters/events.js +1 -0
  282. package/dist/src/surfaces/api/presenters/execution.js +59 -0
  283. package/dist/src/surfaces/api/presenters/observability.js +1 -0
  284. package/dist/src/surfaces/api/presenters/orchestration.js +19 -0
  285. package/dist/src/surfaces/api/presenters/resources.js +15 -0
  286. package/dist/src/surfaces/api/presenters/status.js +3 -0
  287. package/dist/src/surfaces/api/presenters/system.js +14 -0
  288. package/dist/src/surfaces/api/presenters/work.js +16 -0
  289. package/dist/src/surfaces/api/problem-details.js +9 -0
  290. package/dist/src/surfaces/api/router.js +13 -0
  291. package/dist/src/surfaces/api/routes/activities.js +1 -0
  292. package/dist/src/surfaces/api/routes/applications.js +1 -0
  293. package/dist/src/surfaces/api/routes/commands.js +82 -0
  294. package/dist/src/surfaces/api/routes/control-plane.js +6 -0
  295. package/dist/src/surfaces/api/routes/events.js +1 -0
  296. package/dist/src/surfaces/api/routes/execution.js +8 -0
  297. package/dist/src/surfaces/api/routes/index.js +18 -0
  298. package/dist/src/surfaces/api/routes/observability.js +1 -0
  299. package/dist/src/surfaces/api/routes/orchestration.js +1 -0
  300. package/dist/src/surfaces/api/routes/pagination.js +78 -0
  301. package/dist/src/surfaces/api/routes/read.js +135 -0
  302. package/dist/src/surfaces/api/routes/resources.js +1 -0
  303. package/dist/src/surfaces/api/routes/responses.js +67 -0
  304. package/dist/src/surfaces/api/routes/system.js +1 -0
  305. package/dist/src/surfaces/api/routes/work.js +9 -0
  306. package/dist/src/surfaces/cli/commands/api.js +1 -0
  307. package/dist/src/surfaces/cli/commands/audit.js +10 -0
  308. package/dist/src/surfaces/cli/commands/correlate.js +2 -0
  309. package/dist/src/surfaces/cli/commands/doctor.js +6 -0
  310. package/dist/src/surfaces/cli/commands/init.js +39 -0
  311. package/dist/src/surfaces/cli/commands/sandbox-entrypoint.js +33 -0
  312. package/dist/src/surfaces/cli/commands/sandbox-setup.js +29 -0
  313. package/dist/src/surfaces/cli/commands/sandbox.js +105 -0
  314. package/dist/src/surfaces/cli/commands/self-update.js +38 -0
  315. package/dist/src/surfaces/cli/commands/smoke.js +16 -0
  316. package/dist/src/surfaces/cli/commands/start.js +1 -0
  317. package/dist/src/surfaces/cli/commands/stop.js +13 -0
  318. package/dist/src/surfaces/cli/commands/tick.js +1 -0
  319. package/dist/src/surfaces/cli/commands/ui.js +2 -0
  320. package/dist/src/surfaces/cli/commands/validate-state.js +5 -0
  321. package/dist/src/surfaces/cli/infrastructure/docker-cli.js +221 -0
  322. package/dist/src/surfaces/cli/infrastructure/process-log.js +86 -0
  323. package/dist/src/surfaces/cli/main.js +140 -0
  324. package/dist/src/surfaces/cli/usage.js +33 -0
  325. package/dist/src/surfaces/contracts/config.js +34 -0
  326. package/dist/src/surfaces/index.js +47 -0
  327. package/dist/src/surfaces/web-assets/assets/index-Bfn4FwZG.css +1 -0
  328. package/dist/src/surfaces/web-assets/assets/index-ipB6JPGU.js +1090 -0
  329. package/dist/src/surfaces/web-assets/index.html +13 -0
  330. package/dist/src/surfaces/web-host/asset-source.js +1 -0
  331. package/dist/src/surfaces/web-host/packaged-assets.js +44 -0
  332. package/dist/src/work/application/work-projection.js +59 -0
  333. package/dist/src/work/application/work-repository.js +18 -0
  334. package/dist/src/work/application/work-service.js +117 -0
  335. package/dist/src/work/contracts/commands.js +1 -0
  336. package/dist/src/work/contracts/config.js +2 -0
  337. package/dist/src/work/contracts/events.js +103 -0
  338. package/dist/src/work/contracts/identifiers.js +5 -0
  339. package/dist/src/work/contracts/streams.js +6 -0
  340. package/dist/src/work/contracts/views.js +1 -0
  341. package/dist/src/work/contracts/vocabulary.js +6 -0
  342. package/dist/src/work/domain/work-item.js +89 -0
  343. package/dist/src/work/index.js +11 -0
  344. package/docker/Dockerfile +10 -6
  345. package/docker/Dockerfile.packaged +3 -3
  346. package/package.json +29 -4
  347. package/prompts/implement.md +2 -2
  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/templates/SETUP.md +0 -115
  442. /package/dist/src/{core → activities/pr}/contracts.js +0 -0
  443. /package/dist/src/{domain/types.js → control-plane/contracts/views.js} +0 -0
@@ -0,0 +1,42 @@
1
+ import { createActivityEventSchemas } from './event-schema.js';
2
+ export const ActivityEventType = {
3
+ PrDiscovered: 'pr.discovered',
4
+ PrRevisionChanged: 'pr.revision-changed',
5
+ PrStateChanged: 'pr.state-changed',
6
+ PrChecksChanged: 'pr.checks-changed',
7
+ PrReviewAccepted: 'pr.review-accepted',
8
+ ReviewAcceptanceSignalRecorded: 'review.acceptance-signal-recorded',
9
+ PrReviewChangesRequested: 'pr.review-changes-requested',
10
+ PrReviewRejected: 'pr.review-rejected',
11
+ PrMergeDenied: 'pr.merge-denied',
12
+ PrApproveDenied: 'pr.approve-denied',
13
+ PrMergeAuthorized: 'pr.merge-authorized',
14
+ PrApproveRequested: 'pr.approve-requested',
15
+ PrMergeRequested: 'pr.merge-requested',
16
+ PrApproveDecisionClaimed: 'pr.approve-decision-claimed',
17
+ PrMergeDecisionClaimed: 'pr.merge-decision-claimed',
18
+ };
19
+ const { draftSchema, eventSchema } = createActivityEventSchemas(ActivityEventType);
20
+ export function decodeActivityEvent(event) {
21
+ const result = eventSchema.safeParse(event);
22
+ if (!result.success)
23
+ throw invalidActivityEvent(event, result.error);
24
+ return result.data;
25
+ }
26
+ export function selectActivityEvent(event) {
27
+ return ownsActivityEventType(event.eventType) ? decodeActivityEvent(event) : null;
28
+ }
29
+ export function decodeActivityEventDraft(draft) {
30
+ const result = draftSchema.safeParse(draft);
31
+ if (!result.success)
32
+ throw new Error(`Invalid Activity event draft ${draft.eventId} (${draft.eventType}): ${result.error.message}`, { cause: result.error });
33
+ return result.data;
34
+ }
35
+ function ownsActivityEventType(eventType) {
36
+ return (eventType.startsWith('activities.') ||
37
+ eventType.startsWith('pr.') ||
38
+ eventType.startsWith('review.'));
39
+ }
40
+ function invalidActivityEvent(event, cause) {
41
+ return new Error(`Invalid Activity event ${event.eventId} at global position ${event.globalPosition} (${event.eventType}): ${cause.message}`, { cause });
42
+ }
@@ -0,0 +1,29 @@
1
+ export const activityName = (value) => {
2
+ if (!/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/.test(value))
3
+ throw new Error(`Invalid Activity name: ${value}`);
4
+ return value;
5
+ };
6
+ export const activationId = (value) => {
7
+ if (value.trim().length === 0)
8
+ throw new Error('ActivationId must not be empty');
9
+ if (!isWellFormedUnicode(value))
10
+ throw new Error('ActivationId must contain well-formed Unicode');
11
+ return value;
12
+ };
13
+ function isWellFormedUnicode(value) {
14
+ for (let index = 0; index < value.length; index += 1) {
15
+ const code = value.charCodeAt(index);
16
+ if (code >= 0xd800 && code <= 0xdbff) {
17
+ if (index + 1 >= value.length)
18
+ return false;
19
+ const next = value.charCodeAt(index + 1);
20
+ if (next < 0xdc00 || next > 0xdfff)
21
+ return false;
22
+ index += 1;
23
+ }
24
+ else if (code >= 0xdc00 && code <= 0xdfff) {
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ }
@@ -0,0 +1,71 @@
1
+ import { activityName } from './identifiers.js';
2
+ export class ActivityRegistry {
3
+ entries = new Map();
4
+ register(definition) {
5
+ activityName(definition.name);
6
+ if (this.entries.has(definition.name))
7
+ throw new Error(`Activity ${definition.name} is already registered`);
8
+ const uniqueKinds = new Set(definition.outcomeKinds);
9
+ if (uniqueKinds.size !== definition.outcomeKinds.length)
10
+ throw new Error(`Duplicate Activity outcome kind declared by ${definition.name}`);
11
+ const descriptor = Object.freeze({
12
+ name: definition.name,
13
+ outcomeKinds: Object.freeze([...definition.outcomeKinds]),
14
+ resources: Object.freeze([...definition.resources]),
15
+ executionKind: definition.executionKind,
16
+ });
17
+ this.entries.set(definition.name, {
18
+ descriptor,
19
+ validateInput(input) {
20
+ return parse(definition.name, 'input', definition.inputSchema, input);
21
+ },
22
+ validateOutcome(output) {
23
+ assertDeclaredOutcomeKind(descriptor, output);
24
+ return parse(definition.name, 'outcome', definition.outcomeSchema, output);
25
+ },
26
+ async execute(invocation, context) {
27
+ const input = parse(definition.name, 'input', definition.inputSchema, invocation.input);
28
+ const output = await definition.handler.execute({ ...invocation, input }, context);
29
+ assertDeclaredOutcomeKind(descriptor, output);
30
+ return parse(definition.name, 'outcome', definition.outcomeSchema, output);
31
+ },
32
+ });
33
+ }
34
+ describe(name) {
35
+ return this.entry(name).descriptor;
36
+ }
37
+ validateInput(name, input) {
38
+ return this.entry(name).validateInput(input);
39
+ }
40
+ validateOutcome(name, output) {
41
+ return this.entry(name).validateOutcome(output);
42
+ }
43
+ execute(invocation, context) {
44
+ return this.entry(invocation.activity).execute(invocation, context);
45
+ }
46
+ list() {
47
+ return [...this.entries.values()].map((entry) => entry.descriptor);
48
+ }
49
+ entry(name) {
50
+ const parsedName = activityName(name);
51
+ const entry = this.entries.get(parsedName);
52
+ if (entry === undefined)
53
+ throw new Error(`Unknown Activity: ${name}`);
54
+ return entry;
55
+ }
56
+ }
57
+ function assertDeclaredOutcomeKind(definition, value) {
58
+ if (typeof value !== 'object' || value === null || !('kind' in value))
59
+ return;
60
+ const kind = Reflect.get(value, 'kind');
61
+ if (typeof kind === 'string' && !definition.outcomeKinds.includes(kind))
62
+ throw new Error(`Undeclared Activity outcome kind ${kind} returned by ${definition.name}`);
63
+ }
64
+ function parse(name, kind, schema, value) {
65
+ const parsed = schema.safeParse(value);
66
+ if (parsed.success)
67
+ return parsed.data;
68
+ const issues = parsed.error?.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join('; ') ??
69
+ 'invalid value';
70
+ throw new Error(`Activity ${name} ${kind} invalid: ${issues}`);
71
+ }
@@ -0,0 +1,17 @@
1
+ export const ActivityStreamKind = { Decision: 'activity-decision' };
2
+ export const activityDecisionId = (value, action) => {
3
+ if (!value.endsWith(`:pr.${action}`) || value.length === `:pr.${action}`.length) {
4
+ throw new Error(`Invalid ${action} ActivityDecisionId: ${value}`);
5
+ }
6
+ return value;
7
+ };
8
+ export const activityDecisionStream = (activation, action) => ({
9
+ kind: ActivityStreamKind.Decision,
10
+ id: activityDecisionId(`${segment(activation)}:pr.${segment(action)}`, action),
11
+ });
12
+ export const isActivityDecisionStream = (stream) => stream.kind === ActivityStreamKind.Decision;
13
+ function segment(value) {
14
+ if (value.trim().length === 0)
15
+ throw new Error('Activity decision stream segment must not be empty');
16
+ return encodeURIComponent(value);
17
+ }
@@ -0,0 +1,58 @@
1
+ import { defineClosedVocabulary } from '../../kernel/index.js';
2
+ import { activityName } from './identifiers.js';
3
+ export const ActivityExecutionKind = defineClosedVocabulary({
4
+ Agent: 'agent',
5
+ Script: 'script',
6
+ Deterministic: 'deterministic',
7
+ });
8
+ export const ActivityWorkspaceMode = defineClosedVocabulary({
9
+ ReadOnly: 'read-only',
10
+ Branch: 'branch',
11
+ });
12
+ export const ActivityResourceCardinality = defineClosedVocabulary({
13
+ ZeroOrOne: 'zero-or-one',
14
+ ExactlyOne: 'exactly-one',
15
+ OneOrMore: 'one-or-more',
16
+ });
17
+ export const ActivityResourceRole = defineClosedVocabulary({
18
+ Primary: 'primary',
19
+ Secondary: 'secondary',
20
+ });
21
+ export const ExternalExecutionKind = defineClosedVocabulary({
22
+ Process: 'process',
23
+ RemoteSession: 'remote-session',
24
+ });
25
+ export const RetrySafety = defineClosedVocabulary({
26
+ SafeToRetry: 'safe-to-retry',
27
+ RequiresReconciliation: 'requires-reconciliation',
28
+ });
29
+ export const ActivityFailureCode = defineClosedVocabulary({
30
+ IntentWriteFailed: 'intent-write-failed',
31
+ InvalidAgentResult: 'invalid-agent-result',
32
+ AmbiguousRunnerResult: 'ambiguous-runner-result',
33
+ RunnerFailed: 'runner-failed',
34
+ });
35
+ export const ActivityOutcomeKind = defineClosedVocabulary({
36
+ Waiting: 'waiting',
37
+ Done: 'done',
38
+ Rejected: 'rejected',
39
+ Blocked: 'blocked',
40
+ Failed: 'failed',
41
+ });
42
+ export const ActivityRunnerTransportStatus = defineClosedVocabulary({
43
+ Succeeded: 'succeeded',
44
+ Failed: 'failed',
45
+ Cancelled: 'cancelled',
46
+ Ambiguous: 'ambiguous',
47
+ });
48
+ export const IntentAppendStatus = defineClosedVocabulary({
49
+ Appended: 'appended',
50
+ Known: 'known',
51
+ Ambiguous: 'ambiguous',
52
+ Failed: 'failed',
53
+ });
54
+ export const BuiltInActivityName = {
55
+ Agent: activityName(ActivityExecutionKind.Agent),
56
+ PullRequestApprove: activityName('pr.approve'),
57
+ PullRequestMerge: activityName('pr.merge'),
58
+ };
@@ -0,0 +1,21 @@
1
+ export * from './agent/agent-activity-definition.js';
2
+ export * from './agent/agent-activity.js';
3
+ export * from './agent/agent-result.js';
4
+ export * from './contracts/activity.js';
5
+ export * from './contracts/config.js';
6
+ export * from './contracts/events.js';
7
+ export * from './contracts/identifiers.js';
8
+ export * from './contracts/registry.js';
9
+ export * from './contracts/streams.js';
10
+ export * from './contracts/vocabulary.js';
11
+ export * from './pr/application.js';
12
+ export * from './pr/approve.js';
13
+ export * from './pr/contracts.js';
14
+ export * from './pr/merge-authority-gate.js';
15
+ export * from './pr/merge.js';
16
+ export * from './pr/policy.js';
17
+ export * from './pr/projection.js';
18
+ export * from './pr/vocabulary.js';
19
+ export * from './review/authorization.js';
20
+ export * from './review/contracts.js';
21
+ export * from './review/signals.js';
@@ -0,0 +1,111 @@
1
+ import { z } from 'zod';
2
+ import { ActivityFailureCode, ActivityOutcomeKind, ActivityResourceRole, IntentAppendStatus, } from '../contracts/vocabulary.js';
3
+ import { PullRequestDenialCode } from './vocabulary.js';
4
+ import { ResourceCorrelationRole, resourceId, } from '../../resources/index.js';
5
+ import { isPullRequestLikeResource } from './capability.js';
6
+ export const pullRequestTargetSchema = z
7
+ .union([
8
+ z.literal(ActivityResourceRole.Primary),
9
+ z.object({ resourceId: z.string().min(1).transform(resourceId) }).strict(),
10
+ ])
11
+ .default(ActivityResourceRole.Primary);
12
+ export const pullRequestOutcomeSchema = z.union([
13
+ z
14
+ .object({
15
+ kind: z.literal(ActivityOutcomeKind.Waiting),
16
+ data: z
17
+ .object({ intentEventId: z.string(), signalKind: z.literal('delivery-result') })
18
+ .strict(),
19
+ })
20
+ .strict(),
21
+ z
22
+ .object({
23
+ kind: z.literal(ActivityOutcomeKind.Done),
24
+ data: z.object({ deliveryEventId: z.string() }).strict(),
25
+ })
26
+ .strict(),
27
+ z
28
+ .object({
29
+ kind: z.literal(ActivityOutcomeKind.Blocked),
30
+ data: z
31
+ .object({
32
+ reason: z.enum([
33
+ PullRequestDenialCode.MissingResource,
34
+ PullRequestDenialCode.AmbiguousResource,
35
+ PullRequestDenialCode.CorrelationConflict,
36
+ PullRequestDenialCode.Closed,
37
+ PullRequestDenialCode.StaleApproval,
38
+ PullRequestDenialCode.ChecksPending,
39
+ PullRequestDenialCode.ChecksFailing,
40
+ PullRequestDenialCode.UntrustedActor,
41
+ PullRequestDenialCode.TooManyFilesChanged,
42
+ PullRequestDenialCode.BlockedPathChanged,
43
+ PullRequestDenialCode.ChangedFilesUnavailable,
44
+ ]),
45
+ })
46
+ .strict(),
47
+ })
48
+ .strict(),
49
+ z
50
+ .object({
51
+ kind: z.literal(ActivityOutcomeKind.Failed),
52
+ data: z
53
+ .object({
54
+ reason: z.literal(ActivityFailureCode.IntentWriteFailed),
55
+ })
56
+ .strict(),
57
+ })
58
+ .strict(),
59
+ ]);
60
+ export function resolvePrimaryCapability(invocationResources, authority, workItemId, target, capability) {
61
+ const primaryCandidates = authority.resources.filter((entry) => isPullRequestLikeResource(entry.resource.capabilities) &&
62
+ entry.correlations.some((correlation) => correlation.role === ResourceCorrelationRole.Primary &&
63
+ correlation.workItemId === workItemId));
64
+ const targetedCandidates = primaryCandidates.filter((entry) => target === ActivityResourceRole.Primary || entry.resource.resourceId === target.resourceId);
65
+ const capableIds = new Set(invocationResources
66
+ .filter((resource) => resource.capabilities.includes(capability))
67
+ .map((resource) => resource.resourceId));
68
+ const matches = targetedCandidates.filter((entry) => capableIds.has(entry.resource.resourceId));
69
+ if (matches.length === 1)
70
+ return { allowed: true, resourceId: matches[0].resource.resourceId };
71
+ return {
72
+ allowed: false,
73
+ reason: matches.length === 0
74
+ ? PullRequestDenialCode.MissingResource
75
+ : PullRequestDenialCode.AmbiguousResource,
76
+ candidates: candidateAudit(authority, primaryCandidates.map((entry) => entry.resource.resourceId)),
77
+ };
78
+ }
79
+ export function selectionDenialAudit(target, candidates) {
80
+ return {
81
+ target,
82
+ candidates,
83
+ resourceId: null,
84
+ revision: null,
85
+ };
86
+ }
87
+ export function selectedDenialAudit(authority, selected) {
88
+ const view = authority.pullRequests.find((candidate) => candidate.resourceId === selected);
89
+ return {
90
+ resourceId: selected,
91
+ revision: view?.headRevision ?? null,
92
+ };
93
+ }
94
+ export async function appendResolved(journal, appender, stream, event) {
95
+ const result = await appender.append(stream, event);
96
+ if (result !== IntentAppendStatus.Ambiguous)
97
+ return result;
98
+ const events = await journal.readStream(stream);
99
+ return events.some((candidate) => candidate.eventId === event.eventId)
100
+ ? IntentAppendStatus.Known
101
+ : IntentAppendStatus.Failed;
102
+ }
103
+ function candidateAudit(authority, resourceIds) {
104
+ return [...resourceIds]
105
+ .sort((left, right) => left.localeCompare(right))
106
+ .map((id) => ({
107
+ resourceId: id,
108
+ revision: authority.pullRequests.find((candidate) => candidate.resourceId === id)?.headRevision ??
109
+ null,
110
+ }));
111
+ }
@@ -0,0 +1,158 @@
1
+ import { resourceStream, } from '../../resources/index.js';
2
+ import { workItemStream } from '../../work/index.js';
3
+ import { ActivityEventType } from '../contracts/events.js';
4
+ import { ActivityResourceRole } from '../contracts/vocabulary.js';
5
+ import { isReviewAuthorized } from '../review/authorization.js';
6
+ import { isPullRequestLikeResource } from './capability.js';
7
+ import { checksChanged, discovered, mergeAuthorized, mergeDenied, reviewAcceptanceSignalRecorded, reviewAccepted, reviewChangesRequested, reviewRejected, revisionChanged, stateChanged, } from './event-drafts.js';
8
+ import { decidePullRequestAuthority } from './policy.js';
9
+ import { acceptedReviewSignalProjection, pullRequestProjection } from './projection.js';
10
+ import { PullRequestDenialCode } from './vocabulary.js';
11
+ export function createPullRequestService(journal, work, resources) {
12
+ return new JournalPullRequestService(journal, work, resources);
13
+ }
14
+ class JournalPullRequestService {
15
+ journal;
16
+ work;
17
+ resources;
18
+ constructor(journal, work, resources) {
19
+ this.journal = journal;
20
+ this.work = work;
21
+ this.resources = resources;
22
+ }
23
+ async get(resourceId) {
24
+ const events = await this.journal.readStream(resourceStream(resourceId));
25
+ return events.reduce((view, event) => pullRequestProjection.project(view, event), pullRequestProjection.initial(resourceId));
26
+ }
27
+ async observe(command, context) {
28
+ if (!(await this.hasVerifiedPrimaryCorrelation(command)))
29
+ throw new Error('Pull request lacks verified primary correlation');
30
+ if ((await this.work.get(command.workItemId)) === null)
31
+ throw new Error('Pull request WorkItem missing');
32
+ const current = await this.get(command.resourceId);
33
+ if (current === null) {
34
+ await this.append(command.resourceId, discovered(command, context));
35
+ }
36
+ else {
37
+ await this.appendObservationChanges(current, command, context);
38
+ }
39
+ const view = await this.get(command.resourceId);
40
+ if (view === null)
41
+ throw new Error('Pull request observation was not recorded');
42
+ return view;
43
+ }
44
+ async acceptReviewSignal(command, context) {
45
+ const rejection = await this.reviewRejection(command.resourceId, command.revision);
46
+ if (rejection !== null) {
47
+ await this.append(command.resourceId, reviewRejected(command.resourceId, rejection, context));
48
+ return;
49
+ }
50
+ const signal = reviewAcceptanceSignalRecorded(command, context);
51
+ const outcome = isReviewAuthorized(command)
52
+ ? reviewAccepted(command, context)
53
+ : reviewRejected(command.resourceId, PullRequestDenialCode.UntrustedActor, context);
54
+ await this.append(command.resourceId, [signal, outcome]);
55
+ }
56
+ async requestChangesSignal(command, context) {
57
+ const rejection = await this.reviewRejection(command.resourceId, command.revision);
58
+ await this.append(command.resourceId, rejection === null
59
+ ? reviewChangesRequested(command, context)
60
+ : reviewRejected(command.resourceId, rejection, context));
61
+ }
62
+ async authorizeMerge(workItemId, context) {
63
+ const prior = await this.priorMergeDecision(context.commandId);
64
+ if (prior !== null)
65
+ return prior;
66
+ const input = await this.authorityInput(workItemId);
67
+ const decision = decidePullRequestAuthority(input);
68
+ if (decision.allowed) {
69
+ const stream = resourceStream(decision.resourceId);
70
+ await this.appendStream(stream, mergeAuthorized(stream, decision.revision, context));
71
+ return true;
72
+ }
73
+ const stream = denialStream(input, workItemId);
74
+ await this.appendStream(stream, mergeDenied(stream, decision.reason, context));
75
+ return false;
76
+ }
77
+ async decideAuthority(workItemId, options) {
78
+ return decidePullRequestAuthority(await this.authorityInput(workItemId), options);
79
+ }
80
+ async appendObservationChanges(current, command, context) {
81
+ if (current.headRevision !== command.headRevision ||
82
+ current.baseRevision !== command.baseRevision)
83
+ await this.append(command.resourceId, revisionChanged(command, context));
84
+ if (current.state !== command.state)
85
+ await this.append(command.resourceId, stateChanged(command, context));
86
+ if (current.checks !== command.checks)
87
+ await this.append(command.resourceId, checksChanged(command, context));
88
+ }
89
+ async append(resourceId, event) {
90
+ const stream = resourceStream(resourceId);
91
+ await this.appendStream(stream, event);
92
+ }
93
+ async appendStream(stream, event) {
94
+ const events = Array.isArray(event) ? event : [event];
95
+ await this.journal.append(stream, (await this.journal.readStream(stream)).length, events);
96
+ }
97
+ async priorMergeDecision(commandId) {
98
+ const events = await this.journal.readAll(0);
99
+ if (events.some((event) => event.eventId === `${commandId}:${ActivityEventType.PrMergeAuthorized}`))
100
+ return true;
101
+ return events.some((event) => event.eventId === `${commandId}:${ActivityEventType.PrMergeDenied}`)
102
+ ? false
103
+ : null;
104
+ }
105
+ async hasVerifiedPrimaryCorrelation(command) {
106
+ const resource = await this.resources.get(command.resourceId);
107
+ if (resource === null ||
108
+ !isPullRequestLikeResource(resource.capabilities) ||
109
+ resource.primaryCorrelationConflict !== undefined)
110
+ return false;
111
+ const correlations = await this.resources.correlations(command.resourceId);
112
+ const primary = correlations.filter((value) => value.role === ActivityResourceRole.Primary);
113
+ return primary.length === 1 && primary[0]?.workItemId === command.workItemId;
114
+ }
115
+ async reviewRejection(resourceId, revision) {
116
+ const resource = await this.resources.get(resourceId);
117
+ const view = await this.get(resourceId);
118
+ if (resource === null || !isPullRequestLikeResource(resource.capabilities) || view === null)
119
+ return PullRequestDenialCode.MissingResource;
120
+ const correlations = await this.resources.correlations(resourceId);
121
+ if (resource.primaryCorrelationConflict !== undefined ||
122
+ correlations.filter((value) => value.role === ActivityResourceRole.Primary).length !== 1)
123
+ return PullRequestDenialCode.CorrelationConflict;
124
+ return view.headRevision === revision ? null : PullRequestDenialCode.StaleApproval;
125
+ }
126
+ async authorityInput(workItemId) {
127
+ const correlations = await this.resources.correlationsForWork(workItemId);
128
+ const entries = await Promise.all(correlations.map(async ({ resourceId }) => this.resourceEntry(resourceId)));
129
+ const resources = entries.filter(isPresent);
130
+ const pullRequests = (await Promise.all(resources.map(({ resource }) => this.get(resource.resourceId)))).filter(isPresent);
131
+ const acceptedSignals = (await Promise.all(resources.map(({ resource }) => this.acceptedSignals(resource.resourceId)))).flat();
132
+ return {
133
+ work: await this.work.get(workItemId),
134
+ resources,
135
+ pullRequests,
136
+ acceptedSignals,
137
+ };
138
+ }
139
+ async acceptedSignals(resourceId) {
140
+ const events = await this.journal.readStream(resourceStream(resourceId));
141
+ return events.reduce((view, event) => acceptedReviewSignalProjection.project(view, event), acceptedReviewSignalProjection.initial(resourceId));
142
+ }
143
+ async resourceEntry(resourceId) {
144
+ const resource = await this.resources.get(resourceId);
145
+ if (resource === null)
146
+ return null;
147
+ return { resource, correlations: await this.resources.correlations(resourceId) };
148
+ }
149
+ }
150
+ function isPresent(value) {
151
+ return value !== null;
152
+ }
153
+ function denialStream(input, workItemId) {
154
+ const resource = input.resources.find((entry) => isPullRequestLikeResource(entry.resource.capabilities));
155
+ return resource === undefined
156
+ ? workItemStream(workItemId)
157
+ : resourceStream(resource.resource.resourceId);
158
+ }
@@ -0,0 +1,85 @@
1
+ import { z } from 'zod';
2
+ import { ActivityOutcomeKind } from '../contracts/vocabulary.js';
3
+ import { BuiltInResourceCapability, resourceStream } from '../../resources/index.js';
4
+ import { workItemStream } from '../../work/index.js';
5
+ import { ActivityEventType } from '../contracts/events.js';
6
+ import { ActivityExecutionKind, BuiltInActivityName } from '../contracts/vocabulary.js';
7
+ import { pullRequestOutcomeSchema, pullRequestTargetSchema, resolvePrimaryCapability, selectedDenialAudit, selectionDenialAudit, } from './activity-support.js';
8
+ import { claimAndCompleteDecision, completeDecisionClaim, readDecisionClaim, } from './decision-claim.js';
9
+ import { approveDenied, deliveryIntentRequested } from './event-drafts.js';
10
+ import { activityCommandContext, createJournalIntentAppender, } from './intent.js';
11
+ import { decidePullRequestAuthority } from './policy.js';
12
+ const inputSchema = z
13
+ .object({ target: pullRequestTargetSchema, body: z.string().optional() })
14
+ .strict()
15
+ .transform((input) => input.body === undefined
16
+ ? { target: input.target }
17
+ : { target: input.target, body: input.body });
18
+ export function createPullRequestApproveActivity(journal, pullRequests, appender = createJournalIntentAppender(journal)) {
19
+ return {
20
+ name: BuiltInActivityName.PullRequestApprove,
21
+ inputSchema,
22
+ outcomeSchema: pullRequestOutcomeSchema,
23
+ outcomeKinds: [
24
+ ActivityOutcomeKind.Waiting,
25
+ ActivityOutcomeKind.Done,
26
+ ActivityOutcomeKind.Blocked,
27
+ ActivityOutcomeKind.Failed,
28
+ ],
29
+ resources: [],
30
+ executionKind: ActivityExecutionKind.Deterministic,
31
+ handler: {
32
+ execute: (invocation, context) => executeApproval(journal, pullRequests, appender, invocation, context),
33
+ },
34
+ };
35
+ }
36
+ async function executeApproval(journal, pullRequests, appender, invocation, context) {
37
+ const command = activityCommandContext(invocation.activationId, invocation.orchestrationGroupId, context.occurredAt);
38
+ const prior = await readDecisionClaim(journal, invocation.activationId, 'approve');
39
+ if (prior !== null)
40
+ return completeDecisionClaim(journal, appender, prior);
41
+ const authority = await pullRequests.authorityInput(invocation.workItemId);
42
+ const resource = resolvePrimaryCapability(invocation.resources, authority, invocation.workItemId, invocation.input.target, BuiltInResourceCapability.Approvable);
43
+ if (!resource.allowed) {
44
+ const denial = approveDenied(workItemStream(invocation.workItemId), resource.reason, command, {
45
+ ...selectionDenialAudit(invocation.input.target, resource.candidates),
46
+ body: invocation.input.body ?? null,
47
+ });
48
+ return claimAndCompleteDecision(journal, appender, invocation.activationId, 'approve', {
49
+ decisionKind: 'denied',
50
+ outcome: { kind: ActivityOutcomeKind.Blocked, data: { reason: resource.reason } },
51
+ fact: denial,
52
+ });
53
+ }
54
+ const decision = decidePullRequestAuthority(authority, {
55
+ target: { resourceId: resource.resourceId },
56
+ requireAcceptedReview: false,
57
+ requireChecks: false,
58
+ });
59
+ if (!decision.allowed) {
60
+ const denial = approveDenied(resourceStream(resource.resourceId), decision.reason, command, {
61
+ ...selectedDenialAudit(authority, resource.resourceId),
62
+ body: invocation.input.body ?? null,
63
+ });
64
+ return claimAndCompleteDecision(journal, appender, invocation.activationId, 'approve', {
65
+ decisionKind: 'denied',
66
+ outcome: { kind: ActivityOutcomeKind.Blocked, data: { reason: decision.reason } },
67
+ fact: denial,
68
+ });
69
+ }
70
+ const intent = deliveryIntentRequested(decision.resourceId, ActivityEventType.PrApproveRequested, {
71
+ activationId: invocation.activationId,
72
+ workflowInstanceId: invocation.workflowInstanceId,
73
+ resourceId: decision.resourceId,
74
+ revision: decision.revision,
75
+ body: invocation.input.body ?? null,
76
+ }, command);
77
+ return claimAndCompleteDecision(journal, appender, invocation.activationId, 'approve', {
78
+ decisionKind: 'requested',
79
+ outcome: {
80
+ kind: ActivityOutcomeKind.Waiting,
81
+ data: { intentEventId: intent.eventId, signalKind: 'delivery-result' },
82
+ },
83
+ fact: intent,
84
+ });
85
+ }
@@ -0,0 +1,11 @@
1
+ import { BuiltInResourceCapability } from '../../resources/index.js';
2
+ // A resource is PR-shaped by what it can do, never by its registered kind —
3
+ // a provider may model a mergeable resource under a different kind entirely.
4
+ const PULL_REQUEST_CAPABILITIES = [
5
+ BuiltInResourceCapability.Mergeable,
6
+ BuiltInResourceCapability.Reviewable,
7
+ BuiltInResourceCapability.Approvable,
8
+ ];
9
+ export function isPullRequestLikeResource(capabilities) {
10
+ return PULL_REQUEST_CAPABILITIES.some((capability) => capabilities.includes(capability));
11
+ }