smol-symphony 0.2.0 → 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 (540) hide show
  1. package/AGENTS.md +41 -22
  2. package/DESIGN.md +494 -273
  3. package/README.md +109 -57
  4. package/SPEC.md +33 -24
  5. package/WORKFLOW.minimal.yaml +34 -0
  6. package/{WORKFLOW.template.md → WORKFLOW.template.yaml} +409 -256
  7. package/WORKFLOW.yaml +487 -0
  8. package/assets/skills/symphony-issues/SKILL.md +136 -0
  9. package/assets/symphony-mise.system.toml +68 -0
  10. package/dist/bin/symphony.js +22 -786
  11. package/dist/bin/symphony.js.map +1 -1
  12. package/dist/core/actions/context.js +109 -0
  13. package/dist/core/actions/context.js.map +1 -0
  14. package/dist/{actions/parsing.js → core/actions/parse.js} +33 -114
  15. package/dist/core/actions/parse.js.map +1 -0
  16. package/dist/core/actions/plan.js +197 -0
  17. package/dist/core/actions/plan.js.map +1 -0
  18. package/dist/core/actions/predicates.js +111 -0
  19. package/dist/core/actions/predicates.js.map +1 -0
  20. package/dist/core/actions/run-fold.js +248 -0
  21. package/dist/core/actions/run-fold.js.map +1 -0
  22. package/dist/core/actions/template.js +118 -0
  23. package/dist/core/actions/template.js.map +1 -0
  24. package/dist/core/cli/args.js +116 -0
  25. package/dist/core/cli/args.js.map +1 -0
  26. package/dist/core/coerce.js +75 -0
  27. package/dist/core/coerce.js.map +1 -0
  28. package/dist/core/credential/account-id.js +20 -0
  29. package/dist/core/credential/account-id.js.map +1 -0
  30. package/dist/core/credential/adapter-config.js +136 -0
  31. package/dist/core/credential/adapter-config.js.map +1 -0
  32. package/dist/core/credential/availability.js +98 -0
  33. package/dist/core/credential/availability.js.map +1 -0
  34. package/dist/core/credential/extract.js +228 -0
  35. package/dist/core/credential/extract.js.map +1 -0
  36. package/dist/core/credential/fake-creds.js +171 -0
  37. package/dist/core/credential/fake-creds.js.map +1 -0
  38. package/dist/core/credential/identity.js +125 -0
  39. package/dist/core/credential/identity.js.map +1 -0
  40. package/dist/core/credential/shape.js +230 -0
  41. package/dist/core/credential/shape.js.map +1 -0
  42. package/dist/core/credential/strings.js +15 -0
  43. package/dist/core/credential/strings.js.map +1 -0
  44. package/dist/core/doctor/checks.js +303 -0
  45. package/dist/core/doctor/checks.js.map +1 -0
  46. package/dist/core/git/result.js +107 -0
  47. package/dist/core/git/result.js.map +1 -0
  48. package/dist/core/http/decisions.js +225 -0
  49. package/dist/core/http/decisions.js.map +1 -0
  50. package/dist/{http.js → core/http/render.js} +472 -738
  51. package/dist/core/http/render.js.map +1 -0
  52. package/dist/{http-handlers.js → core/http/routes.js} +52 -87
  53. package/dist/core/http/routes.js.map +1 -0
  54. package/dist/core/http/views.js +181 -0
  55. package/dist/core/http/views.js.map +1 -0
  56. package/dist/core/image/managed-image.js +95 -0
  57. package/dist/core/image/managed-image.js.map +1 -0
  58. package/dist/core/issue/file.js +149 -0
  59. package/dist/core/issue/file.js.map +1 -0
  60. package/dist/core/issue/parse.js +210 -0
  61. package/dist/core/issue/parse.js.map +1 -0
  62. package/dist/core/mcp/dispatch.js +239 -0
  63. package/dist/core/mcp/dispatch.js.map +1 -0
  64. package/dist/core/mcp/post-move.js +92 -0
  65. package/dist/core/mcp/post-move.js.map +1 -0
  66. package/dist/core/mcp/protocol.js +293 -0
  67. package/dist/core/mcp/protocol.js.map +1 -0
  68. package/dist/core/mcp/url.js +162 -0
  69. package/dist/core/mcp/url.js.map +1 -0
  70. package/dist/core/path.js +63 -0
  71. package/dist/core/path.js.map +1 -0
  72. package/dist/core/reconcile/image-decide.js +48 -0
  73. package/dist/core/reconcile/image-decide.js.map +1 -0
  74. package/dist/core/reconcile/ledger.js +142 -0
  75. package/dist/core/reconcile/ledger.js.map +1 -0
  76. package/dist/core/reconcile/pr-classify.js +62 -0
  77. package/dist/core/reconcile/pr-classify.js.map +1 -0
  78. package/dist/{reconciler → core/reconcile}/pr-decide.js +25 -12
  79. package/dist/core/reconcile/pr-decide.js.map +1 -0
  80. package/dist/core/reconcile/pr-loop.js +161 -0
  81. package/dist/core/reconcile/pr-loop.js.map +1 -0
  82. package/dist/core/reconcile/pr-notes.js +35 -0
  83. package/dist/core/reconcile/pr-notes.js.map +1 -0
  84. package/dist/core/reconcile/vm-decide.js +70 -0
  85. package/dist/core/reconcile/vm-decide.js.map +1 -0
  86. package/dist/core/reconcile/vm-reap.js +207 -0
  87. package/dist/core/reconcile/vm-reap.js.map +1 -0
  88. package/dist/core/reconcile/workspace-decide.js +162 -0
  89. package/dist/core/reconcile/workspace-decide.js.map +1 -0
  90. package/dist/core/runlog/summary.js +231 -0
  91. package/dist/core/runlog/summary.js.map +1 -0
  92. package/dist/core/runner/dispatch-config.js +95 -0
  93. package/dist/core/runner/dispatch-config.js.map +1 -0
  94. package/dist/core/runner/injection.js +61 -0
  95. package/dist/core/runner/injection.js.map +1 -0
  96. package/dist/core/runner/mise.js +210 -0
  97. package/dist/core/runner/mise.js.map +1 -0
  98. package/dist/core/runner/prompt.js +720 -0
  99. package/dist/core/runner/prompt.js.map +1 -0
  100. package/dist/core/runner/turn.js +242 -0
  101. package/dist/core/runner/turn.js.map +1 -0
  102. package/dist/core/runner/vm-plan.js +390 -0
  103. package/dist/core/runner/vm-plan.js.map +1 -0
  104. package/dist/core/schedule/admission.js +123 -0
  105. package/dist/core/schedule/admission.js.map +1 -0
  106. package/dist/core/schedule/circuit-breaker.js +111 -0
  107. package/dist/core/schedule/circuit-breaker.js.map +1 -0
  108. package/dist/core/schedule/eligibility.js +83 -0
  109. package/dist/core/schedule/eligibility.js.map +1 -0
  110. package/dist/core/schedule/reconcile-issue.js +82 -0
  111. package/dist/core/schedule/reconcile-issue.js.map +1 -0
  112. package/dist/core/schedule/retry.js +96 -0
  113. package/dist/core/schedule/retry.js.map +1 -0
  114. package/dist/core/schedule/sleep-cycle.js +133 -0
  115. package/dist/core/schedule/sleep-cycle.js.map +1 -0
  116. package/dist/core/schedule/slots.js +124 -0
  117. package/dist/core/schedule/slots.js.map +1 -0
  118. package/dist/core/schedule/tick.js +553 -0
  119. package/dist/core/schedule/tick.js.map +1 -0
  120. package/dist/core/schedule/token-fold.js +181 -0
  121. package/dist/core/schedule/token-fold.js.map +1 -0
  122. package/dist/core/state-resolve.js +86 -0
  123. package/dist/core/state-resolve.js.map +1 -0
  124. package/dist/core/vm-guards.js +278 -0
  125. package/dist/core/vm-guards.js.map +1 -0
  126. package/dist/core/workflow/derive.js +107 -0
  127. package/dist/core/workflow/derive.js.map +1 -0
  128. package/dist/core/workflow/parse.js +687 -0
  129. package/dist/core/workflow/parse.js.map +1 -0
  130. package/dist/core/workflow/prompt-probe.js +78 -0
  131. package/dist/core/workflow/prompt-probe.js.map +1 -0
  132. package/dist/core/workflow/validate.js +189 -0
  133. package/dist/core/workflow/validate.js.map +1 -0
  134. package/dist/core/workspace-key.js +19 -0
  135. package/dist/core/workspace-key.js.map +1 -0
  136. package/dist/shell/actions-runner.js +356 -0
  137. package/dist/shell/actions-runner.js.map +1 -0
  138. package/dist/shell/adapter/adapter-registry.js +45 -0
  139. package/dist/shell/adapter/adapter-registry.js.map +1 -0
  140. package/dist/shell/adapter/clock-random.js +96 -0
  141. package/dist/shell/adapter/clock-random.js.map +1 -0
  142. package/dist/shell/adapter/gondolin-dispatch-helpers.js +158 -0
  143. package/dist/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
  144. package/dist/shell/adapter/gondolin-dispatch.js +385 -0
  145. package/dist/shell/adapter/gondolin-dispatch.js.map +1 -0
  146. package/dist/shell/adapter/gondolin-image-converter.js +233 -0
  147. package/dist/shell/adapter/gondolin-image-converter.js.map +1 -0
  148. package/dist/shell/adapter/gondolin-image-fetch.js +180 -0
  149. package/dist/shell/adapter/gondolin-image-fetch.js.map +1 -0
  150. package/dist/shell/adapter/launcher-asset.js +57 -0
  151. package/dist/shell/adapter/launcher-asset.js.map +1 -0
  152. package/dist/shell/adapter/mise-config-asset.js +65 -0
  153. package/dist/shell/adapter/mise-config-asset.js.map +1 -0
  154. package/dist/shell/adapter/workflow-loader.js +304 -0
  155. package/dist/shell/adapter/workflow-loader.js.map +1 -0
  156. package/dist/shell/cli/doctor.js +268 -0
  157. package/dist/shell/cli/doctor.js.map +1 -0
  158. package/dist/shell/effect-interpreter-families.js +314 -0
  159. package/dist/shell/effect-interpreter-families.js.map +1 -0
  160. package/dist/shell/effect-interpreter.js +29 -0
  161. package/dist/shell/effect-interpreter.js.map +1 -0
  162. package/dist/shell/interp/acp-frame.js +137 -0
  163. package/dist/shell/interp/acp-frame.js.map +1 -0
  164. package/dist/shell/interp/acp-ws-conn.js +320 -0
  165. package/dist/shell/interp/acp-ws-conn.js.map +1 -0
  166. package/dist/shell/interp/acp-ws-frames.js +159 -0
  167. package/dist/shell/interp/acp-ws-frames.js.map +1 -0
  168. package/dist/shell/interp/acp-ws.js +197 -0
  169. package/dist/shell/interp/acp-ws.js.map +1 -0
  170. package/dist/shell/interp/acp.js +319 -0
  171. package/dist/shell/interp/acp.js.map +1 -0
  172. package/dist/shell/interp/credential-defaults.js +128 -0
  173. package/dist/shell/interp/credential-defaults.js.map +1 -0
  174. package/dist/shell/interp/credential-hooks.js +149 -0
  175. package/dist/shell/interp/credential-hooks.js.map +1 -0
  176. package/dist/shell/interp/credential-registry.js +226 -0
  177. package/dist/shell/interp/credential-registry.js.map +1 -0
  178. package/dist/shell/interp/credential.js +103 -0
  179. package/dist/shell/interp/credential.js.map +1 -0
  180. package/dist/shell/interp/gh.js +163 -0
  181. package/dist/shell/interp/gh.js.map +1 -0
  182. package/dist/shell/interp/git.js +28 -0
  183. package/dist/shell/interp/git.js.map +1 -0
  184. package/dist/shell/interp/log.js +213 -0
  185. package/dist/shell/interp/log.js.map +1 -0
  186. package/dist/shell/interp/process.js +178 -0
  187. package/dist/shell/interp/process.js.map +1 -0
  188. package/dist/shell/interp/runlog.js +193 -0
  189. package/dist/shell/interp/runlog.js.map +1 -0
  190. package/dist/shell/interp/timer.js +64 -0
  191. package/dist/shell/interp/timer.js.map +1 -0
  192. package/dist/shell/interp/tracker-disk.js +99 -0
  193. package/dist/shell/interp/tracker-disk.js.map +1 -0
  194. package/dist/shell/interp/tracker-parse.js +71 -0
  195. package/dist/shell/interp/tracker-parse.js.map +1 -0
  196. package/dist/shell/interp/tracker-scan.js +238 -0
  197. package/dist/shell/interp/tracker-scan.js.map +1 -0
  198. package/dist/shell/interp/tracker-write.js +91 -0
  199. package/dist/shell/interp/tracker-write.js.map +1 -0
  200. package/dist/shell/interp/tracker.js +41 -0
  201. package/dist/shell/interp/tracker.js.map +1 -0
  202. package/dist/shell/interp/tty.js +48 -0
  203. package/dist/shell/interp/tty.js.map +1 -0
  204. package/dist/shell/interp/vm.js +199 -0
  205. package/dist/shell/interp/vm.js.map +1 -0
  206. package/dist/shell/interp/workspace.js +310 -0
  207. package/dist/shell/interp/workspace.js.map +1 -0
  208. package/dist/shell/main-acp.js +78 -0
  209. package/dist/shell/main-acp.js.map +1 -0
  210. package/dist/shell/main-adapters.js +222 -0
  211. package/dist/shell/main-adapters.js.map +1 -0
  212. package/dist/shell/main-credential.js +122 -0
  213. package/dist/shell/main-credential.js.map +1 -0
  214. package/dist/shell/main-doctor.js +22 -0
  215. package/dist/shell/main-doctor.js.map +1 -0
  216. package/dist/shell/main-entry.js +46 -0
  217. package/dist/shell/main-entry.js.map +1 -0
  218. package/dist/shell/main-http-csrf.js +45 -0
  219. package/dist/shell/main-http-csrf.js.map +1 -0
  220. package/dist/shell/main-http-handler.js +389 -0
  221. package/dist/shell/main-http-handler.js.map +1 -0
  222. package/dist/shell/main-http-mcp.js +122 -0
  223. package/dist/shell/main-http-mcp.js.map +1 -0
  224. package/dist/shell/main-http-views.js +253 -0
  225. package/dist/shell/main-http-views.js.map +1 -0
  226. package/dist/shell/main-http.js +76 -0
  227. package/dist/shell/main-http.js.map +1 -0
  228. package/dist/shell/main-loops.js +130 -0
  229. package/dist/shell/main-loops.js.map +1 -0
  230. package/dist/shell/main-mcp.js +129 -0
  231. package/dist/shell/main-mcp.js.map +1 -0
  232. package/dist/shell/main-orchestrator.js +120 -0
  233. package/dist/shell/main-orchestrator.js.map +1 -0
  234. package/dist/shell/main-preflight.js +43 -0
  235. package/dist/shell/main-preflight.js.map +1 -0
  236. package/dist/shell/main-reconcilers-helpers.js +244 -0
  237. package/dist/shell/main-reconcilers-helpers.js.map +1 -0
  238. package/dist/shell/main-reconcilers-pr.js +148 -0
  239. package/dist/shell/main-reconcilers-pr.js.map +1 -0
  240. package/dist/shell/main-reconcilers.js +225 -0
  241. package/dist/shell/main-reconcilers.js.map +1 -0
  242. package/dist/shell/main-runner.js +355 -0
  243. package/dist/shell/main-runner.js.map +1 -0
  244. package/dist/shell/main-scaffold.js +116 -0
  245. package/dist/shell/main-scaffold.js.map +1 -0
  246. package/dist/shell/main-shutdown.js +115 -0
  247. package/dist/shell/main-shutdown.js.map +1 -0
  248. package/dist/shell/main-startup.js +48 -0
  249. package/dist/shell/main-startup.js.map +1 -0
  250. package/dist/shell/main-substrates.js +43 -0
  251. package/dist/shell/main-substrates.js.map +1 -0
  252. package/dist/shell/main.js +385 -0
  253. package/dist/shell/main.js.map +1 -0
  254. package/dist/shell/orchestrator-feedback.js +69 -0
  255. package/dist/shell/orchestrator-feedback.js.map +1 -0
  256. package/dist/shell/orchestrator-image.js +167 -0
  257. package/dist/shell/orchestrator-image.js.map +1 -0
  258. package/dist/shell/orchestrator-loop.js +468 -0
  259. package/dist/shell/orchestrator-loop.js.map +1 -0
  260. package/dist/shell/orchestrator-reconcile.js +36 -0
  261. package/dist/shell/orchestrator-reconcile.js.map +1 -0
  262. package/dist/shell/reconciler-loop.js +228 -0
  263. package/dist/shell/reconciler-loop.js.map +1 -0
  264. package/dist/shell/runner-loop-turn.js +301 -0
  265. package/dist/shell/runner-loop-turn.js.map +1 -0
  266. package/dist/shell/runner-loop.js +338 -0
  267. package/dist/shell/runner-loop.js.map +1 -0
  268. package/dist/shell/server/http.js +208 -0
  269. package/dist/shell/server/http.js.map +1 -0
  270. package/dist/shell/server/mcp-runtime-effects.js +237 -0
  271. package/dist/shell/server/mcp-runtime-effects.js.map +1 -0
  272. package/dist/shell/server/mcp-runtime.js +99 -0
  273. package/dist/shell/server/mcp-runtime.js.map +1 -0
  274. package/dist/shell/workspace-key.js +14 -0
  275. package/dist/shell/workspace-key.js.map +1 -0
  276. package/dist/types/acp.js +8 -0
  277. package/dist/types/acp.js.map +1 -0
  278. package/dist/types/actions/plan.js +6 -0
  279. package/dist/types/actions/plan.js.map +1 -0
  280. package/dist/types/actions/predicates.js +6 -0
  281. package/dist/types/actions/predicates.js.map +1 -0
  282. package/dist/types/actions/run-fold.js +8 -0
  283. package/dist/types/actions/run-fold.js.map +1 -0
  284. package/dist/types/actions.js +7 -0
  285. package/dist/types/actions.js.map +1 -0
  286. package/dist/types/adapter/clock-random.js +4 -0
  287. package/dist/types/adapter/clock-random.js.map +1 -0
  288. package/dist/types/adapter/gondolin-image-converter.js +5 -0
  289. package/dist/types/adapter/gondolin-image-converter.js.map +1 -0
  290. package/dist/types/adapter/gondolin-image-fetch.js +5 -0
  291. package/dist/types/adapter/gondolin-image-fetch.js.map +1 -0
  292. package/dist/types/adapter/workflow-loader.js +4 -0
  293. package/dist/types/adapter/workflow-loader.js.map +1 -0
  294. package/dist/types/cli/args.js +8 -0
  295. package/dist/types/cli/args.js.map +1 -0
  296. package/dist/types/config.js +8 -0
  297. package/dist/types/config.js.map +1 -0
  298. package/dist/types/credential-interp.js +6 -0
  299. package/dist/types/credential-interp.js.map +1 -0
  300. package/dist/types/credentials.js +10 -0
  301. package/dist/types/credentials.js.map +1 -0
  302. package/dist/types/doctor.js +7 -0
  303. package/dist/types/doctor.js.map +1 -0
  304. package/dist/types/domain.js +7 -0
  305. package/dist/types/domain.js.map +1 -0
  306. package/dist/types/effect.js +15 -0
  307. package/dist/types/effect.js.map +1 -0
  308. package/dist/types/errors.js +39 -0
  309. package/dist/types/errors.js.map +1 -0
  310. package/dist/types/http/decisions.js +6 -0
  311. package/dist/types/http/decisions.js.map +1 -0
  312. package/dist/types/http/render.js +10 -0
  313. package/dist/types/http/render.js.map +1 -0
  314. package/dist/types/http/views.js +6 -0
  315. package/dist/types/http/views.js.map +1 -0
  316. package/dist/types/http.js +9 -0
  317. package/dist/types/http.js.map +1 -0
  318. package/dist/types/image/managed-image.js +7 -0
  319. package/dist/types/image/managed-image.js.map +1 -0
  320. package/dist/types/interp/effect-interpreter.js +8 -0
  321. package/dist/types/interp/effect-interpreter.js.map +1 -0
  322. package/dist/types/interp/tracker.js +7 -0
  323. package/dist/types/interp/tracker.js.map +1 -0
  324. package/dist/types/issue/file.js +6 -0
  325. package/dist/types/issue/file.js.map +1 -0
  326. package/dist/types/issue/parse.js +8 -0
  327. package/dist/types/issue/parse.js.map +1 -0
  328. package/dist/types/main-acp.js +13 -0
  329. package/dist/types/main-acp.js.map +1 -0
  330. package/dist/types/main-adapters.js +5 -0
  331. package/dist/types/main-adapters.js.map +1 -0
  332. package/dist/types/main-credential.js +21 -0
  333. package/dist/types/main-credential.js.map +1 -0
  334. package/dist/types/main-doctor.js +6 -0
  335. package/dist/types/main-doctor.js.map +1 -0
  336. package/dist/types/main-http-handler.js +12 -0
  337. package/dist/types/main-http-handler.js.map +1 -0
  338. package/dist/types/main-http.js +5 -0
  339. package/dist/types/main-http.js.map +1 -0
  340. package/dist/types/main-loops.js +5 -0
  341. package/dist/types/main-loops.js.map +1 -0
  342. package/dist/types/main-mcp.js +12 -0
  343. package/dist/types/main-mcp.js.map +1 -0
  344. package/dist/types/main-orchestrator.js +5 -0
  345. package/dist/types/main-orchestrator.js.map +1 -0
  346. package/dist/types/main-reconcilers.js +11 -0
  347. package/dist/types/main-reconcilers.js.map +1 -0
  348. package/dist/types/main-runner.js +13 -0
  349. package/dist/types/main-runner.js.map +1 -0
  350. package/dist/types/main-startup.js +5 -0
  351. package/dist/types/main-startup.js.map +1 -0
  352. package/dist/types/main-substrates.js +5 -0
  353. package/dist/types/main-substrates.js.map +1 -0
  354. package/dist/types/mcp/dispatch.js +4 -0
  355. package/dist/types/mcp/dispatch.js.map +1 -0
  356. package/dist/types/mcp/post-move.js +7 -0
  357. package/dist/types/mcp/post-move.js.map +1 -0
  358. package/dist/types/mcp.js +9 -0
  359. package/dist/types/mcp.js.map +1 -0
  360. package/dist/types/ports.js +12 -0
  361. package/dist/types/ports.js.map +1 -0
  362. package/dist/types/reconcile/image-decide.js +5 -0
  363. package/dist/types/reconcile/image-decide.js.map +1 -0
  364. package/dist/types/reconcile/ledger.js +7 -0
  365. package/dist/types/reconcile/ledger.js.map +1 -0
  366. package/dist/types/reconcile/pr-loop.js +8 -0
  367. package/dist/types/reconcile/pr-loop.js.map +1 -0
  368. package/dist/types/reconcile/vm-reap.js +8 -0
  369. package/dist/types/reconcile/vm-reap.js.map +1 -0
  370. package/dist/types/reconcile/workspace-decide.js +7 -0
  371. package/dist/types/reconcile/workspace-decide.js.map +1 -0
  372. package/dist/types/reconcile.js +9 -0
  373. package/dist/types/reconcile.js.map +1 -0
  374. package/dist/types/runlog.js +7 -0
  375. package/dist/types/runlog.js.map +1 -0
  376. package/dist/types/runner/actions-runner.js +12 -0
  377. package/dist/types/runner/actions-runner.js.map +1 -0
  378. package/dist/types/runner/gondolin-dispatch.js +5 -0
  379. package/dist/types/runner/gondolin-dispatch.js.map +1 -0
  380. package/dist/types/runner/injection.js +6 -0
  381. package/dist/types/runner/injection.js.map +1 -0
  382. package/dist/types/runner/runner-loop.js +5 -0
  383. package/dist/types/runner/runner-loop.js.map +1 -0
  384. package/dist/types/runner/turn.js +4 -0
  385. package/dist/types/runner/turn.js.map +1 -0
  386. package/dist/types/runner/vm-plan.js +4 -0
  387. package/dist/types/runner/vm-plan.js.map +1 -0
  388. package/dist/types/runtime.js +9 -0
  389. package/dist/types/runtime.js.map +1 -0
  390. package/dist/types/schedule/admission.js +7 -0
  391. package/dist/types/schedule/admission.js.map +1 -0
  392. package/dist/types/schedule/circuit-breaker.js +2 -0
  393. package/dist/types/schedule/circuit-breaker.js.map +1 -0
  394. package/dist/types/schedule/eligibility.js +9 -0
  395. package/dist/types/schedule/eligibility.js.map +1 -0
  396. package/dist/types/schedule/orchestrator-loop.js +10 -0
  397. package/dist/types/schedule/orchestrator-loop.js.map +1 -0
  398. package/dist/types/schedule/sleep-cycle.js +4 -0
  399. package/dist/types/schedule/sleep-cycle.js.map +1 -0
  400. package/dist/types/schedule/slots.js +8 -0
  401. package/dist/types/schedule/slots.js.map +1 -0
  402. package/dist/types/schedule/tick.js +9 -0
  403. package/dist/types/schedule/tick.js.map +1 -0
  404. package/dist/types/server/mcp-runtime.js +8 -0
  405. package/dist/types/server/mcp-runtime.js.map +1 -0
  406. package/dist/types/workflow/parse.js +4 -0
  407. package/dist/types/workflow/parse.js.map +1 -0
  408. package/package.json +22 -10
  409. package/patches/@earendil-works+gondolin+0.12.0.patch +173 -0
  410. package/prompts/Reflect.md +91 -0
  411. package/prompts/Review.md +97 -0
  412. package/prompts/Todo.md +96 -0
  413. package/prompts/_footer.md +41 -0
  414. package/prompts/_preamble.md +42 -0
  415. package/prompts-minimal/Todo.md +26 -0
  416. package/scripts/postinstall.mjs +63 -0
  417. package/scripts/vm-agent.mjs +312 -90
  418. package/WORKFLOW.md +0 -744
  419. package/dist/acp-bridge.js +0 -324
  420. package/dist/acp-bridge.js.map +0 -1
  421. package/dist/actions/cache.js +0 -191
  422. package/dist/actions/cache.js.map +0 -1
  423. package/dist/actions/effects.js +0 -41
  424. package/dist/actions/effects.js.map +0 -1
  425. package/dist/actions/executor.js +0 -570
  426. package/dist/actions/executor.js.map +0 -1
  427. package/dist/actions/index.js +0 -13
  428. package/dist/actions/index.js.map +0 -1
  429. package/dist/actions/parsing.js.map +0 -1
  430. package/dist/actions/predicate-env.js +0 -27
  431. package/dist/actions/predicate-env.js.map +0 -1
  432. package/dist/actions/predicates.js +0 -49
  433. package/dist/actions/predicates.js.map +0 -1
  434. package/dist/actions/templating.js +0 -66
  435. package/dist/actions/templating.js.map +0 -1
  436. package/dist/actions/types.js +0 -15
  437. package/dist/actions/types.js.map +0 -1
  438. package/dist/agent/acp.js +0 -473
  439. package/dist/agent/acp.js.map +0 -1
  440. package/dist/agent/adapter-names.js +0 -159
  441. package/dist/agent/adapter-names.js.map +0 -1
  442. package/dist/agent/adapters.js +0 -511
  443. package/dist/agent/adapters.js.map +0 -1
  444. package/dist/agent/credential-extractors.js +0 -342
  445. package/dist/agent/credential-extractors.js.map +0 -1
  446. package/dist/agent/credential-secrets.js +0 -628
  447. package/dist/agent/credential-secrets.js.map +0 -1
  448. package/dist/agent/credential-ticker.js +0 -57
  449. package/dist/agent/credential-ticker.js.map +0 -1
  450. package/dist/agent/gondolin-creds-staging.js +0 -356
  451. package/dist/agent/gondolin-creds-staging.js.map +0 -1
  452. package/dist/agent/gondolin-dispatch.js +0 -375
  453. package/dist/agent/gondolin-dispatch.js.map +0 -1
  454. package/dist/agent/gondolin.js +0 -124
  455. package/dist/agent/gondolin.js.map +0 -1
  456. package/dist/agent/runner-decisions.js +0 -134
  457. package/dist/agent/runner-decisions.js.map +0 -1
  458. package/dist/agent/runner.js +0 -1456
  459. package/dist/agent/runner.js.map +0 -1
  460. package/dist/agent/tool-call-summary.js +0 -102
  461. package/dist/agent/tool-call-summary.js.map +0 -1
  462. package/dist/agent/vm-acp-mapping.js +0 -73
  463. package/dist/agent/vm-acp-mapping.js.map +0 -1
  464. package/dist/agent/vm-guards.js +0 -262
  465. package/dist/agent/vm-guards.js.map +0 -1
  466. package/dist/agent/vm-port.js +0 -22
  467. package/dist/agent/vm-port.js.map +0 -1
  468. package/dist/agent/vm-process-registry.js +0 -79
  469. package/dist/agent/vm-process-registry.js.map +0 -1
  470. package/dist/bin/cli-args.js +0 -105
  471. package/dist/bin/cli-args.js.map +0 -1
  472. package/dist/errors.js +0 -15
  473. package/dist/errors.js.map +0 -1
  474. package/dist/http-disk.js +0 -135
  475. package/dist/http-disk.js.map +0 -1
  476. package/dist/http-handlers.js.map +0 -1
  477. package/dist/http.js.map +0 -1
  478. package/dist/issues.js +0 -178
  479. package/dist/issues.js.map +0 -1
  480. package/dist/logging.js +0 -203
  481. package/dist/logging.js.map +0 -1
  482. package/dist/mcp.js +0 -706
  483. package/dist/mcp.js.map +0 -1
  484. package/dist/memory.js +0 -85
  485. package/dist/memory.js.map +0 -1
  486. package/dist/orchestrator-decisions.js +0 -331
  487. package/dist/orchestrator-decisions.js.map +0 -1
  488. package/dist/orchestrator.js +0 -1569
  489. package/dist/orchestrator.js.map +0 -1
  490. package/dist/prompt.js +0 -65
  491. package/dist/prompt.js.map +0 -1
  492. package/dist/reconciler/cache.js +0 -65
  493. package/dist/reconciler/cache.js.map +0 -1
  494. package/dist/reconciler/index.js +0 -448
  495. package/dist/reconciler/index.js.map +0 -1
  496. package/dist/reconciler/ledger.js +0 -131
  497. package/dist/reconciler/ledger.js.map +0 -1
  498. package/dist/reconciler/pr-adapters.js +0 -174
  499. package/dist/reconciler/pr-adapters.js.map +0 -1
  500. package/dist/reconciler/pr-decide.js.map +0 -1
  501. package/dist/reconciler/pr.js +0 -422
  502. package/dist/reconciler/pr.js.map +0 -1
  503. package/dist/reconciler/types.js +0 -12
  504. package/dist/reconciler/types.js.map +0 -1
  505. package/dist/reconciler/vm.js +0 -243
  506. package/dist/reconciler/vm.js.map +0 -1
  507. package/dist/reconciler/workspace-defaults.js +0 -83
  508. package/dist/reconciler/workspace-defaults.js.map +0 -1
  509. package/dist/reconciler/workspace.js +0 -272
  510. package/dist/reconciler/workspace.js.map +0 -1
  511. package/dist/runlog.js +0 -403
  512. package/dist/runlog.js.map +0 -1
  513. package/dist/scaffold.js +0 -165
  514. package/dist/scaffold.js.map +0 -1
  515. package/dist/trackers/local.js +0 -445
  516. package/dist/trackers/local.js.map +0 -1
  517. package/dist/trackers/types.js +0 -10
  518. package/dist/trackers/types.js.map +0 -1
  519. package/dist/types.js +0 -3
  520. package/dist/types.js.map +0 -1
  521. package/dist/util/clock.js +0 -12
  522. package/dist/util/clock.js.map +0 -1
  523. package/dist/util/crypto.js +0 -25
  524. package/dist/util/crypto.js.map +0 -1
  525. package/dist/util/frontmatter.js +0 -70
  526. package/dist/util/frontmatter.js.map +0 -1
  527. package/dist/util/fs-issues.js +0 -22
  528. package/dist/util/fs-issues.js.map +0 -1
  529. package/dist/util/process.js +0 -152
  530. package/dist/util/process.js.map +0 -1
  531. package/dist/util/workspace-key.js +0 -10
  532. package/dist/util/workspace-key.js.map +0 -1
  533. package/dist/workflow-loader.js +0 -147
  534. package/dist/workflow-loader.js.map +0 -1
  535. package/dist/workflow.js +0 -822
  536. package/dist/workflow.js.map +0 -1
  537. package/dist/workspace-types.js +0 -8
  538. package/dist/workspace-types.js.map +0 -1
  539. package/dist/workspace.js +0 -443
  540. package/dist/workspace.js.map +0 -1
@@ -0,0 +1,111 @@
1
+ // FCIS rewrite — pure `if:` predicate evaluation (ported from
2
+ // src/actions/predicates.ts + predicate-env.ts of the reference orchestrator).
3
+ //
4
+ // The reference `evaluatePredicate` was async because the branch_exists /
5
+ // file_present shapes reached IO through an injected `PredicateEnv`
6
+ // (git rev-parse / fs.stat). In the functional core that IO is FORBIDDEN, so
7
+ // this module is split into two pure, synchronous halves:
8
+ //
9
+ // 1. `evaluatePredicate(predicate, ctx, workspacePath)` decides AS DATA. It
10
+ // either RESOLVES immediately (null/undefined → true; string-truthy;
11
+ // empty-after-render → false) or EMITS a probe Effect the shell answers:
12
+ // - { branch_exists } → a `git.branch_exists` Effect, and
13
+ // - { file_present } → an `fs.path_exists` Effect.
14
+ // Unknown `$var` references surface as an ERROR decision (the reference
15
+ // threw a TemplateError; silent "" expansion masked operator typos).
16
+ //
17
+ // 2. `foldPredicateProbe(result)` folds the shell's EffectResult boolean back
18
+ // into the final predicate value once the probe has run.
19
+ //
20
+ // 100% SYNCHRONOUS. No async / await / Promise. No IO, no node: imports, no
21
+ // clock or randomness. Imports ONLY from src/types (and the sibling core
22
+ // templating module). (NodeNext ESM → .js extensions on relative imports.)
23
+ import { renderField } from './template.js';
24
+ import { joinPosix } from '../path.js';
25
+ // ─── template substitution ────────────────────────────────────────────────────
26
+ // Shared with the core planner via `renderField` (same $-grammar, same
27
+ // unknown-var error). `renderField` labels the error with the action-field name;
28
+ // here the relevant label IS the offending variable, which the reference's
29
+ // PredicateEnv surfaced. We re-label the returned TemplateError with the bad
30
+ // variable (parsed out of the message renderField already embeds) so callers see
31
+ // `field: "<varname>"`, matching the reference predicate-env behavior.
32
+ const BAD_VAR_RE = /unknown template variable "\$([A-Za-z_][A-Za-z0-9_]*)"/;
33
+ function render(template, ctx) {
34
+ const r = renderField('<predicate>', template, ctx);
35
+ if (r.ok)
36
+ return { ok: true, text: r.value };
37
+ const field = BAD_VAR_RE.exec(r.error.message)?.[1] ?? r.error.field;
38
+ return { ok: false, error: { field, message: r.error.message } };
39
+ }
40
+ // Path join is the canonical lexical `joinPosix` from core/path.ts (this module
41
+ // was the SUPERSET behaviour that became canonical — empty-base/absolute-rel
42
+ // handling). The reference used node:path, forbidden in the pure core.
43
+ /**
44
+ * Decide a predicate against the context, AS DATA.
45
+ *
46
+ * `null`/`undefined` → resolved true (no `if:` → run unconditionally).
47
+ *
48
+ * String form is a truthiness check on the rendered template: `if: $repo`
49
+ * resolves true iff `$repo` renders to non-empty after trimming. An empty (or
50
+ * empty-after-render) string is explicitly FALSE — the intent of `if: $repo`
51
+ * with `$repo` unset is "skip when the var is empty", not "always run".
52
+ *
53
+ * `{ branch_exists }` / `{ file_present }` render their argument, short-circuit
54
+ * to resolved-false on an empty ref/path, otherwise EMIT a probe Effect the
55
+ * shell runs; the boolean is folded back via `foldPredicateProbe`.
56
+ *
57
+ * An unknown `$var` anywhere returns a `{ kind: 'error' }` decision (the
58
+ * reference threw a TemplateError).
59
+ */
60
+ export function evaluatePredicate(predicate, ctx, workspacePath) {
61
+ if (predicate === null || predicate === undefined) {
62
+ return { kind: 'resolved', value: true };
63
+ }
64
+ if (typeof predicate === 'string') {
65
+ const r = render(predicate, ctx);
66
+ if (!r.ok)
67
+ return { kind: 'error', error: r.error };
68
+ return { kind: 'resolved', value: r.text.trim().length > 0 };
69
+ }
70
+ if ('branch_exists' in predicate) {
71
+ const r = render(predicate.branch_exists, ctx);
72
+ if (!r.ok)
73
+ return { kind: 'error', error: r.error };
74
+ const ref = r.text.trim();
75
+ if (ref.length === 0)
76
+ return { kind: 'resolved', value: false };
77
+ return {
78
+ kind: 'probe',
79
+ effect: { family: 'git', kind: 'branch_exists', cwd: workspacePath, ref },
80
+ };
81
+ }
82
+ if ('file_present' in predicate) {
83
+ const r = render(predicate.file_present, ctx);
84
+ if (!r.ok)
85
+ return { kind: 'error', error: r.error };
86
+ const file = r.text.trim();
87
+ if (file.length === 0)
88
+ return { kind: 'resolved', value: false };
89
+ return {
90
+ kind: 'probe',
91
+ effect: { family: 'fs', kind: 'path_exists', path: joinPosix(workspacePath, file) },
92
+ };
93
+ }
94
+ // Unreachable for a well-typed ActionPredicate; mirror the reference's
95
+ // defensive `return false`.
96
+ return { kind: 'resolved', value: false };
97
+ }
98
+ /**
99
+ * Fold the shell's EffectResult for a `{ kind: 'probe' }` decision back into the
100
+ * final predicate boolean. Accepts the two probe result shapes this module can
101
+ * emit (`branch_exists` / `path_exists`); any other / failed result folds to
102
+ * `false` (a probe that could not run means "predicate not satisfied", matching
103
+ * the reference's missing-ref / fs-error → false behavior).
104
+ */
105
+ export function foldPredicateProbe(result) {
106
+ if ('kind' in result && (result.kind === 'branch_exists' || result.kind === 'path_exists')) {
107
+ return result.exists;
108
+ }
109
+ return false;
110
+ }
111
+ //# sourceMappingURL=predicates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicates.js","sourceRoot":"","sources":["../../../src/core/actions/predicates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,248 @@
1
+ // FCIS rewrite — pure executor state machine for the typed-action DAG.
2
+ //
3
+ // Ported faithfully from the reference `src/actions/executor.ts`
4
+ // (`runEffects` + `runWithRetry` + `finalizeOutcome`/`finalizeFailure`). The
5
+ // reference was an async driver that AWAITED `applyAction`, slept on
6
+ // `node:timers/promises`, and called `log.warn` directly. In the functional
7
+ // core all of that becomes DATA:
8
+ //
9
+ // • IO (running the action attempt) happens in the shell. The shell applies
10
+ // one attempt, then hands the resulting `ActionOutcome` back to this fold.
11
+ // • The retry backoff `delay()` becomes a returned `timer.sleep` Effect plus a
12
+ // `retry` decision telling the shell to re-apply the same action.
13
+ // • The diagnostic `log.warn`/`log.debug` calls become `log.emit` Effects.
14
+ // • The ledger (bounded `ActionStatus[]`, most-recent-first) is THREADED
15
+ // through as plain data: each call takes the prior ledger and returns the
16
+ // next one.
17
+ //
18
+ // The shell drives this as a loop per action:
19
+ // 1. beginAction(...) → push an in_progress ledger row.
20
+ // 2. apply the action (IO) → produce an ActionOutcome.
21
+ // 3. foldActionOutcome(...) → decide retry / route / abort / done,
22
+ // emit Effects, and return the next ledger.
23
+ // 4. on `retry`, the shell sleeps (it already has the timer.sleep Effect),
24
+ // re-applies, and folds again with an incremented `attempt`.
25
+ //
26
+ // Predicate evaluation, template-render failures, and skip-on-`if=false` are
27
+ // handled by sibling core modules (`predicates.ts`, `template.ts`); the helpers
28
+ // here cover the "an attempt ran and produced an outcome" half of the loop plus
29
+ // the ledger bookkeeping the shell needs around it.
30
+ //
31
+ // 100% SYNCHRONOUS. No async / await / Promise. No IO, no node: imports, no
32
+ // wall clock or randomness (an ISO timestamp is injected as a plain string).
33
+ // Imports ONLY from src/types. (NodeNext ESM → .js extensions on relative
34
+ // imports.)
35
+ /**
36
+ * Most-recent-first slice length surfaced on the snapshot. The reference keeps
37
+ * twice this many rows internally (so a burst of in_progress→error→… updates
38
+ * doesn't evict still-relevant rows before they finalize) and slices to
39
+ * `MAX_ACTION_HISTORY` only when emitting.
40
+ */
41
+ export const MAX_ACTION_HISTORY = 16;
42
+ const LEDGER_CAP = MAX_ACTION_HISTORY * 2;
43
+ // ─── ledger bookkeeping (pure; the reference's `push` / `upd` closures) ───────
44
+ /**
45
+ * Push a fresh in_progress row for an action attempt, most-recent-first, and
46
+ * cap the ledger at `LEDGER_CAP` rows. Returns the NEXT ledger (does not mutate
47
+ * the input).
48
+ *
49
+ * Mirrors the reference's `push` closure that `unshift`ed an in_progress row in
50
+ * `runOneEffect` before evaluating the predicate / applying the action.
51
+ */
52
+ export function beginAction(ledger, input) {
53
+ const row = {
54
+ resource: input.resource,
55
+ action: input.action,
56
+ state: 'in_progress',
57
+ started_at: input.nowIso,
58
+ finished_at: null,
59
+ error: null,
60
+ };
61
+ const next = [row, ...ledger];
62
+ if (next.length > LEDGER_CAP)
63
+ next.length = LEDGER_CAP;
64
+ return next;
65
+ }
66
+ /**
67
+ * Mark the most-recent in_progress row for `action` with the given patch.
68
+ * Returns the NEXT ledger. Mirrors the reference's `upd` closure (find the
69
+ * first in_progress row keyed by action name; spread the patch onto it).
70
+ *
71
+ * When no matching in_progress row exists the ledger is returned unchanged
72
+ * (the reference's `upd` no-ops on a missing index).
73
+ */
74
+ export function updateAction(ledger, action, patch) {
75
+ const idx = ledger.findIndex((a) => a.action === action && a.state === 'in_progress');
76
+ if (idx < 0)
77
+ return ledger.slice();
78
+ const next = ledger.slice();
79
+ next[idx] = { ...next[idx], ...patch };
80
+ return next;
81
+ }
82
+ // ─── retry / route / abort decision ───────────────────────────────────────────
83
+ /**
84
+ * Exponential backoff for the `attempt`-th (0-based) failed action attempt:
85
+ * `backoffMs * 2^attempt`. Mirrors the reference's
86
+ * `policy.retry.backoff_ms * Math.pow(2, attempt)`.
87
+ */
88
+ export function actionBackoffMs(policy, attempt) {
89
+ return policy.backoffMs * Math.pow(2, attempt);
90
+ }
91
+ function warn(message, fields) {
92
+ return { family: 'log', kind: 'emit', level: 'warn', message, fields };
93
+ }
94
+ /**
95
+ * Fold one applied-action `ActionOutcome` against its `NormalizedActionPolicy`,
96
+ * threading the `ActionStatus` ledger and emitting the side effects as data.
97
+ *
98
+ * `attempt` is the 0-based number of the attempt that just produced `outcome`
99
+ * (0 for the first try). The reference's `runWithRetry` loop semantics:
100
+ *
101
+ * • `outcome.ok || outcome.route_to` short-circuits the retry loop. We never
102
+ * retry a routed failure — a routed handoff is clean, not a transient error.
103
+ * • otherwise, if `attempt < retryCount`, schedule a retry with
104
+ * `backoffMs * 2^attempt` backoff.
105
+ * • otherwise the retries are exhausted → finalize the failure.
106
+ *
107
+ * Finalization (the reference's `finalizeOutcome` / `finalizeFailure`):
108
+ * • success → `done`, ledger row finalized.
109
+ * • failure → route to `outcome.route_to` ?? (policy.then is an object ?
110
+ * policy.then.route_to : null). A non-null route → `route`; null → `abort`.
111
+ * Ledger row finalized to `error` with the failure reason either way.
112
+ */
113
+ export function foldActionOutcome(input) {
114
+ const { action, outcome, policy, attempt, nowIso } = input;
115
+ // ── success ────────────────────────────────────────────────────────────
116
+ if (outcome.ok) {
117
+ return {
118
+ decision: { kind: 'done' },
119
+ ledger: updateAction(input.ledger, action, { state: 'done', finished_at: nowIso }),
120
+ effects: [],
121
+ };
122
+ }
123
+ const reason = outcome.reason ?? 'unknown';
124
+ // ── retry (only when NOT routed and retries remain) ──────────────────────
125
+ // A routed failure is a clean handoff and is never retried — mirrors the
126
+ // reference's `if (outcome.route_to) return outcome` short-circuit ahead of
127
+ // the retry-budget check.
128
+ if (!outcome.route_to && attempt < policy.retryCount) {
129
+ const backoffMs = actionBackoffMs(policy, attempt);
130
+ return {
131
+ decision: { kind: 'retry', attempt: attempt + 1, backoffMs },
132
+ // Leave the in_progress row in place: the attempt is still "running"
133
+ // from the dashboard's view until it ultimately succeeds or exhausts.
134
+ ledger: input.ledger.slice(),
135
+ effects: [
136
+ warn('action retrying', {
137
+ action,
138
+ attempt: attempt + 1,
139
+ next_backoff_ms: backoffMs,
140
+ error: outcome.reason,
141
+ }),
142
+ { family: 'timer', kind: 'sleep', ms: backoffMs },
143
+ ],
144
+ };
145
+ }
146
+ // ── terminal failure: route or abort ─────────────────────────────────────
147
+ const route = outcome.route_to ?? (typeof policy.then === 'object' ? policy.then.route_to : null);
148
+ const ledger = updateAction(input.ledger, action, {
149
+ state: 'error',
150
+ finished_at: nowIso,
151
+ error: reason,
152
+ });
153
+ if (route !== null) {
154
+ return {
155
+ decision: { kind: 'route', routeTo: route, reason },
156
+ ledger,
157
+ effects: [warn('action failed', { action, reason, route_to: route })],
158
+ };
159
+ }
160
+ return {
161
+ decision: { kind: 'abort', reason },
162
+ ledger,
163
+ effects: [warn('action failed', { action, reason, route_to: null })],
164
+ };
165
+ }
166
+ // ─── render-failure / skip helpers (the non-retry ledger transitions) ─────────
167
+ /**
168
+ * Finalize the in_progress row for an action whose template render failed (the
169
+ * reference's `render_failed` Effect branch). Returns the next ledger and an
170
+ * `abort` decision — a render failure stops the cleanup loop, mirroring the
171
+ * reference returning `{ aborted: true }`.
172
+ */
173
+ export function foldRenderFailed(input) {
174
+ const ledger = updateAction(input.ledger, input.action, {
175
+ state: 'error',
176
+ finished_at: input.nowIso,
177
+ error: input.error,
178
+ });
179
+ return {
180
+ decision: { kind: 'abort', reason: input.error },
181
+ ledger,
182
+ effects: [warn('action template render failed', { action: input.action, error: input.error })],
183
+ };
184
+ }
185
+ /**
186
+ * Finalize the in_progress row for an action whose `if:` predicate resolved
187
+ * false (skip). The reference marked the row `done` (skips are not failures) and
188
+ * continued. Returns the next ledger and a `done` decision.
189
+ */
190
+ export function foldSkipped(input) {
191
+ const ledger = updateAction(input.ledger, input.action, {
192
+ state: 'done',
193
+ finished_at: input.nowIso,
194
+ });
195
+ return {
196
+ decision: { kind: 'done' },
197
+ ledger,
198
+ effects: [
199
+ { family: 'log', kind: 'emit', level: 'debug', message: 'action skipped', fields: { action: input.action, reason: 'if=false' } },
200
+ ],
201
+ };
202
+ }
203
+ /**
204
+ * Finalize the in_progress row for an action whose `if:` predicate could not be
205
+ * evaluated (an error decision, e.g. an unknown `$var`). The reference treated
206
+ * this as an abort (it returned `{ aborted: true, reason }`).
207
+ */
208
+ export function foldPredicateError(input) {
209
+ const ledger = updateAction(input.ledger, input.action, {
210
+ state: 'error',
211
+ finished_at: input.nowIso,
212
+ error: input.error,
213
+ });
214
+ return { decision: { kind: 'abort', reason: input.error }, ledger, effects: [] };
215
+ }
216
+ // ─── snapshot packing (the reference's `toActionsSnapshot`) ──────────────────
217
+ /**
218
+ * Aggregate a finished cleanup loop into the runner's result shape (the
219
+ * reference's `ActionExecResult`). `ok` is true iff the loop did not abort;
220
+ * `route_to`/`reason` carry the last route/abort decision the loop hit.
221
+ *
222
+ * Kept here (not in the snapshot packer) because the runner needs both the
223
+ * loop's terminal decision AND the bounded ledger.
224
+ */
225
+ export function summarizeRun(input) {
226
+ return {
227
+ ok: input.abortReason === null,
228
+ reason: input.abortReason,
229
+ route_to: input.routeTo,
230
+ actions: input.ledger.slice(0, MAX_ACTION_HISTORY),
231
+ };
232
+ }
233
+ /**
234
+ * Pack a finished run into a `Snapshot`-shaped record the orchestrator surfaces
235
+ * alongside reconciler resources. `ready` mirrors the run's `ok`; `last_error`
236
+ * is the most-recent errored row's message. Mirrors the reference's
237
+ * `toActionsSnapshot`.
238
+ */
239
+ export function toActionsSnapshot(id, result) {
240
+ const lastErr = result.actions.find((a) => a.state === 'error')?.error ?? null;
241
+ return {
242
+ id,
243
+ ready: result.ok,
244
+ last_error: lastErr,
245
+ actions: result.actions.slice(0, MAX_ACTION_HISTORY),
246
+ };
247
+ }
248
+ //# sourceMappingURL=run-fold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-fold.js","sourceRoot":"","sources":["../../../src/core/actions/run-fold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ // FCIS rewrite — strict template render.
2
+ //
3
+ // FUNCTIONAL CORE. Every function here is SYNCHRONOUS and pure: (data) -> data.
4
+ // No IO, no async, no clock, no randomness, no Effects. Imports ONLY from
5
+ // src/types. Ports the original behavior of src/actions/templating.ts
6
+ // ({renderTemplate, renderTree}) — $-substitution against the fixed
7
+ // ActionContext namespace, unknown-var = error.
8
+ //
9
+ // The behavioral change from the original, forced by the FCIS layout:
10
+ // TemplateError is DATA ({ field, message }, per src/types/actions.ts), not a
11
+ // thrown class. renderField returns a discriminated result; the caller (a future
12
+ // core planner) folds the error into an ActionOutcome instead of try/catch. The
13
+ // legacy "throw" shape is preserved only as the strict `renderOrThrow` helper for
14
+ // call-sites that still want it.
15
+ // ─── Template rendering ──────────────────────────────────────────────────────
16
+ // `$name` / `\$name` (escape). Matches the original VAR_RE exactly:
17
+ // group 1 = optional leading backslash (the escape)
18
+ // group 2 = the identifier
19
+ const VAR_RE = /(\\?)\$([A-Za-z_][A-Za-z0-9_]*)/g;
20
+ /**
21
+ * Substitute `$name` references in `template` against the fixed ActionContext
22
+ * namespace. Faithful to src/actions/templating.ts:
23
+ * • `$name` → the named ActionContext field (null/undefined → "").
24
+ * • `\$name` → literal `$name` (escape).
25
+ * • `$` + non-word → left alone (regex only matches `$` + identifier).
26
+ * • unknown `$name` → ERROR (the original threw; silent "" expansion masks
27
+ * operator typos — the `$SYMPHONY_PR_TITTLE` bug).
28
+ *
29
+ * `field` is the action-field label (e.g. "title_from") carried into the
30
+ * TemplateError so a failure points at the offending field, matching the new
31
+ * TemplateError data shape in src/types/actions.ts.
32
+ */
33
+ export function renderField(field, template, ctx) {
34
+ // Non-string passthrough is handled by renderTree; renderField is the
35
+ // string-typed leaf. A non-string here is a programming error, but we mirror
36
+ // the original's defensive passthrough rather than crash.
37
+ if (typeof template !== 'string') {
38
+ return { ok: true, value: template };
39
+ }
40
+ // `name in ctx` membership, typed without `any` (ActionContext is a plain
41
+ // object literal, so own + inherited enumerable keys coincide).
42
+ const vars = ctx;
43
+ let firstError = null;
44
+ const out = template.replace(VAR_RE, (_full, escape, name) => {
45
+ if (escape === '\\')
46
+ return `$${name}`;
47
+ if (!(name in vars)) {
48
+ firstError ??= {
49
+ field,
50
+ message: `unknown template variable "$${name}" (available: ${Object.keys(vars).join(', ')})`,
51
+ };
52
+ return ''; // value discarded; firstError short-circuits the return below.
53
+ }
54
+ const v = vars[name];
55
+ return v === null || v === undefined ? '' : String(v);
56
+ });
57
+ if (firstError !== null)
58
+ return { ok: false, error: firstError };
59
+ return { ok: true, value: out };
60
+ }
61
+ /**
62
+ * Strict variant matching the ORIGINAL throwing contract for the rare call-site
63
+ * that wants it. Prefer renderField (error-as-data) in core; this exists so the
64
+ * shell can keep a one-liner where a throw is the natural control flow.
65
+ *
66
+ * NOTE: throwing is acceptable here only because the thrown value carries the
67
+ * same TemplateError DATA — callers should catch and fold, not let it escape an
68
+ * effect boundary.
69
+ */
70
+ export function renderOrThrow(template, ctx) {
71
+ const r = renderField('<template>', template, ctx);
72
+ if (!r.ok) {
73
+ const e = new Error(r.error.message);
74
+ e.name = 'TemplateError';
75
+ e.templateError = r.error;
76
+ throw e;
77
+ }
78
+ return r.value;
79
+ }
80
+ /**
81
+ * Render every string leaf of a value against the ActionContext, recursing into
82
+ * arrays and plain objects. Numbers / booleans / null pass through unchanged.
83
+ * Faithful to src/actions/templating.ts:renderTree, but returns the first
84
+ * TemplateError as data instead of throwing.
85
+ *
86
+ * `path` seeds the `field` label on errors (e.g. `cmd[1]`, `env.FOO`) so a
87
+ * failure deep in an action record still points at the offending leaf.
88
+ */
89
+ export function renderTree(value, ctx, path = '') {
90
+ if (typeof value === 'string') {
91
+ const r = renderField(path || '<root>', value, ctx);
92
+ if (!r.ok)
93
+ return r;
94
+ return { ok: true, value: r.value };
95
+ }
96
+ if (Array.isArray(value)) {
97
+ const out = [];
98
+ for (let i = 0; i < value.length; i++) {
99
+ const r = renderTree(value[i], ctx, `${path}[${i}]`);
100
+ if (!r.ok)
101
+ return r;
102
+ out.push(r.value);
103
+ }
104
+ return { ok: true, value: out };
105
+ }
106
+ if (value && typeof value === 'object') {
107
+ const out = {};
108
+ for (const [k, v] of Object.entries(value)) {
109
+ const r = renderTree(v, ctx, path ? `${path}.${k}` : k);
110
+ if (!r.ok)
111
+ return r;
112
+ out[k] = r.value;
113
+ }
114
+ return { ok: true, value: out };
115
+ }
116
+ return { ok: true, value };
117
+ }
118
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/core/actions/template.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ // FCIS rewrite — pure CLI argument parsing for the `symphony` binary.
2
+ //
3
+ // Functional core: every export here is a pure, synchronous (data) -> data
4
+ // function. No IO, no clock, no randomness, no node: imports, no process.
5
+ // Imports ONLY from src/types.
6
+ //
7
+ // Ported from src/bin/cli-args.ts:parseCli. The original performed three side
8
+ // effects inline that violate the core contract and are RETURNED here instead:
9
+ // 1. `process.exit(2)` on a bad/unexpected arg → a returned `{ kind: 'error' }`
10
+ // directive carrying the message + exit code; the shell raises it.
11
+ // 2. `-h/--help` prints usage then `process.exit(0)` → a returned
12
+ // `{ kind: 'help' }` directive carrying the usage text + exit code 0.
13
+ // 3. `path.resolve(process.cwd(), 'WORKFLOW.yaml')` for the default workflow path
14
+ // → the CWD is INJECTED as a parameter and the join is a pure string op.
15
+ //
16
+ // The shell (composition root) calls `parseCli(argv, cwd)`, and on a
17
+ // non-`ok` result writes the directive's message to the matching stream and
18
+ // exits with the directive's code.
19
+ /** Default workflow filename used when no path argument is supplied. */
20
+ export const DEFAULT_WORKFLOW_FILENAME = 'WORKFLOW.yaml';
21
+ /** Usage text (ported verbatim from the original `-h/--help` branch). */
22
+ export const USAGE = `symphony [path-to-WORKFLOW.yaml] [--port PORT] [--verbose]\n` +
23
+ `symphony doctor [path-to-WORKFLOW.yaml] [--port PORT]\n` +
24
+ `symphony reconcile [path-to-WORKFLOW.yaml] [--force] [--port PORT]\n\n` +
25
+ `If path is omitted, ./WORKFLOW.yaml is used.\n` +
26
+ `\`doctor\` runs every adoption-prerequisite probe non-fatally, prints a\n` +
27
+ `PASS/FAIL line per check plus a one-line fix for each FAIL, and exits 0\n` +
28
+ `iff every check passes.\n` +
29
+ `\`reconcile --force\` requests an immediate reconcile pass (VM / workspace /\n` +
30
+ `PR janitors) at startup.\n` +
31
+ `\`--verbose\` (alias \`--foreground\`, \`-v\`) mirrors structured logs to the\n` +
32
+ `console; by default they go to the log file only so the console stays clean.\n`;
33
+ /** Pure path join: trailing-slash-tolerant `${cwd}/${name}`, no node:path. */
34
+ function joinDefaultWorkflow(cwd, name) {
35
+ const base = cwd.replace(/\/+$/, '');
36
+ // An empty/`/` cwd collapses to an absolute path at root; otherwise join.
37
+ return base === '' ? `/${name}` : `${base}/${name}`;
38
+ }
39
+ /** The `--port` invalid-value message, shared by both `--port V` and `--port=V`. */
40
+ const invalidPort = (raw) => ({ kind: 'error', message: `error: invalid --port value: ${raw}\n`, exitCode: 2 });
41
+ /**
42
+ * Parse `argv` (already sliced past `node script`) into a {@link CliResult}.
43
+ *
44
+ * `cwd` is injected (the original read `process.cwd()`); it is only used to
45
+ * resolve the default WORKFLOW.yaml path when no positional path is supplied.
46
+ *
47
+ * Faithful port of src/bin/cli-args.ts:parseCli — same subcommand detection,
48
+ * same flag handling, same precedence — but every `process.exit`/stream write
49
+ * is returned as a {@link CliHelp}/{@link CliError} directive for the shell.
50
+ */
51
+ export function parseCli(argv, cwd) {
52
+ // Detect subcommands. `reconcile`/`doctor` share the parsed-args skeleton with
53
+ // the default `serve` mode; the subcommand is preserved verbatim (collapsing
54
+ // `reconcile`→`serve` would let the missing-workflow scaffold prompt fire on a
55
+ // `reconcile` invocation that has nothing to scaffold against).
56
+ let subcommand = 'serve';
57
+ let rest = argv;
58
+ if (argv[0] === 'reconcile') {
59
+ subcommand = 'reconcile';
60
+ rest = argv.slice(1);
61
+ }
62
+ else if (argv[0] === 'doctor') {
63
+ subcommand = 'doctor';
64
+ rest = argv.slice(1);
65
+ }
66
+ let workflow = null;
67
+ let port = null;
68
+ let reconcileForce = false;
69
+ let verbose = false;
70
+ for (let i = 0; i < rest.length; i++) {
71
+ const a = rest[i];
72
+ if (a === '--port' || a === '-p') {
73
+ const v = rest[++i];
74
+ if (v === undefined) {
75
+ return { kind: 'error', message: `error: --port requires a value\n`, exitCode: 2 };
76
+ }
77
+ const n = parseInt(v, 10);
78
+ if (!Number.isFinite(n) || n < 0)
79
+ return invalidPort(v);
80
+ port = n;
81
+ }
82
+ else if (a.startsWith('--port=')) {
83
+ const n = parseInt(a.slice('--port='.length), 10);
84
+ // The original interpolated the WHOLE arg (`--port=foo`) into the message.
85
+ if (!Number.isFinite(n) || n < 0)
86
+ return invalidPort(a);
87
+ port = n;
88
+ }
89
+ else if (subcommand === 'reconcile' && a === '--force') {
90
+ reconcileForce = true;
91
+ }
92
+ else if (a === '--verbose' || a === '-v' || a === '--foreground') {
93
+ verbose = true;
94
+ }
95
+ else if (a === '-h' || a === '--help') {
96
+ return { kind: 'help', message: USAGE, exitCode: 0 };
97
+ }
98
+ else if (workflow === null) {
99
+ workflow = a;
100
+ }
101
+ else {
102
+ return { kind: 'error', message: `error: unexpected argument: ${a}\n`, exitCode: 2 };
103
+ }
104
+ }
105
+ return {
106
+ kind: 'ok',
107
+ cli: {
108
+ subcommand,
109
+ workflow: workflow ?? joinDefaultWorkflow(cwd, DEFAULT_WORKFLOW_FILENAME),
110
+ port,
111
+ reconcileForce,
112
+ verbose,
113
+ },
114
+ };
115
+ }
116
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/core/cli/args.ts"],"names":[],"mappings":"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"}