@atolis-hq/wake 0.2.96 → 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 -2365
  414. package/dist/src/core/workspace-cleanup.js +0 -117
  415. package/dist/src/domain/branch-naming.js +0 -14
  416. package/dist/src/domain/custom-commands.js +0 -58
  417. package/dist/src/domain/event-types.js +0 -158
  418. package/dist/src/domain/manual-labels.js +0 -1
  419. package/dist/src/domain/resource-uri.js +0 -38
  420. package/dist/src/domain/runner-routing.js +0 -127
  421. package/dist/src/domain/runtime-events.js +0 -36
  422. package/dist/src/domain/schema.js +0 -1233
  423. package/dist/src/domain/sources.js +0 -16
  424. package/dist/src/domain/stages.js +0 -36
  425. package/dist/src/domain/work-item-labels.js +0 -48
  426. package/dist/src/domain/work-item-lifecycle.js +0 -10
  427. package/dist/src/domain/work-item-status.js +0 -33
  428. package/dist/src/domain/workflows.js +0 -159
  429. package/dist/src/lib/deep-merge.js +0 -14
  430. package/dist/src/lib/detached-process-logging.js +0 -46
  431. package/dist/src/lib/event-log.js +0 -21
  432. package/dist/src/lib/format.js +0 -41
  433. package/dist/src/lib/json-file.js +0 -23
  434. package/dist/src/lib/lock.js +0 -181
  435. package/dist/src/lib/log-rotation.js +0 -42
  436. package/dist/src/lib/paths.js +0 -52
  437. package/dist/src/lib/process-identity.js +0 -54
  438. package/dist/src/lib/state-health.js +0 -30
  439. package/dist/src/lib/work-id.js +0 -19
  440. package/dist/src/lib/yaml-file.js +0 -20
  441. /package/dist/src/{core → activities/pr}/contracts.js +0 -0
  442. /package/dist/src/{domain/types.js → control-plane/contracts/views.js} +0 -0
@@ -1,81 +0,0 @@
1
- import { currentProcessIdentity } from '../lib/process-identity.js';
2
- function createEventQueue() {
3
- const queue = [];
4
- const waiters = [];
5
- let closed = false;
6
- function emit(value) {
7
- const waiter = waiters.shift();
8
- if (waiter !== undefined) {
9
- waiter(value);
10
- return;
11
- }
12
- queue.push(value);
13
- }
14
- async function nextQueued() {
15
- const value = queue.shift();
16
- if (value !== undefined)
17
- return value;
18
- if (closed)
19
- return { kind: 'done' };
20
- return new Promise((resolve) => waiters.push(resolve));
21
- }
22
- return {
23
- push(event) {
24
- if (!closed)
25
- emit({ kind: 'event', event });
26
- },
27
- close() {
28
- if (closed)
29
- return;
30
- closed = true;
31
- emit({ kind: 'done' });
32
- },
33
- fail(error) {
34
- if (closed)
35
- return;
36
- closed = true;
37
- emit({ kind: 'error', error });
38
- },
39
- iterable: {
40
- async *[Symbol.asyncIterator]() {
41
- while (true) {
42
- const value = await nextQueued();
43
- if (value.kind === 'done')
44
- return;
45
- if (value.kind === 'error')
46
- throw value.error;
47
- yield value.event;
48
- }
49
- },
50
- },
51
- };
52
- }
53
- export function createAgentExecution(input, execute) {
54
- const controller = new AbortController();
55
- const events = createEventQueue();
56
- const result = Promise.resolve()
57
- .then(() => execute({
58
- ...input,
59
- cancellationSignal: controller.signal,
60
- onRuntimeEvent: async (event) => {
61
- await input.onRuntimeEvent?.(event);
62
- events.push(event);
63
- },
64
- }))
65
- .then((value) => {
66
- events.close();
67
- return value;
68
- }, (error) => {
69
- events.fail(error);
70
- throw error;
71
- });
72
- return {
73
- runId: input.runId,
74
- processIdentity: currentProcessIdentity(),
75
- events: events.iterable,
76
- async cancel(reason) {
77
- controller.abort(reason);
78
- },
79
- result,
80
- };
81
- }
@@ -1,198 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { LABELS_REQUESTED_EVENT, PUBLISH_CONFIRMED_EVENT, PUBLISH_FAILED_EVENT, PUBLISH_INTENT_REQUESTED_EVENT, PUBLISH_SENT_UNCONFIRMED_EVENT, } from '../domain/event-types.js';
3
- import { createEventEnvelope } from '../lib/event-log.js';
4
- const outboxMaxAttempts = 3;
5
- const outboundIntentEventTypes = new Set([PUBLISH_INTENT_REQUESTED_EVENT, LABELS_REQUESTED_EVENT]);
6
- const outboundConfirmationEventTypes = new Set([
7
- 'ticket.reply.published',
8
- 'ticket.labels.updated',
9
- PUBLISH_CONFIRMED_EVENT,
10
- 'pr.comment.reply.published',
11
- 'pr.review-comment.reply.published',
12
- ]);
13
- function intentId(event) {
14
- const intentEventId = event.payload.intentEventId;
15
- return typeof intentEventId === 'string' ? intentEventId : undefined;
16
- }
17
- // The outbox: outbound delivery (comments, labels) attempted independently of
18
- // run-outcome recording, with a durable, bounded retry trace. Extracted from
19
- // tick-runner.ts so it can be exercised in isolation; it has the cleanest
20
- // boundary of the tick's collaborators — no dependency on candidate selection.
21
- export function createOutbox(deps) {
22
- async function recordDeliveryFailure(intentEvent, err) {
23
- const occurredAt = deps.clock.now().toISOString();
24
- const failureEvent = createEventEnvelope({
25
- eventId: `${intentEvent.eventId}-delivery-failed-${randomUUID()}`,
26
- workItemKey: intentEvent.workItemKey,
27
- streamScope: 'work-item',
28
- direction: 'internal',
29
- sourceSystem: 'wake',
30
- sourceEventType: PUBLISH_FAILED_EVENT,
31
- sourceRefs: intentEvent.sourceRefs,
32
- occurredAt,
33
- ingestedAt: occurredAt,
34
- trigger: 'context-only',
35
- payload: {
36
- intentEventId: intentEvent.eventId,
37
- intentEventType: intentEvent.sourceEventType,
38
- idempotencyKey: intentEvent.payload.idempotencyKey,
39
- deliveryState: 'PENDING',
40
- error: err instanceof Error ? err.message : String(err),
41
- },
42
- });
43
- await deps.stateStore.appendEventEnvelope(failureEvent);
44
- await deps.projectionUpdater.rebuildFromEvents([failureEvent]);
45
- }
46
- async function recordSentUnconfirmed(intentEvent) {
47
- const occurredAt = deps.clock.now().toISOString();
48
- const sentEvent = createEventEnvelope({
49
- eventId: `${intentEvent.eventId}-sent-unconfirmed-${randomUUID()}`,
50
- workItemKey: intentEvent.workItemKey,
51
- streamScope: 'work-item',
52
- direction: 'internal',
53
- sourceSystem: 'wake',
54
- sourceEventType: PUBLISH_SENT_UNCONFIRMED_EVENT,
55
- sourceRefs: intentEvent.sourceRefs,
56
- occurredAt,
57
- ingestedAt: occurredAt,
58
- trigger: 'context-only',
59
- payload: {
60
- intentEventId: intentEvent.eventId,
61
- intentEventType: intentEvent.sourceEventType,
62
- idempotencyKey: intentEvent.payload.idempotencyKey,
63
- deliveryState: 'SENT_UNCONFIRMED',
64
- },
65
- });
66
- await deps.stateStore.appendEventEnvelope(sentEvent);
67
- await deps.projectionUpdater.rebuildFromEvents([sentEvent]);
68
- }
69
- async function recordConfirmed(intentEvent, payload = {}) {
70
- const confirmedAt = deps.clock.now().toISOString();
71
- const confirmedEvent = createEventEnvelope({
72
- eventId: `${intentEvent.eventId}-confirmed`,
73
- workItemKey: intentEvent.workItemKey,
74
- streamScope: 'work-item',
75
- direction: 'internal',
76
- sourceSystem: 'wake',
77
- sourceEventType: PUBLISH_CONFIRMED_EVENT,
78
- sourceRefs: intentEvent.sourceRefs,
79
- occurredAt: confirmedAt,
80
- ingestedAt: confirmedAt,
81
- trigger: 'context-only',
82
- payload: {
83
- intentEventId: intentEvent.eventId,
84
- idempotencyKey: intentEvent.payload.idempotencyKey,
85
- deliveryState: 'CONFIRMED',
86
- ...payload,
87
- },
88
- });
89
- const appended = await deps.stateStore.appendEventEnvelope(confirmedEvent);
90
- await deps.projectionUpdater.rebuildFromEvents([appended]);
91
- }
92
- // Outbound delivery (comments, labels) is attempted independently of run-outcome
93
- // recording: a delivery failure must never rewrite an already-recorded run result
94
- // (S1), and must always leave a durable, retryable trace instead of being lost
95
- // (E5). This never throws — failures become a `wake.publish.failed` event.
96
- async function attemptDelivery(event) {
97
- if (deps.outboundSink === undefined) {
98
- return;
99
- }
100
- try {
101
- await recordSentUnconfirmed(event);
102
- const deliveryEvents = await deps.outboundSink.deliverIntent({ event });
103
- for (const deliveryEvent of deliveryEvents) {
104
- await deps.stateStore.appendEventEnvelope(deliveryEvent);
105
- }
106
- await deps.projectionUpdater.rebuildFromEvents(deliveryEvents);
107
- if (deliveryEvents.length === 0) {
108
- // No confirmation event was produced (e.g. a no-op label update) but the
109
- // sink did not throw. Record that delivery was attempted successfully so
110
- // the outbox scan below does not retry it indefinitely.
111
- await recordConfirmed(event);
112
- }
113
- }
114
- catch (err) {
115
- await recordDeliveryFailure(event, err);
116
- }
117
- }
118
- async function deliverOutboundEvent(event) {
119
- await deps.stateStore.appendEventEnvelope(event);
120
- await deps.projectionUpdater.rebuildFromEvents([event]);
121
- await attemptDelivery(event);
122
- }
123
- async function suppressOutboundEvent(event, input) {
124
- const suppressedEvent = await deps.stateStore.appendEventEnvelope({
125
- ...event,
126
- payload: {
127
- ...event.payload,
128
- deliveryState: 'CONFIRMED',
129
- suppressedPublishReason: input.suppressedPublishReason,
130
- },
131
- });
132
- await deps.projectionUpdater.rebuildFromEvents([suppressedEvent]);
133
- await recordConfirmed(event, { suppressedPublishReason: input.suppressedPublishReason });
134
- }
135
- // Adopts the outbox pattern: an intent is only considered delivered once a
136
- // matching confirmation event exists. Anything left unconfirmed by a prior tick
137
- // (e.g. the process crashed mid-delivery) is retried here, bounded so a
138
- // permanently failing sink dead-letters instead of retrying forever.
139
- async function retryUnconfirmedDeliveries() {
140
- if (deps.outboundSink === undefined) {
141
- return;
142
- }
143
- const events = await deps.stateStore.listEventEnvelopes();
144
- const confirmedIntentIds = new Set();
145
- const failureAttempts = new Map();
146
- const uncertainIntentIds = new Set();
147
- for (const event of events) {
148
- const intentEventId = intentId(event);
149
- if (intentEventId === undefined) {
150
- continue;
151
- }
152
- if (outboundConfirmationEventTypes.has(event.sourceEventType)) {
153
- confirmedIntentIds.add(intentEventId);
154
- }
155
- if (event.sourceEventType === PUBLISH_FAILED_EVENT) {
156
- failureAttempts.set(intentEventId, (failureAttempts.get(intentEventId) ?? 0) + 1);
157
- }
158
- if (event.sourceEventType === PUBLISH_SENT_UNCONFIRMED_EVENT) {
159
- uncertainIntentIds.add(intentEventId);
160
- }
161
- }
162
- for (const intent of events) {
163
- if (!outboundIntentEventTypes.has(intent.sourceEventType)) {
164
- continue;
165
- }
166
- if (confirmedIntentIds.has(intent.eventId)) {
167
- continue;
168
- }
169
- if ((failureAttempts.get(intent.eventId) ?? 0) >= outboxMaxAttempts) {
170
- continue;
171
- }
172
- if (uncertainIntentIds.has(intent.eventId) &&
173
- deps.outboundSink.reconcileIntent !== undefined) {
174
- try {
175
- const reconciledEvents = await deps.outboundSink.reconcileIntent({ event: intent });
176
- for (const reconciledEvent of reconciledEvents) {
177
- await deps.stateStore.appendEventEnvelope(reconciledEvent);
178
- }
179
- await deps.projectionUpdater.rebuildFromEvents(reconciledEvents);
180
- if (reconciledEvents.length > 0) {
181
- continue;
182
- }
183
- }
184
- catch (err) {
185
- await recordDeliveryFailure(intent, err);
186
- continue;
187
- }
188
- }
189
- await attemptDelivery(intent);
190
- }
191
- }
192
- return {
193
- attemptDelivery,
194
- deliverOutboundEvent,
195
- retryUnconfirmedDeliveries,
196
- suppressOutboundEvent,
197
- };
198
- }
@@ -1,389 +0,0 @@
1
- import { failedRunnerSentinel } from '../domain/stages.js';
2
- import { resolveCustomCommand } from '../domain/custom-commands.js';
3
- import { builtInDefaultWorkflowDefinition, chooseAction as chooseWorkflowAction, isKnownWorkflowStage, selectWorkflowForEvent, workflowForProjection, } from '../domain/workflows.js';
4
- import { alwaysManualIgnoredLabels } from '../domain/manual-labels.js';
5
- import { autoApprovalLabel } from './approval-intents.js';
6
- function isAwaitingApproval(issue) {
7
- const context = issue.context;
8
- // pendingApprovalAction persists through a changes-requested review round
9
- // within the same gated cycle (that fold path never touches it), so it's
10
- // the faithful "is this item currently gated on human sign-off" signal —
11
- // context.status alone flips between 'awaiting-approval' and
12
- // 'changes-requested' within the same gated cycle and can't be used here.
13
- // The lastRunSentinel fallback tolerates a projection folded before
14
- // pendingApprovalAction was reliably set on every gated DONE.
15
- return (typeof context.pendingApprovalAction === 'string' ||
16
- context.lastRunSentinel === 'AWAITING_APPROVAL');
17
- }
18
- function belowFailureRetryLimit(issue, config) {
19
- if (config === undefined) {
20
- return true;
21
- }
22
- const context = issue.context;
23
- const failureCount = typeof context.failureCount === 'number' && Number.isInteger(context.failureCount)
24
- ? context.failureCount
25
- : 0;
26
- return failureCount < config.retry.maxFailureRetries;
27
- }
28
- // Commands are matched as a token at the start of a (trimmed) line, not as a
29
- // substring anywhere in the body — so "I have *not* /approved this yet" or a
30
- // quoted reply containing /approved does not approve the gate.
31
- const approvedCommandPattern = /^\/approved\b/i;
32
- const changesCommandPattern = /^\/changes\b/i;
33
- const prReviewApprovalMarker = '<!-- wake:pr-review-approved -->';
34
- const prReviewChangesMarker = '<!-- wake:pr-review-changes-requested -->';
35
- // The action Wake runs when a correlated PR gets new reviewer feedback while
36
- // the work item is awaiting approval. Not configurable per workflow: it's a
37
- // lateral response to a PR surface, not a workflow stage.
38
- const reviewFeedbackAction = 'revise';
39
- function matchesCommand(body, pattern) {
40
- return body.split(/\r?\n/).some((line) => pattern.test(line.trim()));
41
- }
42
- function labelsAndAssigneesQualify(input) {
43
- if (input.requiredLabels.length === 0 && input.requiredAssignees.length === 0) {
44
- return false;
45
- }
46
- const labels = new Set(input.labels);
47
- const assignees = new Set(input.assignees);
48
- if (input.requiredLabels.some((label) => !labels.has(label))) {
49
- return false;
50
- }
51
- const ignoredLabels = new Set([...input.ignoredLabels, ...alwaysManualIgnoredLabels]);
52
- if ([...ignoredLabels].some((label) => labels.has(label))) {
53
- return false;
54
- }
55
- if (input.requiredAssignees.length > 0 &&
56
- !input.requiredAssignees.some((login) => assignees.has(login))) {
57
- return false;
58
- }
59
- return true;
60
- }
61
- function latestUnhandledHumanComment(issue) {
62
- const context = issue.context;
63
- const handledCommentId = typeof context.lastHandledCommentId === 'string' ? context.lastHandledCommentId : undefined;
64
- // Only consider human comments that appear after the last bot comment.
65
- // A human /approved posted before Wake's approval-request comment must not
66
- // be re-consumed as approval for a later awaiting-approval cycle.
67
- const lastBotIndex = issue.comments.reduce((acc, c, i) => (c.isBotAuthored ? i : acc), -1);
68
- const humanCommentsAfterBot = issue.comments
69
- .slice(lastBotIndex + 1)
70
- .filter((c) => !c.isBotAuthored);
71
- const latestHumanComment = humanCommentsAfterBot.at(-1);
72
- if (latestHumanComment === undefined || latestHumanComment.id === handledCommentId) {
73
- return undefined;
74
- }
75
- return latestHumanComment;
76
- }
77
- function latestUnhandledComment(issue) {
78
- const context = issue.context;
79
- const handledCommentId = typeof context.lastHandledCommentId === 'string' ? context.lastHandledCommentId : undefined;
80
- const lastBotIndex = issue.comments.reduce((acc, c, i) => (c.isBotAuthored ? i : acc), -1);
81
- const latest = issue.comments.slice(lastBotIndex).at(-1);
82
- if (latest === undefined || latest.id === handledCommentId) {
83
- return undefined;
84
- }
85
- return latest;
86
- }
87
- export function createPolicyEngine() {
88
- return {
89
- isEligible(issue, config) {
90
- if (issue.issue.state !== 'open') {
91
- return false;
92
- }
93
- if (issue.issue.labels.some((label) => alwaysManualIgnoredLabels.includes(label))) {
94
- return false;
95
- }
96
- // Defense-in-depth: the issues source filters PR-shaped items at poll
97
- // time, so no NEW projection can ever have isPullRequest: true. But a
98
- // pre-existing state/<workId>.json written by a pre-this-branch
99
- // version of Wake could still hold isPullRequest: true, since the old
100
- // fold created projections regardless of eligibility.
101
- if (issue.issue.isPullRequest) {
102
- return false;
103
- }
104
- // Source policy is always checked first — workflow selectors are optional secondary filter.
105
- if (!labelsAndAssigneesQualify({
106
- labels: issue.issue.labels,
107
- assignees: issue.issue.assignees,
108
- requiredLabels: config.sources.github.policy.requiredLabels,
109
- ignoredLabels: config.sources.github.policy.ignoredLabels,
110
- requiredAssignees: config.sources.github.policy.requiredAssignees,
111
- })) {
112
- return false;
113
- }
114
- // If workflow selectors are configured as the routing mechanism, the issue must have
115
- // a workflow assigned (set by a matching selector when the issue was first minted).
116
- if (config.workflowSelectors.length > 0) {
117
- const context = issue.context;
118
- return typeof context.workflow === 'string';
119
- }
120
- return true;
121
- },
122
- needsWakeAction(issue, workflow = builtInDefaultWorkflowDefinition, config) {
123
- const context = issue.context;
124
- const handledCommentId = typeof context.lastHandledCommentId === 'string' ? context.lastHandledCommentId : undefined;
125
- const lastCompletedAction = typeof context.lastCompletedAction === 'string' ? context.lastCompletedAction : undefined;
126
- const lastRunSentinel = typeof context.lastRunSentinel === 'string' ? context.lastRunSentinel : undefined;
127
- const lastRetrySafety = typeof context.lastRetrySafety === 'string' ? context.lastRetrySafety : undefined;
128
- if (issue.wake.lastRunId === undefined) {
129
- return true;
130
- }
131
- if (issue.latestComment !== undefined &&
132
- !issue.latestComment.isBotAuthored &&
133
- issue.latestComment.id !== handledCommentId) {
134
- if (lastRunSentinel === failedRunnerSentinel) {
135
- return belowFailureRetryLimit(issue, config);
136
- }
137
- return true;
138
- }
139
- if (isAwaitingApproval(issue)) {
140
- return false;
141
- }
142
- if (lastRunSentinel === failedRunnerSentinel) {
143
- if (lastRetrySafety === 'SAFE_TO_RETRY' || lastRetrySafety === 'SAFE_TO_RESUME') {
144
- return belowFailureRetryLimit(issue, config);
145
- }
146
- return false;
147
- }
148
- if (lastRunSentinel === 'REJECTED') {
149
- return false;
150
- }
151
- if (lastRunSentinel === 'BLOCKED') {
152
- return false;
153
- }
154
- const workflowAction = chooseWorkflowAction(issue, workflow);
155
- return workflowAction !== null && lastCompletedAction !== workflowAction.action;
156
- },
157
- chooseAction(issue, workflow = builtInDefaultWorkflowDefinition) {
158
- return chooseWorkflowAction(issue, workflow)?.action ?? null;
159
- },
160
- chooseRetryActionAfterHumanReply(issue, workflow = builtInDefaultWorkflowDefinition) {
161
- const context = issue.context;
162
- const failed = context.lastRunSentinel === failedRunnerSentinel;
163
- const blocked = context.lastRunSentinel === 'BLOCKED';
164
- if (failed && context.lastFailureClass === 'quota') {
165
- return typeof context.lastRunAction === 'string' ? context.lastRunAction : null;
166
- }
167
- if (!blocked && !failed) {
168
- return null;
169
- }
170
- if (latestUnhandledHumanComment(issue) === undefined) {
171
- return null;
172
- }
173
- if (typeof context.blockedFromStage !== 'string') {
174
- return null;
175
- }
176
- return (chooseWorkflowAction({
177
- ...issue,
178
- wake: {
179
- ...issue.wake,
180
- stage: context.blockedFromStage,
181
- },
182
- }, workflow)?.action ?? null);
183
- },
184
- resolveApprovalTransition(issue) {
185
- if (!isAwaitingApproval(issue)) {
186
- return null;
187
- }
188
- const context = issue.context;
189
- const pendingAction = typeof context.pendingApprovalAction === 'string'
190
- ? context.pendingApprovalAction
191
- : undefined;
192
- // No new human comment since the last handled one; stay idle instead of
193
- // falling through to the LLM while awaiting explicit approval feedback.
194
- const latestHumanComment = latestUnhandledHumanComment(issue);
195
- const latestComment = latestUnhandledComment(issue);
196
- if (pendingAction === undefined) {
197
- return null;
198
- }
199
- if (context.pendingApprovalAllowAutoApproval === true &&
200
- issue.issue.labels.includes(autoApprovalLabel)) {
201
- return {
202
- approved: true,
203
- pendingAction,
204
- automatic: true,
205
- reason: 'Issue has wake:auto and the pending action prompt declared allowAutoApproval: true.',
206
- };
207
- }
208
- if (latestComment?.isBotAuthored === true &&
209
- latestComment.resourceUri !== undefined &&
210
- latestComment.body.includes(prReviewApprovalMarker)) {
211
- return {
212
- approved: true,
213
- pendingAction,
214
- targetResourceUri: latestComment.resourceUri,
215
- triggeringCommentId: latestComment.id,
216
- triggeringCommentBody: latestComment.body,
217
- };
218
- }
219
- if (latestHumanComment === undefined) {
220
- return null;
221
- }
222
- const approved = matchesCommand(latestHumanComment.body, approvedCommandPattern);
223
- const changesRequested = matchesCommand(latestHumanComment.body, changesCommandPattern);
224
- // Neither an explicit /approved nor /changes: treat this as
225
- // conversation, not a decision. Stay idle rather than re-running the
226
- // pending action off the back of an unmarked clarifying question (S2).
227
- // The comment stays unhandled, so it's reconsidered on the next tick and
228
- // by a human who follows up with an explicit command.
229
- if (!approved && !changesRequested) {
230
- return null;
231
- }
232
- return {
233
- approved,
234
- pendingAction,
235
- ...(changesRequested
236
- ? {
237
- changesRequested: true,
238
- triggeringCommentId: latestHumanComment.id,
239
- triggeringCommentBody: latestHumanComment.body,
240
- }
241
- : {}),
242
- };
243
- },
244
- // Callers must try resolveApprovalTransition first and only fall back to
245
- // this when it returns null. resolveApprovalTransition doesn't check
246
- // resourceUri, so a PR-surface comment that happens to carry an explicit
247
- // /approved or /changes command is deliberately still routed
248
- // there — this function only ever sees comments resolveApprovalTransition
249
- // already passed on (plain PR feedback with no command).
250
- resolvePendingReviewFeedback(issue) {
251
- if (!isAwaitingApproval(issue)) {
252
- return null;
253
- }
254
- const latestHumanComment = latestUnhandledHumanComment(issue);
255
- const latestComment = latestUnhandledComment(issue);
256
- if (latestComment?.isBotAuthored === true &&
257
- latestComment.resourceUri !== undefined &&
258
- latestComment.body.includes(prReviewChangesMarker)) {
259
- return reviewFeedbackAction;
260
- }
261
- // resourceUri is set only on comments folded from a correlated PR/review
262
- // surface (schema.ts's commentSnapshotSchema: "absent = the originating
263
- // issue thread"). A comment on that surface is itself the deliberate
264
- // act — unlike an issue-thread reply, it doesn't need an explicit
265
- // /approved-style command to count as a decision.
266
- if (latestHumanComment === undefined || latestHumanComment.resourceUri === undefined) {
267
- return null;
268
- }
269
- return reviewFeedbackAction;
270
- },
271
- // A rejecting review watcher (or an already-folded /changes reply) sets
272
- // context.status = 'changes-requested' with no fresh comment required —
273
- // this is the gap #472 described: nothing distinguished a plan-review
274
- // rejection from "never reviewed yet." Bounding (escalating to 'blocked'
275
- // once config.retry.maxChangesRequestedRetries is exceeded) already
276
- // happened at fold time, so this only has to check the current status.
277
- resolveChangesRequestedAction(issue) {
278
- if (!isAwaitingApproval(issue) || issue.context.status !== 'changes-requested') {
279
- return null;
280
- }
281
- return typeof issue.context.pendingApprovalAction === 'string'
282
- ? issue.context.pendingApprovalAction
283
- : null;
284
- },
285
- resolveCustomCommandRequest(issue, config) {
286
- return resolveCustomCommand(issue, config);
287
- },
288
- // The single eligibility predicate: is this issue open, on a known workflow
289
- // stage, and does it have a next action Wake should run? Returns the
290
- // resolved action plus the workflow it belongs to, or null when there is
291
- // nothing to do. This used to be duplicated as two independently-drifting
292
- // copies (the pending-label marker and the runner's candidate `find`), which
293
- // is exactly the class of "a rule change didn't propagate everywhere" that
294
- // caused the #258 incident — keep it as the one source of truth.
295
- resolveNextEligibleAction(issue, config) {
296
- if (!this.isEligible(issue, config)) {
297
- return null;
298
- }
299
- const workflow = workflowForProjection(issue, config);
300
- if (workflow === null || !isKnownWorkflowStage(issue.wake.stage, workflow)) {
301
- return null;
302
- }
303
- if (isAwaitingApproval(issue)) {
304
- const customCommand = resolveCustomCommand(issue, config);
305
- if (customCommand !== null) {
306
- return { action: customCommand.action, workflow };
307
- }
308
- const approval = this.resolveApprovalTransition(issue);
309
- if (approval !== null) {
310
- return { action: approval.pendingAction, workflow };
311
- }
312
- const changesRequestedAction = this.resolveChangesRequestedAction(issue);
313
- if (changesRequestedAction !== null) {
314
- return { action: changesRequestedAction, workflow };
315
- }
316
- const reviewAction = this.resolvePendingReviewFeedback(issue);
317
- if (reviewAction !== null) {
318
- return { action: reviewAction, workflow };
319
- }
320
- return null;
321
- }
322
- const nextAction = resolveCustomCommand(issue, config)?.action ??
323
- this.chooseAction(issue, workflow) ??
324
- this.chooseRetryActionAfterHumanReply(issue, workflow);
325
- if (nextAction === null || !this.needsWakeAction(issue, workflow, config)) {
326
- return null;
327
- }
328
- return { action: nextAction, workflow };
329
- },
330
- qualifiesForMint(unresolved, config) {
331
- const resourceUri = unresolved.sourceRefs.resourceUri;
332
- if (resourceUri === undefined) {
333
- return false;
334
- }
335
- const kind = resourceUri.split(':')[1];
336
- if (kind === 'schedule') {
337
- const workflow = unresolved.payload.workflow;
338
- return typeof workflow === 'string' && config.workflows[workflow] !== undefined;
339
- }
340
- // Source policy enforcement is always checked first — workflow selectors are optional secondary routing.
341
- if (kind === 'issue') {
342
- // Real github source stamps payload.ticket (sourceEventType
343
- // 'ticket.upsert'); the fake ticketing harness stamps payload.issue
344
- // (sourceEventType 'fake.issue.upsert') — the same dual-key
345
- // recognition projection-updater.ts's createProjectionFromIssueEvent
346
- // already applies when folding these into a projection. Qualification
347
- // must accept both or the fake never qualifies anything, which would
348
- // silently defeat every fixture that exercises minting through it.
349
- const ticket = (unresolved.payload.ticket ?? unresolved.payload.issue);
350
- if (ticket === undefined) {
351
- return false;
352
- }
353
- if (!labelsAndAssigneesQualify({
354
- labels: Array.isArray(ticket.labels) ? ticket.labels : [],
355
- assignees: Array.isArray(ticket.assignees) ? ticket.assignees : [],
356
- requiredLabels: config.sources.github.policy.requiredLabels,
357
- ignoredLabels: config.sources.github.policy.ignoredLabels,
358
- requiredAssignees: config.sources.github.policy.requiredAssignees,
359
- })) {
360
- return false;
361
- }
362
- // Issue passed source policy; if workflow selectors are configured, also check routing.
363
- if (config.workflowSelectors.length > 0) {
364
- return selectWorkflowForEvent(unresolved, config) !== null;
365
- }
366
- return true;
367
- }
368
- if (kind === 'pr') {
369
- if (!config.sources.github.pullRequests.enabled) {
370
- return false;
371
- }
372
- const pr = unresolved.payload.pr;
373
- const requiredAuthors = config.sources.github.pullRequests.policy.requiredAuthors;
374
- // If requiredAuthors is empty, source policy allows any author.
375
- if (requiredAuthors.length > 0) {
376
- if (typeof pr?.author !== 'string' || !requiredAuthors.includes(pr.author)) {
377
- return false;
378
- }
379
- }
380
- // PR passed source policy; if workflow selectors are configured, also check routing.
381
- if (config.workflowSelectors.length > 0) {
382
- return selectWorkflowForEvent(unresolved, config) !== null;
383
- }
384
- return true;
385
- }
386
- return false;
387
- },
388
- };
389
- }