@atolis-hq/wake 0.2.97 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (443) hide show
  1. package/README.md +5 -5
  2. package/dist/src/activities/agent/agent-activity-definition.js +26 -0
  3. package/dist/src/activities/agent/agent-activity.js +171 -0
  4. package/dist/src/activities/agent/agent-result.js +149 -0
  5. package/dist/src/activities/contracts/activity.js +10 -0
  6. package/dist/src/activities/contracts/config.js +2 -0
  7. package/dist/src/activities/contracts/event-schema.js +302 -0
  8. package/dist/src/activities/contracts/events.js +42 -0
  9. package/dist/src/activities/contracts/identifiers.js +29 -0
  10. package/dist/src/activities/contracts/registry.js +71 -0
  11. package/dist/src/activities/contracts/streams.js +17 -0
  12. package/dist/src/activities/contracts/vocabulary.js +58 -0
  13. package/dist/src/activities/index.js +21 -0
  14. package/dist/src/activities/pr/activity-support.js +111 -0
  15. package/dist/src/activities/pr/application.js +158 -0
  16. package/dist/src/activities/pr/approve.js +85 -0
  17. package/dist/src/activities/pr/capability.js +11 -0
  18. package/dist/src/activities/pr/decision-claim.js +76 -0
  19. package/dist/src/activities/pr/event-drafts.js +66 -0
  20. package/dist/src/activities/pr/intent.js +37 -0
  21. package/dist/src/activities/pr/merge-authority-gate.js +14 -0
  22. package/dist/src/activities/pr/merge.js +110 -0
  23. package/dist/src/activities/pr/policy.js +135 -0
  24. package/dist/src/activities/pr/projection.js +130 -0
  25. package/dist/src/activities/pr/vocabulary.js +30 -0
  26. package/dist/src/activities/review/authorization.js +22 -0
  27. package/dist/src/activities/review/contracts.js +22 -0
  28. package/dist/src/activities/review/signals.js +3 -0
  29. package/dist/src/bootstrap/analytics-projection.js +26 -0
  30. package/dist/src/bootstrap/board-projection.js +337 -0
  31. package/dist/src/bootstrap/composition-root.js +382 -0
  32. package/dist/src/bootstrap/config/load-config.js +51 -0
  33. package/dist/src/bootstrap/config/root-schema.js +134 -0
  34. package/dist/src/bootstrap/external-ref.js +12 -0
  35. package/dist/src/bootstrap/fake-provider-files.js +44 -0
  36. package/dist/src/bootstrap/fake-scenarios.js +22 -0
  37. package/dist/src/bootstrap/index.js +48 -0
  38. package/dist/src/bootstrap/initialise.js +436 -0
  39. package/dist/src/bootstrap/paths.js +15 -0
  40. package/dist/src/bootstrap/projection-runtime.js +27 -0
  41. package/dist/src/bootstrap/runner-quota-reporter.js +21 -0
  42. package/dist/src/bootstrap/runner-registry.js +30 -0
  43. package/dist/src/bootstrap/schedule-checkpoint-store.js +49 -0
  44. package/dist/src/bootstrap/self-update-application.js +195 -0
  45. package/dist/src/bootstrap/self-update-failure-log.js +33 -0
  46. package/dist/src/bootstrap/source-update-port.js +47 -0
  47. package/dist/src/bootstrap/status-publish-activity.js +42 -0
  48. package/dist/src/bootstrap/surface-api-applications.js +325 -0
  49. package/dist/src/bootstrap/surface-api-execution-applications.js +95 -0
  50. package/dist/src/bootstrap/surface-api-metadata.js +12 -0
  51. package/dist/src/bootstrap/surface-api-projection-pages.js +22 -0
  52. package/dist/src/bootstrap/surface-api-run-context.js +5 -0
  53. package/dist/src/bootstrap/surface-api-transcripts.js +57 -0
  54. package/dist/src/bootstrap/surface-api-work-applications.js +199 -0
  55. package/dist/src/bootstrap/surface-applications.js +7 -0
  56. package/dist/src/bootstrap/surface-cli-applications.js +701 -0
  57. package/dist/src/bootstrap/update-ledger.js +61 -0
  58. package/dist/src/bootstrap/update-maintenance-lease.js +176 -0
  59. package/dist/src/{version.js → bootstrap/version.js} +35 -51
  60. package/dist/src/control-plane/application/advance-once.js +184 -0
  61. package/dist/src/control-plane/application/control-plane-projection.js +42 -0
  62. package/dist/src/control-plane/application/control-plane-service.js +42 -0
  63. package/dist/src/control-plane/application/intake-pipeline.js +29 -0
  64. package/dist/src/control-plane/application/runner-control-service.js +66 -0
  65. package/dist/src/control-plane/application/runner-pipeline.js +57 -0
  66. package/dist/src/control-plane/application/schedule-service.js +47 -0
  67. package/dist/src/control-plane/application/work-cancellation-policy.js +31 -0
  68. package/dist/src/control-plane/contracts/commands.js +10 -0
  69. package/dist/src/control-plane/contracts/config.js +22 -0
  70. package/dist/src/control-plane/contracts/events.js +81 -0
  71. package/dist/src/control-plane/contracts/streams.js +5 -0
  72. package/dist/src/control-plane/domain/dispatch-policy.js +15 -0
  73. package/dist/src/control-plane/domain/quota-policy.js +26 -0
  74. package/dist/src/control-plane/domain/runner-quota.js +35 -0
  75. package/dist/src/control-plane/domain/schedule-policy.js +46 -0
  76. package/dist/src/control-plane/index.js +20 -0
  77. package/dist/src/control-plane/infrastructure/intake-host.js +24 -0
  78. package/dist/src/control-plane/infrastructure/resident-host.js +45 -0
  79. package/dist/src/control-plane/infrastructure/tick-host.js +35 -0
  80. package/dist/src/execution/application/activation-claim.js +50 -0
  81. package/dist/src/execution/application/active-run-cancellation.js +14 -0
  82. package/dist/src/execution/application/execution-activity.js +97 -0
  83. package/dist/src/execution/application/execution-projection.js +17 -0
  84. package/dist/src/execution/application/execution-service.js +372 -0
  85. package/dist/src/execution/application/execution-validation.js +26 -0
  86. package/dist/src/execution/application/recovery-service.js +212 -0
  87. package/dist/src/execution/application/run-lifecycle.js +115 -0
  88. package/dist/src/execution/application/run-liveness-service.js +80 -0
  89. package/dist/src/execution/application/run-repository.js +27 -0
  90. package/dist/src/execution/contracts/commands.js +1 -0
  91. package/dist/src/execution/contracts/config.js +35 -0
  92. package/dist/src/execution/contracts/control-plane.js +1 -0
  93. package/dist/src/execution/contracts/event-factory.js +53 -0
  94. package/dist/src/execution/contracts/events.js +274 -0
  95. package/dist/src/execution/contracts/identifiers.js +5 -0
  96. package/dist/src/execution/contracts/liveness.js +1 -0
  97. package/dist/src/execution/contracts/results.js +1 -0
  98. package/dist/src/execution/contracts/runner.js +15 -0
  99. package/dist/src/execution/contracts/streams.js +10 -0
  100. package/dist/src/execution/contracts/views.js +1 -0
  101. package/dist/src/execution/contracts/vocabulary.js +43 -0
  102. package/dist/src/execution/contracts/workspace.js +1 -0
  103. package/dist/src/execution/domain/run-result.js +34 -0
  104. package/dist/src/execution/domain/run.js +142 -0
  105. package/dist/src/execution/index.js +31 -0
  106. package/dist/src/execution/infrastructure/agent-runner-adapter.js +114 -0
  107. package/dist/src/execution/infrastructure/process-execution.js +29 -0
  108. package/dist/src/execution/infrastructure/prompt-templates.js +42 -0
  109. package/dist/src/execution/infrastructure/runners/claude.js +120 -0
  110. package/dist/src/execution/infrastructure/runners/codex.js +143 -0
  111. package/dist/src/execution/infrastructure/runners/command.js +4 -0
  112. package/dist/src/execution/infrastructure/runners/cursor.js +69 -0
  113. package/dist/src/execution/infrastructure/runners/fake-scenarios.js +99 -0
  114. package/dist/src/execution/infrastructure/runners/fake.js +65 -0
  115. package/dist/src/execution/infrastructure/runners/registry.js +26 -0
  116. package/dist/src/execution/infrastructure/transcript-store.js +223 -0
  117. package/dist/src/execution/infrastructure/transcripts.js +11 -0
  118. package/dist/src/execution/infrastructure/workspace/fake-workspace.js +19 -0
  119. package/dist/src/execution/infrastructure/workspace/git-workspace.js +241 -0
  120. package/dist/src/integrations/application/agent-run-publication-reactor.js +111 -0
  121. package/dist/src/integrations/application/artifact-registration-reactor.js +159 -0
  122. package/dist/src/integrations/application/poll-service.js +25 -0
  123. package/dist/src/integrations/application/terminal-agent-run-report.js +40 -0
  124. package/dist/src/integrations/application/work-admission.js +31 -0
  125. package/dist/src/integrations/application/work-conclusion.js +19 -0
  126. package/dist/src/integrations/contracts/artifact-events.js +60 -0
  127. package/dist/src/integrations/contracts/artifact-vocabulary.js +9 -0
  128. package/dist/src/integrations/contracts/config.js +14 -0
  129. package/dist/src/integrations/contracts/identifiers.js +5 -0
  130. package/dist/src/integrations/contracts/intake-rules.js +14 -0
  131. package/dist/src/integrations/contracts/intake.js +1 -0
  132. package/dist/src/integrations/contracts/outcome-vocabulary.js +7 -0
  133. package/dist/src/integrations/contracts/provider.js +37 -0
  134. package/dist/src/integrations/contracts/streams.js +10 -0
  135. package/dist/src/integrations/delivery/application/delivery-outcome-reactor.js +75 -0
  136. package/dist/src/integrations/delivery/application/delivery-projector.js +165 -0
  137. package/dist/src/integrations/delivery/application/delivery-service.js +173 -0
  138. package/dist/src/integrations/delivery/contracts/commands.js +1 -0
  139. package/dist/src/integrations/delivery/contracts/config.js +1 -0
  140. package/dist/src/integrations/delivery/contracts/event-factory.js +18 -0
  141. package/dist/src/integrations/delivery/contracts/events.js +86 -0
  142. package/dist/src/integrations/delivery/contracts/intents.js +89 -0
  143. package/dist/src/integrations/delivery/contracts/views.js +1 -0
  144. package/dist/src/integrations/delivery/contracts/vocabulary.js +22 -0
  145. package/dist/src/integrations/fake/durable-delivery-provider.js +48 -0
  146. package/dist/src/integrations/fake/external-sink.js +9 -0
  147. package/dist/src/integrations/fake/external-source.js +44 -0
  148. package/dist/src/integrations/fake/inbound-translator.js +130 -0
  149. package/dist/src/integrations/fake/provider.js +95 -0
  150. package/dist/src/integrations/github/application/agent-context-reader.js +54 -0
  151. package/dist/src/integrations/github/application/agent-run-comment.js +94 -0
  152. package/dist/src/integrations/github/application/comment-history-reader.js +43 -0
  153. package/dist/src/integrations/github/application/inbound-context.js +10 -0
  154. package/dist/src/integrations/github/application/inbound-review-signals.js +159 -0
  155. package/dist/src/integrations/github/application/inbound-translator.js +231 -0
  156. package/dist/src/integrations/github/application/inbound-watch-gate-signals.js +84 -0
  157. package/dist/src/integrations/github/application/intake-policy.js +23 -0
  158. package/dist/src/integrations/github/application/outbound-translator.js +47 -0
  159. package/dist/src/integrations/github/application/poll-service.js +29 -0
  160. package/dist/src/integrations/github/application/pull-request-translation.js +10 -0
  161. package/dist/src/integrations/github/application/resource-links.js +8 -0
  162. package/dist/src/integrations/github/application/review-command-translator.js +16 -0
  163. package/dist/src/integrations/github/application/wake-labels.js +95 -0
  164. package/dist/src/integrations/github/contracts/config.js +47 -0
  165. package/dist/src/integrations/github/contracts/events.js +127 -0
  166. package/dist/src/integrations/github/contracts/external-key.js +19 -0
  167. package/dist/src/integrations/github/contracts/payloads.js +9 -0
  168. package/dist/src/integrations/github/contracts/vocabulary.js +55 -0
  169. package/dist/src/integrations/github/index.js +31 -0
  170. package/dist/src/integrations/github/infrastructure/client-reads.js +214 -0
  171. package/dist/src/integrations/github/infrastructure/client.js +132 -0
  172. package/dist/src/integrations/github/infrastructure/content-fingerprint.js +10 -0
  173. package/dist/src/integrations/github/infrastructure/delivery.js +31 -0
  174. package/dist/src/integrations/github/infrastructure/etag-cache.js +56 -0
  175. package/dist/src/integrations/github/infrastructure/gh-auth.js +19 -0
  176. package/dist/src/integrations/github/infrastructure/issue-source.js +109 -0
  177. package/dist/src/integrations/github/infrastructure/pr-source.js +186 -0
  178. package/dist/src/integrations/github/infrastructure/review-source.js +70 -0
  179. package/dist/src/integrations/github/infrastructure/source.js +108 -0
  180. package/dist/src/integrations/github/provider.js +96 -0
  181. package/dist/src/integrations/index.js +30 -0
  182. package/dist/src/kernel/contracts/checkpoint-store.js +1 -0
  183. package/dist/src/kernel/contracts/clock.js +1 -0
  184. package/dist/src/kernel/contracts/commands.js +1 -0
  185. package/dist/src/kernel/contracts/event-journal.js +2 -0
  186. package/dist/src/kernel/contracts/event-schema.js +54 -0
  187. package/dist/src/kernel/contracts/events.js +11 -0
  188. package/dist/src/kernel/contracts/id-generator.js +1 -0
  189. package/dist/src/kernel/contracts/identifiers.js +8 -0
  190. package/dist/src/kernel/contracts/projection-store.js +1 -0
  191. package/dist/src/kernel/contracts/relations.js +1 -0
  192. package/dist/src/kernel/contracts/schema.js +17 -0
  193. package/dist/src/kernel/contracts/vocabulary.js +6 -0
  194. package/dist/src/kernel/domain/event-envelope.js +29 -0
  195. package/dist/src/kernel/domain/match-mode.js +11 -0
  196. package/dist/src/kernel/domain/relation.js +10 -0
  197. package/dist/src/kernel/index.js +17 -0
  198. package/dist/src/{lib/clock.js → kernel/infrastructure/system-clock.js} +3 -3
  199. package/dist/src/kernel/infrastructure/ulid-id-generator.js +9 -0
  200. package/dist/src/main.js +137 -1030
  201. package/dist/src/orchestration/application/accept-activity-outcome.js +25 -0
  202. package/dist/src/orchestration/application/accept-signal.js +35 -0
  203. package/dist/src/orchestration/application/advance-workflow.js +160 -0
  204. package/dist/src/orchestration/application/coordination-claims.js +107 -0
  205. package/dist/src/orchestration/application/group-budget-recorder.js +43 -0
  206. package/dist/src/orchestration/application/orchestration-projection.js +20 -0
  207. package/dist/src/orchestration/application/orchestration-repository.js +36 -0
  208. package/dist/src/orchestration/application/orchestration-service.js +82 -0
  209. package/dist/src/orchestration/application/request-child.js +118 -0
  210. package/dist/src/orchestration/application/signal-reactor.js +17 -0
  211. package/dist/src/orchestration/application/start-workflow.js +51 -0
  212. package/dist/src/orchestration/application/watch-reactor.js +82 -0
  213. package/dist/src/orchestration/contracts/activity-outcome.js +18 -0
  214. package/dist/src/orchestration/contracts/commands.js +1 -0
  215. package/dist/src/orchestration/contracts/config.js +128 -0
  216. package/dist/src/orchestration/contracts/event-decoder.js +263 -0
  217. package/dist/src/orchestration/contracts/events.js +41 -0
  218. package/dist/src/orchestration/contracts/identifiers.js +35 -0
  219. package/dist/src/orchestration/contracts/streams.js +38 -0
  220. package/dist/src/orchestration/contracts/views.js +1 -0
  221. package/dist/src/orchestration/contracts/vocabulary.js +30 -0
  222. package/dist/src/orchestration/domain/activation-policy.js +55 -0
  223. package/dist/src/orchestration/domain/approval-defaults.js +17 -0
  224. package/dist/src/orchestration/domain/child-policy.js +63 -0
  225. package/dist/src/orchestration/domain/compiler.js +162 -0
  226. package/dist/src/orchestration/domain/coordination-events.js +25 -0
  227. package/dist/src/orchestration/domain/decision-events.js +47 -0
  228. package/dist/src/orchestration/domain/interpreter.js +49 -0
  229. package/dist/src/orchestration/domain/operator-retry-policy.js +34 -0
  230. package/dist/src/orchestration/domain/retry-policy.js +26 -0
  231. package/dist/src/orchestration/domain/signal-policy.js +120 -0
  232. package/dist/src/orchestration/domain/supplemental-policy.js +61 -0
  233. package/dist/src/orchestration/domain/transition.js +55 -0
  234. package/dist/src/orchestration/domain/workflow-graph.js +41 -0
  235. package/dist/src/orchestration/domain/workflow-instance-events.js +236 -0
  236. package/dist/src/orchestration/domain/workflow-instance.js +41 -0
  237. package/dist/src/orchestration/domain/workflow-selector.js +21 -0
  238. package/dist/src/orchestration/index.js +19 -0
  239. package/dist/src/persistence/application/projection-runner.js +79 -0
  240. package/dist/src/persistence/filesystem/file-checkpoint-store.js +35 -0
  241. package/dist/src/persistence/filesystem/file-event-journal.js +143 -0
  242. package/dist/src/persistence/filesystem/file-lock.js +91 -0
  243. package/dist/src/persistence/filesystem/file-projection-store.js +64 -0
  244. package/dist/src/persistence/index.js +8 -0
  245. package/dist/src/persistence/memory/in-memory-checkpoint-store.js +14 -0
  246. package/dist/src/persistence/memory/in-memory-event-journal.js +88 -0
  247. package/dist/src/persistence/memory/in-memory-projection-store.js +17 -0
  248. package/dist/src/resources/application/lookup-projections.js +48 -0
  249. package/dist/src/resources/application/resource-lookup.js +16 -0
  250. package/dist/src/resources/application/resource-projections.js +81 -0
  251. package/dist/src/resources/application/resource-repository.js +18 -0
  252. package/dist/src/resources/application/resource-service.js +83 -0
  253. package/dist/src/resources/contracts/commands.js +1 -0
  254. package/dist/src/resources/contracts/config.js +2 -0
  255. package/dist/src/resources/contracts/events.js +83 -0
  256. package/dist/src/resources/contracts/identifiers.js +15 -0
  257. package/dist/src/resources/contracts/streams.js +6 -0
  258. package/dist/src/resources/contracts/views.js +1 -0
  259. package/dist/src/resources/contracts/vocabulary.js +67 -0
  260. package/dist/src/resources/domain/correlation.js +8 -0
  261. package/dist/src/resources/domain/resource.js +58 -0
  262. package/dist/src/resources/index.js +14 -0
  263. package/dist/src/surfaces/api/contracts/activities.js +1 -0
  264. package/dist/src/surfaces/api/contracts/board.js +2 -0
  265. package/dist/src/surfaces/api/contracts/common.js +46 -0
  266. package/dist/src/surfaces/api/contracts/control-plane.js +5 -0
  267. package/dist/src/surfaces/api/contracts/events.js +1 -0
  268. package/dist/src/surfaces/api/contracts/execution.js +1 -0
  269. package/dist/src/surfaces/api/contracts/index.js +13 -0
  270. package/dist/src/surfaces/api/contracts/observability.js +1 -0
  271. package/dist/src/surfaces/api/contracts/orchestration.js +1 -0
  272. package/dist/src/surfaces/api/contracts/resources.js +1 -0
  273. package/dist/src/surfaces/api/contracts/status.js +1 -0
  274. package/dist/src/surfaces/api/contracts/system.js +1 -0
  275. package/dist/src/surfaces/api/contracts/transport-values.js +39 -0
  276. package/dist/src/surfaces/api/contracts/work.js +17 -0
  277. package/dist/src/surfaces/api/http-server.js +121 -0
  278. package/dist/src/surfaces/api/presenters/activities.js +1 -0
  279. package/dist/src/surfaces/api/presenters/board.js +3 -0
  280. package/dist/src/surfaces/api/presenters/control-plane.js +1 -0
  281. package/dist/src/surfaces/api/presenters/events.js +1 -0
  282. package/dist/src/surfaces/api/presenters/execution.js +59 -0
  283. package/dist/src/surfaces/api/presenters/observability.js +1 -0
  284. package/dist/src/surfaces/api/presenters/orchestration.js +19 -0
  285. package/dist/src/surfaces/api/presenters/resources.js +15 -0
  286. package/dist/src/surfaces/api/presenters/status.js +3 -0
  287. package/dist/src/surfaces/api/presenters/system.js +14 -0
  288. package/dist/src/surfaces/api/presenters/work.js +16 -0
  289. package/dist/src/surfaces/api/problem-details.js +9 -0
  290. package/dist/src/surfaces/api/router.js +13 -0
  291. package/dist/src/surfaces/api/routes/activities.js +1 -0
  292. package/dist/src/surfaces/api/routes/applications.js +1 -0
  293. package/dist/src/surfaces/api/routes/commands.js +82 -0
  294. package/dist/src/surfaces/api/routes/control-plane.js +6 -0
  295. package/dist/src/surfaces/api/routes/events.js +1 -0
  296. package/dist/src/surfaces/api/routes/execution.js +8 -0
  297. package/dist/src/surfaces/api/routes/index.js +18 -0
  298. package/dist/src/surfaces/api/routes/observability.js +1 -0
  299. package/dist/src/surfaces/api/routes/orchestration.js +1 -0
  300. package/dist/src/surfaces/api/routes/pagination.js +78 -0
  301. package/dist/src/surfaces/api/routes/read.js +135 -0
  302. package/dist/src/surfaces/api/routes/resources.js +1 -0
  303. package/dist/src/surfaces/api/routes/responses.js +67 -0
  304. package/dist/src/surfaces/api/routes/system.js +1 -0
  305. package/dist/src/surfaces/api/routes/work.js +9 -0
  306. package/dist/src/surfaces/cli/commands/api.js +1 -0
  307. package/dist/src/surfaces/cli/commands/audit.js +10 -0
  308. package/dist/src/surfaces/cli/commands/correlate.js +2 -0
  309. package/dist/src/surfaces/cli/commands/doctor.js +6 -0
  310. package/dist/src/surfaces/cli/commands/init.js +39 -0
  311. package/dist/src/surfaces/cli/commands/sandbox-entrypoint.js +33 -0
  312. package/dist/src/surfaces/cli/commands/sandbox-setup.js +29 -0
  313. package/dist/src/surfaces/cli/commands/sandbox.js +105 -0
  314. package/dist/src/surfaces/cli/commands/self-update.js +38 -0
  315. package/dist/src/surfaces/cli/commands/smoke.js +16 -0
  316. package/dist/src/surfaces/cli/commands/start.js +1 -0
  317. package/dist/src/surfaces/cli/commands/stop.js +13 -0
  318. package/dist/src/surfaces/cli/commands/tick.js +1 -0
  319. package/dist/src/surfaces/cli/commands/ui.js +2 -0
  320. package/dist/src/surfaces/cli/commands/validate-state.js +5 -0
  321. package/dist/src/surfaces/cli/infrastructure/docker-cli.js +221 -0
  322. package/dist/src/surfaces/cli/infrastructure/process-log.js +86 -0
  323. package/dist/src/surfaces/cli/main.js +140 -0
  324. package/dist/src/surfaces/cli/usage.js +33 -0
  325. package/dist/src/surfaces/contracts/config.js +34 -0
  326. package/dist/src/surfaces/index.js +47 -0
  327. package/dist/src/surfaces/web-assets/assets/index-Bfn4FwZG.css +1 -0
  328. package/dist/src/surfaces/web-assets/assets/index-ipB6JPGU.js +1090 -0
  329. package/dist/src/surfaces/web-assets/index.html +13 -0
  330. package/dist/src/surfaces/web-host/asset-source.js +1 -0
  331. package/dist/src/surfaces/web-host/packaged-assets.js +44 -0
  332. package/dist/src/work/application/work-projection.js +59 -0
  333. package/dist/src/work/application/work-repository.js +18 -0
  334. package/dist/src/work/application/work-service.js +117 -0
  335. package/dist/src/work/contracts/commands.js +1 -0
  336. package/dist/src/work/contracts/config.js +2 -0
  337. package/dist/src/work/contracts/events.js +103 -0
  338. package/dist/src/work/contracts/identifiers.js +5 -0
  339. package/dist/src/work/contracts/streams.js +6 -0
  340. package/dist/src/work/contracts/views.js +1 -0
  341. package/dist/src/work/contracts/vocabulary.js +6 -0
  342. package/dist/src/work/domain/work-item.js +89 -0
  343. package/dist/src/work/index.js +11 -0
  344. package/docker/Dockerfile +10 -6
  345. package/docker/Dockerfile.packaged +3 -3
  346. package/package.json +29 -4
  347. package/prompts/implement.md +2 -2
  348. package/dist/src/adapters/claude/claude-runner.js +0 -529
  349. package/dist/src/adapters/codex/codex-runner.js +0 -503
  350. package/dist/src/adapters/cursor/cursor-runner.js +0 -418
  351. package/dist/src/adapters/docker/docker-cli.js +0 -150
  352. package/dist/src/adapters/fake/fake-artifact-verifier.js +0 -14
  353. package/dist/src/adapters/fake/fake-github-pull-request-activity-source.js +0 -77
  354. package/dist/src/adapters/fake/fake-resource-index.js +0 -21
  355. package/dist/src/adapters/fake/fake-runner.js +0 -77
  356. package/dist/src/adapters/fake/fake-ticketing-system.js +0 -185
  357. package/dist/src/adapters/fake/fake-workspace-manager.js +0 -81
  358. package/dist/src/adapters/fs/resource-index.js +0 -126
  359. package/dist/src/adapters/fs/self-update-ledger.js +0 -17
  360. package/dist/src/adapters/fs/state-store.js +0 -775
  361. package/dist/src/adapters/git/git-workspace-manager.js +0 -289
  362. package/dist/src/adapters/github/github-artifact-verifier.js +0 -38
  363. package/dist/src/adapters/github/github-auth.js +0 -16
  364. package/dist/src/adapters/github/github-client.js +0 -249
  365. package/dist/src/adapters/github/github-etag-cache.js +0 -57
  366. package/dist/src/adapters/github/github-issues-work-source.js +0 -692
  367. package/dist/src/adapters/github/github-pull-request-activity-source.js +0 -584
  368. package/dist/src/adapters/github/github-pull-request-merge-actor.js +0 -45
  369. package/dist/src/adapters/http/ui-assets.js +0 -1188
  370. package/dist/src/adapters/http/ui-data.js +0 -1107
  371. package/dist/src/adapters/http/ui-server.js +0 -458
  372. package/dist/src/adapters/runner/cli-command.js +0 -73
  373. package/dist/src/adapters/runner/prompt-templates.js +0 -76
  374. package/dist/src/adapters/runner/runner-cli-adapter.js +0 -112
  375. package/dist/src/adapters/runner/runner-registry.js +0 -139
  376. package/dist/src/adapters/runner/runtime-events.js +0 -32
  377. package/dist/src/adapters/runner/stage-prompt.js +0 -268
  378. package/dist/src/adapters/runner/transcripts.js +0 -25
  379. package/dist/src/cli/audit-command.js +0 -36
  380. package/dist/src/cli/correlate-command.js +0 -62
  381. package/dist/src/cli/doctor-command.js +0 -48
  382. package/dist/src/cli/init-command.js +0 -18
  383. package/dist/src/cli/sandbox-command.js +0 -258
  384. package/dist/src/cli/sandbox-entrypoint-command.js +0 -88
  385. package/dist/src/cli/sandbox-exec-logging.js +0 -7
  386. package/dist/src/cli/sandbox-resume.js +0 -79
  387. package/dist/src/cli/sandbox-setup-command.js +0 -31
  388. package/dist/src/cli/scaffold-assets.js +0 -100
  389. package/dist/src/cli/self-update-command.js +0 -198
  390. package/dist/src/cli/startup-preflight.js +0 -134
  391. package/dist/src/cli/stop-command.js +0 -46
  392. package/dist/src/cli/ui-command.js +0 -27
  393. package/dist/src/config/defaults.js +0 -10
  394. package/dist/src/config/discover-config-files.js +0 -11
  395. package/dist/src/config/load-config.js +0 -69
  396. package/dist/src/config/split-config.js +0 -14
  397. package/dist/src/core/active-run-recovery.js +0 -44
  398. package/dist/src/core/approval-intents.js +0 -16
  399. package/dist/src/core/audit-events.js +0 -82
  400. package/dist/src/core/control-plane.js +0 -192
  401. package/dist/src/core/event-builders.js +0 -153
  402. package/dist/src/core/event-resolver.js +0 -249
  403. package/dist/src/core/lifecycle-service.js +0 -8
  404. package/dist/src/core/live-execution.js +0 -81
  405. package/dist/src/core/outbox.js +0 -198
  406. package/dist/src/core/policy-engine.js +0 -389
  407. package/dist/src/core/projection-updater.js +0 -693
  408. package/dist/src/core/quota-backoff.js +0 -69
  409. package/dist/src/core/run-lease.js +0 -38
  410. package/dist/src/core/scheduled-workflow-source.js +0 -199
  411. package/dist/src/core/sink-router.js +0 -107
  412. package/dist/src/core/stale-run-reconciler.js +0 -352
  413. package/dist/src/core/tick-runner.js +0 -2442
  414. package/dist/src/core/workspace-cleanup.js +0 -117
  415. package/dist/src/domain/branch-naming.js +0 -14
  416. package/dist/src/domain/custom-commands.js +0 -58
  417. package/dist/src/domain/event-types.js +0 -158
  418. package/dist/src/domain/manual-labels.js +0 -1
  419. package/dist/src/domain/resource-uri.js +0 -38
  420. package/dist/src/domain/runner-routing.js +0 -127
  421. package/dist/src/domain/runtime-events.js +0 -36
  422. package/dist/src/domain/schema.js +0 -1233
  423. package/dist/src/domain/sources.js +0 -16
  424. package/dist/src/domain/stages.js +0 -36
  425. package/dist/src/domain/work-item-labels.js +0 -48
  426. package/dist/src/domain/work-item-lifecycle.js +0 -10
  427. package/dist/src/domain/work-item-status.js +0 -33
  428. package/dist/src/domain/workflows.js +0 -159
  429. package/dist/src/lib/deep-merge.js +0 -14
  430. package/dist/src/lib/detached-process-logging.js +0 -46
  431. package/dist/src/lib/event-log.js +0 -21
  432. package/dist/src/lib/format.js +0 -41
  433. package/dist/src/lib/json-file.js +0 -23
  434. package/dist/src/lib/lock.js +0 -181
  435. package/dist/src/lib/log-rotation.js +0 -42
  436. package/dist/src/lib/paths.js +0 -52
  437. package/dist/src/lib/process-identity.js +0 -54
  438. package/dist/src/lib/state-health.js +0 -30
  439. package/dist/src/lib/work-id.js +0 -19
  440. package/dist/src/lib/yaml-file.js +0 -20
  441. package/templates/SETUP.md +0 -115
  442. /package/dist/src/{core → activities/pr}/contracts.js +0 -0
  443. /package/dist/src/{domain/types.js → control-plane/contracts/views.js} +0 -0
@@ -0,0 +1,39 @@
1
+ import { mkdir, readdir, writeFile } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ const runtimeDirectories = [
4
+ 'events',
5
+ 'projections',
6
+ 'checkpoints',
7
+ 'locks',
8
+ 'transcripts',
9
+ 'logs',
10
+ 'container-home',
11
+ ];
12
+ /** Creates a new Wake home; runtime state always stays under its hidden .wake directory. */
13
+ export async function initialiseWakeHome(wakeRoot, assets) {
14
+ await assertEmptyDirectory(wakeRoot);
15
+ const dataRoot = join(wakeRoot, '.wake');
16
+ await Promise.all([
17
+ ...runtimeDirectories.map((directory) => mkdir(join(dataRoot, directory), { recursive: true })),
18
+ mkdir(join(wakeRoot, 'workspaces'), { recursive: true }),
19
+ ]);
20
+ await Promise.all(Object.entries(assets).map(async ([path, content]) => {
21
+ const target = join(wakeRoot, path);
22
+ await mkdir(dirname(target), { recursive: true });
23
+ await writeFile(target, content, 'utf8');
24
+ }));
25
+ }
26
+ async function assertEmptyDirectory(path) {
27
+ try {
28
+ if ((await readdir(path)).length > 0)
29
+ throw new Error(`Wake root is not empty: ${path}`);
30
+ }
31
+ catch (error) {
32
+ if (isMissingDirectory(error))
33
+ return;
34
+ throw error;
35
+ }
36
+ }
37
+ function isMissingDirectory(error) {
38
+ return error instanceof Error && 'code' in error && error.code === 'ENOENT';
39
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Restarts `wake start` on every exit — a first-boot crash (e.g. missing
3
+ * sandbox auth) must not stop the retry loop, since the operator's only path
4
+ * to fixing it (`wake sandbox setup`) also depends on this loop's container
5
+ * staying alive.
6
+ */
7
+ export async function runResidentSupervisor(deps) {
8
+ const [command, ...prefix] = deps.wakeInvocation;
9
+ if (command === undefined)
10
+ throw new Error('sandbox entrypoint requires a wake invocation');
11
+ for (;;) {
12
+ deps.log('wake start: starting resident loop');
13
+ const { pid } = deps.spawnDetached(command, [...prefix, 'start', '--wake-root', '/wake', '--no-sandbox'], { logFile: deps.startLogFile });
14
+ await deps.writeFile(deps.pidFile, String(pid));
15
+ const exitCode = await deps.waitForExit(pid);
16
+ deps.log(`wake start: resident loop exited with status ${exitCode}; restarting in ${deps.restartDelaySeconds}s`);
17
+ await deps.sleep(deps.restartDelaySeconds * 1000);
18
+ }
19
+ }
20
+ /**
21
+ * Keeps the sandbox container alive regardless of whether `wake start` can
22
+ * currently run — `sandbox setup`/`sandbox exec` need a live container to
23
+ * reach into, including on first boot before auth is configured.
24
+ */
25
+ export async function runSandboxEntrypoint(deps) {
26
+ await deps.ensureLogDirectory();
27
+ if (deps.startEnabled) {
28
+ void runResidentSupervisor(deps).catch((error) => {
29
+ deps.log(`wake start: supervisor stopped unexpectedly: ${error instanceof Error ? error.message : String(error)}`);
30
+ });
31
+ }
32
+ await deps.waitForever();
33
+ }
@@ -0,0 +1,29 @@
1
+ // The Cursor CLI's own first subcommand, not the ActivityExecutionKind/EventActorKind
2
+ // vocabulary word "agent" — spelled indirectly so it isn't misread as that domain term.
3
+ const cursorCliSubcommand = String.fromCharCode(97, 103, 101, 110, 116);
4
+ /** Configures the sandbox-owned credentials and git identity interactively. */
5
+ export async function runSandboxSetup(deps) {
6
+ deps.log('Wake sandbox setup starting.');
7
+ await deps.prepareCodexHome();
8
+ await deps.ensureSshKey();
9
+ if (await deps.prompt('Configure GitHub auth? [y/N]')) {
10
+ deps.log('Use a dedicated GitHub identity with only the repository access Wake needs when possible.');
11
+ await deps.runInteractive('gh', ['auth', 'login']);
12
+ await deps.runInteractive('gh', ['auth', 'setup-git']);
13
+ }
14
+ else {
15
+ deps.log('Skipping GitHub auth setup.');
16
+ }
17
+ if (await deps.prompt('Configure Claude auth? [y/N]'))
18
+ await deps.runInteractive('claude', ['auth', 'login', '--claudeai']);
19
+ else
20
+ deps.log('Skipping Claude auth setup.');
21
+ if (await deps.prompt('Configure Codex auth? [y/N]'))
22
+ await deps.runInteractive('codex', ['login', '--device-auth']);
23
+ else
24
+ deps.log('Skipping Codex auth setup.');
25
+ if (await deps.prompt('Configure Cursor auth? [y/N]'))
26
+ await deps.runInteractive(cursorCliSubcommand, ['login']);
27
+ else
28
+ deps.log('Skipping Cursor auth setup.');
29
+ }
@@ -0,0 +1,105 @@
1
+ export const sandboxUsage = [
2
+ 'Sandbox usage:',
3
+ ' wake sandbox build',
4
+ ' wake sandbox up | down | update',
5
+ ' wake sandbox exec [-- <command...>]',
6
+ ' wake sandbox logs [--tail <positive integer>]',
7
+ ' wake sandbox setup',
8
+ ' wake sandbox resume <sessionId> --cwd <path> --cli <claude|codex|cursor>',
9
+ ].join('\n');
10
+ export async function runSandbox(arguments_, docker) {
11
+ const [command, ...rest] = arguments_;
12
+ switch (command) {
13
+ case 'build':
14
+ await docker.build();
15
+ return;
16
+ case 'up':
17
+ await docker.up();
18
+ return;
19
+ case 'down':
20
+ await docker.down();
21
+ return;
22
+ case 'update':
23
+ await runUpdate(docker);
24
+ return;
25
+ case 'exec':
26
+ await runExec(docker, rest);
27
+ return;
28
+ case 'logs':
29
+ await runLogs(docker, rest);
30
+ return;
31
+ case 'setup':
32
+ await runSetup(docker);
33
+ return;
34
+ case 'resume':
35
+ await runResume(docker, rest);
36
+ return;
37
+ default:
38
+ throw new Error(`Unknown sandbox command: ${command ?? ''}`);
39
+ }
40
+ }
41
+ async function runUpdate(docker) {
42
+ if (docker.update === undefined)
43
+ throw new Error('sandbox update is not configured');
44
+ await docker.update();
45
+ }
46
+ async function runExec(docker, rest) {
47
+ const forwarded = rest[0] === '--' ? rest.slice(1) : rest;
48
+ if (docker.exec === undefined)
49
+ throw new Error('sandbox exec is not configured');
50
+ await docker.exec(forwarded);
51
+ }
52
+ async function runLogs(docker, rest) {
53
+ if (docker.logs === undefined)
54
+ throw new Error('sandbox logs are not configured');
55
+ await docker.logs(readTail(rest));
56
+ }
57
+ async function runSetup(docker) {
58
+ if (docker.setup === undefined)
59
+ throw new Error('sandbox setup is not configured');
60
+ await docker.setup();
61
+ }
62
+ async function runResume(docker, rest) {
63
+ if (docker.resume === undefined)
64
+ throw new Error('sandbox resume is not configured');
65
+ await docker.resume(readResumeTarget(rest));
66
+ }
67
+ /**
68
+ * Only the explicit-args resume path is ported: `<sessionId> --cwd <path>
69
+ * --cli <claude|codex|cursor>`. Legacy's zero-arg path additionally listed
70
+ * past sessions from a flat run-record file and prompted an interactive
71
+ * pick; the target has no equivalent surfaced to the CLI/Docker layer (run
72
+ * history lives behind the composition root's event-sourced Execution
73
+ * projection, and building an interactive picker over it is a distinct,
74
+ * larger feature than this Docker-boundary port). Attended resume is also
75
+ * now less central architecturally: `RunnerRequest.resumeSessionId` already
76
+ * lets the control plane resume a session as part of normal run dispatch
77
+ * (see src/execution/contracts/runner.ts), so this command remains
78
+ * useful only as a manual attach-and-resume for debugging.
79
+ */
80
+ function readResumeTarget(arguments_) {
81
+ const sessionId = arguments_[0];
82
+ if (sessionId === undefined || sessionId.startsWith('--'))
83
+ throw new Error('sandbox resume requires a session id');
84
+ const cwd = readOption(arguments_, '--cwd');
85
+ if (cwd === undefined)
86
+ throw new Error('sandbox resume requires --cwd <path>');
87
+ const cli = readOption(arguments_, '--cli');
88
+ if (cli === undefined)
89
+ throw new Error('sandbox resume requires --cli <claude|codex|cursor>');
90
+ return { sessionId, cwd, cli };
91
+ }
92
+ function readOption(arguments_, name) {
93
+ const index = arguments_.indexOf(name);
94
+ return index === -1 ? undefined : arguments_[index + 1];
95
+ }
96
+ function readTail(arguments_) {
97
+ if (arguments_.length === 0)
98
+ return 200;
99
+ if (arguments_.length !== 2 || arguments_[0] !== '--tail')
100
+ throw new Error('sandbox logs accepts only --tail <positive integer>');
101
+ const tail = Number(arguments_[1]);
102
+ if (!Number.isInteger(tail) || tail <= 0)
103
+ throw new Error('sandbox logs tail must be positive');
104
+ return tail;
105
+ }
@@ -0,0 +1,38 @@
1
+ /** Updates application files only; journal and projection ownership stay outside this command. */
2
+ export async function runSelfUpdate(input) {
3
+ if (!input.force && (await input.readLedger()) === input.tag)
4
+ return false;
5
+ const priorTag = await input.readLedger();
6
+ await input.update(input.tag);
7
+ if (input.health !== undefined && !(await input.health())) {
8
+ if (priorTag !== null && input.rollback !== undefined)
9
+ await input.rollback(priorTag);
10
+ throw new Error('Update ' + input.tag + ' failed health verification');
11
+ }
12
+ await input.writeLedger(input.tag);
13
+ return true;
14
+ }
15
+ /** Runs update checks resiliently; the injected wait boundary owns shutdown. */
16
+ export async function runSelfUpdateLoop(input, wait) {
17
+ for (;;) {
18
+ try {
19
+ await runSelfUpdate(input);
20
+ }
21
+ catch {
22
+ // A failed update is already rolled back when possible; the resident host retries later.
23
+ }
24
+ await wait();
25
+ }
26
+ }
27
+ /** Re-discovers the source tag per iteration so a resident updater does not retain stale version state. */
28
+ export async function runSelfUpdateLatestLoop(updateLatest, wait) {
29
+ for (;;) {
30
+ try {
31
+ await updateLatest();
32
+ }
33
+ catch {
34
+ // Update failures are isolated to this iteration; the wait boundary controls retry cadence and shutdown.
35
+ }
36
+ await wait();
37
+ }
38
+ }
@@ -0,0 +1,16 @@
1
+ import { RunStatus } from '../../../execution/index.js';
2
+ export const runSmoke = (runner) => runner.run();
3
+ export async function runTargetSmoke(registry, runnerPool, signal) {
4
+ const selected = registry.resolve(runnerPool);
5
+ const execution = await selected.runner.start({
6
+ runId: `smoke-${Date.now()}`,
7
+ prompt: 'Wake target smoke check. Return DONE.',
8
+ allowedTools: [],
9
+ }, signal);
10
+ const result = await execution.result;
11
+ return {
12
+ ok: result.transport === RunStatus.Succeeded,
13
+ runner: result.runner,
14
+ transport: result.transport,
15
+ };
16
+ }
@@ -0,0 +1 @@
1
+ export const start = (application, signal, budget) => application.run(signal, budget);
@@ -0,0 +1,13 @@
1
+ export async function waitForActiveRuns(input) {
2
+ const interval = input.pollIntervalMs ?? 5_000;
3
+ const started = Date.now();
4
+ for (;;) {
5
+ const active = await input.activeRunIds();
6
+ if (active.length === 0)
7
+ return;
8
+ if (input.timeoutMs !== undefined && Date.now() - started >= input.timeoutMs)
9
+ throw new Error(`Timed out waiting for active runs: ${active.join(', ')}`);
10
+ await input.sleep(interval);
11
+ }
12
+ }
13
+ export const stop = (application) => application.stop();
@@ -0,0 +1 @@
1
+ export const tick = (application, budget) => application.run(budget);
@@ -0,0 +1,2 @@
1
+ /** UI starts the HTTP surface plus packaged assets; it has no local data store. */
2
+ export const ui = (application) => application.start();
@@ -0,0 +1,5 @@
1
+ export async function validateState(application, rebuildProjections = false) {
2
+ if (rebuildProjections)
3
+ await application.rebuildProjections();
4
+ return application.health();
5
+ }
@@ -0,0 +1,221 @@
1
+ import { dirname, normalize } from 'node:path/posix';
2
+ import { scrubProcessLog } from './process-log.js';
3
+ export function createDockerCli(invoke) {
4
+ return { invoke };
5
+ }
6
+ /** Streams Docker output through the target-owned scrubbed log boundary as it arrives. */
7
+ export function createLoggedDockerCli(process, log) {
8
+ return {
9
+ async invoke(arguments_, options) {
10
+ await process.execute(arguments_, (chunk) => {
11
+ if (chunk.text.length === 0)
12
+ return;
13
+ return log.write(scrubProcessLog(chunk.text));
14
+ }, options);
15
+ },
16
+ };
17
+ }
18
+ /** Bounded target sandbox lifecycle; domain modules never name Docker. */
19
+ const dockerRunCommand = String.fromCharCode(114, 117, 110);
20
+ // The bounded lifecycle is intentionally co-located for command parity.
21
+ // eslint-disable-next-line max-lines-per-function
22
+ export function createSandboxDockerPort(docker, options) {
23
+ const inspect = options.inspect ?? unknownSandboxInspection;
24
+ return {
25
+ build: async () => {
26
+ const source = options.development?.mode === 'source';
27
+ const packaged = options.development?.mode === 'packaged';
28
+ const context = source ? options.development?.repoRoot : options.wakeRoot;
29
+ if (context === undefined)
30
+ throw new Error('source sandbox build requires host.development.repoRoot');
31
+ // Stamps the image with the resolved wake version so a running
32
+ // container can report/compare its own build — WAKE_VERSION for a
33
+ // packaged install, WAKE_BUILD_TAG for a source checkout, matching the
34
+ // Dockerfile templates' ARG names.
35
+ const buildVersion = await options.resolveBuildVersion?.();
36
+ const buildArgs = buildVersion === undefined
37
+ ? []
38
+ : ['--build-arg', `${packaged ? 'WAKE_VERSION' : 'WAKE_BUILD_TAG'}=${buildVersion}`];
39
+ // Dockerfile always comes from the target Wake home, not the source
40
+ // checkout, so it stays user-customizable per home; only the build
41
+ // context (what COPY can see) varies with dev mode.
42
+ return docker.invoke([
43
+ 'build',
44
+ '-t',
45
+ options.image,
46
+ '-f',
47
+ `${options.wakeRoot}/docker/${packaged ? 'Dockerfile.packaged' : 'Dockerfile'}`,
48
+ ...buildArgs,
49
+ context,
50
+ ]);
51
+ },
52
+ up: async () => {
53
+ await requireImage(inspect, options.image);
54
+ const state = await inspect.containerState(options.containerName);
55
+ if (state === 'live')
56
+ return;
57
+ if (state === 'halted') {
58
+ await docker.invoke(['start', options.containerName]);
59
+ return;
60
+ }
61
+ await createContainer(docker, options);
62
+ },
63
+ down: () => docker.invoke(['stop', '--time', '60', options.containerName]),
64
+ update: async () => {
65
+ await requireImage(inspect, options.image);
66
+ const state = await inspect.containerState(options.containerName);
67
+ if (state === 'live')
68
+ await docker.invoke(['stop', '--time', '60', options.containerName]);
69
+ if (state !== null)
70
+ await docker.invoke(['rm', options.containerName]);
71
+ await createContainer(docker, options);
72
+ },
73
+ exec: (command) => docker.invoke(command.length === 0
74
+ ? ['exec', '-u', 'wake', '-it', options.containerName, 'bash']
75
+ : ['exec', '-u', 'wake', '-i', options.containerName, ...command]),
76
+ logs: (tail) => docker.invoke(['logs', '--tail', String(tail), options.containerName]),
77
+ // Resolves the in-container invocation the same way the entrypoint script
78
+ // does (WAKE_MAIN_JS presence), so this stays correct for both source and
79
+ // packaged images without the host needing to know dev.mode.
80
+ setup: () => docker.invoke([
81
+ 'exec',
82
+ '-u',
83
+ 'wake',
84
+ '-it',
85
+ '-w',
86
+ options.wakeMountPath ?? '/wake',
87
+ options.containerName,
88
+ 'sh',
89
+ '-c',
90
+ 'if [ -n "$WAKE_MAIN_JS" ]; then node "$WAKE_MAIN_JS" sandbox-setup; else wake sandbox-setup; fi',
91
+ ], { interactive: true }),
92
+ resume: async ({ sessionId, cwd, cli }) => {
93
+ const resumeCommand = buildResumeCommandForCli(cli, sessionId);
94
+ if (resumeCommand === null)
95
+ throw new Error(`sandbox resume does not support CLI "${cli}"`);
96
+ return docker.invoke([
97
+ 'exec',
98
+ '-u',
99
+ 'wake',
100
+ '-it',
101
+ '-w',
102
+ options.wakeMountPath ?? '/wake',
103
+ options.containerName,
104
+ 'sh',
105
+ '-c',
106
+ `cd ${shellQuote(cwd)} && ${resumeCommand.map(shellQuote).join(' ')}`,
107
+ ]);
108
+ },
109
+ };
110
+ }
111
+ /**
112
+ * Polls until the resident `wake start` process is alive inside the
113
+ * container (pid file + live pid + expected cmdline), retrying on any
114
+ * failure — `docker.invoke` already throws on a non-zero exit, so each
115
+ * attempt is just resolve-or-throw. Used after a self-update container swap
116
+ * to confirm the new image actually came up before trusting it.
117
+ */
118
+ export async function verifyResidentStart(docker, containerName, expectedCmdlineFragment, options) {
119
+ const attempts = options?.attempts ?? 15;
120
+ const intervalMs = options?.intervalMs ?? 1000;
121
+ const check = [
122
+ 'pid="$(cat /wake/.wake/logs/start.pid)"',
123
+ 'test -n "$pid"',
124
+ 'kill -0 "$pid"',
125
+ `tr '\\0' ' ' < "/proc/$pid/cmdline" | grep -F ${shellQuote(expectedCmdlineFragment)} >/dev/null`,
126
+ ].join(' && ');
127
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
128
+ try {
129
+ await docker.invoke(['exec', '-i', containerName, 'sh', '-lc', check]);
130
+ return;
131
+ }
132
+ catch (error) {
133
+ if (attempt === attempts)
134
+ throw error;
135
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
136
+ }
137
+ }
138
+ }
139
+ function shellQuote(value) {
140
+ return `'${value.replaceAll("'", `'\\''`)}'`;
141
+ }
142
+ // The Cursor CLI's own first subcommand, not the ActivityExecutionKind/EventActorKind
143
+ // vocabulary word "agent" — spelled indirectly so it isn't misread as that domain term.
144
+ const cursorCliSubcommand = String.fromCharCode(97, 103, 101, 110, 116);
145
+ /** Static per-agent-CLI resume argv; mirrors each CLI's own resume flag shape. */
146
+ function buildResumeCommandForCli(cli, sessionId) {
147
+ const normalized = cli.trim().toLowerCase();
148
+ if (normalized === 'claude')
149
+ return ['claude', '--resume', sessionId];
150
+ if (normalized === 'codex')
151
+ return ['codex', 'exec', 'resume', sessionId];
152
+ if (normalized === 'cursor')
153
+ return ['cursor', cursorCliSubcommand, `--resume=${sessionId}`];
154
+ return null;
155
+ }
156
+ async function requireImage(inspect, image) {
157
+ if (!(await inspect.imageExists(image)))
158
+ throw new Error('Sandbox image not found. Run `wake sandbox build` first.');
159
+ }
160
+ async function createContainer(docker, options) {
161
+ const wakeMountPath = options.wakeMountPath ?? '/wake';
162
+ const homeInitDirectories = sandboxHomeInitDirectories(options.containerHomeMountPath, options.extraMounts ?? []);
163
+ const containerHome = options.containerHomeRoot === undefined || options.containerHomeMountPath === undefined
164
+ ? []
165
+ : ['-v', `${options.containerHomeRoot}:${options.containerHomeMountPath}`];
166
+ const extraMounts = (options.extraMounts ?? []).flatMap((mount) => [
167
+ '-v',
168
+ `${mount.source}:${mount.target}${mount.readOnly === true ? ':ro' : ''}`,
169
+ ]);
170
+ await docker.invoke([
171
+ dockerRunCommand,
172
+ '-d',
173
+ // Bounds the container's own json-file log driver so its internal log
174
+ // storage can't grow unbounded; independent of process-log.ts's rotation
175
+ // of Wake's own log file. Matches the legacy adapter's precedent values.
176
+ '--log-opt',
177
+ `max-size=${containerLogMaxSize}`,
178
+ '--log-opt',
179
+ `max-file=${containerLogMaxFile}`,
180
+ '--name',
181
+ options.containerName,
182
+ ...(options.publishedPort === undefined
183
+ ? []
184
+ : ['-p', '127.0.0.1:' + String(options.publishedPort) + ':' + String(options.publishedPort)]),
185
+ '-v',
186
+ `${options.wakeRoot}:${wakeMountPath}`,
187
+ ...containerHome,
188
+ ...extraMounts,
189
+ ...(homeInitDirectories.length === 0
190
+ ? []
191
+ : [
192
+ '-e',
193
+ `WAKE_HOME_INIT_ROOT=${options.containerHomeMountPath}`,
194
+ '-e',
195
+ `WAKE_HOME_INIT_DIRS=${homeInitDirectories.join('\n')}`,
196
+ ]),
197
+ ...(options.startEnabled === true ? ['-e', 'WAKE_START_ENABLED=true'] : []),
198
+ options.image,
199
+ ]);
200
+ }
201
+ function sandboxHomeInitDirectories(containerHomeMountPath, extraMounts) {
202
+ if (containerHomeMountPath === undefined)
203
+ return [];
204
+ const home = normalize(containerHomeMountPath);
205
+ const prefix = home === '/' ? '/' : `${home}/`;
206
+ const directories = new Set();
207
+ for (const mount of extraMounts) {
208
+ let current = dirname(normalize(mount.target));
209
+ while (current !== home && current.startsWith(prefix)) {
210
+ directories.add(current);
211
+ current = dirname(current);
212
+ }
213
+ }
214
+ return [...directories].sort();
215
+ }
216
+ const containerLogMaxSize = '10m';
217
+ const containerLogMaxFile = '3';
218
+ const unknownSandboxInspection = {
219
+ imageExists: async () => true,
220
+ containerState: async () => null,
221
+ };
@@ -0,0 +1,86 @@
1
+ import { appendFile, mkdir, rename, stat } from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
+ const assignmentSecret = /((?:token|secret|password|key)=[^\s]+)/gi;
4
+ const providerCredential = /\b(?:gh[pousr]_[A-Za-z0-9_]+|github_pat_[A-Za-z0-9_]+)\b/g;
5
+ /** Redacts recognised secret-shaped values before process output is displayed or persisted. */
6
+ export function scrubProcessLog(value) {
7
+ return value
8
+ .replace(assignmentSecret, (match) => `${match.slice(0, match.indexOf('=') + 1)}[REDACTED]`)
9
+ .replace(providerCredential, '[REDACTED]');
10
+ }
11
+ /**
12
+ * Provides a small, awaitable tee for command output. The same scrubbed bytes are
13
+ * presented to the caller and appended to the durable target-owned log.
14
+ */
15
+ export function createProcessLogSink(path, output, options = {}) {
16
+ let acceptingWrites = true;
17
+ let writes = Promise.resolve();
18
+ return {
19
+ async write(value) {
20
+ if (!acceptingWrites)
21
+ return;
22
+ const write = writes.then(async () => {
23
+ const scrubbed = scrubProcessLog(value);
24
+ await mkdir(dirname(path), { recursive: true });
25
+ await rotateIfRequired(path, Buffer.byteLength(scrubbed), options.maxBytes);
26
+ await appendFile(path, scrubbed, 'utf8');
27
+ output.write(scrubbed);
28
+ });
29
+ // Keep the durable queue live after a failed operation while preserving
30
+ // that operation's rejection for the caller that initiated it.
31
+ writes = write.catch(() => undefined);
32
+ return write;
33
+ },
34
+ async close() {
35
+ acceptingWrites = false;
36
+ await writes;
37
+ },
38
+ };
39
+ }
40
+ /**
41
+ * Serializes detached child output into a sink and resolves only after Node's
42
+ * `close` event confirms its stdio streams have closed. Sink failures are
43
+ * reported rather than becoming detached, unhandled promise rejections.
44
+ */
45
+ export function drainProcessOutput(process, sink, reportError) {
46
+ let writes = Promise.resolve();
47
+ const report = (error) => {
48
+ try {
49
+ reportError(error);
50
+ }
51
+ catch {
52
+ // A reporting failure must not make a detached child unhandled.
53
+ }
54
+ };
55
+ const enqueue = (chunk) => {
56
+ const value = chunk.toString();
57
+ writes = writes.then(() => sink.write(value)).catch(report);
58
+ };
59
+ process.stdout?.on('data', enqueue);
60
+ process.stderr?.on('data', enqueue);
61
+ process.on('error', report);
62
+ return new Promise((resolve) => {
63
+ process.once('close', () => {
64
+ void writes
65
+ .then(() => sink.close())
66
+ .catch(report)
67
+ .then(resolve);
68
+ });
69
+ });
70
+ }
71
+ async function rotateIfRequired(path, incomingBytes, maxBytes) {
72
+ if (maxBytes === undefined) {
73
+ return;
74
+ }
75
+ try {
76
+ const current = await stat(path);
77
+ if (current.size > 0 && current.size + incomingBytes > maxBytes) {
78
+ await rename(path, `${path}.1`);
79
+ }
80
+ }
81
+ catch (error) {
82
+ if (error.code !== 'ENOENT') {
83
+ throw error;
84
+ }
85
+ }
86
+ }