@atolis-hq/wake 0.2.97 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (442) hide show
  1. package/dist/src/activities/agent/agent-activity-definition.js +26 -0
  2. package/dist/src/activities/agent/agent-activity.js +171 -0
  3. package/dist/src/activities/agent/agent-result.js +149 -0
  4. package/dist/src/activities/contracts/activity.js +10 -0
  5. package/dist/src/activities/contracts/config.js +2 -0
  6. package/dist/src/activities/contracts/event-schema.js +302 -0
  7. package/dist/src/activities/contracts/events.js +42 -0
  8. package/dist/src/activities/contracts/identifiers.js +29 -0
  9. package/dist/src/activities/contracts/registry.js +71 -0
  10. package/dist/src/activities/contracts/streams.js +17 -0
  11. package/dist/src/activities/contracts/vocabulary.js +58 -0
  12. package/dist/src/activities/index.js +21 -0
  13. package/dist/src/activities/pr/activity-support.js +111 -0
  14. package/dist/src/activities/pr/application.js +158 -0
  15. package/dist/src/activities/pr/approve.js +85 -0
  16. package/dist/src/activities/pr/capability.js +11 -0
  17. package/dist/src/activities/pr/decision-claim.js +76 -0
  18. package/dist/src/activities/pr/event-drafts.js +66 -0
  19. package/dist/src/activities/pr/intent.js +37 -0
  20. package/dist/src/activities/pr/merge-authority-gate.js +14 -0
  21. package/dist/src/activities/pr/merge.js +110 -0
  22. package/dist/src/activities/pr/policy.js +135 -0
  23. package/dist/src/activities/pr/projection.js +130 -0
  24. package/dist/src/activities/pr/vocabulary.js +30 -0
  25. package/dist/src/activities/review/authorization.js +22 -0
  26. package/dist/src/activities/review/contracts.js +22 -0
  27. package/dist/src/activities/review/signals.js +3 -0
  28. package/dist/src/bootstrap/analytics-projection.js +26 -0
  29. package/dist/src/bootstrap/board-projection.js +337 -0
  30. package/dist/src/bootstrap/composition-root.js +382 -0
  31. package/dist/src/bootstrap/config/load-config.js +51 -0
  32. package/dist/src/bootstrap/config/root-schema.js +134 -0
  33. package/dist/src/bootstrap/external-ref.js +12 -0
  34. package/dist/src/bootstrap/fake-provider-files.js +44 -0
  35. package/dist/src/bootstrap/fake-scenarios.js +22 -0
  36. package/dist/src/bootstrap/index.js +48 -0
  37. package/dist/src/bootstrap/initialise.js +434 -0
  38. package/dist/src/bootstrap/paths.js +15 -0
  39. package/dist/src/bootstrap/projection-runtime.js +27 -0
  40. package/dist/src/bootstrap/runner-quota-reporter.js +21 -0
  41. package/dist/src/bootstrap/runner-registry.js +30 -0
  42. package/dist/src/bootstrap/schedule-checkpoint-store.js +49 -0
  43. package/dist/src/bootstrap/self-update-application.js +195 -0
  44. package/dist/src/bootstrap/self-update-failure-log.js +33 -0
  45. package/dist/src/bootstrap/source-update-port.js +47 -0
  46. package/dist/src/bootstrap/status-publish-activity.js +42 -0
  47. package/dist/src/bootstrap/surface-api-applications.js +325 -0
  48. package/dist/src/bootstrap/surface-api-execution-applications.js +95 -0
  49. package/dist/src/bootstrap/surface-api-metadata.js +12 -0
  50. package/dist/src/bootstrap/surface-api-projection-pages.js +22 -0
  51. package/dist/src/bootstrap/surface-api-run-context.js +5 -0
  52. package/dist/src/bootstrap/surface-api-transcripts.js +57 -0
  53. package/dist/src/bootstrap/surface-api-work-applications.js +199 -0
  54. package/dist/src/bootstrap/surface-applications.js +7 -0
  55. package/dist/src/bootstrap/surface-cli-applications.js +701 -0
  56. package/dist/src/bootstrap/update-ledger.js +61 -0
  57. package/dist/src/bootstrap/update-maintenance-lease.js +176 -0
  58. package/dist/src/{version.js → bootstrap/version.js} +35 -51
  59. package/dist/src/control-plane/application/advance-once.js +184 -0
  60. package/dist/src/control-plane/application/control-plane-projection.js +42 -0
  61. package/dist/src/control-plane/application/control-plane-service.js +42 -0
  62. package/dist/src/control-plane/application/intake-pipeline.js +29 -0
  63. package/dist/src/control-plane/application/runner-control-service.js +66 -0
  64. package/dist/src/control-plane/application/runner-pipeline.js +57 -0
  65. package/dist/src/control-plane/application/schedule-service.js +47 -0
  66. package/dist/src/control-plane/application/work-cancellation-policy.js +31 -0
  67. package/dist/src/control-plane/contracts/commands.js +10 -0
  68. package/dist/src/control-plane/contracts/config.js +22 -0
  69. package/dist/src/control-plane/contracts/events.js +81 -0
  70. package/dist/src/control-plane/contracts/streams.js +5 -0
  71. package/dist/src/control-plane/domain/dispatch-policy.js +15 -0
  72. package/dist/src/control-plane/domain/quota-policy.js +26 -0
  73. package/dist/src/control-plane/domain/runner-quota.js +35 -0
  74. package/dist/src/control-plane/domain/schedule-policy.js +46 -0
  75. package/dist/src/control-plane/index.js +20 -0
  76. package/dist/src/control-plane/infrastructure/intake-host.js +24 -0
  77. package/dist/src/control-plane/infrastructure/resident-host.js +45 -0
  78. package/dist/src/control-plane/infrastructure/tick-host.js +35 -0
  79. package/dist/src/execution/application/activation-claim.js +50 -0
  80. package/dist/src/execution/application/active-run-cancellation.js +14 -0
  81. package/dist/src/execution/application/execution-activity.js +97 -0
  82. package/dist/src/execution/application/execution-projection.js +17 -0
  83. package/dist/src/execution/application/execution-service.js +372 -0
  84. package/dist/src/execution/application/execution-validation.js +26 -0
  85. package/dist/src/execution/application/recovery-service.js +212 -0
  86. package/dist/src/execution/application/run-lifecycle.js +115 -0
  87. package/dist/src/execution/application/run-liveness-service.js +80 -0
  88. package/dist/src/execution/application/run-repository.js +27 -0
  89. package/dist/src/execution/contracts/commands.js +1 -0
  90. package/dist/src/execution/contracts/config.js +35 -0
  91. package/dist/src/execution/contracts/control-plane.js +1 -0
  92. package/dist/src/execution/contracts/event-factory.js +53 -0
  93. package/dist/src/execution/contracts/events.js +274 -0
  94. package/dist/src/execution/contracts/identifiers.js +5 -0
  95. package/dist/src/execution/contracts/liveness.js +1 -0
  96. package/dist/src/execution/contracts/results.js +1 -0
  97. package/dist/src/execution/contracts/runner.js +15 -0
  98. package/dist/src/execution/contracts/streams.js +10 -0
  99. package/dist/src/execution/contracts/views.js +1 -0
  100. package/dist/src/execution/contracts/vocabulary.js +43 -0
  101. package/dist/src/execution/contracts/workspace.js +1 -0
  102. package/dist/src/execution/domain/run-result.js +34 -0
  103. package/dist/src/execution/domain/run.js +142 -0
  104. package/dist/src/execution/index.js +31 -0
  105. package/dist/src/execution/infrastructure/agent-runner-adapter.js +114 -0
  106. package/dist/src/execution/infrastructure/process-execution.js +29 -0
  107. package/dist/src/execution/infrastructure/prompt-templates.js +42 -0
  108. package/dist/src/execution/infrastructure/runners/claude.js +120 -0
  109. package/dist/src/execution/infrastructure/runners/codex.js +143 -0
  110. package/dist/src/execution/infrastructure/runners/command.js +4 -0
  111. package/dist/src/execution/infrastructure/runners/cursor.js +69 -0
  112. package/dist/src/execution/infrastructure/runners/fake-scenarios.js +99 -0
  113. package/dist/src/execution/infrastructure/runners/fake.js +65 -0
  114. package/dist/src/execution/infrastructure/runners/registry.js +26 -0
  115. package/dist/src/execution/infrastructure/transcript-store.js +223 -0
  116. package/dist/src/execution/infrastructure/transcripts.js +11 -0
  117. package/dist/src/execution/infrastructure/workspace/fake-workspace.js +19 -0
  118. package/dist/src/execution/infrastructure/workspace/git-workspace.js +241 -0
  119. package/dist/src/integrations/application/agent-run-publication-reactor.js +111 -0
  120. package/dist/src/integrations/application/artifact-registration-reactor.js +159 -0
  121. package/dist/src/integrations/application/poll-service.js +25 -0
  122. package/dist/src/integrations/application/terminal-agent-run-report.js +40 -0
  123. package/dist/src/integrations/application/work-admission.js +31 -0
  124. package/dist/src/integrations/application/work-conclusion.js +19 -0
  125. package/dist/src/integrations/contracts/artifact-events.js +60 -0
  126. package/dist/src/integrations/contracts/artifact-vocabulary.js +9 -0
  127. package/dist/src/integrations/contracts/config.js +14 -0
  128. package/dist/src/integrations/contracts/identifiers.js +5 -0
  129. package/dist/src/integrations/contracts/intake-rules.js +14 -0
  130. package/dist/src/integrations/contracts/intake.js +1 -0
  131. package/dist/src/integrations/contracts/outcome-vocabulary.js +7 -0
  132. package/dist/src/integrations/contracts/provider.js +37 -0
  133. package/dist/src/integrations/contracts/streams.js +10 -0
  134. package/dist/src/integrations/delivery/application/delivery-outcome-reactor.js +75 -0
  135. package/dist/src/integrations/delivery/application/delivery-projector.js +165 -0
  136. package/dist/src/integrations/delivery/application/delivery-service.js +173 -0
  137. package/dist/src/integrations/delivery/contracts/commands.js +1 -0
  138. package/dist/src/integrations/delivery/contracts/config.js +1 -0
  139. package/dist/src/integrations/delivery/contracts/event-factory.js +18 -0
  140. package/dist/src/integrations/delivery/contracts/events.js +86 -0
  141. package/dist/src/integrations/delivery/contracts/intents.js +89 -0
  142. package/dist/src/integrations/delivery/contracts/views.js +1 -0
  143. package/dist/src/integrations/delivery/contracts/vocabulary.js +22 -0
  144. package/dist/src/integrations/fake/durable-delivery-provider.js +48 -0
  145. package/dist/src/integrations/fake/external-sink.js +9 -0
  146. package/dist/src/integrations/fake/external-source.js +44 -0
  147. package/dist/src/integrations/fake/inbound-translator.js +130 -0
  148. package/dist/src/integrations/fake/provider.js +95 -0
  149. package/dist/src/integrations/github/application/agent-context-reader.js +54 -0
  150. package/dist/src/integrations/github/application/agent-run-comment.js +94 -0
  151. package/dist/src/integrations/github/application/comment-history-reader.js +43 -0
  152. package/dist/src/integrations/github/application/inbound-context.js +10 -0
  153. package/dist/src/integrations/github/application/inbound-review-signals.js +159 -0
  154. package/dist/src/integrations/github/application/inbound-translator.js +231 -0
  155. package/dist/src/integrations/github/application/inbound-watch-gate-signals.js +84 -0
  156. package/dist/src/integrations/github/application/intake-policy.js +23 -0
  157. package/dist/src/integrations/github/application/outbound-translator.js +47 -0
  158. package/dist/src/integrations/github/application/poll-service.js +29 -0
  159. package/dist/src/integrations/github/application/pull-request-translation.js +10 -0
  160. package/dist/src/integrations/github/application/resource-links.js +8 -0
  161. package/dist/src/integrations/github/application/review-command-translator.js +16 -0
  162. package/dist/src/integrations/github/application/wake-labels.js +95 -0
  163. package/dist/src/integrations/github/contracts/config.js +47 -0
  164. package/dist/src/integrations/github/contracts/events.js +127 -0
  165. package/dist/src/integrations/github/contracts/external-key.js +19 -0
  166. package/dist/src/integrations/github/contracts/payloads.js +9 -0
  167. package/dist/src/integrations/github/contracts/vocabulary.js +55 -0
  168. package/dist/src/integrations/github/index.js +31 -0
  169. package/dist/src/integrations/github/infrastructure/client-reads.js +214 -0
  170. package/dist/src/integrations/github/infrastructure/client.js +132 -0
  171. package/dist/src/integrations/github/infrastructure/content-fingerprint.js +10 -0
  172. package/dist/src/integrations/github/infrastructure/delivery.js +31 -0
  173. package/dist/src/integrations/github/infrastructure/etag-cache.js +56 -0
  174. package/dist/src/integrations/github/infrastructure/gh-auth.js +19 -0
  175. package/dist/src/integrations/github/infrastructure/issue-source.js +109 -0
  176. package/dist/src/integrations/github/infrastructure/pr-source.js +186 -0
  177. package/dist/src/integrations/github/infrastructure/review-source.js +70 -0
  178. package/dist/src/integrations/github/infrastructure/source.js +108 -0
  179. package/dist/src/integrations/github/provider.js +96 -0
  180. package/dist/src/integrations/index.js +30 -0
  181. package/dist/src/kernel/contracts/checkpoint-store.js +1 -0
  182. package/dist/src/kernel/contracts/clock.js +1 -0
  183. package/dist/src/kernel/contracts/commands.js +1 -0
  184. package/dist/src/kernel/contracts/event-journal.js +2 -0
  185. package/dist/src/kernel/contracts/event-schema.js +54 -0
  186. package/dist/src/kernel/contracts/events.js +11 -0
  187. package/dist/src/kernel/contracts/id-generator.js +1 -0
  188. package/dist/src/kernel/contracts/identifiers.js +8 -0
  189. package/dist/src/kernel/contracts/projection-store.js +1 -0
  190. package/dist/src/kernel/contracts/relations.js +1 -0
  191. package/dist/src/kernel/contracts/schema.js +17 -0
  192. package/dist/src/kernel/contracts/vocabulary.js +6 -0
  193. package/dist/src/kernel/domain/event-envelope.js +29 -0
  194. package/dist/src/kernel/domain/match-mode.js +11 -0
  195. package/dist/src/kernel/domain/relation.js +10 -0
  196. package/dist/src/kernel/index.js +17 -0
  197. package/dist/src/{lib/clock.js → kernel/infrastructure/system-clock.js} +3 -3
  198. package/dist/src/kernel/infrastructure/ulid-id-generator.js +9 -0
  199. package/dist/src/main.js +137 -1030
  200. package/dist/src/orchestration/application/accept-activity-outcome.js +25 -0
  201. package/dist/src/orchestration/application/accept-signal.js +35 -0
  202. package/dist/src/orchestration/application/advance-workflow.js +160 -0
  203. package/dist/src/orchestration/application/coordination-claims.js +107 -0
  204. package/dist/src/orchestration/application/group-budget-recorder.js +43 -0
  205. package/dist/src/orchestration/application/orchestration-projection.js +20 -0
  206. package/dist/src/orchestration/application/orchestration-repository.js +36 -0
  207. package/dist/src/orchestration/application/orchestration-service.js +82 -0
  208. package/dist/src/orchestration/application/request-child.js +118 -0
  209. package/dist/src/orchestration/application/signal-reactor.js +17 -0
  210. package/dist/src/orchestration/application/start-workflow.js +51 -0
  211. package/dist/src/orchestration/application/watch-reactor.js +82 -0
  212. package/dist/src/orchestration/contracts/activity-outcome.js +18 -0
  213. package/dist/src/orchestration/contracts/commands.js +1 -0
  214. package/dist/src/orchestration/contracts/config.js +128 -0
  215. package/dist/src/orchestration/contracts/event-decoder.js +263 -0
  216. package/dist/src/orchestration/contracts/events.js +41 -0
  217. package/dist/src/orchestration/contracts/identifiers.js +35 -0
  218. package/dist/src/orchestration/contracts/streams.js +38 -0
  219. package/dist/src/orchestration/contracts/views.js +1 -0
  220. package/dist/src/orchestration/contracts/vocabulary.js +30 -0
  221. package/dist/src/orchestration/domain/activation-policy.js +55 -0
  222. package/dist/src/orchestration/domain/approval-defaults.js +17 -0
  223. package/dist/src/orchestration/domain/child-policy.js +63 -0
  224. package/dist/src/orchestration/domain/compiler.js +162 -0
  225. package/dist/src/orchestration/domain/coordination-events.js +25 -0
  226. package/dist/src/orchestration/domain/decision-events.js +47 -0
  227. package/dist/src/orchestration/domain/interpreter.js +49 -0
  228. package/dist/src/orchestration/domain/operator-retry-policy.js +34 -0
  229. package/dist/src/orchestration/domain/retry-policy.js +26 -0
  230. package/dist/src/orchestration/domain/signal-policy.js +120 -0
  231. package/dist/src/orchestration/domain/supplemental-policy.js +61 -0
  232. package/dist/src/orchestration/domain/transition.js +55 -0
  233. package/dist/src/orchestration/domain/workflow-graph.js +41 -0
  234. package/dist/src/orchestration/domain/workflow-instance-events.js +236 -0
  235. package/dist/src/orchestration/domain/workflow-instance.js +41 -0
  236. package/dist/src/orchestration/domain/workflow-selector.js +21 -0
  237. package/dist/src/orchestration/index.js +19 -0
  238. package/dist/src/persistence/application/projection-runner.js +79 -0
  239. package/dist/src/persistence/filesystem/file-checkpoint-store.js +35 -0
  240. package/dist/src/persistence/filesystem/file-event-journal.js +143 -0
  241. package/dist/src/persistence/filesystem/file-lock.js +91 -0
  242. package/dist/src/persistence/filesystem/file-projection-store.js +64 -0
  243. package/dist/src/persistence/index.js +8 -0
  244. package/dist/src/persistence/memory/in-memory-checkpoint-store.js +14 -0
  245. package/dist/src/persistence/memory/in-memory-event-journal.js +88 -0
  246. package/dist/src/persistence/memory/in-memory-projection-store.js +17 -0
  247. package/dist/src/resources/application/lookup-projections.js +48 -0
  248. package/dist/src/resources/application/resource-lookup.js +16 -0
  249. package/dist/src/resources/application/resource-projections.js +81 -0
  250. package/dist/src/resources/application/resource-repository.js +18 -0
  251. package/dist/src/resources/application/resource-service.js +83 -0
  252. package/dist/src/resources/contracts/commands.js +1 -0
  253. package/dist/src/resources/contracts/config.js +2 -0
  254. package/dist/src/resources/contracts/events.js +83 -0
  255. package/dist/src/resources/contracts/identifiers.js +15 -0
  256. package/dist/src/resources/contracts/streams.js +6 -0
  257. package/dist/src/resources/contracts/views.js +1 -0
  258. package/dist/src/resources/contracts/vocabulary.js +67 -0
  259. package/dist/src/resources/domain/correlation.js +8 -0
  260. package/dist/src/resources/domain/resource.js +58 -0
  261. package/dist/src/resources/index.js +14 -0
  262. package/dist/src/surfaces/api/contracts/activities.js +1 -0
  263. package/dist/src/surfaces/api/contracts/board.js +2 -0
  264. package/dist/src/surfaces/api/contracts/common.js +46 -0
  265. package/dist/src/surfaces/api/contracts/control-plane.js +5 -0
  266. package/dist/src/surfaces/api/contracts/events.js +1 -0
  267. package/dist/src/surfaces/api/contracts/execution.js +1 -0
  268. package/dist/src/surfaces/api/contracts/index.js +13 -0
  269. package/dist/src/surfaces/api/contracts/observability.js +1 -0
  270. package/dist/src/surfaces/api/contracts/orchestration.js +1 -0
  271. package/dist/src/surfaces/api/contracts/resources.js +1 -0
  272. package/dist/src/surfaces/api/contracts/status.js +1 -0
  273. package/dist/src/surfaces/api/contracts/system.js +1 -0
  274. package/dist/src/surfaces/api/contracts/transport-values.js +39 -0
  275. package/dist/src/surfaces/api/contracts/work.js +17 -0
  276. package/dist/src/surfaces/api/http-server.js +121 -0
  277. package/dist/src/surfaces/api/presenters/activities.js +1 -0
  278. package/dist/src/surfaces/api/presenters/board.js +3 -0
  279. package/dist/src/surfaces/api/presenters/control-plane.js +1 -0
  280. package/dist/src/surfaces/api/presenters/events.js +1 -0
  281. package/dist/src/surfaces/api/presenters/execution.js +59 -0
  282. package/dist/src/surfaces/api/presenters/observability.js +1 -0
  283. package/dist/src/surfaces/api/presenters/orchestration.js +19 -0
  284. package/dist/src/surfaces/api/presenters/resources.js +15 -0
  285. package/dist/src/surfaces/api/presenters/status.js +3 -0
  286. package/dist/src/surfaces/api/presenters/system.js +14 -0
  287. package/dist/src/surfaces/api/presenters/work.js +16 -0
  288. package/dist/src/surfaces/api/problem-details.js +9 -0
  289. package/dist/src/surfaces/api/router.js +13 -0
  290. package/dist/src/surfaces/api/routes/activities.js +1 -0
  291. package/dist/src/surfaces/api/routes/applications.js +1 -0
  292. package/dist/src/surfaces/api/routes/commands.js +82 -0
  293. package/dist/src/surfaces/api/routes/control-plane.js +6 -0
  294. package/dist/src/surfaces/api/routes/events.js +1 -0
  295. package/dist/src/surfaces/api/routes/execution.js +8 -0
  296. package/dist/src/surfaces/api/routes/index.js +18 -0
  297. package/dist/src/surfaces/api/routes/observability.js +1 -0
  298. package/dist/src/surfaces/api/routes/orchestration.js +1 -0
  299. package/dist/src/surfaces/api/routes/pagination.js +78 -0
  300. package/dist/src/surfaces/api/routes/read.js +135 -0
  301. package/dist/src/surfaces/api/routes/resources.js +1 -0
  302. package/dist/src/surfaces/api/routes/responses.js +67 -0
  303. package/dist/src/surfaces/api/routes/system.js +1 -0
  304. package/dist/src/surfaces/api/routes/work.js +9 -0
  305. package/dist/src/surfaces/cli/commands/api.js +1 -0
  306. package/dist/src/surfaces/cli/commands/audit.js +10 -0
  307. package/dist/src/surfaces/cli/commands/correlate.js +2 -0
  308. package/dist/src/surfaces/cli/commands/doctor.js +6 -0
  309. package/dist/src/surfaces/cli/commands/init.js +39 -0
  310. package/dist/src/surfaces/cli/commands/sandbox-entrypoint.js +33 -0
  311. package/dist/src/surfaces/cli/commands/sandbox-setup.js +29 -0
  312. package/dist/src/surfaces/cli/commands/sandbox.js +105 -0
  313. package/dist/src/surfaces/cli/commands/self-update.js +38 -0
  314. package/dist/src/surfaces/cli/commands/smoke.js +16 -0
  315. package/dist/src/surfaces/cli/commands/start.js +1 -0
  316. package/dist/src/surfaces/cli/commands/stop.js +13 -0
  317. package/dist/src/surfaces/cli/commands/tick.js +1 -0
  318. package/dist/src/surfaces/cli/commands/ui.js +2 -0
  319. package/dist/src/surfaces/cli/commands/validate-state.js +5 -0
  320. package/dist/src/surfaces/cli/infrastructure/docker-cli.js +221 -0
  321. package/dist/src/surfaces/cli/infrastructure/process-log.js +86 -0
  322. package/dist/src/surfaces/cli/main.js +140 -0
  323. package/dist/src/surfaces/cli/usage.js +33 -0
  324. package/dist/src/surfaces/contracts/config.js +34 -0
  325. package/dist/src/surfaces/index.js +47 -0
  326. package/dist/src/surfaces/web-assets/assets/index-Bfn4FwZG.css +1 -0
  327. package/dist/src/surfaces/web-assets/assets/index-ipB6JPGU.js +1090 -0
  328. package/dist/src/surfaces/web-assets/index.html +13 -0
  329. package/dist/src/surfaces/web-host/asset-source.js +1 -0
  330. package/dist/src/surfaces/web-host/packaged-assets.js +44 -0
  331. package/dist/src/work/application/work-projection.js +59 -0
  332. package/dist/src/work/application/work-repository.js +18 -0
  333. package/dist/src/work/application/work-service.js +117 -0
  334. package/dist/src/work/contracts/commands.js +1 -0
  335. package/dist/src/work/contracts/config.js +2 -0
  336. package/dist/src/work/contracts/events.js +103 -0
  337. package/dist/src/work/contracts/identifiers.js +5 -0
  338. package/dist/src/work/contracts/streams.js +6 -0
  339. package/dist/src/work/contracts/views.js +1 -0
  340. package/dist/src/work/contracts/vocabulary.js +6 -0
  341. package/dist/src/work/domain/work-item.js +89 -0
  342. package/dist/src/work/index.js +11 -0
  343. package/docker/Dockerfile +10 -6
  344. package/docker/Dockerfile.packaged +3 -3
  345. package/package.json +29 -4
  346. package/prompts/implement.md +2 -2
  347. package/templates/SETUP.md +7 -7
  348. package/dist/src/adapters/claude/claude-runner.js +0 -529
  349. package/dist/src/adapters/codex/codex-runner.js +0 -503
  350. package/dist/src/adapters/cursor/cursor-runner.js +0 -418
  351. package/dist/src/adapters/docker/docker-cli.js +0 -150
  352. package/dist/src/adapters/fake/fake-artifact-verifier.js +0 -14
  353. package/dist/src/adapters/fake/fake-github-pull-request-activity-source.js +0 -77
  354. package/dist/src/adapters/fake/fake-resource-index.js +0 -21
  355. package/dist/src/adapters/fake/fake-runner.js +0 -77
  356. package/dist/src/adapters/fake/fake-ticketing-system.js +0 -185
  357. package/dist/src/adapters/fake/fake-workspace-manager.js +0 -81
  358. package/dist/src/adapters/fs/resource-index.js +0 -126
  359. package/dist/src/adapters/fs/self-update-ledger.js +0 -17
  360. package/dist/src/adapters/fs/state-store.js +0 -775
  361. package/dist/src/adapters/git/git-workspace-manager.js +0 -289
  362. package/dist/src/adapters/github/github-artifact-verifier.js +0 -38
  363. package/dist/src/adapters/github/github-auth.js +0 -16
  364. package/dist/src/adapters/github/github-client.js +0 -249
  365. package/dist/src/adapters/github/github-etag-cache.js +0 -57
  366. package/dist/src/adapters/github/github-issues-work-source.js +0 -692
  367. package/dist/src/adapters/github/github-pull-request-activity-source.js +0 -584
  368. package/dist/src/adapters/github/github-pull-request-merge-actor.js +0 -45
  369. package/dist/src/adapters/http/ui-assets.js +0 -1188
  370. package/dist/src/adapters/http/ui-data.js +0 -1107
  371. package/dist/src/adapters/http/ui-server.js +0 -458
  372. package/dist/src/adapters/runner/cli-command.js +0 -73
  373. package/dist/src/adapters/runner/prompt-templates.js +0 -76
  374. package/dist/src/adapters/runner/runner-cli-adapter.js +0 -112
  375. package/dist/src/adapters/runner/runner-registry.js +0 -139
  376. package/dist/src/adapters/runner/runtime-events.js +0 -32
  377. package/dist/src/adapters/runner/stage-prompt.js +0 -268
  378. package/dist/src/adapters/runner/transcripts.js +0 -25
  379. package/dist/src/cli/audit-command.js +0 -36
  380. package/dist/src/cli/correlate-command.js +0 -62
  381. package/dist/src/cli/doctor-command.js +0 -48
  382. package/dist/src/cli/init-command.js +0 -18
  383. package/dist/src/cli/sandbox-command.js +0 -258
  384. package/dist/src/cli/sandbox-entrypoint-command.js +0 -88
  385. package/dist/src/cli/sandbox-exec-logging.js +0 -7
  386. package/dist/src/cli/sandbox-resume.js +0 -79
  387. package/dist/src/cli/sandbox-setup-command.js +0 -31
  388. package/dist/src/cli/scaffold-assets.js +0 -100
  389. package/dist/src/cli/self-update-command.js +0 -198
  390. package/dist/src/cli/startup-preflight.js +0 -134
  391. package/dist/src/cli/stop-command.js +0 -46
  392. package/dist/src/cli/ui-command.js +0 -27
  393. package/dist/src/config/defaults.js +0 -10
  394. package/dist/src/config/discover-config-files.js +0 -11
  395. package/dist/src/config/load-config.js +0 -69
  396. package/dist/src/config/split-config.js +0 -14
  397. package/dist/src/core/active-run-recovery.js +0 -44
  398. package/dist/src/core/approval-intents.js +0 -16
  399. package/dist/src/core/audit-events.js +0 -82
  400. package/dist/src/core/control-plane.js +0 -192
  401. package/dist/src/core/event-builders.js +0 -153
  402. package/dist/src/core/event-resolver.js +0 -249
  403. package/dist/src/core/lifecycle-service.js +0 -8
  404. package/dist/src/core/live-execution.js +0 -81
  405. package/dist/src/core/outbox.js +0 -198
  406. package/dist/src/core/policy-engine.js +0 -389
  407. package/dist/src/core/projection-updater.js +0 -693
  408. package/dist/src/core/quota-backoff.js +0 -69
  409. package/dist/src/core/run-lease.js +0 -38
  410. package/dist/src/core/scheduled-workflow-source.js +0 -199
  411. package/dist/src/core/sink-router.js +0 -107
  412. package/dist/src/core/stale-run-reconciler.js +0 -352
  413. package/dist/src/core/tick-runner.js +0 -2442
  414. package/dist/src/core/workspace-cleanup.js +0 -117
  415. package/dist/src/domain/branch-naming.js +0 -14
  416. package/dist/src/domain/custom-commands.js +0 -58
  417. package/dist/src/domain/event-types.js +0 -158
  418. package/dist/src/domain/manual-labels.js +0 -1
  419. package/dist/src/domain/resource-uri.js +0 -38
  420. package/dist/src/domain/runner-routing.js +0 -127
  421. package/dist/src/domain/runtime-events.js +0 -36
  422. package/dist/src/domain/schema.js +0 -1233
  423. package/dist/src/domain/sources.js +0 -16
  424. package/dist/src/domain/stages.js +0 -36
  425. package/dist/src/domain/work-item-labels.js +0 -48
  426. package/dist/src/domain/work-item-lifecycle.js +0 -10
  427. package/dist/src/domain/work-item-status.js +0 -33
  428. package/dist/src/domain/workflows.js +0 -159
  429. package/dist/src/lib/deep-merge.js +0 -14
  430. package/dist/src/lib/detached-process-logging.js +0 -46
  431. package/dist/src/lib/event-log.js +0 -21
  432. package/dist/src/lib/format.js +0 -41
  433. package/dist/src/lib/json-file.js +0 -23
  434. package/dist/src/lib/lock.js +0 -181
  435. package/dist/src/lib/log-rotation.js +0 -42
  436. package/dist/src/lib/paths.js +0 -52
  437. package/dist/src/lib/process-identity.js +0 -54
  438. package/dist/src/lib/state-health.js +0 -30
  439. package/dist/src/lib/work-id.js +0 -19
  440. package/dist/src/lib/yaml-file.js +0 -20
  441. /package/dist/src/{core → activities/pr}/contracts.js +0 -0
  442. /package/dist/src/{domain/types.js → control-plane/contracts/views.js} +0 -0
@@ -0,0 +1,223 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, readdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { TranscriptGroupKind, } from '../contracts/vocabulary.js';
5
+ export class TranscriptStore {
6
+ transcriptsRoot;
7
+ fileSystem;
8
+ constructor(transcriptsRoot, fileSystem = { remove: rm }) {
9
+ this.transcriptsRoot = transcriptsRoot;
10
+ this.fileSystem = fileSystem;
11
+ }
12
+ async capturePrompt(capture) {
13
+ const timestamp = timestampForFile(capture.timestamp);
14
+ const directory = this.stagingDirectory(capture.workItemId, capture.runId);
15
+ await mkdir(directory, { recursive: true });
16
+ await writeFile(join(directory, messageFile(timestamp, capture.runId, 'prompt')), capture.text, 'utf8');
17
+ }
18
+ async captureResponse(capture) {
19
+ const timestamp = timestampForFile(capture.timestamp);
20
+ const group = capture.sessionId === undefined
21
+ ? runGroup(capture.runId)
22
+ : sessionGroup(capture.cli, capture.sessionId);
23
+ const destination = this.groupDirectory(capture.workItemId, group);
24
+ await this.moveStagedPrompt(capture.workItemId, capture.runId, destination);
25
+ await writeFile(join(destination, messageFile(timestamp, capture.runId, 'response')), capture.text, 'utf8');
26
+ }
27
+ async finalisePrompt(capture) {
28
+ const staging = this.stagingDirectory(capture.workItemId, capture.runId);
29
+ const promptFiles = (await filesOrEmpty(staging)).filter((file) => file.endsWith('.prompt.txt'));
30
+ if (promptFiles.length === 0)
31
+ return;
32
+ const destination = this.groupDirectory(capture.workItemId, runGroup(capture.runId));
33
+ await mkdir(destination, { recursive: true });
34
+ for (const promptFile of promptFiles) {
35
+ await rename(join(staging, promptFile), join(destination, promptFile));
36
+ }
37
+ await this.fileSystem.remove(staging, { recursive: true, force: true });
38
+ }
39
+ async listGroups(workItemId) {
40
+ const groups = [];
41
+ for (const name of await filesOrEmpty(this.workItemDirectory(workItemId))) {
42
+ const parsed = parseGroup(name);
43
+ if (parsed === undefined)
44
+ continue;
45
+ const messages = await this.readGroup(workItemId, name);
46
+ const latest = messages.at(-1);
47
+ if (latest === undefined)
48
+ continue;
49
+ groups.push({
50
+ ...parsed,
51
+ latestAt: latest.timestamp,
52
+ runIds: [...new Set(messages.map((message) => message.runId))],
53
+ });
54
+ }
55
+ return groups.sort((left, right) => {
56
+ if (left.kind !== right.kind)
57
+ return left.kind === TranscriptGroupKind.Session ? -1 : 1;
58
+ return left.id.localeCompare(right.id);
59
+ });
60
+ }
61
+ async readGroup(workItemId, groupId) {
62
+ assertSegment(groupId, 'Transcript group ID');
63
+ const messages = [];
64
+ const directory = this.groupDirectory(workItemId, groupId);
65
+ for (const file of await filesOrEmpty(directory)) {
66
+ const parsed = parseMessageFile(file);
67
+ if (parsed === undefined)
68
+ continue;
69
+ messages.push({ ...parsed, text: await readFile(join(directory, file), 'utf8') });
70
+ }
71
+ return messages.sort((left, right) => left.timestamp.localeCompare(right.timestamp));
72
+ }
73
+ async groupForRun(workItemId, runId) {
74
+ for (const group of await this.listGroups(workItemId)) {
75
+ if (group.runIds.includes(runId))
76
+ return group.id;
77
+ }
78
+ return undefined;
79
+ }
80
+ async markWorkItemCleaned(workItemId, retentionMs, cleanedAt) {
81
+ assertRetention(retentionMs);
82
+ const directory = this.workItemDirectory(workItemId);
83
+ if (retentionMs === 0) {
84
+ await this.fileSystem.remove(directory, { recursive: true, force: true });
85
+ return;
86
+ }
87
+ try {
88
+ await readFile(join(directory, '.cleaned-at'), 'utf8');
89
+ return;
90
+ }
91
+ catch (error) {
92
+ if (!isMissing(error))
93
+ throw error;
94
+ }
95
+ const timestamp = normaliseTimestamp(cleanedAt);
96
+ await mkdir(directory, { recursive: true });
97
+ await writeFile(join(directory, '.cleaned-at'), timestamp, 'utf8');
98
+ }
99
+ async sweepExpired(retentionMs, now, onError = () => { }) {
100
+ assertRetention(retentionMs);
101
+ const currentTime = Date.parse(normaliseTimestamp(now));
102
+ const expired = [];
103
+ for (const workItemId of await filesOrEmpty(this.transcriptsRoot)) {
104
+ const directory = this.workItemDirectory(workItemId);
105
+ const marker = join(directory, '.cleaned-at');
106
+ let cleanedAt;
107
+ try {
108
+ cleanedAt = await readFile(marker, 'utf8');
109
+ }
110
+ catch (error) {
111
+ if (isMissing(error))
112
+ continue;
113
+ onError(workItemId, error);
114
+ continue;
115
+ }
116
+ try {
117
+ if (Date.parse(normaliseTimestamp(cleanedAt)) + retentionMs <= currentTime) {
118
+ await this.fileSystem.remove(directory, { recursive: true, force: true });
119
+ expired.push(workItemId);
120
+ }
121
+ }
122
+ catch (error) {
123
+ onError(workItemId, error);
124
+ }
125
+ }
126
+ return expired.sort();
127
+ }
128
+ workItemDirectory(workItemId) {
129
+ assertSegment(workItemId, 'Work item ID');
130
+ return join(this.transcriptsRoot, workItemId);
131
+ }
132
+ groupDirectory(workItemId, groupId) {
133
+ assertSegment(groupId, 'Transcript group ID');
134
+ return join(this.workItemDirectory(workItemId), groupId);
135
+ }
136
+ stagingDirectory(workItemId, runId) {
137
+ return join(this.workItemDirectory(workItemId), `.pending--${safe(runId)}`);
138
+ }
139
+ async moveStagedPrompt(workItemId, runId, destination) {
140
+ const staging = this.stagingDirectory(workItemId, runId);
141
+ await mkdir(destination, { recursive: true });
142
+ const promptFiles = await filesOrEmpty(staging);
143
+ for (const promptFile of promptFiles.filter((file) => file.endsWith('.prompt.txt'))) {
144
+ await rename(join(staging, promptFile), join(destination, promptFile));
145
+ }
146
+ await this.fileSystem.remove(staging, { recursive: true, force: true });
147
+ }
148
+ }
149
+ function runGroup(runId) {
150
+ return `run--${safe(runId)}`;
151
+ }
152
+ function sessionGroup(cli, sessionId) {
153
+ return `session--${safe(cli)}--${opaque(sessionId)}`;
154
+ }
155
+ function safe(value) {
156
+ return encodeURIComponent(value).replaceAll('-', '%2D').replaceAll('.', '%2E');
157
+ }
158
+ function opaque(value) {
159
+ return createHash('sha256').update(value).digest('base64url');
160
+ }
161
+ function messageFile(timestamp, runId, kind) {
162
+ return `${timestamp}.${encodeURIComponent(runId)}.${kind}.txt`;
163
+ }
164
+ function parseMessageFile(file) {
165
+ const match = /^(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.\d{3}Z)\.(.+)\.(prompt|response)\.txt$/.exec(file);
166
+ if (match === null)
167
+ return undefined;
168
+ const [, fileTimestamp, encodedRunId, kind] = match;
169
+ if (fileTimestamp === undefined || encodedRunId === undefined || kind === undefined)
170
+ return undefined;
171
+ return {
172
+ timestamp: timestampFromFile(fileTimestamp),
173
+ runId: decodeURIComponent(encodedRunId),
174
+ kind: kind,
175
+ };
176
+ }
177
+ function parseGroup(id) {
178
+ const session = /^session--(.+)--(.+)$/.exec(id);
179
+ if (session?.[1] !== undefined && session[2] !== undefined) {
180
+ return { id, kind: TranscriptGroupKind.Session, cli: decodeURIComponent(session[1]) };
181
+ }
182
+ if (/^run--.+$/.test(id))
183
+ return { id, kind: TranscriptGroupKind.Run };
184
+ return undefined;
185
+ }
186
+ function timestampForFile(timestamp) {
187
+ return normaliseTimestamp(timestamp).replaceAll(':', '-');
188
+ }
189
+ function timestampFromFile(timestamp) {
190
+ return normaliseTimestamp(`${timestamp.slice(0, 13)}:${timestamp.slice(14, 16)}:${timestamp.slice(17)}`);
191
+ }
192
+ function normaliseTimestamp(timestamp) {
193
+ const parsed = new Date(timestamp);
194
+ if (Number.isNaN(parsed.getTime()))
195
+ throw new Error(`Invalid transcript timestamp: ${timestamp}`);
196
+ return parsed.toISOString();
197
+ }
198
+ function assertRetention(retentionMs) {
199
+ if (!Number.isInteger(retentionMs) || retentionMs < 0)
200
+ throw new Error('Transcript retention must be a non-negative integer');
201
+ }
202
+ function assertSegment(value, label) {
203
+ if (value.length === 0 ||
204
+ value === '.' ||
205
+ value === '..' ||
206
+ value.includes('/') ||
207
+ value.includes('\\')) {
208
+ throw new Error(`${label} must be a single filesystem segment`);
209
+ }
210
+ }
211
+ async function filesOrEmpty(directory) {
212
+ try {
213
+ return await readdir(directory);
214
+ }
215
+ catch (error) {
216
+ if (isMissing(error))
217
+ return [];
218
+ throw error;
219
+ }
220
+ }
221
+ function isMissing(error) {
222
+ return typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT';
223
+ }
@@ -0,0 +1,11 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ export async function writeTranscript(directory, runId, kind, text) {
4
+ await mkdir(directory, { recursive: true });
5
+ const path = join(directory, `${safe(runId)}.${kind}.txt`);
6
+ await writeFile(path, text, 'utf8');
7
+ return path;
8
+ }
9
+ function safe(value) {
10
+ return value.replace(/[^a-zA-Z0-9._-]/g, '-');
11
+ }
@@ -0,0 +1,19 @@
1
+ export class FakeWorkspaceProvider {
2
+ path;
3
+ branch;
4
+ requests = [];
5
+ constructor(path = '/fake/workspace', branch = 'wake/fake-work') {
6
+ this.path = path;
7
+ this.branch = branch;
8
+ }
9
+ async acquire(request) {
10
+ this.requests.push(request);
11
+ return {
12
+ workspaceId: `workspace-${this.requests.length}`,
13
+ path: this.path,
14
+ ...(this.branch === undefined ? {} : { branch: this.branch }),
15
+ mode: request.mode,
16
+ release: async () => { },
17
+ };
18
+ }
19
+ }
@@ -0,0 +1,241 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { access, mkdir, readdir, readFile, realpath, rm, writeFile } from 'node:fs/promises';
3
+ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
4
+ import { promisify } from 'node:util';
5
+ import { RunStatus, WorkspaceMode } from '../../contracts/vocabulary.js';
6
+ const exec = promisify(execFile);
7
+ export class GitWorkspaceProvider {
8
+ root;
9
+ resolver;
10
+ git;
11
+ markerRoot;
12
+ recoveryFileSystem;
13
+ constructor(root, resolver, git = async (arguments_) => {
14
+ await exec('git', arguments_);
15
+ }, recoveryFileSystem = {
16
+ remove: async (path) => rm(path, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }),
17
+ canonicalize: realpath,
18
+ }) {
19
+ this.root = root;
20
+ this.resolver = resolver;
21
+ this.git = git;
22
+ this.markerRoot = join(this.root, '.wake-workspace-ownership');
23
+ this.recoveryFileSystem = recoveryFileSystem;
24
+ }
25
+ async acquire(request) {
26
+ const locator = await this.resolver.cloneLocator(request.repositoryResource.resourceId);
27
+ const name = `${request.workItemId}-${request.mode}-${slug(locator)}`;
28
+ const path = resolve(this.root, name);
29
+ const markerPath = join(this.markerRoot, `${name}.json`);
30
+ await mkdir(dirname(markerPath), { recursive: true });
31
+ await writeFile(markerPath, JSON.stringify({
32
+ runId: request.runId,
33
+ workItemId: request.workItemId,
34
+ repositoryResourceId: request.repositoryResource.resourceId,
35
+ mode: request.mode,
36
+ workspaceId: name,
37
+ path,
38
+ }), 'utf8');
39
+ const existingWorkspace = await exists(join(path, '.git'));
40
+ if (!existingWorkspace) {
41
+ await mkdir(dirname(path), { recursive: true });
42
+ await this.git(['clone', locator, path]);
43
+ }
44
+ const branch = request.mode === WorkspaceMode.Branch ? request.workItemId : undefined;
45
+ if (branch !== undefined)
46
+ await this.git(['-C', path, 'switch', ...(existingWorkspace ? [] : ['--create']), branch]);
47
+ return {
48
+ workspaceId: name,
49
+ path,
50
+ mode: request.mode,
51
+ ...(branch === undefined ? {} : { branch }),
52
+ release: async () => {
53
+ if (request.mode !== WorkspaceMode.ReadOnly)
54
+ return;
55
+ await rm(path, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 });
56
+ await rm(markerPath, { force: true });
57
+ },
58
+ };
59
+ }
60
+ async recover(runs, options = {}) {
61
+ const scope = await recoveryScope(this.root, this.markerRoot);
62
+ if (scope === null)
63
+ return emptyRecovery();
64
+ const markers = await recoveryMarkerNames(this.markerRoot);
65
+ let reclaimed = 0;
66
+ const reclaimedWorkItemIds = [];
67
+ const failures = [];
68
+ for (const filename of markers) {
69
+ if (await options.isPaused?.())
70
+ break;
71
+ const result = await recoverMarker({
72
+ filename,
73
+ markerRoot: this.markerRoot,
74
+ scope,
75
+ runs,
76
+ fileSystem: this.recoveryFileSystem,
77
+ options,
78
+ });
79
+ reclaimed += result.reclaimed;
80
+ reclaimedWorkItemIds.push(...(result.reclaimedWorkItemIds ?? []));
81
+ failures.push(...result.failures);
82
+ }
83
+ return { reclaimed, reclaimedWorkItemIds, failures };
84
+ }
85
+ }
86
+ async function recoveryScope(root, markerRoot) {
87
+ const canonicalRoot = await canonicalPath(root);
88
+ const canonicalMarkerRoot = await canonicalPath(markerRoot);
89
+ if (canonicalRoot === null ||
90
+ canonicalMarkerRoot === null ||
91
+ !isStrictDescendant(canonicalRoot, canonicalMarkerRoot)) {
92
+ return null;
93
+ }
94
+ return { root: canonicalRoot, markerRoot: canonicalMarkerRoot };
95
+ }
96
+ async function recoveryMarkerNames(markerRoot) {
97
+ try {
98
+ return await readdir(markerRoot);
99
+ }
100
+ catch {
101
+ return [];
102
+ }
103
+ }
104
+ async function recoverMarker(input) {
105
+ if (!input.filename.endsWith('.json'))
106
+ return emptyRecovery();
107
+ const markerPath = join(input.markerRoot, input.filename);
108
+ const marker = await readMarker(markerPath);
109
+ try {
110
+ return await reclaimOwnedMarker(input, markerPath, marker);
111
+ }
112
+ catch (error) {
113
+ return {
114
+ reclaimed: 0,
115
+ failures: [{ markerPath, path: marker?.path ?? markerPath, message: errorMessage(error) }],
116
+ };
117
+ }
118
+ }
119
+ async function reclaimOwnedMarker(input, markerPath, marker) {
120
+ if (marker === null ||
121
+ !(await isOwnedWorkspace(input.scope, markerPath, marker, input.fileSystem)))
122
+ return emptyRecovery();
123
+ if (input.runs.some((run) => (run.status === RunStatus.Started || run.status === RunStatus.Ambiguous) &&
124
+ (run.runId === marker.runId || run.workspace?.path === marker.path)))
125
+ return emptyRecovery();
126
+ if ((await input.options.retainWorkItem?.(marker.workItemId)) === true)
127
+ return emptyRecovery();
128
+ if (!(await canRemoveOwnedWorkspace(input.scope, marker.path)))
129
+ return emptyRecovery();
130
+ if ((await canonicalPath(marker.path)) !== null)
131
+ await input.fileSystem.remove(marker.path);
132
+ if ((await input.options.onWorkspaceReclaimed?.(marker.workItemId)) === false)
133
+ return emptyRecovery();
134
+ await rm(markerPath, { force: true });
135
+ return {
136
+ reclaimed: 1,
137
+ reclaimedWorkItemIds: [marker.workItemId],
138
+ failures: [],
139
+ };
140
+ }
141
+ function emptyRecovery() {
142
+ return { reclaimed: 0, reclaimedWorkItemIds: [], failures: [] };
143
+ }
144
+ async function canRemoveOwnedWorkspace(scope, path) {
145
+ const canonicalTarget = await canonicalPath(path);
146
+ return (canonicalTarget === null ||
147
+ (isStrictDescendant(scope.root, canonicalTarget) &&
148
+ !isDescendantOrSame(scope.markerRoot, canonicalTarget)));
149
+ }
150
+ function errorMessage(error) {
151
+ return error instanceof Error ? error.message : String(error);
152
+ }
153
+ async function readMarker(path) {
154
+ try {
155
+ const value = JSON.parse(await readFile(path, 'utf8'));
156
+ if (!isOwnershipMarker(value))
157
+ return null;
158
+ return value;
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ }
164
+ function isOwnershipMarker(value) {
165
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
166
+ return false;
167
+ const marker = value;
168
+ return (typeof marker.runId === 'string' &&
169
+ typeof marker.workItemId === 'string' &&
170
+ typeof marker.repositoryResourceId === 'string' &&
171
+ (marker.mode === WorkspaceMode.ReadOnly || marker.mode === WorkspaceMode.Branch) &&
172
+ typeof marker.workspaceId === 'string' &&
173
+ typeof marker.path === 'string');
174
+ }
175
+ async function isOwnedWorkspace(scope, markerPath, marker, fileSystem) {
176
+ if (!isSafeWorkspaceId(marker.workspaceId))
177
+ return false;
178
+ if (basename(markerPath) !== `${marker.workspaceId}.json`)
179
+ return false;
180
+ if (!isAbsolute(marker.path))
181
+ return false;
182
+ const expectedPath = resolve(scope.root, marker.workspaceId);
183
+ if (resolve(marker.path) !== expectedPath)
184
+ return false;
185
+ if (!isStrictDescendant(scope.root, expectedPath))
186
+ return false;
187
+ if (isDescendantOrSame(scope.markerRoot, expectedPath))
188
+ return false;
189
+ const canonicalMarkerPath = await canonicalizeMarkerPath(fileSystem, markerPath);
190
+ if (canonicalMarkerPath === null)
191
+ return false;
192
+ return isStrictDescendant(scope.markerRoot, canonicalMarkerPath);
193
+ }
194
+ async function canonicalizeMarkerPath(fileSystem, path) {
195
+ try {
196
+ return await fileSystem.canonicalize(path);
197
+ }
198
+ catch (error) {
199
+ if (isNotFound(error))
200
+ return null;
201
+ throw error;
202
+ }
203
+ }
204
+ function isSafeWorkspaceId(value) {
205
+ return value !== '' && value !== '.' && value !== '..' && basename(value) === value;
206
+ }
207
+ function isStrictDescendant(root, target) {
208
+ const path = relative(root, target);
209
+ return path !== '' && !path.startsWith('..') && !isAbsolute(path);
210
+ }
211
+ function isDescendantOrSame(root, target) {
212
+ return root === target || isStrictDescendant(root, target);
213
+ }
214
+ async function canonicalPath(path) {
215
+ try {
216
+ return await realpath(path);
217
+ }
218
+ catch (error) {
219
+ if (isNotFound(error))
220
+ return null;
221
+ throw error;
222
+ }
223
+ }
224
+ function isNotFound(error) {
225
+ return typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT';
226
+ }
227
+ async function exists(path) {
228
+ try {
229
+ await access(path);
230
+ return true;
231
+ }
232
+ catch {
233
+ return false;
234
+ }
235
+ }
236
+ function slug(value) {
237
+ return value
238
+ .toLowerCase()
239
+ .replace(/[^a-z0-9]+/g, '-')
240
+ .replace(/^-|-$/g, '');
241
+ }
@@ -0,0 +1,111 @@
1
+ import { BuiltInActivityName } from '../../activities/index.js';
2
+ import { RunStatus } from '../../execution/index.js';
3
+ import { createEventDraft, EventActorKind, EventSourceKind, } from '../../kernel/index.js';
4
+ import { ApprovalAuthorityKind, isApprovalAwaitingSignalKind, OrchestrationEventType, OrchestrationStreamKind, WatchGateVerdictSignal, } from '../../orchestration/index.js';
5
+ import { ResourceCorrelationRole, resourceStream } from '../../resources/index.js';
6
+ import { DeliveryIntentEventType } from '../delivery/contracts/intents.js';
7
+ import { projectTerminalAgentRunReport } from './terminal-agent-run-report.js';
8
+ /** Projects terminal agent runs into one durable outbound intent per primary resource. */
9
+ export class AgentRunPublicationReactor {
10
+ dependencies;
11
+ constructor(dependencies) {
12
+ this.dependencies = dependencies;
13
+ }
14
+ async runOnce(limit = 100) {
15
+ const consumer = 'reactor:agent-run-publication';
16
+ const events = await this.dependencies.journal.readAll(await this.dependencies.checkpoints.load(consumer), limit);
17
+ for (const event of events) {
18
+ if (event.eventType === OrchestrationEventType.ActivityOutcomeAccepted)
19
+ await this.publishAcceptedOutcome(event.stream.id, event.payload.activationId, event.recordedAt, event.eventId, event.correlationId);
20
+ if (event.eventType === OrchestrationEventType.ActivityExecutionFailed)
21
+ await this.publish(event.payload.runId, event.recordedAt, event.eventId, event.correlationId);
22
+ await this.dependencies.checkpoints.save(consumer, event.globalPosition);
23
+ }
24
+ return events.length;
25
+ }
26
+ async publishAcceptedOutcome(workflowInstanceId, activationId, occurredAt, causationId, correlationId) {
27
+ const run = (await this.dependencies.runs.list(activationId)).find((candidate) => candidate.workflowInstanceId === workflowInstanceId &&
28
+ candidate.status === RunStatus.Succeeded &&
29
+ candidate.activity === BuiltInActivityName.Agent);
30
+ if (run === undefined)
31
+ return;
32
+ await this.publish(run.runId, occurredAt, causationId, correlationId);
33
+ }
34
+ async publish(id, occurredAt, causationId, correlationId) {
35
+ const run = (await this.dependencies.runs.load(id)).view;
36
+ if (run?.activity !== BuiltInActivityName.Agent || run.finishedAt === undefined)
37
+ return;
38
+ const allWorkflows = await this.dependencies.orchestration.listAll();
39
+ const workflow = allWorkflows.find((value) => value.workflowInstanceId === run.workflowInstanceId);
40
+ if (workflow === undefined)
41
+ return;
42
+ const primary = (await this.dependencies.resources.correlationsForWork(workflow.workItemId)).find((value) => value.role === ResourceCorrelationRole.Primary);
43
+ if (primary === undefined)
44
+ return;
45
+ const stage = await this.stageForActivation(workflow.workflowInstanceId, run.activationId);
46
+ const report = projectTerminalAgentRunReport(reportInput(run, stage, workflow, allWorkflows));
47
+ if (report === null)
48
+ return;
49
+ const stream = resourceStream(primary.resourceId);
50
+ const sequence = (await this.dependencies.journal.readStream(stream)).length;
51
+ try {
52
+ await this.dependencies.journal.append(stream, sequence, [
53
+ createEventDraft({
54
+ eventId: `agent-run:${run.runId}`,
55
+ eventType: DeliveryIntentEventType.AgentRunPublishRequested,
56
+ occurredAt,
57
+ correlationId: correlationId,
58
+ causationId: causationId,
59
+ actor: { kind: EventActorKind.Integration, id: 'agent-run-publication' },
60
+ source: { kind: EventSourceKind.Internal, id: 'agent-run-publication' },
61
+ stream,
62
+ payload: {
63
+ workflowInstanceId: run.workflowInstanceId,
64
+ activationId: run.activationId,
65
+ resourceId: primary.resourceId,
66
+ report,
67
+ },
68
+ }),
69
+ ]);
70
+ }
71
+ catch {
72
+ /* idempotency is the deterministic run event id */
73
+ }
74
+ }
75
+ async stageForActivation(workflowInstanceId, activationId) {
76
+ const events = await this.dependencies.journal.readStream({
77
+ kind: OrchestrationStreamKind.WorkflowInstance,
78
+ id: workflowInstanceId,
79
+ });
80
+ const request = events.findIndex((event) => event.eventType === OrchestrationEventType.ActivityRequested &&
81
+ event.payload.activationId === activationId);
82
+ for (let index = request - 1; index >= 0; index -= 1) {
83
+ const event = events[index];
84
+ if (event?.eventType === OrchestrationEventType.StageEntered)
85
+ return event.payload.stage;
86
+ }
87
+ return undefined;
88
+ }
89
+ }
90
+ function reportInput(run, stage, workflow, allWorkflows) {
91
+ const watchGateVerdict = watchGateVerdictFor(run, workflow, allWorkflows);
92
+ const isWaiting = workflow.waitingFor !== undefined &&
93
+ isApprovalAwaitingSignalKind(workflow.waitingFor.signalKind);
94
+ return {
95
+ run,
96
+ ...(stage === undefined ? {} : { stage }),
97
+ ...(isWaiting ? { awaitingApproval: true } : {}),
98
+ ...(watchGateVerdict === undefined ? {} : { watchGateVerdict }),
99
+ };
100
+ }
101
+ function watchGateVerdictFor(run, workflow, allWorkflows) {
102
+ if (run.agent?.outcome !== 'DONE' && run.agent?.outcome !== 'REJECTED')
103
+ return undefined;
104
+ if (workflow.parentWorkflowInstanceId === undefined || workflow.watchId === undefined)
105
+ return undefined;
106
+ const parent = allWorkflows.find((value) => value.workflowInstanceId === workflow.parentWorkflowInstanceId);
107
+ if (parent?.waitingFor?.signalKind !== WatchGateVerdictSignal)
108
+ return undefined;
109
+ const namesThisWatch = parent.waitingFor.from?.some((entry) => entry.kind === ApprovalAuthorityKind.Watch && entry.watch === workflow.watchId);
110
+ return namesThisWatch === true ? { runId: run.runId } : undefined;
111
+ }