@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,1233 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { z } from 'zod';
5
- import { reservedCommandNames } from './custom-commands.js';
6
- import { runnerSentinelValues } from './stages.js';
7
- import { correlationProvenanceSchema, correlationRelationSchema, correlationRoleSchema, resourceUriSchema, } from './resource-uri.js';
8
- import { runtimeEventTypeValues } from './runtime-events.js';
9
- import { alwaysManualIgnoredLabels } from './manual-labels.js';
10
- import { workItemStatusSchema } from './work-item-status.js';
11
- export { AUTONOMOUS_DECISION_AUDIT_EVENT, CORRELATION_PRIMARY_CONFLICT_EVENT, CORRELATION_REGISTERED_EVENT, CORRELATION_RETRACTED_EVENT, WORK_ITEM_CREATED_EVENT, } from './event-types.js';
12
- const isoTimestampSchema = z.string().datetime({ offset: true });
13
- const identifierSchema = z.string().min(1);
14
- export const reportedArtifactSchema = z.object({
15
- kind: z.literal('pr'),
16
- url: z.string().url(),
17
- });
18
- export const wakeArtifactsEnvelopeSchema = z.object({
19
- artifacts: z.array(reportedArtifactSchema).default([]),
20
- });
21
- export const runnerSentinelSchema = z.enum(runnerSentinelValues);
22
- // A projection persisted before ADR 0002 can still have context.lastRunSentinel
23
- // = "AWAITING_APPROVAL" on disk. That field is read (not just replayed) on
24
- // every ordinary parseIssueStateRecord call, not only during an explicit
25
- // event-log rebuild, so the strict current-vocabulary schema above would
26
- // reject an untouched legacy projection outright. This schema stays
27
- // permissive to that one retired value so existing on-disk state keeps
28
- // loading until it's naturally refreshed by a new run.
29
- const legacyTolerantRunnerSentinelSchema = z.enum([...runnerSentinelValues, 'AWAITING_APPROVAL']);
30
- export const executionOutcomeValues = [
31
- 'COMPLETED',
32
- 'STARTUP_FAILED',
33
- 'PROCESS_FAILED',
34
- 'TIMED_OUT',
35
- 'STALLED',
36
- 'CANCELED_BY_RECONCILIATION',
37
- 'CANCELED_BY_SOURCE_CLOSED',
38
- 'CANCELED_BY_UNASSIGNMENT',
39
- 'CANCELED_BY_SUPERSEDING_EVENT',
40
- 'CANCELED_BY_WORKFLOW_CHANGE',
41
- 'CANCELED_BY_OPERATOR',
42
- 'QUOTA_EXHAUSTED',
43
- 'MALFORMED_OUTPUT',
44
- 'SUPERSEDED',
45
- ];
46
- export const workflowOutcomeValues = [
47
- 'DONE',
48
- 'BLOCKED',
49
- 'AWAITING_APPROVAL',
50
- 'AWAITING_INPUT',
51
- 'CHANGES_REQUESTED',
52
- ];
53
- export const executionAttemptLifecycleValues = [
54
- 'CREATED',
55
- 'CLAIMED',
56
- 'PREPARING',
57
- 'PROCESS_STARTING',
58
- 'RUNNING',
59
- 'FINALISING',
60
- 'TERMINAL',
61
- ];
62
- export const executionOutcomeSchema = z.enum(executionOutcomeValues);
63
- export const workflowOutcomeSchema = z.enum(workflowOutcomeValues);
64
- export const executionAttemptLifecycleSchema = z.enum(executionAttemptLifecycleValues);
65
- export const runtimeEventSchema = z.object({
66
- type: z.enum(runtimeEventTypeValues),
67
- runId: z.string(),
68
- workItemId: z.string(),
69
- runner: z.object({
70
- name: z.string(),
71
- kind: z.enum(['fake', 'claude', 'codex', 'cursor']),
72
- cli: z.string(),
73
- model: z.string().optional(),
74
- }),
75
- sessionId: z.string().optional(),
76
- timestamp: isoTimestampSchema,
77
- sequence: z.number().int().nonnegative(),
78
- payload: z.record(z.string(), z.unknown()).default({}),
79
- });
80
- export const defaultAgentIdentity = 'Wake';
81
- export const defaultSmokePrompt = `This is ${defaultAgentIdentity}, reply with "hi ${defaultAgentIdentity} only"`;
82
- const claudeEffortSchema = z.enum(['low', 'medium', 'high', 'xhigh', 'max']);
83
- const codexReasoningEffortSchema = z.enum(['low', 'medium', 'high']);
84
- const cursorModeSchema = z.enum(['ask', 'agent']);
85
- const claudeRunnerSettingsSchema = z.object({
86
- command: z.string().default('claude'),
87
- model: z.string().default('haiku'),
88
- smokeModel: z.string().default('haiku'),
89
- sessionName: z.string().default(defaultAgentIdentity),
90
- remoteControlName: z.string().default(defaultAgentIdentity),
91
- smokePrompt: z.string().default(defaultSmokePrompt),
92
- timeoutMs: z
93
- .number()
94
- .int()
95
- .positive()
96
- .default(30 * 60 * 1000),
97
- remoteControl: z
98
- .object({
99
- enabled: z.boolean().default(false),
100
- })
101
- .default({ enabled: false }),
102
- effort: claudeEffortSchema.optional(),
103
- });
104
- const codexRunnerSettingsSchema = z.object({
105
- command: z.string().default('codex'),
106
- model: z.string().default('gpt-5.5'),
107
- smokeModel: z.string().default('gpt-5.4-mini'),
108
- smokePrompt: z.string().default(defaultSmokePrompt),
109
- timeoutMs: z
110
- .number()
111
- .int()
112
- .positive()
113
- .default(30 * 60 * 1000),
114
- reasoningEffort: codexReasoningEffortSchema.optional(),
115
- });
116
- const fakeRunnerEntrySchema = z.object({
117
- kind: z.literal('fake'),
118
- cli: z.string().default('Fake'),
119
- });
120
- const claudeRunnerEntrySchema = claudeRunnerSettingsSchema.extend({
121
- kind: z.literal('claude'),
122
- });
123
- const codexRunnerEntrySchema = codexRunnerSettingsSchema.extend({
124
- kind: z.literal('codex'),
125
- });
126
- const cursorRunnerSettingsSchema = z.object({
127
- command: z.string().default('cursor'),
128
- model: z.string().default('composer-2.5'),
129
- smokeModel: z.string().default('auto'),
130
- smokePrompt: z.string().default(defaultSmokePrompt),
131
- timeoutMs: z
132
- .number()
133
- .int()
134
- .positive()
135
- .default(30 * 60 * 1000),
136
- defaultMode: cursorModeSchema.optional(),
137
- });
138
- const cursorRunnerEntrySchema = cursorRunnerSettingsSchema.extend({
139
- kind: z.literal('cursor'),
140
- });
141
- const runnerEntrySchema = z.discriminatedUnion('kind', [
142
- fakeRunnerEntrySchema,
143
- claudeRunnerEntrySchema,
144
- codexRunnerEntrySchema,
145
- cursorRunnerEntrySchema,
146
- ]);
147
- const stageRouteSchema = z.object({
148
- action: identifierSchema.optional(),
149
- tier: z.string().optional(),
150
- runner: z.string().optional(),
151
- promptContext: z.record(z.string(), z.unknown()).optional(),
152
- });
153
- const runnerRoutingSchema = z.object({
154
- runnerName: z.string(),
155
- runnerKind: z.enum(['fake', 'claude', 'codex', 'cursor']),
156
- tier: z.string().optional(),
157
- reason: z.string(),
158
- });
159
- const sinkEntrySchema = z
160
- .object({
161
- kind: z.string().min(1),
162
- subscribe: z.array(z.string().min(1)).default([]),
163
- })
164
- .passthrough();
165
- export const wakeResultEnvelopeSchema = z.object({
166
- status: runnerSentinelSchema,
167
- });
168
- const stageHistoryEntrySchema = z.object({
169
- stage: identifierSchema,
170
- changedAt: isoTimestampSchema,
171
- reason: z.string(),
172
- });
173
- const reviewThreadAnchorSchema = z.object({
174
- path: z.string(),
175
- line: z.number().int().positive().optional(),
176
- });
177
- const commentSnapshotSchema = z.object({
178
- id: z.string(),
179
- body: z.string(),
180
- author: z.object({
181
- login: z.string(),
182
- }),
183
- createdAt: isoTimestampSchema,
184
- updatedAt: isoTimestampSchema,
185
- isBotAuthored: z.boolean().default(false),
186
- // Which correlated surface this comment came from; absent = the originating
187
- // issue thread, keeping every pre-existing comment valid under this schema.
188
- resourceUri: resourceUriSchema.optional(),
189
- reviewThread: reviewThreadAnchorSchema.optional(),
190
- });
191
- const issueSnapshotSchema = z.object({
192
- repo: z.string(),
193
- number: z.number().int().positive(),
194
- title: z.string(),
195
- body: z.string(),
196
- labels: z.array(z.string()),
197
- assignees: z.array(z.string()),
198
- isPullRequest: z.boolean().default(false),
199
- state: z.enum(['open', 'closed']),
200
- url: z.string().url(),
201
- createdAt: isoTimestampSchema,
202
- updatedAt: isoTimestampSchema,
203
- });
204
- export const sourceStateRecordSchema = z.object({
205
- schemaVersion: z.literal(1),
206
- source: z.string(),
207
- key: z.string(),
208
- lastSuccessfulPollAt: isoTimestampSchema,
209
- });
210
- export const eventEnvelopeSourceRefsSchema = z.object({
211
- repo: z.string().optional(),
212
- issueNumber: z.number().int().positive().optional(),
213
- commentId: z.string().optional(),
214
- reviewId: z.string().optional(),
215
- runId: z.string().optional(),
216
- sink: z.string().optional(),
217
- sourceUrl: z.string().optional(),
218
- // Per-event provenance: which external resource this one event came from.
219
- // Item-level ownership lives only in the correlation registry, never here.
220
- resourceUri: resourceUriSchema.optional(),
221
- // An adapter-supplied hint: the resourceUri of the resource this one
222
- // "belongs to" for correlation purposes (e.g. a PR review-thread comment's
223
- // parent PR). Opaque to core — never parsed, only used as a fallback key
224
- // for resourceIndex.resolve() when resourceUri itself misses the index.
225
- // The adapter that emits an event is the only party allowed to know its
226
- // own locator grammar; this keeps that knowledge out of core/.
227
- parentResourceUri: resourceUriSchema.optional(),
228
- });
229
- /**
230
- * Shared key for events whose resource failed mint qualification (spec D1').
231
- * Never a real work item: `readIssueState(UNRESOLVED_WORK_ITEM_KEY)` always
232
- * returns null, so these events are durable and inspectable via the event
233
- * log but must never materialize a projection or an index entry. Exported
234
- * from here (rather than only living in tick-runner.ts, which mints these
235
- * events) so projection-updater.ts's fold can also recognize and skip it —
236
- * an unqualified event's sourceEventType is still `ticket.upsert` /
237
- * `fake.issue.upsert` / etc., which the fold would otherwise happily turn
238
- * into a projection the first time it sees this key with no current record.
239
- */
240
- export const UNRESOLVED_WORK_ITEM_KEY = 'unresolved';
241
- // The envelope's `workItemKey` already carries the identity; this payload is
242
- // deliberately empty.
243
- export const workItemCreatedPayloadSchema = z.object({});
244
- export const correlationRegisteredPayloadSchema = z.object({
245
- resourceUri: resourceUriSchema,
246
- role: correlationRoleSchema,
247
- relation: correlationRelationSchema,
248
- provenance: correlationProvenanceSchema,
249
- registeredBy: z.string().optional(),
250
- });
251
- export const correlationRetractedPayloadSchema = z.object({
252
- resourceUri: resourceUriSchema,
253
- });
254
- // Warning event emitted when a second `primary` registration lands on an
255
- // already-claimed URI (ADR 0001 §6). Fold behavior lives in the projection.
256
- export const correlationPrimaryConflictPayloadSchema = z.object({
257
- resourceUri: resourceUriSchema,
258
- incumbentWorkItemKey: z.string(),
259
- });
260
- // Folded shape of a `wake.correlation.registered`/`wake.correlation.retracted`
261
- // event, one entry per resourceUri currently held by this work item
262
- // (ADR 0001 §5). `registeredAt` comes from the folding event's `occurredAt`.
263
- export const correlatedResourceSchema = z.object({
264
- resourceUri: resourceUriSchema,
265
- role: correlationRoleSchema,
266
- relation: correlationRelationSchema,
267
- provenance: correlationProvenanceSchema,
268
- registeredBy: z.string().optional(),
269
- registeredAt: isoTimestampSchema,
270
- });
271
- export const eventEnvelopeSchema = z.object({
272
- schemaVersion: z.literal(1),
273
- eventId: z.string(),
274
- workItemKey: z.string(),
275
- streamScope: z.enum(['global-intake', 'work-item']),
276
- direction: z.enum(['inbound', 'outbound', 'internal']),
277
- sourceSystem: z.string(),
278
- sourceEventType: z.string(),
279
- sourceRefs: eventEnvelopeSourceRefsSchema,
280
- occurredAt: isoTimestampSchema,
281
- ingestedAt: isoTimestampSchema,
282
- trigger: z.enum(['immediate', 'context-only']),
283
- payload: z.record(z.string(), z.unknown()),
284
- raw: z.record(z.string(), z.unknown()).optional(),
285
- derivedHints: z.record(z.string(), z.unknown()).optional(),
286
- });
287
- export const failurePhaseSchema = z.enum([
288
- 'workspace-validation',
289
- 'workspace-prep',
290
- 'process-starting',
291
- 'running',
292
- 'result-parsing',
293
- 'publishing',
294
- 'unknown',
295
- ]);
296
- export const externalSideEffectsSchema = z.enum(['none', 'confirmed', 'unknown']);
297
- export const retrySafetySchema = z.enum([
298
- 'SAFE_TO_RETRY',
299
- 'SAFE_TO_RESUME',
300
- 'REQUIRES_RECONCILIATION',
301
- 'MANUAL_REVIEW_REQUIRED',
302
- 'NOT_RETRYABLE',
303
- ]);
304
- // Typed `context` — every field is optional so an on-disk projection missing
305
- // some/all of them (pre-dating this schema, or simply untouched since) still
306
- // parses. See docs/superpowers/specs/2026-07-28-canonical-work-item-status-design.md §4/§8.
307
- export const issueContextSchema = z.object({
308
- // Retry/failure bookkeeping, folded from RUN_COMPLETED (projection-updater.ts).
309
- failureCount: z.number().int().nonnegative().optional(),
310
- lastRunAction: z.string().optional(),
311
- lastCompletedAction: z.string().optional(),
312
- lastExecutionOutcome: executionOutcomeSchema.optional(),
313
- lastWorkflowOutcome: workflowOutcomeSchema.optional(),
314
- lastFailurePhase: failurePhaseSchema.optional(),
315
- lastProcessStarted: z.boolean().optional(),
316
- lastWorkspaceChanged: z.boolean().optional(),
317
- lastExternalSideEffects: externalSideEffectsSchema.optional(),
318
- lastRetrySafety: retrySafetySchema.optional(),
319
- blockedFromStage: z.string().optional(),
320
- lastFailureClass: z.enum(['task', 'quota', 'infra']).optional(),
321
- lastHandledCommentId: z.string().optional(),
322
- lastRunSentinel: legacyTolerantRunnerSentinelSchema.optional(),
323
- // Set while approval-gated (context.status === 'awaiting-approval') so the
324
- // approval path knows which action to resume (or skip) once a human responds.
325
- pendingApprovalAction: z.string().optional(),
326
- pendingApprovalAllowAutoApproval: z.boolean().optional(),
327
- // Workflow pinned at mint time (WORKFLOW_SELECTED_EVENT); re-read at every
328
- // label write instead of trusting a threaded local (workflow-name-drift, §6).
329
- workflow: z.string().optional(),
330
- // Canonical status — see work-item-status.ts. Additive alongside
331
- // lastRunSentinel, not a replacement for it (§3).
332
- status: workItemStatusSchema.optional(),
333
- changesRequestedCount: z.number().int().nonnegative().optional(),
334
- // Feedback body threaded into the next auto-revise prompt as
335
- // promptContextOverrides.parentPendingReviewBody (§5).
336
- changesRequestedFeedback: z.string().optional(),
337
- // Orthogonal facts — not folded into `status` (§2).
338
- frozen: z.object({ at: isoTimestampSchema, by: z.string() }).optional(),
339
- deleted: z.object({ at: isoTimestampSchema, by: z.string() }).optional(),
340
- scheduled: z.boolean().optional(),
341
- });
342
- export const issueStateRecordSchema = z.object({
343
- schemaVersion: z.literal(1),
344
- workItemKey: z.string(),
345
- origin: z.string().optional(),
346
- issue: issueSnapshotSchema,
347
- comments: z.array(commentSnapshotSchema).default([]),
348
- latestComment: commentSnapshotSchema.optional(),
349
- wake: z.object({
350
- stage: identifierSchema,
351
- lastRunId: z.string().optional(),
352
- sessionId: z.string().optional(),
353
- sessionCli: z.string().optional(),
354
- workspacePath: z.string().optional(),
355
- blockReason: z.string().optional(),
356
- syncedAt: isoTimestampSchema,
357
- stageHistory: z.array(stageHistoryEntrySchema),
358
- recentEventIds: z.array(z.string()).default([]),
359
- expectedEcho: z
360
- .object({
361
- commentIds: z.array(z.string()).default([]),
362
- labels: z.array(z.string()).default([]),
363
- })
364
- .default({ commentIds: [], labels: [] }),
365
- }),
366
- context: issueContextSchema.default({}),
367
- correlatedResources: z.array(correlatedResourceSchema).default([]),
368
- });
369
- export const runInputSnapshotSchema = z.object({
370
- schemaVersion: z.literal(1),
371
- snapshotId: z.string(),
372
- runId: z.string(),
373
- createdAt: isoTimestampSchema,
374
- action: identifierSchema,
375
- workflowName: identifierSchema,
376
- claimedStage: identifierSchema,
377
- projectionVersion: z.string(),
378
- sourceUpdatedAt: isoTimestampSchema,
379
- sourceRevision: z.string(),
380
- triggerEventId: z.string().optional(),
381
- handledThroughEventId: z.string().optional(),
382
- workflowHash: z.string(),
383
- promptHash: z.string(),
384
- repositoryHead: z.string().optional(),
385
- workspaceHead: z.string().optional(),
386
- runnerConfigurationHash: z.string(),
387
- projection: issueStateRecordSchema,
388
- recentEvents: z.array(eventEnvelopeSchema),
389
- });
390
- const runTokenUsageSchema = z.object({
391
- inputTokens: z.number().nonnegative(),
392
- outputTokens: z.number().nonnegative(),
393
- cacheCreationInputTokens: z.number().nonnegative().optional(),
394
- cacheReadInputTokens: z.number().nonnegative().optional(),
395
- costUsd: z.number().nonnegative().optional(),
396
- turns: z.number().nonnegative().optional(),
397
- });
398
- const runLeaseSchema = z.object({
399
- leaseId: z.string(),
400
- ownerInstanceId: z.string(),
401
- acquiredAt: isoTimestampSchema,
402
- lastRenewedAt: isoTimestampSchema,
403
- expiresAt: isoTimestampSchema,
404
- });
405
- function legacyRunLifecycle(input) {
406
- if (input.lifecycle !== undefined) {
407
- return input;
408
- }
409
- return {
410
- ...input,
411
- lifecycle: input.status === 'running' ? 'RUNNING' : 'TERMINAL',
412
- };
413
- }
414
- export const runRecordSchema = z.preprocess((input) => {
415
- return input !== null && typeof input === 'object'
416
- ? legacyRunLifecycle(input)
417
- : input;
418
- }, z.object({
419
- schemaVersion: z.literal(1),
420
- runId: z.string(),
421
- // The work item this run belongs to. Required: run records are Wake-owned
422
- // state that Wake itself writes, so the work id is always in hand at the
423
- // write site, and an optional key would lie about runtime while re-admitting
424
- // the ticket-shaped ambiguity minted identity exists to remove.
425
- workItemKey: z.string(),
426
- // Human-readable representation content only — the ticket this run was
427
- // launched against (same reasoning as the projection's retained `issue`
428
- // snapshot, spec §9). Never used to find the work item: a transferred issue
429
- // gets a new repo/number while the work item and its runs persist (spec D3).
430
- repo: z.string(),
431
- issueNumber: z.number().int().positive(),
432
- action: identifierSchema,
433
- lifecycle: executionAttemptLifecycleSchema,
434
- status: z.enum([
435
- 'running',
436
- 'completed',
437
- 'awaiting-approval',
438
- 'rejected',
439
- 'blocked',
440
- 'failed',
441
- 'superseded',
442
- ]),
443
- startedAt: isoTimestampSchema,
444
- finishedAt: isoTimestampSchema.optional(),
445
- sessionId: z.string().optional(),
446
- sentinel: legacyTolerantRunnerSentinelSchema.optional(),
447
- executionOutcome: executionOutcomeSchema.optional(),
448
- workflowOutcome: workflowOutcomeSchema.optional(),
449
- failurePhase: failurePhaseSchema.optional(),
450
- processStarted: z.boolean().optional(),
451
- workspaceChanged: z.boolean().optional(),
452
- externalSideEffects: externalSideEffectsSchema.optional(),
453
- retrySafety: retrySafetySchema.optional(),
454
- summary: z.string().optional(),
455
- inputSnapshotId: z.string().optional(),
456
- routing: runnerRoutingSchema.optional(),
457
- lease: runLeaseSchema.optional(),
458
- workerPid: z.number().int().positive().optional(),
459
- workerProcessStartedAt: z.string().optional(),
460
- agentPid: z.number().int().positive().optional(),
461
- agentProcessStartedAt: z.string().optional(),
462
- lastMeaningfulActivityAt: isoTimestampSchema.optional(),
463
- runtimeEvents: z.array(runtimeEventSchema).optional(),
464
- tokenUsage: runTokenUsageSchema.optional(),
465
- metadata: z.record(z.string(), z.unknown()).optional(),
466
- }));
467
- const runnerHealthEntrySchema = z.object({
468
- pausedUntil: isoTimestampSchema.optional(),
469
- // 'reported' = CLI told us the real reset time; 'estimated' = exponential
470
- // backoff guess. Only 'estimated' pauses are eligible for an early recovery
471
- // probe (domain/runner-routing.ts) - a reported time is already trustworthy.
472
- pausedUntilSource: z.enum(['reported', 'estimated']).optional(),
473
- failureCount: z.number().int().nonnegative().default(0),
474
- lastFailureAt: isoTimestampSchema.optional(),
475
- });
476
- const workflowWorkspaceSchema = z.enum(['none', 'read-only', 'branch']);
477
- const workflowTriggerScheduleSchema = z.object({
478
- cron: z.string().min(1),
479
- });
480
- // Matches GitHub's PullRequestMergeMethod GraphQL enum. GitHub's
481
- // enablePullRequestAutoMerge mutation defaults to MERGE when unspecified,
482
- // which fails outright on a repo that only allows squash/rebase merges — so
483
- // this must be explicit rather than inferred.
484
- export const mergeMethodSchema = z.enum(['MERGE', 'SQUASH', 'REBASE']);
485
- const approvedMergePolicySchema = z
486
- .object({
487
- approve: z.boolean().default(false),
488
- autoMerge: z.boolean().default(false),
489
- mergeMethod: mergeMethodSchema.default('MERGE'),
490
- maxFilesChanged: z.number().int().positive().optional(),
491
- blockedPaths: z.array(z.string().min(1)).default([]),
492
- blockedLabels: z.array(z.string().min(1)).default([]),
493
- })
494
- .default({
495
- approve: false,
496
- autoMerge: false,
497
- mergeMethod: 'MERGE',
498
- blockedPaths: [],
499
- blockedLabels: [],
500
- });
501
- const watchSuccessPolicySchema = z.object({
502
- // Resolve the watched parent stage's pending approval gate when the child
503
- // workflow run completes DONE — the child's sentinel is its verdict.
504
- approve: z.boolean().default(false),
505
- merge: approvedMergePolicySchema.optional(),
506
- });
507
- const workflowStageSchema = stageRouteSchema.extend({
508
- workspace: workflowWorkspaceSchema,
509
- onDone: identifierSchema,
510
- watch: z
511
- .array(z.object({
512
- while: z.object({
513
- status: z.array(z.string().min(1)).min(1),
514
- }),
515
- on: z
516
- .object({
517
- event: z.array(z.string().min(1)).min(1),
518
- })
519
- .optional(),
520
- schedule: workflowTriggerScheduleSchema.optional(),
521
- workflow: identifierSchema,
522
- onSuccess: watchSuccessPolicySchema.optional(),
523
- }))
524
- .optional(),
525
- });
526
- const workflowTriggerSchema = z.object({
527
- schedule: workflowTriggerScheduleSchema.optional(),
528
- });
529
- const customCommandSchema = stageRouteSchema.extend({
530
- workspace: workflowWorkspaceSchema.default('read-only'),
531
- });
532
- const workflowDefinitionSchema = z.object({
533
- entryStage: identifierSchema.optional(),
534
- trigger: workflowTriggerSchema.optional(),
535
- stages: z.record(identifierSchema, workflowStageSchema),
536
- });
537
- const workflowSelectorMatchSchema = z
538
- .object({
539
- kind: z.string().min(1).optional(),
540
- sourceEventType: z.string().min(1).optional(),
541
- repo: z.string().min(1).optional(),
542
- requiredLabels: z.array(z.string()).default([]),
543
- ignoredLabels: z.array(z.string()).default([]),
544
- requiredAssignees: z.array(z.string()).default([]),
545
- requiredAuthors: z.array(z.string()).default([]),
546
- })
547
- .default({
548
- requiredLabels: [],
549
- ignoredLabels: [],
550
- requiredAssignees: [],
551
- requiredAuthors: [],
552
- });
553
- const workflowSelectorSchema = z.object({
554
- workflow: identifierSchema,
555
- match: workflowSelectorMatchSchema,
556
- });
557
- function defaultPromptsRoot() {
558
- const sourceDir = dirname(fileURLToPath(import.meta.url));
559
- for (const candidate of [
560
- join(process.cwd(), 'prompts'),
561
- join(sourceDir, '..', '..', 'prompts'),
562
- join(sourceDir, '..', '..', '..', 'prompts'),
563
- ]) {
564
- if (existsSync(candidate)) {
565
- return candidate;
566
- }
567
- }
568
- let dir = sourceDir;
569
- for (let depth = 0; depth < 8; depth += 1) {
570
- if (existsSync(join(dir, 'package.json'))) {
571
- return join(dir, 'prompts');
572
- }
573
- const parent = dirname(dir);
574
- if (parent === dir) {
575
- break;
576
- }
577
- dir = parent;
578
- }
579
- return join(process.cwd(), 'prompts');
580
- }
581
- function promptExists(promptsRoot, stageOrAction) {
582
- return (existsSync(join(promptsRoot, `${stageOrAction}.md`)) ||
583
- existsSync(join(promptsRoot, `${stageOrAction}.start.md`)) ||
584
- existsSync(join(promptsRoot, `${stageOrAction}.resume.md`)));
585
- }
586
- function canReachDone(start, stages) {
587
- const seen = new Set();
588
- let current = start;
589
- while (current !== 'done') {
590
- if (seen.has(current)) {
591
- return false;
592
- }
593
- seen.add(current);
594
- const next = stages[current]?.onDone;
595
- if (next === undefined) {
596
- return false;
597
- }
598
- current = next;
599
- }
600
- return true;
601
- }
602
- export const ledgerSchema = z.object({
603
- schemaVersion: z.literal(1),
604
- // Legacy single-runner pause fields, superseded by `runners` (per-runner
605
- // health, #67). Kept read-only so ledgers written before the fallback/rotation
606
- // change still parse; nothing writes them anymore.
607
- pausedUntil: isoTimestampSchema.optional(),
608
- quotaFailureCount: z.number().int().nonnegative().optional(),
609
- lastQuotaFailureAt: isoTimestampSchema.optional(),
610
- runners: z.record(z.string(), runnerHealthEntrySchema).default({}),
611
- });
612
- const wakeConfigBaseSchema = z.object({
613
- schemaVersion: z.literal(1).default(1),
614
- paths: z.object({
615
- wakeRoot: z.string(),
616
- promptsRoot: z.string().optional(),
617
- }),
618
- sandbox: z
619
- .object({
620
- image: z.string().min(1).default('wake-sandbox'),
621
- // Base image name (no tag) that `wake sandbox self-update` appends a
622
- // release tag to, e.g. "wake-sandbox:v0.0.80". `image` above stays the
623
- // resolved ref that `build`/`up`/`update` actually run.
624
- imageRepository: z.string().min(1).default('wake-sandbox'),
625
- containerName: z.string().min(1).default('wake-sandbox'),
626
- containerMountPath: z.string().min(1).default('/wake'),
627
- containerHomeMountPath: z.string().min(1).default('/home/wake'),
628
- start: z
629
- .object({
630
- enabled: z.boolean().default(true),
631
- })
632
- .default({ enabled: true }),
633
- extraMounts: z
634
- .array(z.object({
635
- source: z.string().min(1),
636
- target: z.string().min(1),
637
- readOnly: z.boolean().optional(),
638
- }))
639
- .default([]),
640
- })
641
- .default({
642
- image: 'wake-sandbox',
643
- imageRepository: 'wake-sandbox',
644
- containerName: 'wake-sandbox',
645
- containerMountPath: '/wake',
646
- containerHomeMountPath: '/home/wake',
647
- start: { enabled: true },
648
- extraMounts: [],
649
- }),
650
- dev: z
651
- .object({
652
- repoRoot: z.string().optional(),
653
- mode: z.enum(['source', 'packaged']).optional(),
654
- })
655
- .default({}),
656
- scheduler: z
657
- .object({
658
- intervalMs: z
659
- .number()
660
- .int()
661
- .positive()
662
- .default(60 * 1000),
663
- // Cap for the idle-cadence backoff (#81): consecutive idle ticks double the
664
- // sleep, up to this ceiling, so a quiet repo doesn't poll every intervalMs.
665
- maxIntervalMs: z
666
- .number()
667
- .int()
668
- .positive()
669
- .default(5 * 60 * 1000),
670
- // Deterministic circuit breaker independent of any specific dispatch-eligibility
671
- // bug: caps total runner invocations (main path + watchers) in a trailing
672
- // window, counted from durable run records, not in-memory state. A storm
673
- // (stuck watcher, misconfigured cron, dedupe bug) hits this ceiling and idles
674
- // instead of compounding cost indefinitely.
675
- dispatchRateLimit: z
676
- .object({
677
- windowMs: z
678
- .number()
679
- .int()
680
- .positive()
681
- .default(60 * 60 * 1000),
682
- maxDispatches: z.number().int().positive().default(20),
683
- })
684
- .default({ windowMs: 60 * 60 * 1000, maxDispatches: 20 }),
685
- })
686
- .default({
687
- intervalMs: 60 * 1000,
688
- maxIntervalMs: 5 * 60 * 1000,
689
- dispatchRateLimit: { windowMs: 60 * 60 * 1000, maxDispatches: 20 },
690
- }),
691
- transcripts: z
692
- .object({
693
- enabled: z.boolean().default(false),
694
- retentionMs: z
695
- .number()
696
- .int()
697
- .nonnegative()
698
- .default(3 * 24 * 60 * 60 * 1000),
699
- })
700
- .default({ enabled: false, retentionMs: 3 * 24 * 60 * 60 * 1000 }),
701
- retry: z
702
- .object({
703
- maxFailureRetries: z.number().int().positive().default(5),
704
- maxChangesRequestedRetries: z.number().int().positive().default(3),
705
- })
706
- .default({ maxFailureRetries: 5, maxChangesRequestedRetries: 3 }),
707
- runners: z.record(z.string(), runnerEntrySchema).default({
708
- fake: { kind: 'fake', cli: 'Fake' },
709
- 'claude-haiku': {
710
- kind: 'claude',
711
- command: 'claude',
712
- model: 'haiku',
713
- smokeModel: 'haiku',
714
- sessionName: defaultAgentIdentity,
715
- remoteControlName: defaultAgentIdentity,
716
- smokePrompt: defaultSmokePrompt,
717
- timeoutMs: 30 * 60 * 1000,
718
- remoteControl: { enabled: false },
719
- },
720
- 'claude-opus': {
721
- kind: 'claude',
722
- command: 'claude',
723
- model: 'claude-opus-4-8',
724
- smokeModel: 'haiku',
725
- sessionName: defaultAgentIdentity,
726
- remoteControlName: defaultAgentIdentity,
727
- smokePrompt: defaultSmokePrompt,
728
- timeoutMs: 30 * 60 * 1000,
729
- remoteControl: { enabled: false },
730
- },
731
- 'codex-mini': {
732
- kind: 'codex',
733
- command: 'codex',
734
- model: 'gpt-5.4-mini',
735
- smokeModel: 'gpt-5.4-mini',
736
- smokePrompt: defaultSmokePrompt,
737
- timeoutMs: 30 * 60 * 1000,
738
- },
739
- 'codex-flagship': {
740
- kind: 'codex',
741
- command: 'codex',
742
- model: 'gpt-5.5',
743
- smokeModel: 'gpt-5.4-mini',
744
- smokePrompt: defaultSmokePrompt,
745
- timeoutMs: 30 * 60 * 1000,
746
- },
747
- 'cursor-composer': {
748
- kind: 'cursor',
749
- command: 'cursor',
750
- model: 'composer-2.5',
751
- smokeModel: 'auto',
752
- smokePrompt: defaultSmokePrompt,
753
- timeoutMs: 30 * 60 * 1000,
754
- },
755
- }),
756
- tiers: z.record(z.string(), z.array(z.string().min(1)).min(1)).default({
757
- light: ['fake'],
758
- standard: ['fake'],
759
- deep: ['fake'],
760
- }),
761
- defaultTier: z.string().default('standard'),
762
- workflows: z.record(identifierSchema, workflowDefinitionSchema).default({
763
- default: {
764
- stages: {
765
- refine: {
766
- action: 'refine',
767
- workspace: 'read-only',
768
- tier: 'light',
769
- onDone: 'implement',
770
- },
771
- implement: {
772
- action: 'implement',
773
- workspace: 'branch',
774
- tier: 'standard',
775
- onDone: 'done',
776
- },
777
- },
778
- },
779
- triage: {
780
- trigger: {
781
- schedule: {
782
- cron: '*/10 * * * *',
783
- },
784
- },
785
- stages: {
786
- assign: {
787
- action: 'triage-assign',
788
- workspace: 'none',
789
- tier: 'light',
790
- onDone: 'done',
791
- promptContext: {
792
- triageCapacityAvailable: true,
793
- triageWipCapDescription: 'Wake has no active running work item at triage start; do not assign more than one issue.',
794
- },
795
- },
796
- },
797
- },
798
- }),
799
- workflowSelectors: z.array(workflowSelectorSchema).default([]),
800
- commands: z.record(identifierSchema, customCommandSchema).default({
801
- ask: {
802
- action: 'ask',
803
- workspace: 'read-only',
804
- tier: 'light',
805
- },
806
- codereview: {
807
- action: 'codereview',
808
- workspace: 'read-only',
809
- tier: 'standard',
810
- },
811
- }),
812
- ui: z
813
- .object({
814
- enabled: z.boolean().default(false),
815
- port: z.number().int().positive().default(4317),
816
- token: z.string().optional(),
817
- tunnel: z
818
- .object({
819
- enabled: z.boolean().default(false),
820
- authToken: z.string().optional(),
821
- })
822
- .default({ enabled: false }),
823
- archiveFreshnessDays: z.number().int().nonnegative().default(5),
824
- })
825
- .default({ enabled: false, port: 4317, tunnel: { enabled: false }, archiveFreshnessDays: 5 }),
826
- sources: z
827
- .object({
828
- github: z
829
- .object({
830
- enabled: z.boolean().default(false),
831
- repos: z.array(z.string().min(1)).default([]),
832
- polling: z
833
- .object({
834
- maxIssuesPerRepo: z.number().int().positive().default(25),
835
- commentPageSize: z.number().int().positive().default(25),
836
- lookbackMs: z.number().int().nonnegative().default(60_000),
837
- })
838
- .default({ maxIssuesPerRepo: 25, commentPageSize: 25, lookbackMs: 60_000 }),
839
- policy: z
840
- .object({
841
- requiredLabels: z.array(z.string()).default([]),
842
- ignoredLabels: z.array(z.string()).default([]),
843
- requiredAssignees: z.array(z.string()).default([]),
844
- })
845
- .default({ requiredLabels: [], ignoredLabels: [], requiredAssignees: [] }),
846
- publication: z
847
- .object({
848
- postStatusComments: z.boolean().default(true),
849
- activeLabel: z.string().optional(),
850
- })
851
- .default({ postStatusComments: true }),
852
- pullRequests: z
853
- .object({
854
- enabled: z.boolean().default(false),
855
- maxPullRequestsPerRepo: z.number().int().positive().default(25),
856
- commentPageSize: z.number().int().positive().default(25),
857
- checks: z
858
- .object({
859
- enabled: z.boolean().default(true),
860
- })
861
- .default({ enabled: true }),
862
- policy: z
863
- .object({
864
- requiredAuthors: z.array(z.string()).default([]),
865
- })
866
- .default({ requiredAuthors: [] }),
867
- })
868
- .default({
869
- enabled: false,
870
- maxPullRequestsPerRepo: 25,
871
- commentPageSize: 25,
872
- checks: { enabled: true },
873
- policy: { requiredAuthors: [] },
874
- }),
875
- })
876
- .default({
877
- enabled: false,
878
- repos: [],
879
- polling: { maxIssuesPerRepo: 25, commentPageSize: 25, lookbackMs: 60_000 },
880
- policy: { requiredLabels: [], ignoredLabels: [], requiredAssignees: [] },
881
- publication: { postStatusComments: true },
882
- pullRequests: {
883
- enabled: false,
884
- maxPullRequestsPerRepo: 25,
885
- commentPageSize: 25,
886
- checks: { enabled: true },
887
- policy: { requiredAuthors: [] },
888
- },
889
- }),
890
- })
891
- .default({
892
- github: {
893
- enabled: false,
894
- repos: [],
895
- polling: { maxIssuesPerRepo: 25, commentPageSize: 25, lookbackMs: 60_000 },
896
- policy: { requiredLabels: [], ignoredLabels: [], requiredAssignees: [] },
897
- publication: { postStatusComments: true },
898
- pullRequests: {
899
- enabled: false,
900
- maxPullRequestsPerRepo: 25,
901
- commentPageSize: 25,
902
- checks: { enabled: true },
903
- policy: { requiredAuthors: [] },
904
- },
905
- },
906
- }),
907
- sinks: z.record(z.string(), sinkEntrySchema).default({}),
908
- });
909
- export const wakeInfraConfigSchema = wakeConfigBaseSchema.pick({
910
- schemaVersion: true,
911
- paths: true,
912
- sandbox: true,
913
- dev: true,
914
- scheduler: true,
915
- transcripts: true,
916
- retry: true,
917
- ui: true,
918
- sources: true,
919
- sinks: true,
920
- });
921
- export const wakeWorkflowConfigSchema = wakeConfigBaseSchema.pick({
922
- runners: true,
923
- tiers: true,
924
- defaultTier: true,
925
- workflows: true,
926
- workflowSelectors: true,
927
- commands: true,
928
- });
929
- export const wakeConfigSchema = wakeConfigBaseSchema.superRefine((config, ctx) => {
930
- const promptsRoot = config.paths.promptsRoot ?? defaultPromptsRoot();
931
- const workflowEntries = Object.entries(config.workflows);
932
- const commandEntries = Object.entries(config.commands);
933
- if (workflowEntries.length === 0) {
934
- ctx.addIssue({
935
- code: z.ZodIssueCode.custom,
936
- path: ['workflows'],
937
- message: 'At least one workflow must be configured.',
938
- });
939
- }
940
- for (const [workflowName, workflow] of workflowEntries) {
941
- const stageNames = Object.keys(workflow.stages);
942
- const stageSet = new Set(stageNames);
943
- if (stageNames.length === 0) {
944
- ctx.addIssue({
945
- code: z.ZodIssueCode.custom,
946
- path: ['workflows', workflowName, 'stages'],
947
- message: 'Workflow must define at least one runnable stage.',
948
- });
949
- continue;
950
- }
951
- for (const reserved of ['queue', 'done']) {
952
- if (stageSet.has(reserved)) {
953
- ctx.addIssue({
954
- code: z.ZodIssueCode.custom,
955
- path: ['workflows', workflowName, 'stages', reserved],
956
- message: `Workflow must not define implicit ${reserved} stage.`,
957
- });
958
- }
959
- }
960
- const actualEntryStage = workflow.entryStage ?? stageNames[0];
961
- if (workflow.entryStage === 'queue') {
962
- ctx.addIssue({
963
- code: z.ZodIssueCode.custom,
964
- path: ['workflows', workflowName, 'entryStage'],
965
- message: 'Workflow entryStage must not be queue.',
966
- });
967
- }
968
- if (actualEntryStage !== undefined && !stageSet.has(actualEntryStage)) {
969
- ctx.addIssue({
970
- code: z.ZodIssueCode.custom,
971
- path: ['workflows', workflowName, 'entryStage'],
972
- message: `Workflow entryStage "${actualEntryStage}" is not a configured stage.`,
973
- });
974
- }
975
- for (const [stageName, stage] of Object.entries(workflow.stages)) {
976
- if (stage.onDone === 'queue') {
977
- ctx.addIssue({
978
- code: z.ZodIssueCode.custom,
979
- path: ['workflows', workflowName, 'stages', stageName, 'onDone'],
980
- message: 'Workflow transitions must not target queue.',
981
- });
982
- }
983
- if (stage.onDone !== 'done' && !stageSet.has(stage.onDone)) {
984
- ctx.addIssue({
985
- code: z.ZodIssueCode.custom,
986
- path: ['workflows', workflowName, 'stages', stageName, 'onDone'],
987
- message: `Workflow transition targets unknown stage "${stage.onDone}".`,
988
- });
989
- }
990
- if (stage.action === undefined && !promptExists(promptsRoot, stageName)) {
991
- ctx.addIssue({
992
- code: z.ZodIssueCode.custom,
993
- path: ['workflows', workflowName, 'stages', stageName, 'action'],
994
- message: `Workflow stage "${stageName}" omits action but no prompts/${stageName}.md template exists.`,
995
- });
996
- }
997
- for (const [index, watcher] of (stage.watch ?? []).entries()) {
998
- if (watcher.on === undefined && watcher.schedule === undefined) {
999
- ctx.addIssue({
1000
- code: z.ZodIssueCode.custom,
1001
- path: ['workflows', workflowName, 'stages', stageName, 'watch', index],
1002
- message: 'Watcher must declare at least one of on or schedule.',
1003
- });
1004
- }
1005
- if (config.workflows[watcher.workflow] === undefined) {
1006
- ctx.addIssue({
1007
- code: z.ZodIssueCode.custom,
1008
- path: ['workflows', workflowName, 'stages', stageName, 'watch', index, 'workflow'],
1009
- message: `Watcher targets unknown workflow "${watcher.workflow}".`,
1010
- });
1011
- }
1012
- }
1013
- }
1014
- if (actualEntryStage !== undefined &&
1015
- stageSet.has(actualEntryStage) &&
1016
- !canReachDone(actualEntryStage, workflow.stages)) {
1017
- ctx.addIssue({
1018
- code: z.ZodIssueCode.custom,
1019
- path: ['workflows', workflowName],
1020
- message: 'Workflow cannot reach done from its entry stage.',
1021
- });
1022
- }
1023
- }
1024
- for (const [index, selector] of config.workflowSelectors.entries()) {
1025
- if (config.workflows[selector.workflow] === undefined) {
1026
- ctx.addIssue({
1027
- code: z.ZodIssueCode.custom,
1028
- path: ['workflowSelectors', index, 'workflow'],
1029
- message: `Workflow selector targets unknown workflow "${selector.workflow}".`,
1030
- });
1031
- }
1032
- }
1033
- for (const [commandName, command] of commandEntries) {
1034
- if (reservedCommandNames.includes(commandName.toLowerCase())) {
1035
- ctx.addIssue({
1036
- code: z.ZodIssueCode.custom,
1037
- path: ['commands', commandName],
1038
- message: `Command "/${commandName}" is reserved for Wake's own control flow.`,
1039
- });
1040
- }
1041
- if (command.action === undefined && !promptExists(promptsRoot, commandName)) {
1042
- ctx.addIssue({
1043
- code: z.ZodIssueCode.custom,
1044
- path: ['commands', commandName, 'action'],
1045
- message: `Command "/${commandName}" omits action but no prompts/${commandName}.md template exists.`,
1046
- });
1047
- }
1048
- }
1049
- });
1050
- export const claudePrintResultSchema = z
1051
- .object({
1052
- type: z.string().optional(),
1053
- subtype: z.string().optional(),
1054
- result: z.string(),
1055
- session_id: z.string().optional(),
1056
- total_cost_usd: z.number().optional(),
1057
- num_turns: z.number().optional(),
1058
- usage: z.record(z.string(), z.unknown()).optional(),
1059
- })
1060
- .passthrough();
1061
- export function parseIssueStateRecord(input) {
1062
- return issueStateRecordSchema.parse(input);
1063
- }
1064
- export function parseRunRecord(input) {
1065
- return runRecordSchema.parse(input);
1066
- }
1067
- export function parseRunInputSnapshot(input) {
1068
- return runInputSnapshotSchema.parse(input);
1069
- }
1070
- export function parseEventEnvelope(input) {
1071
- return eventEnvelopeSchema.parse(input);
1072
- }
1073
- export function parseLedger(input) {
1074
- return ledgerSchema.parse(input);
1075
- }
1076
- function githubTriagePromptContext(config) {
1077
- const triageIgnoredLabels = [
1078
- ...new Set([...alwaysManualIgnoredLabels, ...config.sources.github.policy.ignoredLabels]),
1079
- ];
1080
- return {
1081
- triageIgnoredLabels,
1082
- triageIgnoredLabelsJson: JSON.stringify(triageIgnoredLabels),
1083
- triageReposJson: JSON.stringify(config.sources.github.repos),
1084
- };
1085
- }
1086
- function attachDerivedPromptContext(config) {
1087
- const triageAssignStage = config.workflows.triage?.stages.assign;
1088
- if (triageAssignStage?.promptContext !== undefined) {
1089
- triageAssignStage.promptContext = {
1090
- ...triageAssignStage.promptContext,
1091
- ...githubTriagePromptContext(config),
1092
- };
1093
- }
1094
- return config;
1095
- }
1096
- export function parseWakeConfig(input) {
1097
- if (isRecord(input) &&
1098
- isRecord(input.transcripts) &&
1099
- 'retainAfterWorkspaceCleanup' in input.transcripts) {
1100
- throw new Error('transcripts.retainAfterWorkspaceCleanup is no longer supported; use transcripts.retentionMs instead. Set transcripts.retentionMs to 0 to delete transcripts immediately on workspace cleanup.');
1101
- }
1102
- return structuredClone(attachDerivedPromptContext(wakeConfigSchema.parse(input)));
1103
- }
1104
- function isRecord(value) {
1105
- return typeof value === 'object' && value !== null && !Array.isArray(value);
1106
- }
1107
- export function parseSourceStateRecord(input) {
1108
- return sourceStateRecordSchema.parse(input);
1109
- }
1110
- export function parseClaudePrintResult(input) {
1111
- return claudePrintResultSchema.parse(input);
1112
- }
1113
- function synthesizeBodyFromEnvelope(envelope) {
1114
- const labels = {
1115
- DONE: 'Run completed.',
1116
- REJECTED: 'Run rejected — needs changes.',
1117
- BLOCKED: 'Run blocked — needs input.',
1118
- FAILED: 'Run failed.',
1119
- };
1120
- return labels[envelope.status] ?? 'Run finished.';
1121
- }
1122
- export function parseRunnerResult(result) {
1123
- const wakeResultFencePattern = /^```(?:wake-result[^\n]*\n|[ \t]*\n[ \t]*wake-result[ \t]*\n)([\s\S]*?)^```[ \t]*$/gm;
1124
- let lastMatch = null;
1125
- let match;
1126
- while ((match = wakeResultFencePattern.exec(result)) !== null) {
1127
- lastMatch = match;
1128
- }
1129
- if (lastMatch !== null) {
1130
- try {
1131
- const rawContent = lastMatch[1] ?? 'null';
1132
- // Claude sometimes places the sentinel keyword inside the fence rather than after
1133
- // the closing fence. Strip a trailing sentinel line so JSON.parse sees only the JSON.
1134
- // The capture group includes the newline before the closing fence, so allow \n? after.
1135
- const jsonContent = rawContent.replace(/\n(?:DONE|REJECTED|BLOCKED|FAILED)[ \t]*\n?$/, '') || rawContent;
1136
- const parsed = wakeResultEnvelopeSchema.safeParse(JSON.parse(jsonContent));
1137
- if (parsed.success) {
1138
- const proseBody = result.slice(0, lastMatch.index).trim();
1139
- return {
1140
- status: parsed.data.status,
1141
- body: proseBody || synthesizeBodyFromEnvelope(parsed.data),
1142
- envelope: 'structured',
1143
- result: parsed.data,
1144
- };
1145
- }
1146
- }
1147
- catch {
1148
- // Invalid structured trailers intentionally degrade to last-line parsing.
1149
- }
1150
- }
1151
- const offFenceEnvelopePattern = /^```wake-result[^\n]*\n```[ \t]*\n(\{[^\n]+\})[ \t]*$/gm;
1152
- let offFenceMatch = null;
1153
- while ((match = offFenceEnvelopePattern.exec(result)) !== null) {
1154
- offFenceMatch = match;
1155
- }
1156
- if (offFenceMatch !== null) {
1157
- try {
1158
- const parsed = wakeResultEnvelopeSchema.safeParse(JSON.parse(offFenceMatch[1] ?? 'null'));
1159
- if (parsed.success) {
1160
- return {
1161
- status: parsed.data.status,
1162
- body: result.slice(0, offFenceMatch.index).trim() || synthesizeBodyFromEnvelope(parsed.data),
1163
- envelope: 'structured',
1164
- result: parsed.data,
1165
- };
1166
- }
1167
- }
1168
- catch {
1169
- // Invalid off-fence trailers intentionally degrade to sentinel parsing.
1170
- }
1171
- }
1172
- const lines = result.split('\n');
1173
- const lastLine = lines
1174
- .map((line) => line.trim())
1175
- // Skip closing code fence lines — they appear as the last non-empty line when the
1176
- // sentinel is embedded inside the fenced block or when a plain ``` fence is used.
1177
- .filter((line) => line.length > 0 && line !== '```')
1178
- .at(-1);
1179
- const normalizedLastLine = lastLine?.replace(/^(?:\*\*|__)(.+)(?:\*\*|__)$/, '$1');
1180
- const parsed = runnerSentinelSchema.safeParse(normalizedLastLine);
1181
- if (!parsed.success) {
1182
- const body = result.trim();
1183
- return {
1184
- status: body.length === 0 ? 'FAILED' : 'BLOCKED',
1185
- body,
1186
- // No structured envelope AND no recognizable bare sentinel at all —
1187
- // distinct from 'degraded' (a deliberate bare-sentinel reply) so
1188
- // callers can retry a runner that simply forgot the trailer instead
1189
- // of trusting a fabricated BLOCKED/FAILED default.
1190
- envelope: 'missing',
1191
- };
1192
- }
1193
- let removed = false;
1194
- const body = lines
1195
- .slice()
1196
- .reverse()
1197
- .filter((line) => {
1198
- if (!removed && line.trim() === lastLine) {
1199
- removed = true;
1200
- return false;
1201
- }
1202
- return true;
1203
- })
1204
- .reverse()
1205
- .join('\n')
1206
- .trim();
1207
- return {
1208
- status: parsed.data,
1209
- body,
1210
- envelope: 'degraded',
1211
- };
1212
- }
1213
- export function parseRunnerArtifacts(result) {
1214
- const fencePattern = /^```wake-artifacts[^\n]*\n([\s\S]*?)^```[ \t]*$/gm;
1215
- let lastMatch = null;
1216
- let match;
1217
- while ((match = fencePattern.exec(result)) !== null) {
1218
- lastMatch = match;
1219
- }
1220
- if (lastMatch === null) {
1221
- return { artifacts: [] };
1222
- }
1223
- try {
1224
- const parsed = wakeArtifactsEnvelopeSchema.safeParse(JSON.parse(lastMatch[1] ?? '{}'));
1225
- return parsed.success ? parsed.data : { artifacts: [] };
1226
- }
1227
- catch {
1228
- return { artifacts: [] };
1229
- }
1230
- }
1231
- export function parseRunnerResultSentinel(result) {
1232
- return parseRunnerResult(result).status;
1233
- }