smol-symphony 0.1.0 → 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 (627) hide show
  1. package/AGENTS.md +125 -39
  2. package/DESIGN.md +494 -273
  3. package/PRODUCT.md +2 -1
  4. package/README.md +259 -110
  5. package/SPEC.md +565 -1928
  6. package/WORKFLOW.minimal.yaml +34 -0
  7. package/WORKFLOW.template.yaml +1100 -0
  8. package/WORKFLOW.yaml +487 -0
  9. package/assets/skills/symphony-issues/SKILL.md +136 -0
  10. package/assets/symphony-mise.system.toml +68 -0
  11. package/dist/src/bin/symphony.js +30 -0
  12. package/dist/src/bin/symphony.js.map +1 -0
  13. package/dist/src/core/actions/context.js +109 -0
  14. package/dist/src/core/actions/context.js.map +1 -0
  15. package/dist/src/core/actions/parse.js +192 -0
  16. package/dist/src/core/actions/parse.js.map +1 -0
  17. package/dist/src/core/actions/plan.js +197 -0
  18. package/dist/src/core/actions/plan.js.map +1 -0
  19. package/dist/src/core/actions/predicates.js +111 -0
  20. package/dist/src/core/actions/predicates.js.map +1 -0
  21. package/dist/src/core/actions/run-fold.js +248 -0
  22. package/dist/src/core/actions/run-fold.js.map +1 -0
  23. package/dist/src/core/actions/template.js +118 -0
  24. package/dist/src/core/actions/template.js.map +1 -0
  25. package/dist/src/core/cli/args.js +116 -0
  26. package/dist/src/core/cli/args.js.map +1 -0
  27. package/dist/src/core/coerce.js +75 -0
  28. package/dist/src/core/coerce.js.map +1 -0
  29. package/dist/src/core/credential/account-id.js +20 -0
  30. package/dist/src/core/credential/account-id.js.map +1 -0
  31. package/dist/src/core/credential/adapter-config.js +136 -0
  32. package/dist/src/core/credential/adapter-config.js.map +1 -0
  33. package/dist/src/core/credential/availability.js +98 -0
  34. package/dist/src/core/credential/availability.js.map +1 -0
  35. package/dist/src/core/credential/extract.js +228 -0
  36. package/dist/src/core/credential/extract.js.map +1 -0
  37. package/dist/src/core/credential/fake-creds.js +171 -0
  38. package/dist/src/core/credential/fake-creds.js.map +1 -0
  39. package/dist/src/core/credential/identity.js +125 -0
  40. package/dist/src/core/credential/identity.js.map +1 -0
  41. package/dist/src/core/credential/shape.js +230 -0
  42. package/dist/src/core/credential/shape.js.map +1 -0
  43. package/dist/src/core/credential/strings.js +15 -0
  44. package/dist/src/core/credential/strings.js.map +1 -0
  45. package/dist/src/core/doctor/checks.js +303 -0
  46. package/dist/src/core/doctor/checks.js.map +1 -0
  47. package/dist/src/core/git/result.js +107 -0
  48. package/dist/src/core/git/result.js.map +1 -0
  49. package/dist/src/core/http/decisions.js +225 -0
  50. package/dist/src/core/http/decisions.js.map +1 -0
  51. package/dist/src/core/http/render.js +1635 -0
  52. package/dist/src/core/http/render.js.map +1 -0
  53. package/dist/src/core/http/routes.js +145 -0
  54. package/dist/src/core/http/routes.js.map +1 -0
  55. package/dist/src/core/http/views.js +181 -0
  56. package/dist/src/core/http/views.js.map +1 -0
  57. package/dist/src/core/image/managed-image.js +95 -0
  58. package/dist/src/core/image/managed-image.js.map +1 -0
  59. package/dist/src/core/issue/file.js +149 -0
  60. package/dist/src/core/issue/file.js.map +1 -0
  61. package/dist/src/core/issue/parse.js +210 -0
  62. package/dist/src/core/issue/parse.js.map +1 -0
  63. package/dist/src/core/mcp/dispatch.js +239 -0
  64. package/dist/src/core/mcp/dispatch.js.map +1 -0
  65. package/dist/src/core/mcp/post-move.js +92 -0
  66. package/dist/src/core/mcp/post-move.js.map +1 -0
  67. package/dist/src/core/mcp/protocol.js +293 -0
  68. package/dist/src/core/mcp/protocol.js.map +1 -0
  69. package/dist/src/core/mcp/url.js +162 -0
  70. package/dist/src/core/mcp/url.js.map +1 -0
  71. package/dist/src/core/path.js +63 -0
  72. package/dist/src/core/path.js.map +1 -0
  73. package/dist/src/core/reconcile/image-decide.js +48 -0
  74. package/dist/src/core/reconcile/image-decide.js.map +1 -0
  75. package/dist/src/core/reconcile/ledger.js +142 -0
  76. package/dist/src/core/reconcile/ledger.js.map +1 -0
  77. package/dist/src/core/reconcile/pr-classify.js +62 -0
  78. package/dist/src/core/reconcile/pr-classify.js.map +1 -0
  79. package/dist/src/core/reconcile/pr-decide.js +180 -0
  80. package/dist/src/core/reconcile/pr-decide.js.map +1 -0
  81. package/dist/src/core/reconcile/pr-loop.js +161 -0
  82. package/dist/src/core/reconcile/pr-loop.js.map +1 -0
  83. package/dist/src/core/reconcile/pr-notes.js +35 -0
  84. package/dist/src/core/reconcile/pr-notes.js.map +1 -0
  85. package/dist/src/core/reconcile/vm-decide.js +70 -0
  86. package/dist/src/core/reconcile/vm-decide.js.map +1 -0
  87. package/dist/src/core/reconcile/vm-reap.js +207 -0
  88. package/dist/src/core/reconcile/vm-reap.js.map +1 -0
  89. package/dist/src/core/reconcile/workspace-decide.js +162 -0
  90. package/dist/src/core/reconcile/workspace-decide.js.map +1 -0
  91. package/dist/src/core/runlog/summary.js +231 -0
  92. package/dist/src/core/runlog/summary.js.map +1 -0
  93. package/dist/src/core/runner/dispatch-config.js +95 -0
  94. package/dist/src/core/runner/dispatch-config.js.map +1 -0
  95. package/dist/src/core/runner/injection.js +61 -0
  96. package/dist/src/core/runner/injection.js.map +1 -0
  97. package/dist/src/core/runner/mise.js +210 -0
  98. package/dist/src/core/runner/mise.js.map +1 -0
  99. package/dist/src/core/runner/prompt.js +720 -0
  100. package/dist/src/core/runner/prompt.js.map +1 -0
  101. package/dist/src/core/runner/turn.js +242 -0
  102. package/dist/src/core/runner/turn.js.map +1 -0
  103. package/dist/src/core/runner/vm-plan.js +390 -0
  104. package/dist/src/core/runner/vm-plan.js.map +1 -0
  105. package/dist/src/core/schedule/admission.js +123 -0
  106. package/dist/src/core/schedule/admission.js.map +1 -0
  107. package/dist/src/core/schedule/circuit-breaker.js +111 -0
  108. package/dist/src/core/schedule/circuit-breaker.js.map +1 -0
  109. package/dist/src/core/schedule/eligibility.js +83 -0
  110. package/dist/src/core/schedule/eligibility.js.map +1 -0
  111. package/dist/src/core/schedule/reconcile-issue.js +82 -0
  112. package/dist/src/core/schedule/reconcile-issue.js.map +1 -0
  113. package/dist/src/core/schedule/retry.js +96 -0
  114. package/dist/src/core/schedule/retry.js.map +1 -0
  115. package/dist/src/core/schedule/sleep-cycle.js +133 -0
  116. package/dist/src/core/schedule/sleep-cycle.js.map +1 -0
  117. package/dist/src/core/schedule/slots.js +124 -0
  118. package/dist/src/core/schedule/slots.js.map +1 -0
  119. package/dist/src/core/schedule/tick.js +553 -0
  120. package/dist/src/core/schedule/tick.js.map +1 -0
  121. package/dist/src/core/schedule/token-fold.js +181 -0
  122. package/dist/src/core/schedule/token-fold.js.map +1 -0
  123. package/dist/src/core/state-resolve.js +86 -0
  124. package/dist/src/core/state-resolve.js.map +1 -0
  125. package/dist/src/core/vm-guards.js +278 -0
  126. package/dist/src/core/vm-guards.js.map +1 -0
  127. package/dist/src/core/workflow/derive.js +107 -0
  128. package/dist/src/core/workflow/derive.js.map +1 -0
  129. package/dist/src/core/workflow/parse.js +687 -0
  130. package/dist/src/core/workflow/parse.js.map +1 -0
  131. package/dist/src/core/workflow/prompt-probe.js +78 -0
  132. package/dist/src/core/workflow/prompt-probe.js.map +1 -0
  133. package/dist/src/core/workflow/validate.js +189 -0
  134. package/dist/src/core/workflow/validate.js.map +1 -0
  135. package/dist/src/core/workspace-key.js +19 -0
  136. package/dist/src/core/workspace-key.js.map +1 -0
  137. package/dist/src/shell/actions-runner.js +356 -0
  138. package/dist/src/shell/actions-runner.js.map +1 -0
  139. package/dist/src/shell/adapter/adapter-registry.js +45 -0
  140. package/dist/src/shell/adapter/adapter-registry.js.map +1 -0
  141. package/dist/src/shell/adapter/clock-random.js +96 -0
  142. package/dist/src/shell/adapter/clock-random.js.map +1 -0
  143. package/dist/src/shell/adapter/gondolin-dispatch-helpers.js +158 -0
  144. package/dist/src/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
  145. package/dist/src/shell/adapter/gondolin-dispatch.js +385 -0
  146. package/dist/src/shell/adapter/gondolin-dispatch.js.map +1 -0
  147. package/dist/src/shell/adapter/gondolin-image-converter.js +233 -0
  148. package/dist/src/shell/adapter/gondolin-image-converter.js.map +1 -0
  149. package/dist/src/shell/adapter/gondolin-image-fetch.js +180 -0
  150. package/dist/src/shell/adapter/gondolin-image-fetch.js.map +1 -0
  151. package/dist/src/shell/adapter/launcher-asset.js +57 -0
  152. package/dist/src/shell/adapter/launcher-asset.js.map +1 -0
  153. package/dist/src/shell/adapter/mise-config-asset.js +65 -0
  154. package/dist/src/shell/adapter/mise-config-asset.js.map +1 -0
  155. package/dist/src/shell/adapter/workflow-loader.js +304 -0
  156. package/dist/src/shell/adapter/workflow-loader.js.map +1 -0
  157. package/dist/src/shell/cli/doctor.js +268 -0
  158. package/dist/src/shell/cli/doctor.js.map +1 -0
  159. package/dist/src/shell/effect-interpreter-families.js +314 -0
  160. package/dist/src/shell/effect-interpreter-families.js.map +1 -0
  161. package/dist/src/shell/effect-interpreter.js +29 -0
  162. package/dist/src/shell/effect-interpreter.js.map +1 -0
  163. package/dist/src/shell/interp/acp-frame.js +137 -0
  164. package/dist/src/shell/interp/acp-frame.js.map +1 -0
  165. package/dist/src/shell/interp/acp-ws-conn.js +320 -0
  166. package/dist/src/shell/interp/acp-ws-conn.js.map +1 -0
  167. package/dist/src/shell/interp/acp-ws-frames.js +159 -0
  168. package/dist/src/shell/interp/acp-ws-frames.js.map +1 -0
  169. package/dist/src/shell/interp/acp-ws.js +197 -0
  170. package/dist/src/shell/interp/acp-ws.js.map +1 -0
  171. package/dist/src/shell/interp/acp.js +319 -0
  172. package/dist/src/shell/interp/acp.js.map +1 -0
  173. package/dist/src/shell/interp/credential-defaults.js +128 -0
  174. package/dist/src/shell/interp/credential-defaults.js.map +1 -0
  175. package/dist/src/shell/interp/credential-hooks.js +149 -0
  176. package/dist/src/shell/interp/credential-hooks.js.map +1 -0
  177. package/dist/src/shell/interp/credential-registry.js +226 -0
  178. package/dist/src/shell/interp/credential-registry.js.map +1 -0
  179. package/dist/src/shell/interp/credential.js +103 -0
  180. package/dist/src/shell/interp/credential.js.map +1 -0
  181. package/dist/src/shell/interp/gh.js +163 -0
  182. package/dist/src/shell/interp/gh.js.map +1 -0
  183. package/dist/src/shell/interp/git.js +28 -0
  184. package/dist/src/shell/interp/git.js.map +1 -0
  185. package/dist/src/shell/interp/log.js +213 -0
  186. package/dist/src/shell/interp/log.js.map +1 -0
  187. package/dist/src/shell/interp/process.js +178 -0
  188. package/dist/src/shell/interp/process.js.map +1 -0
  189. package/dist/src/shell/interp/runlog.js +193 -0
  190. package/dist/src/shell/interp/runlog.js.map +1 -0
  191. package/dist/src/shell/interp/timer.js +64 -0
  192. package/dist/src/shell/interp/timer.js.map +1 -0
  193. package/dist/src/shell/interp/tracker-disk.js +99 -0
  194. package/dist/src/shell/interp/tracker-disk.js.map +1 -0
  195. package/dist/src/shell/interp/tracker-parse.js +71 -0
  196. package/dist/src/shell/interp/tracker-parse.js.map +1 -0
  197. package/dist/src/shell/interp/tracker-scan.js +238 -0
  198. package/dist/src/shell/interp/tracker-scan.js.map +1 -0
  199. package/dist/src/shell/interp/tracker-write.js +91 -0
  200. package/dist/src/shell/interp/tracker-write.js.map +1 -0
  201. package/dist/src/shell/interp/tracker.js +41 -0
  202. package/dist/src/shell/interp/tracker.js.map +1 -0
  203. package/dist/src/shell/interp/tty.js +48 -0
  204. package/dist/src/shell/interp/tty.js.map +1 -0
  205. package/dist/src/shell/interp/vm.js +199 -0
  206. package/dist/src/shell/interp/vm.js.map +1 -0
  207. package/dist/src/shell/interp/workspace.js +310 -0
  208. package/dist/src/shell/interp/workspace.js.map +1 -0
  209. package/dist/src/shell/main-acp.js +78 -0
  210. package/dist/src/shell/main-acp.js.map +1 -0
  211. package/dist/src/shell/main-adapters.js +222 -0
  212. package/dist/src/shell/main-adapters.js.map +1 -0
  213. package/dist/src/shell/main-credential.js +122 -0
  214. package/dist/src/shell/main-credential.js.map +1 -0
  215. package/dist/src/shell/main-doctor.js +22 -0
  216. package/dist/src/shell/main-doctor.js.map +1 -0
  217. package/dist/src/shell/main-entry.js +46 -0
  218. package/dist/src/shell/main-entry.js.map +1 -0
  219. package/dist/src/shell/main-http-csrf.js +45 -0
  220. package/dist/src/shell/main-http-csrf.js.map +1 -0
  221. package/dist/src/shell/main-http-handler.js +389 -0
  222. package/dist/src/shell/main-http-handler.js.map +1 -0
  223. package/dist/src/shell/main-http-mcp.js +122 -0
  224. package/dist/src/shell/main-http-mcp.js.map +1 -0
  225. package/dist/src/shell/main-http-views.js +253 -0
  226. package/dist/src/shell/main-http-views.js.map +1 -0
  227. package/dist/src/shell/main-http.js +76 -0
  228. package/dist/src/shell/main-http.js.map +1 -0
  229. package/dist/src/shell/main-loops.js +130 -0
  230. package/dist/src/shell/main-loops.js.map +1 -0
  231. package/dist/src/shell/main-mcp.js +129 -0
  232. package/dist/src/shell/main-mcp.js.map +1 -0
  233. package/dist/src/shell/main-orchestrator.js +120 -0
  234. package/dist/src/shell/main-orchestrator.js.map +1 -0
  235. package/dist/src/shell/main-preflight.js +43 -0
  236. package/dist/src/shell/main-preflight.js.map +1 -0
  237. package/dist/src/shell/main-reconcilers-helpers.js +244 -0
  238. package/dist/src/shell/main-reconcilers-helpers.js.map +1 -0
  239. package/dist/src/shell/main-reconcilers-pr.js +148 -0
  240. package/dist/src/shell/main-reconcilers-pr.js.map +1 -0
  241. package/dist/src/shell/main-reconcilers.js +225 -0
  242. package/dist/src/shell/main-reconcilers.js.map +1 -0
  243. package/dist/src/shell/main-runner.js +355 -0
  244. package/dist/src/shell/main-runner.js.map +1 -0
  245. package/dist/src/shell/main-scaffold.js +116 -0
  246. package/dist/src/shell/main-scaffold.js.map +1 -0
  247. package/dist/src/shell/main-shutdown.js +115 -0
  248. package/dist/src/shell/main-shutdown.js.map +1 -0
  249. package/dist/src/shell/main-startup.js +48 -0
  250. package/dist/src/shell/main-startup.js.map +1 -0
  251. package/dist/src/shell/main-substrates.js +43 -0
  252. package/dist/src/shell/main-substrates.js.map +1 -0
  253. package/dist/src/shell/main.js +385 -0
  254. package/dist/src/shell/main.js.map +1 -0
  255. package/dist/src/shell/orchestrator-feedback.js +69 -0
  256. package/dist/src/shell/orchestrator-feedback.js.map +1 -0
  257. package/dist/src/shell/orchestrator-image.js +167 -0
  258. package/dist/src/shell/orchestrator-image.js.map +1 -0
  259. package/dist/src/shell/orchestrator-loop.js +468 -0
  260. package/dist/src/shell/orchestrator-loop.js.map +1 -0
  261. package/dist/src/shell/orchestrator-reconcile.js +36 -0
  262. package/dist/src/shell/orchestrator-reconcile.js.map +1 -0
  263. package/dist/src/shell/reconciler-loop.js +228 -0
  264. package/dist/src/shell/reconciler-loop.js.map +1 -0
  265. package/dist/src/shell/runner-loop-turn.js +301 -0
  266. package/dist/src/shell/runner-loop-turn.js.map +1 -0
  267. package/dist/src/shell/runner-loop.js +338 -0
  268. package/dist/src/shell/runner-loop.js.map +1 -0
  269. package/dist/src/shell/server/http.js +208 -0
  270. package/dist/src/shell/server/http.js.map +1 -0
  271. package/dist/src/shell/server/mcp-runtime-effects.js +237 -0
  272. package/dist/src/shell/server/mcp-runtime-effects.js.map +1 -0
  273. package/dist/src/shell/server/mcp-runtime.js +99 -0
  274. package/dist/src/shell/server/mcp-runtime.js.map +1 -0
  275. package/dist/src/shell/workspace-key.js +14 -0
  276. package/dist/src/shell/workspace-key.js.map +1 -0
  277. package/dist/src/types/acp.js +8 -0
  278. package/dist/src/types/acp.js.map +1 -0
  279. package/dist/src/types/actions/plan.js +6 -0
  280. package/dist/src/types/actions/plan.js.map +1 -0
  281. package/dist/src/types/actions/predicates.js +6 -0
  282. package/dist/src/types/actions/predicates.js.map +1 -0
  283. package/dist/src/types/actions/run-fold.js +8 -0
  284. package/dist/src/types/actions/run-fold.js.map +1 -0
  285. package/dist/src/types/actions.js +7 -0
  286. package/dist/src/types/actions.js.map +1 -0
  287. package/dist/src/types/adapter/clock-random.js +4 -0
  288. package/dist/src/types/adapter/clock-random.js.map +1 -0
  289. package/dist/src/types/adapter/gondolin-image-converter.js +5 -0
  290. package/dist/src/types/adapter/gondolin-image-converter.js.map +1 -0
  291. package/dist/src/types/adapter/gondolin-image-fetch.js +5 -0
  292. package/dist/src/types/adapter/gondolin-image-fetch.js.map +1 -0
  293. package/dist/src/types/adapter/workflow-loader.js +4 -0
  294. package/dist/src/types/adapter/workflow-loader.js.map +1 -0
  295. package/dist/src/types/cli/args.js +8 -0
  296. package/dist/src/types/cli/args.js.map +1 -0
  297. package/dist/src/types/config.js +8 -0
  298. package/dist/src/types/config.js.map +1 -0
  299. package/dist/src/types/credential-interp.js +6 -0
  300. package/dist/src/types/credential-interp.js.map +1 -0
  301. package/dist/src/types/credentials.js +10 -0
  302. package/dist/src/types/credentials.js.map +1 -0
  303. package/dist/src/types/doctor.js +7 -0
  304. package/dist/src/types/doctor.js.map +1 -0
  305. package/dist/src/types/domain.js +7 -0
  306. package/dist/src/types/domain.js.map +1 -0
  307. package/dist/src/types/effect.js +15 -0
  308. package/dist/src/types/effect.js.map +1 -0
  309. package/dist/src/types/errors.js +39 -0
  310. package/dist/src/types/errors.js.map +1 -0
  311. package/dist/src/types/http/decisions.js +6 -0
  312. package/dist/src/types/http/decisions.js.map +1 -0
  313. package/dist/src/types/http/render.js +10 -0
  314. package/dist/src/types/http/render.js.map +1 -0
  315. package/dist/src/types/http/views.js +6 -0
  316. package/dist/src/types/http/views.js.map +1 -0
  317. package/dist/src/types/http.js +9 -0
  318. package/dist/src/types/http.js.map +1 -0
  319. package/dist/src/types/image/managed-image.js +7 -0
  320. package/dist/src/types/image/managed-image.js.map +1 -0
  321. package/dist/src/types/interp/effect-interpreter.js +8 -0
  322. package/dist/src/types/interp/effect-interpreter.js.map +1 -0
  323. package/dist/src/types/interp/tracker.js +7 -0
  324. package/dist/src/types/interp/tracker.js.map +1 -0
  325. package/dist/src/types/issue/file.js +6 -0
  326. package/dist/src/types/issue/file.js.map +1 -0
  327. package/dist/src/types/issue/parse.js +8 -0
  328. package/dist/src/types/issue/parse.js.map +1 -0
  329. package/dist/src/types/main-acp.js +13 -0
  330. package/dist/src/types/main-acp.js.map +1 -0
  331. package/dist/src/types/main-adapters.js +5 -0
  332. package/dist/src/types/main-adapters.js.map +1 -0
  333. package/dist/src/types/main-credential.js +21 -0
  334. package/dist/src/types/main-credential.js.map +1 -0
  335. package/dist/src/types/main-doctor.js +6 -0
  336. package/dist/src/types/main-doctor.js.map +1 -0
  337. package/dist/src/types/main-http-handler.js +12 -0
  338. package/dist/src/types/main-http-handler.js.map +1 -0
  339. package/dist/src/types/main-http.js +5 -0
  340. package/dist/src/types/main-http.js.map +1 -0
  341. package/dist/src/types/main-loops.js +5 -0
  342. package/dist/src/types/main-loops.js.map +1 -0
  343. package/dist/src/types/main-mcp.js +12 -0
  344. package/dist/src/types/main-mcp.js.map +1 -0
  345. package/dist/src/types/main-orchestrator.js +5 -0
  346. package/dist/src/types/main-orchestrator.js.map +1 -0
  347. package/dist/src/types/main-reconcilers.js +11 -0
  348. package/dist/src/types/main-reconcilers.js.map +1 -0
  349. package/dist/src/types/main-runner.js +13 -0
  350. package/dist/src/types/main-runner.js.map +1 -0
  351. package/dist/src/types/main-startup.js +5 -0
  352. package/dist/src/types/main-startup.js.map +1 -0
  353. package/dist/src/types/main-substrates.js +5 -0
  354. package/dist/src/types/main-substrates.js.map +1 -0
  355. package/dist/src/types/mcp/dispatch.js +4 -0
  356. package/dist/src/types/mcp/dispatch.js.map +1 -0
  357. package/dist/src/types/mcp/post-move.js +7 -0
  358. package/dist/src/types/mcp/post-move.js.map +1 -0
  359. package/dist/src/types/mcp.js +9 -0
  360. package/dist/src/types/mcp.js.map +1 -0
  361. package/dist/src/types/ports.js +12 -0
  362. package/dist/src/types/ports.js.map +1 -0
  363. package/dist/src/types/reconcile/image-decide.js +5 -0
  364. package/dist/src/types/reconcile/image-decide.js.map +1 -0
  365. package/dist/src/types/reconcile/ledger.js +7 -0
  366. package/dist/src/types/reconcile/ledger.js.map +1 -0
  367. package/dist/src/types/reconcile/pr-loop.js +8 -0
  368. package/dist/src/types/reconcile/pr-loop.js.map +1 -0
  369. package/dist/src/types/reconcile/vm-reap.js +8 -0
  370. package/dist/src/types/reconcile/vm-reap.js.map +1 -0
  371. package/dist/src/types/reconcile/workspace-decide.js +7 -0
  372. package/dist/src/types/reconcile/workspace-decide.js.map +1 -0
  373. package/dist/src/types/reconcile.js +9 -0
  374. package/dist/src/types/reconcile.js.map +1 -0
  375. package/dist/src/types/runlog.js +7 -0
  376. package/dist/src/types/runlog.js.map +1 -0
  377. package/dist/src/types/runner/actions-runner.js +12 -0
  378. package/dist/src/types/runner/actions-runner.js.map +1 -0
  379. package/dist/src/types/runner/gondolin-dispatch.js +5 -0
  380. package/dist/src/types/runner/gondolin-dispatch.js.map +1 -0
  381. package/dist/src/types/runner/injection.js +6 -0
  382. package/dist/src/types/runner/injection.js.map +1 -0
  383. package/dist/src/types/runner/runner-loop.js +5 -0
  384. package/dist/src/types/runner/runner-loop.js.map +1 -0
  385. package/dist/src/types/runner/turn.js +4 -0
  386. package/dist/src/types/runner/turn.js.map +1 -0
  387. package/dist/src/types/runner/vm-plan.js +4 -0
  388. package/dist/src/types/runner/vm-plan.js.map +1 -0
  389. package/dist/src/types/runtime.js +9 -0
  390. package/dist/src/types/runtime.js.map +1 -0
  391. package/dist/src/types/schedule/admission.js +7 -0
  392. package/dist/src/types/schedule/admission.js.map +1 -0
  393. package/dist/src/types/schedule/circuit-breaker.js +2 -0
  394. package/dist/src/types/schedule/circuit-breaker.js.map +1 -0
  395. package/dist/src/types/schedule/eligibility.js +9 -0
  396. package/dist/src/types/schedule/eligibility.js.map +1 -0
  397. package/dist/src/types/schedule/orchestrator-loop.js +10 -0
  398. package/dist/src/types/schedule/orchestrator-loop.js.map +1 -0
  399. package/dist/src/types/schedule/sleep-cycle.js +4 -0
  400. package/dist/src/types/schedule/sleep-cycle.js.map +1 -0
  401. package/dist/src/types/schedule/slots.js +8 -0
  402. package/dist/src/types/schedule/slots.js.map +1 -0
  403. package/dist/src/types/schedule/tick.js +9 -0
  404. package/dist/src/types/schedule/tick.js.map +1 -0
  405. package/dist/src/types/server/mcp-runtime.js +8 -0
  406. package/dist/src/types/server/mcp-runtime.js.map +1 -0
  407. package/dist/src/types/workflow/parse.js +4 -0
  408. package/dist/src/types/workflow/parse.js.map +1 -0
  409. package/dist/tests/core/account-id.test.js +35 -0
  410. package/dist/tests/core/account-id.test.js.map +1 -0
  411. package/dist/tests/core/actions-parse.test.js +176 -0
  412. package/dist/tests/core/actions-parse.test.js.map +1 -0
  413. package/dist/tests/core/adapter-config.test.js +133 -0
  414. package/dist/tests/core/adapter-config.test.js.map +1 -0
  415. package/dist/tests/core/admission.test.js +215 -0
  416. package/dist/tests/core/admission.test.js.map +1 -0
  417. package/dist/tests/core/args.test.js +132 -0
  418. package/dist/tests/core/args.test.js.map +1 -0
  419. package/dist/tests/core/availability.test.js +62 -0
  420. package/dist/tests/core/availability.test.js.map +1 -0
  421. package/dist/tests/core/checks.test.js +395 -0
  422. package/dist/tests/core/checks.test.js.map +1 -0
  423. package/dist/tests/core/circuit-breaker.test.js +172 -0
  424. package/dist/tests/core/circuit-breaker.test.js.map +1 -0
  425. package/dist/tests/core/coerce.test.js +87 -0
  426. package/dist/tests/core/coerce.test.js.map +1 -0
  427. package/dist/tests/core/context.test.js +228 -0
  428. package/dist/tests/core/context.test.js.map +1 -0
  429. package/dist/tests/core/decisions.test.js +310 -0
  430. package/dist/tests/core/decisions.test.js.map +1 -0
  431. package/dist/tests/core/derive.test.js +205 -0
  432. package/dist/tests/core/derive.test.js.map +1 -0
  433. package/dist/tests/core/dispatch-config.test.js +164 -0
  434. package/dist/tests/core/dispatch-config.test.js.map +1 -0
  435. package/dist/tests/core/dispatch.test.js +302 -0
  436. package/dist/tests/core/dispatch.test.js.map +1 -0
  437. package/dist/tests/core/eligibility.test.js +163 -0
  438. package/dist/tests/core/eligibility.test.js.map +1 -0
  439. package/dist/tests/core/extract.test.js +139 -0
  440. package/dist/tests/core/extract.test.js.map +1 -0
  441. package/dist/tests/core/fake-creds.test.js +134 -0
  442. package/dist/tests/core/fake-creds.test.js.map +1 -0
  443. package/dist/tests/core/file.test.js +197 -0
  444. package/dist/tests/core/file.test.js.map +1 -0
  445. package/dist/tests/core/git-result.test.js +113 -0
  446. package/dist/tests/core/git-result.test.js.map +1 -0
  447. package/dist/tests/core/identity.test.js +180 -0
  448. package/dist/tests/core/identity.test.js.map +1 -0
  449. package/dist/tests/core/image-decide.test.js +59 -0
  450. package/dist/tests/core/image-decide.test.js.map +1 -0
  451. package/dist/tests/core/injection.test.js +163 -0
  452. package/dist/tests/core/injection.test.js.map +1 -0
  453. package/dist/tests/core/ledger.test.js +218 -0
  454. package/dist/tests/core/ledger.test.js.map +1 -0
  455. package/dist/tests/core/managed-image.test.js +68 -0
  456. package/dist/tests/core/managed-image.test.js.map +1 -0
  457. package/dist/tests/core/mise.test.js +138 -0
  458. package/dist/tests/core/mise.test.js.map +1 -0
  459. package/dist/tests/core/parse.test.js +174 -0
  460. package/dist/tests/core/parse.test.js.map +1 -0
  461. package/dist/tests/core/path.test.js +50 -0
  462. package/dist/tests/core/path.test.js.map +1 -0
  463. package/dist/tests/core/plan.test.js +218 -0
  464. package/dist/tests/core/plan.test.js.map +1 -0
  465. package/dist/tests/core/post-move.test.js +162 -0
  466. package/dist/tests/core/post-move.test.js.map +1 -0
  467. package/dist/tests/core/pr-classify.test.js +117 -0
  468. package/dist/tests/core/pr-classify.test.js.map +1 -0
  469. package/dist/tests/core/pr-decide.test.js +298 -0
  470. package/dist/tests/core/pr-decide.test.js.map +1 -0
  471. package/dist/tests/core/pr-loop.test.js +301 -0
  472. package/dist/tests/core/pr-loop.test.js.map +1 -0
  473. package/dist/tests/core/pr-notes.test.js +165 -0
  474. package/dist/tests/core/pr-notes.test.js.map +1 -0
  475. package/dist/tests/core/predicates.test.js +154 -0
  476. package/dist/tests/core/predicates.test.js.map +1 -0
  477. package/dist/tests/core/prompt.test.js +189 -0
  478. package/dist/tests/core/prompt.test.js.map +1 -0
  479. package/dist/tests/core/protocol.test.js +195 -0
  480. package/dist/tests/core/protocol.test.js.map +1 -0
  481. package/dist/tests/core/reconcile-issue.test.js +116 -0
  482. package/dist/tests/core/reconcile-issue.test.js.map +1 -0
  483. package/dist/tests/core/render.test.js +549 -0
  484. package/dist/tests/core/render.test.js.map +1 -0
  485. package/dist/tests/core/retry.test.js +186 -0
  486. package/dist/tests/core/retry.test.js.map +1 -0
  487. package/dist/tests/core/routes.test.js +247 -0
  488. package/dist/tests/core/routes.test.js.map +1 -0
  489. package/dist/tests/core/run-fold.test.js +299 -0
  490. package/dist/tests/core/run-fold.test.js.map +1 -0
  491. package/dist/tests/core/shape.test.js +185 -0
  492. package/dist/tests/core/shape.test.js.map +1 -0
  493. package/dist/tests/core/sleep-cycle.test.js +150 -0
  494. package/dist/tests/core/sleep-cycle.test.js.map +1 -0
  495. package/dist/tests/core/slots.test.js +201 -0
  496. package/dist/tests/core/slots.test.js.map +1 -0
  497. package/dist/tests/core/state-resolve.test.js +80 -0
  498. package/dist/tests/core/state-resolve.test.js.map +1 -0
  499. package/dist/tests/core/summary.test.js +200 -0
  500. package/dist/tests/core/summary.test.js.map +1 -0
  501. package/dist/tests/core/template.test.js +116 -0
  502. package/dist/tests/core/template.test.js.map +1 -0
  503. package/dist/tests/core/tick.test.js +558 -0
  504. package/dist/tests/core/tick.test.js.map +1 -0
  505. package/dist/tests/core/token-fold.test.js +176 -0
  506. package/dist/tests/core/token-fold.test.js.map +1 -0
  507. package/dist/tests/core/turn.test.js +388 -0
  508. package/dist/tests/core/turn.test.js.map +1 -0
  509. package/dist/tests/core/url.test.js +118 -0
  510. package/dist/tests/core/url.test.js.map +1 -0
  511. package/dist/tests/core/validate.test.js +247 -0
  512. package/dist/tests/core/validate.test.js.map +1 -0
  513. package/dist/tests/core/views.test.js +252 -0
  514. package/dist/tests/core/views.test.js.map +1 -0
  515. package/dist/tests/core/vm-decide.test.js +110 -0
  516. package/dist/tests/core/vm-decide.test.js.map +1 -0
  517. package/dist/tests/core/vm-guards.test.js +153 -0
  518. package/dist/tests/core/vm-guards.test.js.map +1 -0
  519. package/dist/tests/core/vm-plan.test.js +332 -0
  520. package/dist/tests/core/vm-plan.test.js.map +1 -0
  521. package/dist/tests/core/vm-reap.test.js +196 -0
  522. package/dist/tests/core/vm-reap.test.js.map +1 -0
  523. package/dist/tests/core/workflow-parse.test.js +493 -0
  524. package/dist/tests/core/workflow-parse.test.js.map +1 -0
  525. package/dist/tests/core/workspace-decide.test.js +236 -0
  526. package/dist/tests/core/workspace-decide.test.js.map +1 -0
  527. package/dist/tests/helpers/fixtures.js +167 -0
  528. package/dist/tests/helpers/fixtures.js.map +1 -0
  529. package/dist/tests/shell/acp-substrate.test.js +101 -0
  530. package/dist/tests/shell/acp-substrate.test.js.map +1 -0
  531. package/dist/tests/shell/actions-runner-push.test.js +203 -0
  532. package/dist/tests/shell/actions-runner-push.test.js.map +1 -0
  533. package/dist/tests/shell/credential-hooks.test.js +36 -0
  534. package/dist/tests/shell/credential-hooks.test.js.map +1 -0
  535. package/dist/tests/shell/credential-registry.test.js +165 -0
  536. package/dist/tests/shell/credential-registry.test.js.map +1 -0
  537. package/dist/tests/shell/credential-substrate.test.js +179 -0
  538. package/dist/tests/shell/credential-substrate.test.js.map +1 -0
  539. package/dist/tests/shell/dockerfile-mise-pin.test.js +51 -0
  540. package/dist/tests/shell/dockerfile-mise-pin.test.js.map +1 -0
  541. package/dist/tests/shell/doctor.test.js +101 -0
  542. package/dist/tests/shell/doctor.test.js.map +1 -0
  543. package/dist/tests/shell/effect-vm-create.test.js +52 -0
  544. package/dist/tests/shell/effect-vm-create.test.js.map +1 -0
  545. package/dist/tests/shell/gh-port.test.js +63 -0
  546. package/dist/tests/shell/gh-port.test.js.map +1 -0
  547. package/dist/tests/shell/gondolin-dispatch-guard.test.js +144 -0
  548. package/dist/tests/shell/gondolin-dispatch-guard.test.js.map +1 -0
  549. package/dist/tests/shell/gondolin-dispatch-shquote.test.js +168 -0
  550. package/dist/tests/shell/gondolin-dispatch-shquote.test.js.map +1 -0
  551. package/dist/tests/shell/gondolin-image-converter.test.js +208 -0
  552. package/dist/tests/shell/gondolin-image-converter.test.js.map +1 -0
  553. package/dist/tests/shell/gondolin-image-fetch.test.js +93 -0
  554. package/dist/tests/shell/gondolin-image-fetch.test.js.map +1 -0
  555. package/dist/tests/shell/http-handler.test.js +608 -0
  556. package/dist/tests/shell/http-handler.test.js.map +1 -0
  557. package/dist/tests/shell/http-server.test.js +53 -0
  558. package/dist/tests/shell/http-server.test.js.map +1 -0
  559. package/dist/tests/shell/mcp-runtime.test.js +366 -0
  560. package/dist/tests/shell/mcp-runtime.test.js.map +1 -0
  561. package/dist/tests/shell/mise-config-asset.test.js +87 -0
  562. package/dist/tests/shell/mise-config-asset.test.js.map +1 -0
  563. package/dist/tests/shell/orchestrator-loop.test.js +583 -0
  564. package/dist/tests/shell/orchestrator-loop.test.js.map +1 -0
  565. package/dist/tests/shell/reconciler-passes.test.js +314 -0
  566. package/dist/tests/shell/reconciler-passes.test.js.map +1 -0
  567. package/dist/tests/shell/runner-loop-turn.test.js +97 -0
  568. package/dist/tests/shell/runner-loop-turn.test.js.map +1 -0
  569. package/dist/tests/shell/runner-slice.test.js +536 -0
  570. package/dist/tests/shell/runner-slice.test.js.map +1 -0
  571. package/dist/tests/shell/scaffold.test.js +65 -0
  572. package/dist/tests/shell/scaffold.test.js.map +1 -0
  573. package/dist/tests/shell/tick-config.test.js +83 -0
  574. package/dist/tests/shell/tick-config.test.js.map +1 -0
  575. package/dist/tests/shell/tracker-parse-dates.test.js +44 -0
  576. package/dist/tests/shell/tracker-parse-dates.test.js.map +1 -0
  577. package/dist/tests/shell/tracker-write-issue.test.js +154 -0
  578. package/dist/tests/shell/tracker-write-issue.test.js.map +1 -0
  579. package/dist/tests/shell/workflow-prompt-split.test.js +208 -0
  580. package/dist/tests/shell/workflow-prompt-split.test.js.map +1 -0
  581. package/dist/tests/shell/workspace-live-config.test.js +140 -0
  582. package/dist/tests/shell/workspace-live-config.test.js.map +1 -0
  583. package/package.json +31 -11
  584. package/patches/@earendil-works+gondolin+0.12.0.patch +173 -0
  585. package/prompts/Reflect.md +91 -0
  586. package/prompts/Review.md +97 -0
  587. package/prompts/Todo.md +96 -0
  588. package/prompts/_footer.md +41 -0
  589. package/prompts/_preamble.md +42 -0
  590. package/prompts-minimal/Todo.md +26 -0
  591. package/scripts/postinstall.mjs +63 -0
  592. package/scripts/vm-agent.mjs +433 -0
  593. package/WORKFLOW.md +0 -269
  594. package/WORKFLOW.template.md +0 -307
  595. package/dist/agent/acp.js +0 -304
  596. package/dist/agent/acp.js.map +0 -1
  597. package/dist/agent/adapters.js +0 -275
  598. package/dist/agent/adapters.js.map +0 -1
  599. package/dist/agent/codex.js +0 -439
  600. package/dist/agent/codex.js.map +0 -1
  601. package/dist/agent/runner.js +0 -394
  602. package/dist/agent/runner.js.map +0 -1
  603. package/dist/agent/smolvm.js +0 -174
  604. package/dist/agent/smolvm.js.map +0 -1
  605. package/dist/bin/symphony.js +0 -205
  606. package/dist/bin/symphony.js.map +0 -1
  607. package/dist/http.js +0 -1189
  608. package/dist/http.js.map +0 -1
  609. package/dist/logging.js +0 -45
  610. package/dist/logging.js.map +0 -1
  611. package/dist/mcp.js +0 -478
  612. package/dist/mcp.js.map +0 -1
  613. package/dist/orchestrator.js +0 -683
  614. package/dist/orchestrator.js.map +0 -1
  615. package/dist/prompt.js +0 -65
  616. package/dist/prompt.js.map +0 -1
  617. package/dist/trackers/local.js +0 -344
  618. package/dist/trackers/local.js.map +0 -1
  619. package/dist/trackers/types.js +0 -10
  620. package/dist/trackers/types.js.map +0 -1
  621. package/dist/types.js +0 -3
  622. package/dist/types.js.map +0 -1
  623. package/dist/workflow.js +0 -385
  624. package/dist/workflow.js.map +0 -1
  625. package/dist/workspace.js +0 -196
  626. package/dist/workspace.js.map +0 -1
  627. package/scripts/build-vm.sh +0 -67
@@ -0,0 +1,68 @@
1
+ # Symphony-bundled mise (jdx/mise) SYSTEM config — issue 209.
2
+ #
3
+ # The orchestrator stages this file into EVERY agent VM at /etc/mise/config.toml
4
+ # (mise's SYSTEM config = LOWEST precedence; applies everywhere, overridable per
5
+ # project). It is the SINGLE source of truth for the agent runtime (node) + the ACP
6
+ # agent CLIs — read off the host's OWN disk at boot and staged per-dispatch (like the
7
+ # vm-agent launcher), so it is decoupled from the image digest. Bump a pin HERE and
8
+ # restart symphony; NO `npm run build:image` + digest repin is needed. That decoupling
9
+ # is the whole point of issue 209: agent-CLI versioning is no longer coupled to the
10
+ # base image.
11
+ #
12
+ # Pins MUST match the versions the host ACP transport speaks. ALL agent CLIs are
13
+ # pinned DELIBERATELY: an unpinned bump can silently change codex's Responses-API
14
+ # transport, opencode's acp/custom-provider behavior, or Claude Code's model-stream
15
+ # handling (an unpinned claude-code 2.1.156 -> 2.1.160 once stalled dispatches mid-turn,
16
+ # idle on the /v1/messages stream until the stall reaper killed them). Bump these
17
+ # consciously, not by drift.
18
+ #
19
+ # node stays >= 21: the in-VM launcher needs the global WHATWG WebSocket. The agent
20
+ # runtime node is resolved system-scoped (`mise which node` from `/`), so a consuming
21
+ # repo's mise.toml can override `node` for the PROJECT's build/test (the workspace
22
+ # shims) WITHOUT downgrading the agent itself.
23
+ #
24
+ # A consuming repo's own mise.toml / .tool-versions (HIGHER precedence) ADDS project
25
+ # toolchains (rust, go, kotlin+gradle, a different node, ...) on top of this set;
26
+ # `mise install` with cwd = workspace installs the MERGED system + project tool set
27
+ # into the shared, home-based, warm-cached data dir.
28
+ #
29
+ # The `npm:` backend installs an npm package and exposes its bins as mise shims; node
30
+ # comes from mise's core node backend (nodejs.org prebuilts).
31
+ #
32
+ # ── npm lifecycle scripts (load-bearing — issue 209 review) ──────────────────────
33
+ # mise's `npm:` backend installs with `--ignore-scripts=true` by DEFAULT (a supply-
34
+ # chain hardening default; see mise.jdx.dev/dev-tools/backends/npm). That SUPPRESSES
35
+ # the package `postinstall` hooks that some agent CLIs use to materialize their native
36
+ # binary, so a plain string pin would `mise install` cleanly but then fail at RUNTIME
37
+ # when the CLI tries to exec a missing/stub binary. Two of our pins ship a native
38
+ # binary via a `postinstall` (verified against the registry metadata for the pinned
39
+ # versions):
40
+ # • @anthropic-ai/claude-code → "postinstall": "node install.cjs" (bin: claude.exe)
41
+ # • opencode-ai → "postinstall": "node ./postinstall.mjs" (bin: opencode.exe)
42
+ # @openai/codex + @zed-industries/codex-acp ship their native binary via
43
+ # optionalDependencies platform packages resolved at runtime by a JS bin shim
44
+ # (bin/codex.js, bin/codex-acp.js) and declare NO install script; they don't strictly
45
+ # need scripts, but we enable them UNIFORMLY across the native-binary CLIs so the
46
+ # contract is robust to version drift and to the platform packages' own install steps.
47
+ # @agentclientprotocol/claude-agent-acp is pure JS (ships dist/) with no native binary
48
+ # and no install hook, so it stays a plain pin.
49
+ #
50
+ # Opting back in uses the per-tool `npm_args = "--ignore-scripts=false"` option, which
51
+ # ONLY takes effect when npm is the active package manager — hence the explicit
52
+ # `[settings.npm] package_manager = "npm"` below. `auto` (the default) would fall back
53
+ # to npm TODAY (the base image ships no bun/pnpm), but a future baked package manager
54
+ # would silently switch and re-suppress scripts; pinning npm locks the contract.
55
+
56
+ [settings.npm]
57
+ # Force npm as the npm-backend installer so the per-tool `npm_args` below reliably
58
+ # apply (bun/pnpm ignore npm_args and don't run lifecycle scripts by default). The
59
+ # base image ships only `mise`; npm comes from the `node` install above.
60
+ package_manager = "npm"
61
+
62
+ [tools]
63
+ node = "24"
64
+ "npm:@anthropic-ai/claude-code" = { version = "2.1.156", npm_args = "--ignore-scripts=false" }
65
+ "npm:@openai/codex" = { version = "0.135.0", npm_args = "--ignore-scripts=false" }
66
+ "npm:@agentclientprotocol/claude-agent-acp" = "0.39.0"
67
+ "npm:@zed-industries/codex-acp" = { version = "0.15.0", npm_args = "--ignore-scripts=false" }
68
+ "npm:opencode-ai" = { version = "1.15.12", npm_args = "--ignore-scripts=false" }
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ // FCIS rewrite — the `symphony` binary ENTRYPOINT.
3
+ //
4
+ // Usage:
5
+ // symphony [path-to-WORKFLOW.yaml] [--port <port>] [--reconcile-force] [--verbose]
6
+ // symphony doctor [path-to-WORKFLOW.yaml] [--port <port>]
7
+ // symphony reconcile [path-to-WORKFLOW.yaml] [--force] [--port <port>]
8
+ //
9
+ // This file is intentionally a one-liner: the ENTIRE composition lives in the
10
+ // single composition root (src/shell/main.ts — the one file allowed to import the
11
+ // functional core). All this entrypoint does is invoke that root's `main()` and
12
+ // translate an unhandled rejection into a non-zero exit. Keeping it this thin
13
+ // means `package.json`'s `bin` target (dist/bin/symphony.js) and the `tsx`
14
+ // dev/start scripts share exactly the wiring path the tests exercise via
15
+ // `main(argv)`.
16
+ //
17
+ // package.json declares: "bin": { "symphony": "dist/bin/symphony.js" }
18
+ // and dev scripts run this file directly via tsx (src/bin/symphony.ts).
19
+ import process from 'node:process';
20
+ import { main } from '../shell/main.js';
21
+ // The composition root installs its own SIGINT/SIGTERM graceful-shutdown handlers
22
+ // and owns every process.exit on the preflight / bind-failure paths. Here we only
23
+ // backstop a thrown/ rejected main() — a startup failure that escaped bailStartup
24
+ // — with a fatal log + non-zero exit so the operator sees the cause.
25
+ main(process.argv.slice(2)).catch((err) => {
26
+ const e = err;
27
+ process.stderr.write(`fatal: ${e.message}\n${e.stack ?? ''}\n`);
28
+ process.exit(1);
29
+ });
30
+ //# sourceMappingURL=symphony.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symphony.js","sourceRoot":"","sources":["../../../src/bin/symphony.ts"],"names":[],"mappings":";AACA,mDAAmD;AACnD,EAAE;AACF,SAAS;AACT,qFAAqF;AACrF,+DAA+D;AAC/D,yEAAyE;AACzE,EAAE;AACF,8EAA8E;AAC9E,kFAAkF;AAClF,gFAAgF;AAChF,8EAA8E;AAC9E,2EAA2E;AAC3E,yEAAyE;AACzE,gBAAgB;AAChB,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AAExE,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,kFAAkF;AAClF,kFAAkF;AAClF,kFAAkF;AAClF,qEAAqE;AACrE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACjD,MAAM,CAAC,GAAG,GAAY,CAAC;IACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,IAAI,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,109 @@
1
+ // FCIS rewrite — pure ActionContext derivation + forwarded-env computation.
2
+ //
3
+ // Ports the two pure helpers from the original
4
+ // `src/agent/runner-decisions.ts` (`deriveActionContext`, `computeForwardedEnv`)
5
+ // plus the credential-strip filter the runner used to layer on top of
6
+ // `computeForwardedEnv` via `src/agent/vm-guards.ts:stripCredentialEnv`.
7
+ //
8
+ // In the original the runner did:
9
+ // stripCredentialEnv(computeForwardedEnv(forward_env, undefined, readEnv))
10
+ // `stripCredentialEnv` is itself a pure string-name filter (no IO), so the
11
+ // FCIS design folds the strip directly into the pure core function: the single
12
+ // `computeForwardedEnv` here returns the boot env with EVERY credential-bearing
13
+ // var already removed. The credential policy itself (`isCredentialEnvName`) is
14
+ // the ONE wired into the running app — it lives in `core/vm-guards.ts` and is
15
+ // re-exported here (no duplicate). The guest holds only placeholders Gondolin
16
+ // substitutes at egress (host-only refresh / placeholder-only guest invariant),
17
+ // so a real token must never enter the forwarded boot env. `readEnv` is injected
18
+ // so the function stays deterministic and unit-testable (no `process.env` in core).
19
+ //
20
+ // HARD CONSTRAINTS (gate-enforced):
21
+ // - 100% SYNCHRONOUS. No async/await/Promise anywhere.
22
+ // - No IO, no node: imports, no process/fetch, no wall clock, no randomness.
23
+ // - Imports ONLY from src/types/** and other pure-core modules (vm-guards).
24
+ /**
25
+ * Map a `RunningEntryView` snapshot + optional staged `SYMPHONY_*` env into the
26
+ * `ActionContext` the actions executor consumes. Mirrors the prior inline
27
+ * fallback chain in the original `buildActionContext` / `deriveActionContext`
28
+ * so a Done state reads `$branch` from the action-template namespace (the staged
29
+ * `SYMPHONY_*` env feeds the fallbacks).
30
+ *
31
+ * Fallback chain (highest → lowest precedence) per field:
32
+ * branch SYMPHONY_BRANCH → `agent/<identifier>`
33
+ * base_branch SYMPHONY_BASE_BRANCH → view.base_branch_at_dispatch → input.baseBranchDefault → 'main'
34
+ * repo repoEnv (SYMPHONY_REPO)→ view.github_repo_at_dispatch → input.repoDefault → null
35
+ * pr_title SYMPHONY_PR_TITLE → `<id>: <title>` (or `<id>` if untitled)
36
+ * pr_body_file SYMPHONY_PR_BODY_FILE → ''
37
+ */
38
+ export function deriveActionContext(input) {
39
+ const { view, extraEnv } = input;
40
+ const issueId = view.issue.id;
41
+ const issueTitle = view.issue.title;
42
+ const trimmedTitle = issueTitle.trim();
43
+ const defaultPrTitle = trimmedTitle.length > 0 ? `${issueId}: ${trimmedTitle}` : issueId;
44
+ // SYMPHONY_REPO wins; then the dispatch-pinned repo; then the live
45
+ // workspace.github_repo default; null when none is set. The cfg fallback is
46
+ // load-bearing because the dispatch-time pin (github_repo_at_dispatch) is not
47
+ // populated yet — without it a Done transition resolves $repo to null and
48
+ // silently skips push_branch / create_pr_if_missing. Mirrors runner-loop.ts's
49
+ // `|| cfg.workspace.github_repo` for the clone path.
50
+ const repoEnv = input.repoEnv;
51
+ const repoFromEnv = repoEnv && repoEnv.length > 0 ? repoEnv : null;
52
+ const repoPinned = view.github_repo_at_dispatch;
53
+ const repoFromPin = repoPinned && repoPinned.length > 0 ? repoPinned : null;
54
+ const repoDefault = input.repoDefault && input.repoDefault.length > 0 ? input.repoDefault : null;
55
+ const repo = repoFromEnv ?? repoFromPin ?? repoDefault;
56
+ // base_branch: staged env → dispatch-pinned base → live workspace.base_branch
57
+ // default → 'main' (the original's literal floor). Same cfg-fallback rationale
58
+ // as $repo: the dispatch-time pin isn't populated yet.
59
+ const pinnedBase = view.base_branch_at_dispatch;
60
+ const baseDefault = input.baseBranchDefault && input.baseBranchDefault.length > 0 ? input.baseBranchDefault : 'main';
61
+ const baseBranch = extraEnv?.SYMPHONY_BASE_BRANCH ?? (pinnedBase.length > 0 ? pinnedBase : baseDefault);
62
+ return {
63
+ identifier: view.identifier,
64
+ workspace: view.workspace_path,
65
+ branch: extraEnv?.SYMPHONY_BRANCH ?? `agent/${view.identifier}`,
66
+ base_branch: baseBranch,
67
+ issue_title: issueTitle,
68
+ issue_body: view.issue.description ?? '',
69
+ repo,
70
+ pr_title: extraEnv?.SYMPHONY_PR_TITLE ?? defaultPrTitle,
71
+ pr_body_file: extraEnv?.SYMPHONY_PR_BODY_FILE ?? '',
72
+ };
73
+ }
74
+ // ─── Forwarded boot env (with credential strip folded in) ────────────────────
75
+ // The strict boot-env credential policy lives canonically in core/vm-guards.ts
76
+ // (the copy actually wired into the running app via runner/vm-plan.ts). It is
77
+ // imported for `computeForwardedEnv` AND re-exported here so this module's
78
+ // importers (and its test) keep the `actions/context.js` specifier without a
79
+ // duplicate definition + duplicate named-set/prefix/suffix constants.
80
+ // vm-guards.ts is pure core, so importing it from another pure-core module is
81
+ // allowed.
82
+ import { isCredentialEnvName } from '../vm-guards.js';
83
+ export { isCredentialEnvName };
84
+ /**
85
+ * Compute the VM boot env from the `forward_env` list, dropping `omitVar` when
86
+ * set AND every credential-bearing var (strict boot-env policy). `omitVar` lets
87
+ * a caller exclude a single var by name; the runner strips all credential vars
88
+ * uniformly (the guest holds only a placeholder Gondolin substitutes at egress),
89
+ * so callers pass `omitVar = undefined` and rely on the credential filter.
90
+ * `readEnv` is injected so this stays deterministic and unit-testable (no
91
+ * `process.env` in core).
92
+ *
93
+ * A name that survives the credential filter but reads as empty/undefined is
94
+ * skipped (the original only forwarded vars with a non-empty value).
95
+ */
96
+ export function computeForwardedEnv(forwardList, omitVar, readEnv) {
97
+ const env = {};
98
+ for (const k of forwardList) {
99
+ if (k === omitVar)
100
+ continue;
101
+ if (isCredentialEnvName(k))
102
+ continue;
103
+ const v = readEnv(k);
104
+ if (v && v.length > 0)
105
+ env[k] = v;
106
+ }
107
+ return env;
108
+ }
109
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/core/actions/context.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,+CAA+C;AAC/C,iFAAiF;AACjF,sEAAsE;AACtE,yEAAyE;AACzE,EAAE;AACF,kCAAkC;AAClC,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,gFAAgF;AAChF,iFAAiF;AACjF,oFAAoF;AACpF,EAAE;AACF,oCAAoC;AACpC,yDAAyD;AACzD,+EAA+E;AAC/E,8EAA8E;AA8B9E;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IACpC,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAEzF,mEAAmE;IACnE,4EAA4E;IAC5E,8EAA8E;IAC9E,0EAA0E;IAC1E,8EAA8E;IAC9E,qDAAqD;IACrD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,MAAM,WAAW,GAAG,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAAC;IAChD,MAAM,WAAW,GAAG,UAAU,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IACjG,MAAM,IAAI,GAAG,WAAW,IAAI,WAAW,IAAI,WAAW,CAAC;IAEvD,8EAA8E;IAC9E,+EAA+E;IAC/E,uDAAuD;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAAC;IAChD,MAAM,WAAW,GACf,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC;IACnG,MAAM,UAAU,GACd,QAAQ,EAAE,oBAAoB,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAEvF,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,CAAC,cAAc;QAC9B,MAAM,EAAE,QAAQ,EAAE,eAAe,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE;QAC/D,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,UAAU;QACvB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE;QACxC,IAAI;QACJ,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,IAAI,cAAc;QACvD,YAAY,EAAE,QAAQ,EAAE,qBAAqB,IAAI,EAAE;KACpD,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,6EAA6E;AAC7E,sEAAsE;AACtE,8EAA8E;AAC9E,WAAW;AACX,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAA8B,EAC9B,OAA2B,EAC3B,OAA4C;IAE5C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,OAAO;YAAE,SAAS;QAC5B,IAAI,mBAAmB,CAAC,CAAC,CAAC;YAAE,SAAS;QACrC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,192 @@
1
+ // FCIS rewrite — pure parser for per-state `actions:` blocks.
2
+ //
3
+ // Functional core: every export here is a pure, synchronous (data) -> data
4
+ // function. No IO, no clock, no randomness, no node: imports. Imports only from
5
+ // src/types. Lifts the YAML shape of a per-state `actions:` block into the
6
+ // closed `WorkflowAction` union, validating each kind's required fields up-front
7
+ // so a missing `head:` on `create_pr_if_missing` (or a misspelled `kind:`) fails
8
+ // at workflow load instead of at the first dispatch into the terminal state.
9
+ //
10
+ // Ported faithfully from the original src/actions/parsing.ts.
11
+ import { WorkflowError } from '../../types/errors.js';
12
+ import { asString, asInt } from '../coerce.js';
13
+ const KNOWN_KINDS = [
14
+ 'push_branch',
15
+ 'create_pr_if_missing',
16
+ 'run_in_vm',
17
+ ];
18
+ function expectString(stateName, idx, kind, key, v) {
19
+ const s = asString(v);
20
+ if (s === null || s.length === 0) {
21
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] (${kind}): "${key}" must be a non-empty string`);
22
+ }
23
+ return s;
24
+ }
25
+ function parsePredicate(stateName, idx, raw) {
26
+ if (raw === undefined || raw === null)
27
+ return null;
28
+ if (typeof raw === 'string')
29
+ return raw;
30
+ if (typeof raw === 'object' && !Array.isArray(raw)) {
31
+ const m = raw;
32
+ if (typeof m.branch_exists === 'string')
33
+ return { branch_exists: m.branch_exists };
34
+ if (typeof m.file_present === 'string')
35
+ return { file_present: m.file_present };
36
+ }
37
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] "if" must be a "$var" string, {branch_exists: <ref>}, or {file_present: <path>}`);
38
+ }
39
+ function parseErrorPolicy(stateName, idx, raw) {
40
+ if (raw === undefined || raw === null)
41
+ return undefined;
42
+ if (typeof raw !== 'object' || Array.isArray(raw)) {
43
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] "on_error" must be a map`);
44
+ }
45
+ const m = raw;
46
+ const out = {};
47
+ if (m.retry !== undefined) {
48
+ if (typeof m.retry !== 'object' || m.retry === null || Array.isArray(m.retry)) {
49
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] "on_error.retry" must be a map`);
50
+ }
51
+ const r = m.retry;
52
+ const count = asInt(r.count);
53
+ const backoff = asInt(r.backoff_ms);
54
+ if (count === null || count < 0) {
55
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] "on_error.retry.count" must be a non-negative integer`);
56
+ }
57
+ if (backoff === null || backoff < 0) {
58
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] "on_error.retry.backoff_ms" must be a non-negative integer`);
59
+ }
60
+ out.retry = { count, backoff_ms: backoff };
61
+ }
62
+ if (m.then !== undefined) {
63
+ const thenRouteTo = typeof m.then === 'object' && m.then !== null && !Array.isArray(m.then)
64
+ ? m.then.route_to
65
+ : undefined;
66
+ if (m.then === 'abort') {
67
+ out.then = 'abort';
68
+ }
69
+ else if (typeof thenRouteTo === 'string') {
70
+ out.then = { route_to: thenRouteTo };
71
+ }
72
+ else {
73
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] "on_error.then" must be "abort" or {route_to: <state>}`);
74
+ }
75
+ }
76
+ return out;
77
+ }
78
+ function parseAction(stateName, idx, raw) {
79
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
80
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] must be a map with a "kind" field`);
81
+ }
82
+ const m = raw;
83
+ const kind = asString(m.kind);
84
+ if (!kind || !KNOWN_KINDS.includes(kind)) {
85
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] "kind" must be one of: ${KNOWN_KINDS.join(', ')} (got: ${String(m.kind)})`);
86
+ }
87
+ const base = {
88
+ name: asString(m.name) ?? undefined,
89
+ if: parsePredicate(stateName, idx, m.if),
90
+ on_error: parseErrorPolicy(stateName, idx, m.on_error),
91
+ };
92
+ // Strip undefined to keep parsed records clean (deep-equal in tests).
93
+ const cleanBase = {};
94
+ if (base.name !== undefined)
95
+ cleanBase.name = base.name;
96
+ if (base.if !== null)
97
+ cleanBase.if = base.if;
98
+ if (base.on_error !== undefined)
99
+ cleanBase.on_error = base.on_error;
100
+ switch (kind) {
101
+ case 'push_branch':
102
+ return {
103
+ kind: 'push_branch',
104
+ remote: expectString(stateName, idx, kind, 'remote', m.remote),
105
+ ref: expectString(stateName, idx, kind, 'ref', m.ref),
106
+ ...cleanBase,
107
+ };
108
+ case 'create_pr_if_missing':
109
+ return {
110
+ kind: 'create_pr_if_missing',
111
+ base: expectString(stateName, idx, kind, 'base', m.base),
112
+ head: expectString(stateName, idx, kind, 'head', m.head),
113
+ title_from: expectString(stateName, idx, kind, 'title_from', m.title_from),
114
+ body_from: expectString(stateName, idx, kind, 'body_from', m.body_from),
115
+ ...cleanBase,
116
+ };
117
+ case 'run_in_vm': {
118
+ const name = asString(m.name);
119
+ if (!name || name.length === 0) {
120
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] (run_in_vm): "name" is required (run-log label + snapshot key)`);
121
+ }
122
+ // The name labels the action's run-log output + snapshot key. Restrict it
123
+ // to a safe identifier set so the label is unambiguous and free of path
124
+ // separators / leading dots.
125
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name)) {
126
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] (run_in_vm): "name" must match /^[A-Za-z0-9][A-Za-z0-9._-]*$/ (got: ${JSON.stringify(name)})`);
127
+ }
128
+ const cmdRaw = m.cmd;
129
+ if (!Array.isArray(cmdRaw) ||
130
+ cmdRaw.length === 0 ||
131
+ !cmdRaw.every((s) => typeof s === 'string')) {
132
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] (run_in_vm): "cmd" must be a non-empty list of strings`);
133
+ }
134
+ const envRaw = m.env;
135
+ let env;
136
+ if (envRaw !== undefined) {
137
+ if (typeof envRaw !== 'object' || envRaw === null || Array.isArray(envRaw)) {
138
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] (run_in_vm): "env" must be a map of string→string`);
139
+ }
140
+ env = {};
141
+ for (const [k, v] of Object.entries(envRaw)) {
142
+ if (typeof v !== 'string') {
143
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] (run_in_vm): env["${k}"] must be a string`);
144
+ }
145
+ env[k] = v;
146
+ }
147
+ }
148
+ const timeout = m.timeout === undefined ? undefined : asInt(m.timeout);
149
+ if (m.timeout !== undefined && (timeout === null || timeout === undefined || timeout <= 0)) {
150
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions[${idx}] (run_in_vm): "timeout" must be a positive integer (seconds)`);
151
+ }
152
+ const action = {
153
+ kind: 'run_in_vm',
154
+ name,
155
+ cmd: cmdRaw,
156
+ ...cleanBase,
157
+ };
158
+ if (env !== undefined)
159
+ action.env = env;
160
+ if (timeout !== undefined && timeout !== null)
161
+ action.timeout = timeout;
162
+ return action;
163
+ }
164
+ default: {
165
+ // Exhaustiveness check at the type level — adding a new kind to the union
166
+ // without extending this switch is a TypeScript error.
167
+ const _exhaustive = kind;
168
+ void _exhaustive;
169
+ throw new WorkflowError('workflow_parse_error', `unreachable action kind: ${String(kind)}`);
170
+ }
171
+ }
172
+ }
173
+ /**
174
+ * Lift a per-state `actions:` YAML block into the typed `WorkflowAction` union.
175
+ *
176
+ * - `undefined` (no `actions:` key) -> `undefined`.
177
+ * - `null` (declared but empty) -> `[]`.
178
+ * - Any non-list -> throws `WorkflowError('workflow_parse_error', ...)`.
179
+ *
180
+ * Each entry is validated per-kind; the first invalid entry throws.
181
+ */
182
+ export function parseActionsBlock(stateName, raw) {
183
+ if (raw === undefined)
184
+ return undefined;
185
+ if (raw === null)
186
+ return [];
187
+ if (!Array.isArray(raw)) {
188
+ throw new WorkflowError('workflow_parse_error', `state "${stateName}": actions must be a list of typed action records`);
189
+ }
190
+ return raw.map((entry, idx) => parseAction(stateName, idx, entry));
191
+ }
192
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../../src/core/actions/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,197 @@
1
+ // FCIS rewrite — pure action planner (ported from src/actions/effects.ts +
2
+ // the per-kind appliers in src/actions/executor.ts of the reference
3
+ // orchestrator).
4
+ //
5
+ // FUNCTIONAL CORE. Every function here is SYNCHRONOUS and pure: (data) -> data.
6
+ // No IO, no async/await/Promise, no clock, no randomness, no Effects executed.
7
+ // Imports ONLY from src/types (NodeNext ESM → .js extensions on relative
8
+ // imports) plus the sibling pure core helpers (template.ts, predicates.ts).
9
+ //
10
+ // WHAT MOVED INTO CORE (vs. the reference):
11
+ // • The reference `planActions` (src/actions/effects.ts) only rendered each
12
+ // action and emitted a `{ kind:'run' | 'render_failed' }` envelope; the
13
+ // ACTUAL git/gh/vm decisions lived in the async per-kind appliers in
14
+ // executor.ts (applyPushBranch, applyMerge, …). Those appliers WERE the
15
+ // side-effect-deciding logic interleaved with IO.
16
+ // • Here the per-kind mapping is lifted into the pure core: each rendered
17
+ // action is mapped to its git/gh/vm/tracker `Effect[]` SEQUENCE as DATA.
18
+ // The shell becomes a dumb interpreter that runs the emitted effects and
19
+ // folds outcomes back (the conditional branches the appliers used to take
20
+ // — "PR already exists? skip create", "non-fast-forward? force-with-lease"
21
+ // — are still in the shell's run-fold, but the candidate effects, including
22
+ // the NFF fallback sub-sequence, are produced here as data).
23
+ //
24
+ // The push_branch NFF (non-fast-forward) recovery is the keystone (mustFix, all
25
+ // judges): the planner emits BOTH the plain push and the force-with-lease
26
+ // fallback sub-sequence (fetch → rev-parse → push_force_with_lease) as data, so
27
+ // the shell never has to decide what the recovery looks like — only WHETHER to
28
+ // take it (on a non-fast-forward push result).
29
+ import { renderTree } from './template.js';
30
+ import { evaluatePredicate } from './predicates.js';
31
+ // ─── defaults (mirror src/actions/effects.ts) ────────────────────────────────
32
+ const DEFAULT_RETRY_COUNT = 3;
33
+ const DEFAULT_RETRY_BACKOFF_MS = 1_000;
34
+ /** Reference default per-command timeout (executor.ts defaultCommandTimeoutMs). */
35
+ const DEFAULT_COMMAND_TIMEOUT_MS = 300_000;
36
+ /**
37
+ * Pure planner — same inputs always produce the same `PlannedAction[]`.
38
+ *
39
+ * Faithful to src/actions/effects.ts:planActions for the envelope + snapshot
40
+ * keying; extended to emit the per-kind Effect sequence as data.
41
+ */
42
+ export function planActions(actions, ctx, opts) {
43
+ return actions.map((action, index) => planOne(action, index, ctx, opts));
44
+ }
45
+ function planOne(action, index, ctx, opts) {
46
+ const snapshotKey = actionSnapshotKey(action, index);
47
+ const r = renderTree(action, ctx);
48
+ if (!r.ok) {
49
+ return { kind: 'render_failed', snapshotKey, error: r.error };
50
+ }
51
+ const rendered = r.value;
52
+ const predicate = evaluatePredicate(actionPredicate(rendered), ctx, opts.workspacePath);
53
+ const { effects, nffFallback } = mapEffects(rendered, opts);
54
+ return {
55
+ kind: 'run',
56
+ snapshotKey,
57
+ actionKind: rendered.kind,
58
+ rendered,
59
+ predicate,
60
+ policy: normalizePolicy(actionPolicy(rendered)),
61
+ effects,
62
+ nffFallback,
63
+ };
64
+ }
65
+ // ─── snapshot keying (faithful to actionSnapshotKey) ──────────────────────────
66
+ function actionSnapshotKey(action, idx) {
67
+ if (action.name && action.name.length > 0)
68
+ return `${action.kind}:${action.name}`;
69
+ return `${action.kind}:#${idx}`;
70
+ }
71
+ // ─── policy normalization (faithful to effectivePolicy) ───────────────────────
72
+ // NOTE: the new NormalizedActionPolicy shape (src/types/actions.ts) flattens the
73
+ // reference `{ retry: { count, backoff_ms } }` into `{ retryCount, backoffMs }`.
74
+ function normalizePolicy(p) {
75
+ return {
76
+ retryCount: p?.retry?.count ?? DEFAULT_RETRY_COUNT,
77
+ backoffMs: p?.retry?.backoff_ms ?? DEFAULT_RETRY_BACKOFF_MS,
78
+ then: p?.then ?? 'abort',
79
+ };
80
+ }
81
+ // BaseAction carries `if`/`on_error` but the discriminated union has no shared
82
+ // accessor; read them positionally without widening to `any`.
83
+ function actionPredicate(a) {
84
+ return a.if;
85
+ }
86
+ function actionPolicy(a) {
87
+ return a.on_error;
88
+ }
89
+ function mapEffects(action, opts) {
90
+ switch (action.kind) {
91
+ case 'push_branch':
92
+ return mapPushBranch(action, opts);
93
+ case 'create_pr_if_missing':
94
+ return mapCreatePrIfMissing(action, opts);
95
+ case 'run_in_vm':
96
+ return mapRunInVm(action, opts);
97
+ default: {
98
+ // Exhaustiveness guard — a new kind without a mapping is a compile error.
99
+ const _exhaustive = action;
100
+ void _exhaustive;
101
+ return { effects: [], nffFallback: null };
102
+ }
103
+ }
104
+ }
105
+ // push_branch — `git push -u <remote> <ref>`, with the non-fast-forward
106
+ // recovery (fetch → rev-parse remote-tracking → push_force_with_lease) emitted
107
+ // as a SEPARATE data sub-sequence. Mirrors applyPushBranch + isNonFastForward.
108
+ //
109
+ // The reference resolved the remote SHA at runtime (it read the live remote-
110
+ // tracking ref). Core cannot read the remote, so `expectedRemoteSha` is a
111
+ // placeholder ('') the shell rewrites with the SHA the preceding rev_parse
112
+ // returns. The lease keeps the force-push safe under a true concurrent push.
113
+ function mapPushBranch(action, opts) {
114
+ const cwd = opts.workspacePath;
115
+ const effects = [
116
+ { family: 'git', kind: 'push', cwd, remote: action.remote, ref: action.ref },
117
+ ];
118
+ const remoteTrackingRef = `refs/remotes/${action.remote}/${action.ref}`;
119
+ const nffFallback = [
120
+ { family: 'git', kind: 'fetch', cwd, remote: action.remote, ref: action.ref },
121
+ { family: 'git', kind: 'rev_parse', cwd, ref: remoteTrackingRef },
122
+ {
123
+ family: 'git',
124
+ kind: 'push_force_with_lease',
125
+ cwd,
126
+ remote: action.remote,
127
+ ref: action.ref,
128
+ // Placeholder; shell substitutes the SHA from the rev_parse above.
129
+ expectedRemoteSha: '',
130
+ },
131
+ ];
132
+ return { effects, nffFallback };
133
+ }
134
+ // create_pr_if_missing — `gh pr list/view` then `gh pr create` if missing.
135
+ // Mirrors applyCreatePrIfMissing. The reference probed `gh pr view <head>`
136
+ // (non-zero ⇒ open one). The effect union models the probe as
137
+ // `gh.pr_list_for_branch` (head branch → existing PR?), and the create as
138
+ // `gh.pr_create`. The shell skips the create when the probe finds a PR.
139
+ //
140
+ // body_from / `--body-file` vs `--body`: the reference decided this at runtime
141
+ // by stat-ing the body string against the workspace (looksLikeFile). Core
142
+ // cannot stat, so it carries `bodyIsFile` as a STRUCTURAL guess (a single-line
143
+ // path-shaped value); the shell confirms the file exists before choosing the
144
+ // flag. A multi-line body is unambiguously NOT a file.
145
+ function mapCreatePrIfMissing(action, opts) {
146
+ const cwd = opts.workspacePath;
147
+ const effects = [
148
+ { family: 'gh', kind: 'pr_list_for_branch', cwd, branch: action.head },
149
+ {
150
+ family: 'gh',
151
+ kind: 'pr_create',
152
+ cwd,
153
+ base: action.base,
154
+ head: action.head,
155
+ title: action.title_from,
156
+ bodyOrFile: action.body_from,
157
+ bodyIsFile: looksLikeFilePath(action.body_from),
158
+ },
159
+ ];
160
+ return { effects, nffFallback: null };
161
+ }
162
+ // run_in_vm — a plain uncached `vm.exec` on the live per-issue VM. Mirrors
163
+ // applyRunInVm / executeRunInVm. The exec timeout mirrors executeRunInVm:
164
+ // action.timeout (seconds) overrides the bound default (ms).
165
+ function mapRunInVm(action, opts) {
166
+ const env = action.env ?? {};
167
+ const timeoutMs = action.timeout !== undefined
168
+ ? action.timeout * 1000
169
+ : (opts.defaultCommandTimeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS);
170
+ const effects = [
171
+ // vmId is a placeholder the shell binds to the per-issue VM at exec time
172
+ // (core has no handle to the live VM). workdir is the workspace mount.
173
+ {
174
+ family: 'vm',
175
+ kind: 'exec',
176
+ vmId: '',
177
+ command: action.cmd,
178
+ workdir: opts.workspacePath,
179
+ env,
180
+ timeoutMs,
181
+ },
182
+ ];
183
+ return { effects, nffFallback: null };
184
+ }
185
+ // ─── helpers ──────────────────────────────────────────────────────────────────
186
+ /**
187
+ * Structural guess at whether a `body_from` value names a file (so the shell
188
+ * passes `--body-file` rather than `--body`). The reference (looksLikeFile)
189
+ * stat-ed the path against the workspace — an IO read core cannot do — so here
190
+ * we only rule OUT the unambiguous non-paths: empty strings and multi-line
191
+ * bodies. A single-line value is FLAGGED as file-shaped; the shell confirms the
192
+ * file exists before committing to `--body-file`.
193
+ */
194
+ function looksLikeFilePath(value) {
195
+ return value.length > 0 && !value.includes('\n');
196
+ }
197
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../../src/core/actions/plan.ts"],"names":[],"mappings":"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"}