smol-symphony 0.2.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 (716) 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/src/bin/symphony.js +30 -0
  11. package/dist/src/bin/symphony.js.map +1 -0
  12. package/dist/src/core/actions/context.js +109 -0
  13. package/dist/src/core/actions/context.js.map +1 -0
  14. package/dist/{actions/parsing.js → src/core/actions/parse.js} +33 -114
  15. package/dist/src/core/actions/parse.js.map +1 -0
  16. package/dist/src/core/actions/plan.js +197 -0
  17. package/dist/src/core/actions/plan.js.map +1 -0
  18. package/dist/src/core/actions/predicates.js +111 -0
  19. package/dist/src/core/actions/predicates.js.map +1 -0
  20. package/dist/src/core/actions/run-fold.js +248 -0
  21. package/dist/src/core/actions/run-fold.js.map +1 -0
  22. package/dist/src/core/actions/template.js +118 -0
  23. package/dist/src/core/actions/template.js.map +1 -0
  24. package/dist/src/core/cli/args.js +116 -0
  25. package/dist/src/core/cli/args.js.map +1 -0
  26. package/dist/src/core/coerce.js +75 -0
  27. package/dist/src/core/coerce.js.map +1 -0
  28. package/dist/src/core/credential/account-id.js +20 -0
  29. package/dist/src/core/credential/account-id.js.map +1 -0
  30. package/dist/src/core/credential/adapter-config.js +136 -0
  31. package/dist/src/core/credential/adapter-config.js.map +1 -0
  32. package/dist/src/core/credential/availability.js +98 -0
  33. package/dist/src/core/credential/availability.js.map +1 -0
  34. package/dist/src/core/credential/extract.js +228 -0
  35. package/dist/src/core/credential/extract.js.map +1 -0
  36. package/dist/src/core/credential/fake-creds.js +171 -0
  37. package/dist/src/core/credential/fake-creds.js.map +1 -0
  38. package/dist/src/core/credential/identity.js +125 -0
  39. package/dist/src/core/credential/identity.js.map +1 -0
  40. package/dist/src/core/credential/shape.js +230 -0
  41. package/dist/src/core/credential/shape.js.map +1 -0
  42. package/dist/src/core/credential/strings.js +15 -0
  43. package/dist/src/core/credential/strings.js.map +1 -0
  44. package/dist/src/core/doctor/checks.js +303 -0
  45. package/dist/src/core/doctor/checks.js.map +1 -0
  46. package/dist/src/core/git/result.js +107 -0
  47. package/dist/src/core/git/result.js.map +1 -0
  48. package/dist/src/core/http/decisions.js +225 -0
  49. package/dist/src/core/http/decisions.js.map +1 -0
  50. package/dist/{http.js → src/core/http/render.js} +472 -738
  51. package/dist/src/core/http/render.js.map +1 -0
  52. package/dist/{http-handlers.js → src/core/http/routes.js} +52 -87
  53. package/dist/src/core/http/routes.js.map +1 -0
  54. package/dist/src/core/http/views.js +181 -0
  55. package/dist/src/core/http/views.js.map +1 -0
  56. package/dist/src/core/image/managed-image.js +95 -0
  57. package/dist/src/core/image/managed-image.js.map +1 -0
  58. package/dist/src/core/issue/file.js +149 -0
  59. package/dist/src/core/issue/file.js.map +1 -0
  60. package/dist/src/core/issue/parse.js +210 -0
  61. package/dist/src/core/issue/parse.js.map +1 -0
  62. package/dist/src/core/mcp/dispatch.js +239 -0
  63. package/dist/src/core/mcp/dispatch.js.map +1 -0
  64. package/dist/src/core/mcp/post-move.js +92 -0
  65. package/dist/src/core/mcp/post-move.js.map +1 -0
  66. package/dist/src/core/mcp/protocol.js +293 -0
  67. package/dist/src/core/mcp/protocol.js.map +1 -0
  68. package/dist/src/core/mcp/url.js +162 -0
  69. package/dist/src/core/mcp/url.js.map +1 -0
  70. package/dist/src/core/path.js +63 -0
  71. package/dist/src/core/path.js.map +1 -0
  72. package/dist/src/core/reconcile/image-decide.js +48 -0
  73. package/dist/src/core/reconcile/image-decide.js.map +1 -0
  74. package/dist/src/core/reconcile/ledger.js +142 -0
  75. package/dist/src/core/reconcile/ledger.js.map +1 -0
  76. package/dist/src/core/reconcile/pr-classify.js +62 -0
  77. package/dist/src/core/reconcile/pr-classify.js.map +1 -0
  78. package/dist/{reconciler → src/core/reconcile}/pr-decide.js +25 -12
  79. package/dist/src/core/reconcile/pr-decide.js.map +1 -0
  80. package/dist/src/core/reconcile/pr-loop.js +161 -0
  81. package/dist/src/core/reconcile/pr-loop.js.map +1 -0
  82. package/dist/src/core/reconcile/pr-notes.js +35 -0
  83. package/dist/src/core/reconcile/pr-notes.js.map +1 -0
  84. package/dist/src/core/reconcile/vm-decide.js +70 -0
  85. package/dist/src/core/reconcile/vm-decide.js.map +1 -0
  86. package/dist/src/core/reconcile/vm-reap.js +207 -0
  87. package/dist/src/core/reconcile/vm-reap.js.map +1 -0
  88. package/dist/src/core/reconcile/workspace-decide.js +162 -0
  89. package/dist/src/core/reconcile/workspace-decide.js.map +1 -0
  90. package/dist/src/core/runlog/summary.js +231 -0
  91. package/dist/src/core/runlog/summary.js.map +1 -0
  92. package/dist/src/core/runner/dispatch-config.js +95 -0
  93. package/dist/src/core/runner/dispatch-config.js.map +1 -0
  94. package/dist/src/core/runner/injection.js +61 -0
  95. package/dist/src/core/runner/injection.js.map +1 -0
  96. package/dist/src/core/runner/mise.js +210 -0
  97. package/dist/src/core/runner/mise.js.map +1 -0
  98. package/dist/src/core/runner/prompt.js +720 -0
  99. package/dist/src/core/runner/prompt.js.map +1 -0
  100. package/dist/src/core/runner/turn.js +242 -0
  101. package/dist/src/core/runner/turn.js.map +1 -0
  102. package/dist/src/core/runner/vm-plan.js +390 -0
  103. package/dist/src/core/runner/vm-plan.js.map +1 -0
  104. package/dist/src/core/schedule/admission.js +123 -0
  105. package/dist/src/core/schedule/admission.js.map +1 -0
  106. package/dist/src/core/schedule/circuit-breaker.js +111 -0
  107. package/dist/src/core/schedule/circuit-breaker.js.map +1 -0
  108. package/dist/src/core/schedule/eligibility.js +83 -0
  109. package/dist/src/core/schedule/eligibility.js.map +1 -0
  110. package/dist/src/core/schedule/reconcile-issue.js +82 -0
  111. package/dist/src/core/schedule/reconcile-issue.js.map +1 -0
  112. package/dist/src/core/schedule/retry.js +96 -0
  113. package/dist/src/core/schedule/retry.js.map +1 -0
  114. package/dist/src/core/schedule/sleep-cycle.js +133 -0
  115. package/dist/src/core/schedule/sleep-cycle.js.map +1 -0
  116. package/dist/src/core/schedule/slots.js +124 -0
  117. package/dist/src/core/schedule/slots.js.map +1 -0
  118. package/dist/src/core/schedule/tick.js +553 -0
  119. package/dist/src/core/schedule/tick.js.map +1 -0
  120. package/dist/src/core/schedule/token-fold.js +181 -0
  121. package/dist/src/core/schedule/token-fold.js.map +1 -0
  122. package/dist/src/core/state-resolve.js +86 -0
  123. package/dist/src/core/state-resolve.js.map +1 -0
  124. package/dist/src/core/vm-guards.js +278 -0
  125. package/dist/src/core/vm-guards.js.map +1 -0
  126. package/dist/src/core/workflow/derive.js +107 -0
  127. package/dist/src/core/workflow/derive.js.map +1 -0
  128. package/dist/src/core/workflow/parse.js +687 -0
  129. package/dist/src/core/workflow/parse.js.map +1 -0
  130. package/dist/src/core/workflow/prompt-probe.js +78 -0
  131. package/dist/src/core/workflow/prompt-probe.js.map +1 -0
  132. package/dist/src/core/workflow/validate.js +189 -0
  133. package/dist/src/core/workflow/validate.js.map +1 -0
  134. package/dist/src/core/workspace-key.js +19 -0
  135. package/dist/src/core/workspace-key.js.map +1 -0
  136. package/dist/src/shell/actions-runner.js +356 -0
  137. package/dist/src/shell/actions-runner.js.map +1 -0
  138. package/dist/src/shell/adapter/adapter-registry.js +45 -0
  139. package/dist/src/shell/adapter/adapter-registry.js.map +1 -0
  140. package/dist/src/shell/adapter/clock-random.js +96 -0
  141. package/dist/src/shell/adapter/clock-random.js.map +1 -0
  142. package/dist/src/shell/adapter/gondolin-dispatch-helpers.js +158 -0
  143. package/dist/src/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
  144. package/dist/src/shell/adapter/gondolin-dispatch.js +385 -0
  145. package/dist/src/shell/adapter/gondolin-dispatch.js.map +1 -0
  146. package/dist/src/shell/adapter/gondolin-image-converter.js +233 -0
  147. package/dist/src/shell/adapter/gondolin-image-converter.js.map +1 -0
  148. package/dist/src/shell/adapter/gondolin-image-fetch.js +180 -0
  149. package/dist/src/shell/adapter/gondolin-image-fetch.js.map +1 -0
  150. package/dist/src/shell/adapter/launcher-asset.js +57 -0
  151. package/dist/src/shell/adapter/launcher-asset.js.map +1 -0
  152. package/dist/src/shell/adapter/mise-config-asset.js +65 -0
  153. package/dist/src/shell/adapter/mise-config-asset.js.map +1 -0
  154. package/dist/src/shell/adapter/workflow-loader.js +304 -0
  155. package/dist/src/shell/adapter/workflow-loader.js.map +1 -0
  156. package/dist/src/shell/cli/doctor.js +268 -0
  157. package/dist/src/shell/cli/doctor.js.map +1 -0
  158. package/dist/src/shell/effect-interpreter-families.js +314 -0
  159. package/dist/src/shell/effect-interpreter-families.js.map +1 -0
  160. package/dist/src/shell/effect-interpreter.js +29 -0
  161. package/dist/src/shell/effect-interpreter.js.map +1 -0
  162. package/dist/src/shell/interp/acp-frame.js +137 -0
  163. package/dist/src/shell/interp/acp-frame.js.map +1 -0
  164. package/dist/src/shell/interp/acp-ws-conn.js +320 -0
  165. package/dist/src/shell/interp/acp-ws-conn.js.map +1 -0
  166. package/dist/src/shell/interp/acp-ws-frames.js +159 -0
  167. package/dist/src/shell/interp/acp-ws-frames.js.map +1 -0
  168. package/dist/src/shell/interp/acp-ws.js +197 -0
  169. package/dist/src/shell/interp/acp-ws.js.map +1 -0
  170. package/dist/src/shell/interp/acp.js +319 -0
  171. package/dist/src/shell/interp/acp.js.map +1 -0
  172. package/dist/src/shell/interp/credential-defaults.js +128 -0
  173. package/dist/src/shell/interp/credential-defaults.js.map +1 -0
  174. package/dist/src/shell/interp/credential-hooks.js +149 -0
  175. package/dist/src/shell/interp/credential-hooks.js.map +1 -0
  176. package/dist/src/shell/interp/credential-registry.js +226 -0
  177. package/dist/src/shell/interp/credential-registry.js.map +1 -0
  178. package/dist/src/shell/interp/credential.js +103 -0
  179. package/dist/src/shell/interp/credential.js.map +1 -0
  180. package/dist/src/shell/interp/gh.js +163 -0
  181. package/dist/src/shell/interp/gh.js.map +1 -0
  182. package/dist/src/shell/interp/git.js +28 -0
  183. package/dist/src/shell/interp/git.js.map +1 -0
  184. package/dist/src/shell/interp/log.js +213 -0
  185. package/dist/src/shell/interp/log.js.map +1 -0
  186. package/dist/src/shell/interp/process.js +178 -0
  187. package/dist/src/shell/interp/process.js.map +1 -0
  188. package/dist/src/shell/interp/runlog.js +193 -0
  189. package/dist/src/shell/interp/runlog.js.map +1 -0
  190. package/dist/src/shell/interp/timer.js +64 -0
  191. package/dist/src/shell/interp/timer.js.map +1 -0
  192. package/dist/src/shell/interp/tracker-disk.js +99 -0
  193. package/dist/src/shell/interp/tracker-disk.js.map +1 -0
  194. package/dist/src/shell/interp/tracker-parse.js +71 -0
  195. package/dist/src/shell/interp/tracker-parse.js.map +1 -0
  196. package/dist/src/shell/interp/tracker-scan.js +238 -0
  197. package/dist/src/shell/interp/tracker-scan.js.map +1 -0
  198. package/dist/src/shell/interp/tracker-write.js +91 -0
  199. package/dist/src/shell/interp/tracker-write.js.map +1 -0
  200. package/dist/src/shell/interp/tracker.js +41 -0
  201. package/dist/src/shell/interp/tracker.js.map +1 -0
  202. package/dist/src/shell/interp/tty.js +48 -0
  203. package/dist/src/shell/interp/tty.js.map +1 -0
  204. package/dist/src/shell/interp/vm.js +199 -0
  205. package/dist/src/shell/interp/vm.js.map +1 -0
  206. package/dist/src/shell/interp/workspace.js +310 -0
  207. package/dist/src/shell/interp/workspace.js.map +1 -0
  208. package/dist/src/shell/main-acp.js +78 -0
  209. package/dist/src/shell/main-acp.js.map +1 -0
  210. package/dist/src/shell/main-adapters.js +222 -0
  211. package/dist/src/shell/main-adapters.js.map +1 -0
  212. package/dist/src/shell/main-credential.js +122 -0
  213. package/dist/src/shell/main-credential.js.map +1 -0
  214. package/dist/src/shell/main-doctor.js +22 -0
  215. package/dist/src/shell/main-doctor.js.map +1 -0
  216. package/dist/src/shell/main-entry.js +46 -0
  217. package/dist/src/shell/main-entry.js.map +1 -0
  218. package/dist/src/shell/main-http-csrf.js +45 -0
  219. package/dist/src/shell/main-http-csrf.js.map +1 -0
  220. package/dist/src/shell/main-http-handler.js +389 -0
  221. package/dist/src/shell/main-http-handler.js.map +1 -0
  222. package/dist/src/shell/main-http-mcp.js +122 -0
  223. package/dist/src/shell/main-http-mcp.js.map +1 -0
  224. package/dist/src/shell/main-http-views.js +253 -0
  225. package/dist/src/shell/main-http-views.js.map +1 -0
  226. package/dist/src/shell/main-http.js +76 -0
  227. package/dist/src/shell/main-http.js.map +1 -0
  228. package/dist/src/shell/main-loops.js +130 -0
  229. package/dist/src/shell/main-loops.js.map +1 -0
  230. package/dist/src/shell/main-mcp.js +129 -0
  231. package/dist/src/shell/main-mcp.js.map +1 -0
  232. package/dist/src/shell/main-orchestrator.js +120 -0
  233. package/dist/src/shell/main-orchestrator.js.map +1 -0
  234. package/dist/src/shell/main-preflight.js +43 -0
  235. package/dist/src/shell/main-preflight.js.map +1 -0
  236. package/dist/src/shell/main-reconcilers-helpers.js +244 -0
  237. package/dist/src/shell/main-reconcilers-helpers.js.map +1 -0
  238. package/dist/src/shell/main-reconcilers-pr.js +148 -0
  239. package/dist/src/shell/main-reconcilers-pr.js.map +1 -0
  240. package/dist/src/shell/main-reconcilers.js +225 -0
  241. package/dist/src/shell/main-reconcilers.js.map +1 -0
  242. package/dist/src/shell/main-runner.js +355 -0
  243. package/dist/src/shell/main-runner.js.map +1 -0
  244. package/dist/src/shell/main-scaffold.js +116 -0
  245. package/dist/src/shell/main-scaffold.js.map +1 -0
  246. package/dist/src/shell/main-shutdown.js +115 -0
  247. package/dist/src/shell/main-shutdown.js.map +1 -0
  248. package/dist/src/shell/main-startup.js +48 -0
  249. package/dist/src/shell/main-startup.js.map +1 -0
  250. package/dist/src/shell/main-substrates.js +43 -0
  251. package/dist/src/shell/main-substrates.js.map +1 -0
  252. package/dist/src/shell/main.js +385 -0
  253. package/dist/src/shell/main.js.map +1 -0
  254. package/dist/src/shell/orchestrator-feedback.js +69 -0
  255. package/dist/src/shell/orchestrator-feedback.js.map +1 -0
  256. package/dist/src/shell/orchestrator-image.js +167 -0
  257. package/dist/src/shell/orchestrator-image.js.map +1 -0
  258. package/dist/src/shell/orchestrator-loop.js +468 -0
  259. package/dist/src/shell/orchestrator-loop.js.map +1 -0
  260. package/dist/src/shell/orchestrator-reconcile.js +36 -0
  261. package/dist/src/shell/orchestrator-reconcile.js.map +1 -0
  262. package/dist/src/shell/reconciler-loop.js +228 -0
  263. package/dist/src/shell/reconciler-loop.js.map +1 -0
  264. package/dist/src/shell/runner-loop-turn.js +301 -0
  265. package/dist/src/shell/runner-loop-turn.js.map +1 -0
  266. package/dist/src/shell/runner-loop.js +338 -0
  267. package/dist/src/shell/runner-loop.js.map +1 -0
  268. package/dist/src/shell/server/http.js +208 -0
  269. package/dist/src/shell/server/http.js.map +1 -0
  270. package/dist/src/shell/server/mcp-runtime-effects.js +237 -0
  271. package/dist/src/shell/server/mcp-runtime-effects.js.map +1 -0
  272. package/dist/src/shell/server/mcp-runtime.js +99 -0
  273. package/dist/src/shell/server/mcp-runtime.js.map +1 -0
  274. package/dist/src/shell/workspace-key.js +14 -0
  275. package/dist/src/shell/workspace-key.js.map +1 -0
  276. package/dist/src/types/acp.js +8 -0
  277. package/dist/src/types/acp.js.map +1 -0
  278. package/dist/src/types/actions/plan.js +6 -0
  279. package/dist/src/types/actions/plan.js.map +1 -0
  280. package/dist/src/types/actions/predicates.js +6 -0
  281. package/dist/src/types/actions/predicates.js.map +1 -0
  282. package/dist/src/types/actions/run-fold.js +8 -0
  283. package/dist/src/types/actions/run-fold.js.map +1 -0
  284. package/dist/src/types/actions.js +7 -0
  285. package/dist/src/types/actions.js.map +1 -0
  286. package/dist/src/types/adapter/clock-random.js +4 -0
  287. package/dist/src/types/adapter/clock-random.js.map +1 -0
  288. package/dist/src/types/adapter/gondolin-image-converter.js +5 -0
  289. package/dist/src/types/adapter/gondolin-image-converter.js.map +1 -0
  290. package/dist/src/types/adapter/gondolin-image-fetch.js +5 -0
  291. package/dist/src/types/adapter/gondolin-image-fetch.js.map +1 -0
  292. package/dist/src/types/adapter/workflow-loader.js +4 -0
  293. package/dist/src/types/adapter/workflow-loader.js.map +1 -0
  294. package/dist/src/types/cli/args.js +8 -0
  295. package/dist/src/types/cli/args.js.map +1 -0
  296. package/dist/src/types/config.js +8 -0
  297. package/dist/src/types/config.js.map +1 -0
  298. package/dist/src/types/credential-interp.js +6 -0
  299. package/dist/src/types/credential-interp.js.map +1 -0
  300. package/dist/src/types/credentials.js +10 -0
  301. package/dist/src/types/credentials.js.map +1 -0
  302. package/dist/src/types/doctor.js +7 -0
  303. package/dist/src/types/doctor.js.map +1 -0
  304. package/dist/src/types/domain.js +7 -0
  305. package/dist/src/types/domain.js.map +1 -0
  306. package/dist/src/types/effect.js +15 -0
  307. package/dist/src/types/effect.js.map +1 -0
  308. package/dist/src/types/errors.js +39 -0
  309. package/dist/src/types/errors.js.map +1 -0
  310. package/dist/src/types/http/decisions.js +6 -0
  311. package/dist/src/types/http/decisions.js.map +1 -0
  312. package/dist/src/types/http/render.js +10 -0
  313. package/dist/src/types/http/render.js.map +1 -0
  314. package/dist/src/types/http/views.js +6 -0
  315. package/dist/src/types/http/views.js.map +1 -0
  316. package/dist/src/types/http.js +9 -0
  317. package/dist/src/types/http.js.map +1 -0
  318. package/dist/src/types/image/managed-image.js +7 -0
  319. package/dist/src/types/image/managed-image.js.map +1 -0
  320. package/dist/src/types/interp/effect-interpreter.js +8 -0
  321. package/dist/src/types/interp/effect-interpreter.js.map +1 -0
  322. package/dist/src/types/interp/tracker.js +7 -0
  323. package/dist/src/types/interp/tracker.js.map +1 -0
  324. package/dist/src/types/issue/file.js +6 -0
  325. package/dist/src/types/issue/file.js.map +1 -0
  326. package/dist/src/types/issue/parse.js +8 -0
  327. package/dist/src/types/issue/parse.js.map +1 -0
  328. package/dist/src/types/main-acp.js +13 -0
  329. package/dist/src/types/main-acp.js.map +1 -0
  330. package/dist/src/types/main-adapters.js +5 -0
  331. package/dist/src/types/main-adapters.js.map +1 -0
  332. package/dist/src/types/main-credential.js +21 -0
  333. package/dist/src/types/main-credential.js.map +1 -0
  334. package/dist/src/types/main-doctor.js +6 -0
  335. package/dist/src/types/main-doctor.js.map +1 -0
  336. package/dist/src/types/main-http-handler.js +12 -0
  337. package/dist/src/types/main-http-handler.js.map +1 -0
  338. package/dist/src/types/main-http.js +5 -0
  339. package/dist/src/types/main-http.js.map +1 -0
  340. package/dist/src/types/main-loops.js +5 -0
  341. package/dist/src/types/main-loops.js.map +1 -0
  342. package/dist/src/types/main-mcp.js +12 -0
  343. package/dist/src/types/main-mcp.js.map +1 -0
  344. package/dist/src/types/main-orchestrator.js +5 -0
  345. package/dist/src/types/main-orchestrator.js.map +1 -0
  346. package/dist/src/types/main-reconcilers.js +11 -0
  347. package/dist/src/types/main-reconcilers.js.map +1 -0
  348. package/dist/src/types/main-runner.js +13 -0
  349. package/dist/src/types/main-runner.js.map +1 -0
  350. package/dist/src/types/main-startup.js +5 -0
  351. package/dist/src/types/main-startup.js.map +1 -0
  352. package/dist/src/types/main-substrates.js +5 -0
  353. package/dist/src/types/main-substrates.js.map +1 -0
  354. package/dist/src/types/mcp/dispatch.js +4 -0
  355. package/dist/src/types/mcp/dispatch.js.map +1 -0
  356. package/dist/src/types/mcp/post-move.js +7 -0
  357. package/dist/src/types/mcp/post-move.js.map +1 -0
  358. package/dist/src/types/mcp.js +9 -0
  359. package/dist/src/types/mcp.js.map +1 -0
  360. package/dist/src/types/ports.js +12 -0
  361. package/dist/src/types/ports.js.map +1 -0
  362. package/dist/src/types/reconcile/image-decide.js +5 -0
  363. package/dist/src/types/reconcile/image-decide.js.map +1 -0
  364. package/dist/src/types/reconcile/ledger.js +7 -0
  365. package/dist/src/types/reconcile/ledger.js.map +1 -0
  366. package/dist/src/types/reconcile/pr-loop.js +8 -0
  367. package/dist/src/types/reconcile/pr-loop.js.map +1 -0
  368. package/dist/src/types/reconcile/vm-reap.js +8 -0
  369. package/dist/src/types/reconcile/vm-reap.js.map +1 -0
  370. package/dist/src/types/reconcile/workspace-decide.js +7 -0
  371. package/dist/src/types/reconcile/workspace-decide.js.map +1 -0
  372. package/dist/src/types/reconcile.js +9 -0
  373. package/dist/src/types/reconcile.js.map +1 -0
  374. package/dist/src/types/runlog.js +7 -0
  375. package/dist/src/types/runlog.js.map +1 -0
  376. package/dist/src/types/runner/actions-runner.js +12 -0
  377. package/dist/src/types/runner/actions-runner.js.map +1 -0
  378. package/dist/src/types/runner/gondolin-dispatch.js +5 -0
  379. package/dist/src/types/runner/gondolin-dispatch.js.map +1 -0
  380. package/dist/src/types/runner/injection.js +6 -0
  381. package/dist/src/types/runner/injection.js.map +1 -0
  382. package/dist/src/types/runner/runner-loop.js +5 -0
  383. package/dist/src/types/runner/runner-loop.js.map +1 -0
  384. package/dist/src/types/runner/turn.js +4 -0
  385. package/dist/src/types/runner/turn.js.map +1 -0
  386. package/dist/src/types/runner/vm-plan.js +4 -0
  387. package/dist/src/types/runner/vm-plan.js.map +1 -0
  388. package/dist/src/types/runtime.js +9 -0
  389. package/dist/src/types/runtime.js.map +1 -0
  390. package/dist/src/types/schedule/admission.js +7 -0
  391. package/dist/src/types/schedule/admission.js.map +1 -0
  392. package/dist/src/types/schedule/circuit-breaker.js +2 -0
  393. package/dist/src/types/schedule/circuit-breaker.js.map +1 -0
  394. package/dist/src/types/schedule/eligibility.js +9 -0
  395. package/dist/src/types/schedule/eligibility.js.map +1 -0
  396. package/dist/src/types/schedule/orchestrator-loop.js +10 -0
  397. package/dist/src/types/schedule/orchestrator-loop.js.map +1 -0
  398. package/dist/src/types/schedule/sleep-cycle.js +4 -0
  399. package/dist/src/types/schedule/sleep-cycle.js.map +1 -0
  400. package/dist/src/types/schedule/slots.js +8 -0
  401. package/dist/src/types/schedule/slots.js.map +1 -0
  402. package/dist/src/types/schedule/tick.js +9 -0
  403. package/dist/src/types/schedule/tick.js.map +1 -0
  404. package/dist/src/types/server/mcp-runtime.js +8 -0
  405. package/dist/src/types/server/mcp-runtime.js.map +1 -0
  406. package/dist/src/types/workflow/parse.js +4 -0
  407. package/dist/src/types/workflow/parse.js.map +1 -0
  408. package/dist/tests/core/account-id.test.js +35 -0
  409. package/dist/tests/core/account-id.test.js.map +1 -0
  410. package/dist/tests/core/actions-parse.test.js +176 -0
  411. package/dist/tests/core/actions-parse.test.js.map +1 -0
  412. package/dist/tests/core/adapter-config.test.js +133 -0
  413. package/dist/tests/core/adapter-config.test.js.map +1 -0
  414. package/dist/tests/core/admission.test.js +215 -0
  415. package/dist/tests/core/admission.test.js.map +1 -0
  416. package/dist/tests/core/args.test.js +132 -0
  417. package/dist/tests/core/args.test.js.map +1 -0
  418. package/dist/tests/core/availability.test.js +62 -0
  419. package/dist/tests/core/availability.test.js.map +1 -0
  420. package/dist/tests/core/checks.test.js +395 -0
  421. package/dist/tests/core/checks.test.js.map +1 -0
  422. package/dist/tests/core/circuit-breaker.test.js +172 -0
  423. package/dist/tests/core/circuit-breaker.test.js.map +1 -0
  424. package/dist/tests/core/coerce.test.js +87 -0
  425. package/dist/tests/core/coerce.test.js.map +1 -0
  426. package/dist/tests/core/context.test.js +228 -0
  427. package/dist/tests/core/context.test.js.map +1 -0
  428. package/dist/tests/core/decisions.test.js +310 -0
  429. package/dist/tests/core/decisions.test.js.map +1 -0
  430. package/dist/tests/core/derive.test.js +205 -0
  431. package/dist/tests/core/derive.test.js.map +1 -0
  432. package/dist/tests/core/dispatch-config.test.js +164 -0
  433. package/dist/tests/core/dispatch-config.test.js.map +1 -0
  434. package/dist/tests/core/dispatch.test.js +302 -0
  435. package/dist/tests/core/dispatch.test.js.map +1 -0
  436. package/dist/tests/core/eligibility.test.js +163 -0
  437. package/dist/tests/core/eligibility.test.js.map +1 -0
  438. package/dist/tests/core/extract.test.js +139 -0
  439. package/dist/tests/core/extract.test.js.map +1 -0
  440. package/dist/tests/core/fake-creds.test.js +134 -0
  441. package/dist/tests/core/fake-creds.test.js.map +1 -0
  442. package/dist/tests/core/file.test.js +197 -0
  443. package/dist/tests/core/file.test.js.map +1 -0
  444. package/dist/tests/core/git-result.test.js +113 -0
  445. package/dist/tests/core/git-result.test.js.map +1 -0
  446. package/dist/tests/core/identity.test.js +180 -0
  447. package/dist/tests/core/identity.test.js.map +1 -0
  448. package/dist/tests/core/image-decide.test.js +59 -0
  449. package/dist/tests/core/image-decide.test.js.map +1 -0
  450. package/dist/tests/core/injection.test.js +163 -0
  451. package/dist/tests/core/injection.test.js.map +1 -0
  452. package/dist/tests/core/ledger.test.js +218 -0
  453. package/dist/tests/core/ledger.test.js.map +1 -0
  454. package/dist/tests/core/managed-image.test.js +68 -0
  455. package/dist/tests/core/managed-image.test.js.map +1 -0
  456. package/dist/tests/core/mise.test.js +138 -0
  457. package/dist/tests/core/mise.test.js.map +1 -0
  458. package/dist/tests/core/parse.test.js +174 -0
  459. package/dist/tests/core/parse.test.js.map +1 -0
  460. package/dist/tests/core/path.test.js +50 -0
  461. package/dist/tests/core/path.test.js.map +1 -0
  462. package/dist/tests/core/plan.test.js +218 -0
  463. package/dist/tests/core/plan.test.js.map +1 -0
  464. package/dist/tests/core/post-move.test.js +162 -0
  465. package/dist/tests/core/post-move.test.js.map +1 -0
  466. package/dist/tests/core/pr-classify.test.js +117 -0
  467. package/dist/tests/core/pr-classify.test.js.map +1 -0
  468. package/dist/tests/core/pr-decide.test.js +298 -0
  469. package/dist/tests/core/pr-decide.test.js.map +1 -0
  470. package/dist/tests/core/pr-loop.test.js +301 -0
  471. package/dist/tests/core/pr-loop.test.js.map +1 -0
  472. package/dist/tests/core/pr-notes.test.js +165 -0
  473. package/dist/tests/core/pr-notes.test.js.map +1 -0
  474. package/dist/tests/core/predicates.test.js +154 -0
  475. package/dist/tests/core/predicates.test.js.map +1 -0
  476. package/dist/tests/core/prompt.test.js +189 -0
  477. package/dist/tests/core/prompt.test.js.map +1 -0
  478. package/dist/tests/core/protocol.test.js +195 -0
  479. package/dist/tests/core/protocol.test.js.map +1 -0
  480. package/dist/tests/core/reconcile-issue.test.js +116 -0
  481. package/dist/tests/core/reconcile-issue.test.js.map +1 -0
  482. package/dist/tests/core/render.test.js +549 -0
  483. package/dist/tests/core/render.test.js.map +1 -0
  484. package/dist/tests/core/retry.test.js +186 -0
  485. package/dist/tests/core/retry.test.js.map +1 -0
  486. package/dist/tests/core/routes.test.js +247 -0
  487. package/dist/tests/core/routes.test.js.map +1 -0
  488. package/dist/tests/core/run-fold.test.js +299 -0
  489. package/dist/tests/core/run-fold.test.js.map +1 -0
  490. package/dist/tests/core/shape.test.js +185 -0
  491. package/dist/tests/core/shape.test.js.map +1 -0
  492. package/dist/tests/core/sleep-cycle.test.js +150 -0
  493. package/dist/tests/core/sleep-cycle.test.js.map +1 -0
  494. package/dist/tests/core/slots.test.js +201 -0
  495. package/dist/tests/core/slots.test.js.map +1 -0
  496. package/dist/tests/core/state-resolve.test.js +80 -0
  497. package/dist/tests/core/state-resolve.test.js.map +1 -0
  498. package/dist/tests/core/summary.test.js +200 -0
  499. package/dist/tests/core/summary.test.js.map +1 -0
  500. package/dist/tests/core/template.test.js +116 -0
  501. package/dist/tests/core/template.test.js.map +1 -0
  502. package/dist/tests/core/tick.test.js +558 -0
  503. package/dist/tests/core/tick.test.js.map +1 -0
  504. package/dist/tests/core/token-fold.test.js +176 -0
  505. package/dist/tests/core/token-fold.test.js.map +1 -0
  506. package/dist/tests/core/turn.test.js +388 -0
  507. package/dist/tests/core/turn.test.js.map +1 -0
  508. package/dist/tests/core/url.test.js +118 -0
  509. package/dist/tests/core/url.test.js.map +1 -0
  510. package/dist/tests/core/validate.test.js +247 -0
  511. package/dist/tests/core/validate.test.js.map +1 -0
  512. package/dist/tests/core/views.test.js +252 -0
  513. package/dist/tests/core/views.test.js.map +1 -0
  514. package/dist/tests/core/vm-decide.test.js +110 -0
  515. package/dist/tests/core/vm-decide.test.js.map +1 -0
  516. package/dist/tests/core/vm-guards.test.js +153 -0
  517. package/dist/tests/core/vm-guards.test.js.map +1 -0
  518. package/dist/tests/core/vm-plan.test.js +332 -0
  519. package/dist/tests/core/vm-plan.test.js.map +1 -0
  520. package/dist/tests/core/vm-reap.test.js +196 -0
  521. package/dist/tests/core/vm-reap.test.js.map +1 -0
  522. package/dist/tests/core/workflow-parse.test.js +493 -0
  523. package/dist/tests/core/workflow-parse.test.js.map +1 -0
  524. package/dist/tests/core/workspace-decide.test.js +236 -0
  525. package/dist/tests/core/workspace-decide.test.js.map +1 -0
  526. package/dist/tests/helpers/fixtures.js +167 -0
  527. package/dist/tests/helpers/fixtures.js.map +1 -0
  528. package/dist/tests/shell/acp-substrate.test.js +101 -0
  529. package/dist/tests/shell/acp-substrate.test.js.map +1 -0
  530. package/dist/tests/shell/actions-runner-push.test.js +203 -0
  531. package/dist/tests/shell/actions-runner-push.test.js.map +1 -0
  532. package/dist/tests/shell/credential-hooks.test.js +36 -0
  533. package/dist/tests/shell/credential-hooks.test.js.map +1 -0
  534. package/dist/tests/shell/credential-registry.test.js +165 -0
  535. package/dist/tests/shell/credential-registry.test.js.map +1 -0
  536. package/dist/tests/shell/credential-substrate.test.js +179 -0
  537. package/dist/tests/shell/credential-substrate.test.js.map +1 -0
  538. package/dist/tests/shell/dockerfile-mise-pin.test.js +51 -0
  539. package/dist/tests/shell/dockerfile-mise-pin.test.js.map +1 -0
  540. package/dist/tests/shell/doctor.test.js +101 -0
  541. package/dist/tests/shell/doctor.test.js.map +1 -0
  542. package/dist/tests/shell/effect-vm-create.test.js +52 -0
  543. package/dist/tests/shell/effect-vm-create.test.js.map +1 -0
  544. package/dist/tests/shell/gh-port.test.js +63 -0
  545. package/dist/tests/shell/gh-port.test.js.map +1 -0
  546. package/dist/tests/shell/gondolin-dispatch-guard.test.js +144 -0
  547. package/dist/tests/shell/gondolin-dispatch-guard.test.js.map +1 -0
  548. package/dist/tests/shell/gondolin-dispatch-shquote.test.js +168 -0
  549. package/dist/tests/shell/gondolin-dispatch-shquote.test.js.map +1 -0
  550. package/dist/tests/shell/gondolin-image-converter.test.js +208 -0
  551. package/dist/tests/shell/gondolin-image-converter.test.js.map +1 -0
  552. package/dist/tests/shell/gondolin-image-fetch.test.js +93 -0
  553. package/dist/tests/shell/gondolin-image-fetch.test.js.map +1 -0
  554. package/dist/tests/shell/http-handler.test.js +608 -0
  555. package/dist/tests/shell/http-handler.test.js.map +1 -0
  556. package/dist/tests/shell/http-server.test.js +53 -0
  557. package/dist/tests/shell/http-server.test.js.map +1 -0
  558. package/dist/tests/shell/mcp-runtime.test.js +366 -0
  559. package/dist/tests/shell/mcp-runtime.test.js.map +1 -0
  560. package/dist/tests/shell/mise-config-asset.test.js +87 -0
  561. package/dist/tests/shell/mise-config-asset.test.js.map +1 -0
  562. package/dist/tests/shell/orchestrator-loop.test.js +583 -0
  563. package/dist/tests/shell/orchestrator-loop.test.js.map +1 -0
  564. package/dist/tests/shell/reconciler-passes.test.js +314 -0
  565. package/dist/tests/shell/reconciler-passes.test.js.map +1 -0
  566. package/dist/tests/shell/runner-loop-turn.test.js +97 -0
  567. package/dist/tests/shell/runner-loop-turn.test.js.map +1 -0
  568. package/dist/tests/shell/runner-slice.test.js +536 -0
  569. package/dist/tests/shell/runner-slice.test.js.map +1 -0
  570. package/dist/tests/shell/scaffold.test.js +65 -0
  571. package/dist/tests/shell/scaffold.test.js.map +1 -0
  572. package/dist/tests/shell/tick-config.test.js +83 -0
  573. package/dist/tests/shell/tick-config.test.js.map +1 -0
  574. package/dist/tests/shell/tracker-parse-dates.test.js +44 -0
  575. package/dist/tests/shell/tracker-parse-dates.test.js.map +1 -0
  576. package/dist/tests/shell/tracker-write-issue.test.js +154 -0
  577. package/dist/tests/shell/tracker-write-issue.test.js.map +1 -0
  578. package/dist/tests/shell/workflow-prompt-split.test.js +208 -0
  579. package/dist/tests/shell/workflow-prompt-split.test.js.map +1 -0
  580. package/dist/tests/shell/workspace-live-config.test.js +140 -0
  581. package/dist/tests/shell/workspace-live-config.test.js.map +1 -0
  582. package/package.json +21 -9
  583. package/patches/@earendil-works+gondolin+0.12.0.patch +173 -0
  584. package/prompts/Reflect.md +91 -0
  585. package/prompts/Review.md +97 -0
  586. package/prompts/Todo.md +96 -0
  587. package/prompts/_footer.md +41 -0
  588. package/prompts/_preamble.md +42 -0
  589. package/prompts-minimal/Todo.md +26 -0
  590. package/scripts/postinstall.mjs +63 -0
  591. package/scripts/vm-agent.mjs +312 -90
  592. package/WORKFLOW.md +0 -744
  593. package/dist/acp-bridge.js +0 -324
  594. package/dist/acp-bridge.js.map +0 -1
  595. package/dist/actions/cache.js +0 -191
  596. package/dist/actions/cache.js.map +0 -1
  597. package/dist/actions/effects.js +0 -41
  598. package/dist/actions/effects.js.map +0 -1
  599. package/dist/actions/executor.js +0 -570
  600. package/dist/actions/executor.js.map +0 -1
  601. package/dist/actions/index.js +0 -13
  602. package/dist/actions/index.js.map +0 -1
  603. package/dist/actions/parsing.js.map +0 -1
  604. package/dist/actions/predicate-env.js +0 -27
  605. package/dist/actions/predicate-env.js.map +0 -1
  606. package/dist/actions/predicates.js +0 -49
  607. package/dist/actions/predicates.js.map +0 -1
  608. package/dist/actions/templating.js +0 -66
  609. package/dist/actions/templating.js.map +0 -1
  610. package/dist/actions/types.js +0 -15
  611. package/dist/actions/types.js.map +0 -1
  612. package/dist/agent/acp.js +0 -473
  613. package/dist/agent/acp.js.map +0 -1
  614. package/dist/agent/adapter-names.js +0 -159
  615. package/dist/agent/adapter-names.js.map +0 -1
  616. package/dist/agent/adapters.js +0 -511
  617. package/dist/agent/adapters.js.map +0 -1
  618. package/dist/agent/credential-extractors.js +0 -342
  619. package/dist/agent/credential-extractors.js.map +0 -1
  620. package/dist/agent/credential-secrets.js +0 -628
  621. package/dist/agent/credential-secrets.js.map +0 -1
  622. package/dist/agent/credential-ticker.js +0 -57
  623. package/dist/agent/credential-ticker.js.map +0 -1
  624. package/dist/agent/gondolin-creds-staging.js +0 -356
  625. package/dist/agent/gondolin-creds-staging.js.map +0 -1
  626. package/dist/agent/gondolin-dispatch.js +0 -375
  627. package/dist/agent/gondolin-dispatch.js.map +0 -1
  628. package/dist/agent/gondolin.js +0 -124
  629. package/dist/agent/gondolin.js.map +0 -1
  630. package/dist/agent/runner-decisions.js +0 -134
  631. package/dist/agent/runner-decisions.js.map +0 -1
  632. package/dist/agent/runner.js +0 -1456
  633. package/dist/agent/runner.js.map +0 -1
  634. package/dist/agent/tool-call-summary.js +0 -102
  635. package/dist/agent/tool-call-summary.js.map +0 -1
  636. package/dist/agent/vm-acp-mapping.js +0 -73
  637. package/dist/agent/vm-acp-mapping.js.map +0 -1
  638. package/dist/agent/vm-guards.js +0 -262
  639. package/dist/agent/vm-guards.js.map +0 -1
  640. package/dist/agent/vm-port.js +0 -22
  641. package/dist/agent/vm-port.js.map +0 -1
  642. package/dist/agent/vm-process-registry.js +0 -79
  643. package/dist/agent/vm-process-registry.js.map +0 -1
  644. package/dist/bin/cli-args.js +0 -105
  645. package/dist/bin/cli-args.js.map +0 -1
  646. package/dist/bin/symphony.js +0 -794
  647. package/dist/bin/symphony.js.map +0 -1
  648. package/dist/errors.js +0 -15
  649. package/dist/errors.js.map +0 -1
  650. package/dist/http-disk.js +0 -135
  651. package/dist/http-disk.js.map +0 -1
  652. package/dist/http-handlers.js.map +0 -1
  653. package/dist/http.js.map +0 -1
  654. package/dist/issues.js +0 -178
  655. package/dist/issues.js.map +0 -1
  656. package/dist/logging.js +0 -203
  657. package/dist/logging.js.map +0 -1
  658. package/dist/mcp.js +0 -706
  659. package/dist/mcp.js.map +0 -1
  660. package/dist/memory.js +0 -85
  661. package/dist/memory.js.map +0 -1
  662. package/dist/orchestrator-decisions.js +0 -331
  663. package/dist/orchestrator-decisions.js.map +0 -1
  664. package/dist/orchestrator.js +0 -1569
  665. package/dist/orchestrator.js.map +0 -1
  666. package/dist/prompt.js +0 -65
  667. package/dist/prompt.js.map +0 -1
  668. package/dist/reconciler/cache.js +0 -65
  669. package/dist/reconciler/cache.js.map +0 -1
  670. package/dist/reconciler/index.js +0 -448
  671. package/dist/reconciler/index.js.map +0 -1
  672. package/dist/reconciler/ledger.js +0 -131
  673. package/dist/reconciler/ledger.js.map +0 -1
  674. package/dist/reconciler/pr-adapters.js +0 -174
  675. package/dist/reconciler/pr-adapters.js.map +0 -1
  676. package/dist/reconciler/pr-decide.js.map +0 -1
  677. package/dist/reconciler/pr.js +0 -422
  678. package/dist/reconciler/pr.js.map +0 -1
  679. package/dist/reconciler/types.js +0 -12
  680. package/dist/reconciler/types.js.map +0 -1
  681. package/dist/reconciler/vm.js +0 -243
  682. package/dist/reconciler/vm.js.map +0 -1
  683. package/dist/reconciler/workspace-defaults.js +0 -83
  684. package/dist/reconciler/workspace-defaults.js.map +0 -1
  685. package/dist/reconciler/workspace.js +0 -272
  686. package/dist/reconciler/workspace.js.map +0 -1
  687. package/dist/runlog.js +0 -403
  688. package/dist/runlog.js.map +0 -1
  689. package/dist/scaffold.js +0 -165
  690. package/dist/scaffold.js.map +0 -1
  691. package/dist/trackers/local.js +0 -445
  692. package/dist/trackers/local.js.map +0 -1
  693. package/dist/trackers/types.js +0 -10
  694. package/dist/trackers/types.js.map +0 -1
  695. package/dist/types.js +0 -3
  696. package/dist/types.js.map +0 -1
  697. package/dist/util/clock.js +0 -12
  698. package/dist/util/clock.js.map +0 -1
  699. package/dist/util/crypto.js +0 -25
  700. package/dist/util/crypto.js.map +0 -1
  701. package/dist/util/frontmatter.js +0 -70
  702. package/dist/util/frontmatter.js.map +0 -1
  703. package/dist/util/fs-issues.js +0 -22
  704. package/dist/util/fs-issues.js.map +0 -1
  705. package/dist/util/process.js +0 -152
  706. package/dist/util/process.js.map +0 -1
  707. package/dist/util/workspace-key.js +0 -10
  708. package/dist/util/workspace-key.js.map +0 -1
  709. package/dist/workflow-loader.js +0 -147
  710. package/dist/workflow-loader.js.map +0 -1
  711. package/dist/workflow.js +0 -822
  712. package/dist/workflow.js.map +0 -1
  713. package/dist/workspace-types.js +0 -8
  714. package/dist/workspace-types.js.map +0 -1
  715. package/dist/workspace.js +0 -443
  716. package/dist/workspace.js.map +0 -1
package/README.md CHANGED
@@ -19,9 +19,9 @@ workspace for review.
19
19
  ┌──────────────────────────────────────────────────────────────────────────┐
20
20
  │ symphony (node host) │
21
21
  │ │
22
- │ ./issues/<state>/*.md ──┐
23
- │ ./WORKFLOW.md ├──▶ orchestrator ──▶ agent runner
24
- │ ./WORKFLOW.template.md ──┘ poll · reconcile · dispatch
22
+ │ ./issues/<state>/*.md ──┐
23
+ │ ./WORKFLOW.yaml ├──▶ orchestrator ──▶ agent runner
24
+ │ ./WORKFLOW.template.yaml ──┘ poll · reconcile · dispatch
25
25
  │ │ │
26
26
  │ ▼ ACP/RPC │
27
27
  │ ┌───────────────────────────────┐ │
@@ -45,46 +45,96 @@ original architectural narrative, see
45
45
 
46
46
  ## Quick start
47
47
 
48
- Prerequisites:
49
-
50
- - Node.js 20.
51
- - The agent rootfs image. Gondolin is the in-process microVM substrate
52
- (`@earendil-works/gondolin`), so there is no separate VM daemon to run. The
53
- agent image is built **once** from `images/agents/` via `npm run build:image`:
54
- it starts from `node:24-bookworm-slim`, installs base CLI tooling, npm-installs
55
- every ACP-capable coding agent (`claude-agent-acp`, `codex-acp`, `opencode`),
56
- and bakes the in-VM stdio launcher at `/opt/symphony/vm-agent.mjs` into the
57
- image. The build prints a content-addressed build id; pin it (or a
58
- `name:tag` ref like `symphony-agents:latest`) in `WORKFLOW.md`'s
59
- `gondolin.image`. See [images/agents/README.md](./images/agents/README.md)
60
- for the build steps and requirements.
61
- - For the default `acp.adapter: claude`: a credentials file at
62
- `~/.claude/.credentials.json` on the host. Symphony reads it only on the
63
- host side: the guest holds only a token-shaped placeholder, and the host
64
- substitutes the real OAuth access token into the outbound request at
65
- Gondolin egress (TLS-MITM). The credential file itself is never staged into
66
- the VM.
67
-
68
- Run, against an existing workflow file in the current directory:
48
+ The golden path from zero to your first dispatched issue. The details behind
49
+ each step live in [Prerequisites in detail](#prerequisites-in-detail) below — you
50
+ should not need them to get here.
69
51
 
70
52
  ```bash
71
- npx smol-symphony WORKFLOW.md
53
+ # 1. Build the agent rootfs image once. This ships only `mise` (jdx/mise) — node +
54
+ # the coding-agent CLIs are mise-installed at dispatch, the launcher is injected —
55
+ # and tags the result `symphony-agents:latest` — the tag the scaffolded
56
+ # WORKFLOW.yaml pins, so a first run needs no edit.
57
+ git clone https://github.com/dizk/smol-symphony.git
58
+ cd smol-symphony && npm install && npm run build:image
59
+
60
+ # 2. In your project, scaffold the minimal WORKFLOW.yaml. With no workflow file
61
+ # present, symphony offers to write a ~30-line starter (every key required,
62
+ # no power features), then exits so you can glance at it.
63
+ cd /path/to/your/project
64
+ npx smol-symphony WORKFLOW.yaml
65
+
66
+ # 3. Verify the whole setup in one pass before the first dispatch. `symphony
67
+ # doctor` runs every adoption-prerequisite probe — Node version, the
68
+ # `gondolin.image` pin, each configured adapter's host credential, a
69
+ # writable `tracker.root`, and a bindable dashboard port — and prints a
70
+ # PASS/FAIL line per check with a one-line fix for each failure, exiting 0
71
+ # iff every check passes. Unlike startup (which bails on the first failure),
72
+ # it runs all probes so you see the whole picture at once.
73
+ npx smol-symphony doctor WORKFLOW.yaml
74
+
75
+ # 4. Drop one issue into the tracker.
76
+ mkdir -p issues/Todo
77
+ printf -- '---\ntitle: "Say hi"\n---\nAdd a hi() that returns "hi".\n' > issues/Todo/1.md
78
+
79
+ # 5. Run symphony and watch it dispatch.
80
+ npx smol-symphony WORKFLOW.yaml --port 8787
81
+ # Open http://127.0.0.1:8787/ — issue 1 moves from "on disk" into a running
82
+ # session as symphony boots a per-issue microVM and dispatches the agent.
72
83
  ```
73
84
 
74
- (Or `npm i -g smol-symphony` and then `symphony WORKFLOW.md` to skip the
75
- fetch.) Both invoke the `symphony` bin shipped in this package.
76
-
77
- Open the dashboard at `http://127.0.0.1:8787/`. Drop issues into
78
- `issues/Todo/` from the filesystem or the dashboard's `new issue` form;
79
- symphony dispatches them on the next poll.
80
-
81
- The console stays quiet: with the default log file configured, symphony prints
82
- a one-line-per-field startup banner (workflow, tracker root, dashboard URL,
83
- log-file path) and routes the structured `key=value` stream to
84
- `.symphony/logs/symphony.log` only. `tail -f` that file to follow the detail.
85
- Pass `--verbose` (alias `--foreground`) to mirror the structured stream back to
86
- the console for interactive debugging. With no log file configured (the
87
- `SYMPHONY_LOG_FILE=""` override), the structured stream stays on stderr.
85
+ The same first-run scaffold also installs an issue-filing skill at
86
+ `.claude/skills/symphony-issues/SKILL.md` (best-effort it never blocks the
87
+ workflow scaffold), so a coding agent in the freshly-onboarded repo can file
88
+ well-formed tracker issues and decompose a large task into a `blocked_by` DAG
89
+ from day one.
90
+
91
+ The scaffolded file ([WORKFLOW.minimal.yaml](./WORKFLOW.minimal.yaml) is the shipped
92
+ copy) runs as-is once `symphony-agents:latest` exists; the only edits a different
93
+ setup needs are `gondolin.image` (if you pinned a build id) and the adapter
94
+ credential for your chosen agent. When you want a power feature it omits — typed
95
+ action DAGs, PR autopilot, per-state adapters, egress allowlists graduate to
96
+ the annotated [WORKFLOW.template.yaml](./WORKFLOW.template.yaml).
97
+
98
+ (Or `npm i -g smol-symphony` and then `symphony doctor` / `symphony WORKFLOW.yaml`
99
+ to skip the `npx` fetch — both invoke the `symphony` bin shipped in this
100
+ package.)
101
+
102
+ ### Prerequisites in detail
103
+
104
+ - **Node.js ≥ 20.**
105
+ - **The agent rootfs image** (step 1). Gondolin is the in-process microVM
106
+ substrate (`@earendil-works/gondolin`), so there is no separate VM daemon to
107
+ run. The image is built **once** from `images/agents/` via
108
+ `npm run build:image`: it starts from `node:24-bookworm-slim`, installs base
109
+ CLI tooling, and ships only the `mise` (jdx/mise) binary. node + every
110
+ ACP-capable coding agent (`claude-agent-acp`, `codex-acp`, …) are
111
+ NO LONGER baked — they come from a mise SYSTEM config symphony stages into the
112
+ guest at dispatch (`assets/symphony-mise.system.toml`) and installs via
113
+ `mise install` into a warm-cached data dir; a consuming repo's own `mise.toml`
114
+ adds project toolchains (rust, go, kotlin+gradle, …) on top. The in-VM stdio
115
+ launcher is likewise injected at dispatch, not baked. So bumping an agent CLI is
116
+ a one-line edit to the staged mise config + a restart — no image rebuild + repin.
117
+ The build prints a content-addressed build id; pin it (or the
118
+ `symphony-agents:latest` tag) in `WORKFLOW.yaml`'s `gondolin.image`. See
119
+ [images/agents/README.md](./images/agents/README.md) for the build steps and
120
+ requirements, and `gondolin.mise` in
121
+ [WORKFLOW.template.yaml](./WORKFLOW.template.yaml) to tune the data dir or opt out.
122
+ - **An adapter credential.** For the default `acp.adapter: claude`: a
123
+ credentials file at `~/.claude/.credentials.json` on the host. Symphony reads
124
+ it only on the host side: the guest holds only a token-shaped placeholder, and
125
+ the host substitutes the real OAuth access token into the outbound request at
126
+ Gondolin egress (TLS-MITM). The credential file itself is never staged into
127
+ the VM. (For `acp.adapter: codex`, see [WORKFLOW.template.yaml](./WORKFLOW.template.yaml).)
128
+ - **Skipping the `npx` fetch.** `npm i -g smol-symphony` installs the `symphony`
129
+ bin globally so `symphony WORKFLOW.yaml` works without re-fetching; the image
130
+ build still needs a checkout (it lives in `images/agents/`).
131
+ - **Console output.** With the default log file configured, symphony prints a
132
+ one-line-per-field startup banner (workflow, tracker root, dashboard URL,
133
+ log-file path) and routes the structured `key=value` stream to
134
+ `.symphony/logs/symphony.log` only. `tail -f` that file to follow the detail.
135
+ Pass `--verbose` (alias `--foreground`) to mirror the structured stream back
136
+ to the console for interactive debugging. With no log file configured (the
137
+ `SYMPHONY_LOG_FILE=""` override), the structured stream stays on stderr.
88
138
 
89
139
  ### From a checkout
90
140
 
@@ -95,7 +145,7 @@ git clone https://github.com/dizk/smol-symphony.git
95
145
  cd smol-symphony
96
146
  npm install
97
147
  npm run build
98
- npx symphony WORKFLOW.md # the local bin
148
+ npx symphony WORKFLOW.yaml # the local bin
99
149
  ```
100
150
 
101
151
  `npm run dev` (via `tsx watch`) reruns on source edits.
@@ -104,7 +154,7 @@ npx symphony WORKFLOW.md # the local bin
104
154
 
105
155
  Issues live as `.md` files under `tracker.root`. The parent directory is the
106
156
  issue state; the set of valid state directories comes from the `states:` block
107
- in `WORKFLOW.md` (see below) and is auto-mkdir'd on startup.
157
+ in `WORKFLOW.yaml` (see below) and is auto-mkdir'd on startup.
108
158
 
109
159
  ```
110
160
  issues/
@@ -143,12 +193,14 @@ itself in response to `symphony.transition`. The agent inside the VM does
143
193
  **not** have filesystem access to the tracker root: it signals progress
144
194
  through the MCP server and the orchestrator does the file move.
145
195
 
146
- ## WORKFLOW.md
196
+ ## WORKFLOW.yaml
147
197
 
148
- `WORKFLOW.md` is a YAML front matter block (orchestrator config) plus a
149
- [Liquid](https://liquidjs.com/)-templated prompt body. The shipped file in
150
- this repo is the canonical project workflow; see
151
- [WORKFLOW.template.md](./WORKFLOW.template.md) for the annotated reference
198
+ `WORKFLOW.yaml` is a pure YAML config file (the orchestrator config). Each
199
+ active state's prompt lives in its own `prompt_file` — a
200
+ [Liquid](https://liquidjs.com/)-templated file under `prompts/`, wrapped in the
201
+ shared `prompt.preamble_file`/`footer_file`. The shipped file in this repo is
202
+ the canonical project workflow; see
203
+ [WORKFLOW.template.yaml](./WORKFLOW.template.yaml) for the annotated reference
152
204
  covering every supported option, its type, default, and example.
153
205
 
154
206
  The workflow is a **state machine**. A required top-level `states:` block
@@ -156,14 +208,14 @@ declares every state an issue can occupy, its `role` (`active` — dispatched;
156
208
  `terminal` — triggers cleanup and handoff; `holding` — sits outside the
157
209
  dispatch loop, e.g. `Triage`), and optional per-state `adapter`, `model`,
158
210
  `max_turns`, and `allowed_transitions` overrides. A single issue can travel
159
- through any number of states with distinct adapters and instructions; the
160
- prompt body can branch on the current state with Liquid
161
- `{% case issue.state %}`. The shipped workflow uses a two-stage
162
- `Todo → Review → Done` flow (Claude implements, Codex reviews).
211
+ through any number of states with distinct adapters and instructions; each
212
+ active state names its own `prompt_file`, so the agent in each state sees only
213
+ that state's instructions plus the shared preamble/footer. The shipped workflow
214
+ uses a two-stage `Todo → Review → Done` flow (Claude implements, Codex reviews).
163
215
 
164
- Symphony watches the file and re-applies poll interval, concurrency, typed
165
- actions, prompt body, gondolin settings, etc. on change without restart.
166
- In-flight runs keep the settings they started with.
216
+ Symphony watches the file and its prompt files, and re-applies poll interval,
217
+ concurrency, typed actions, prompts, gondolin settings, etc. on change without
218
+ restart. In-flight runs keep the settings they started with.
167
219
 
168
220
  ## Dashboard
169
221
 
@@ -233,7 +285,7 @@ the adapter reaches for inside the VM:
233
285
  | `claude` | `claude-agent-acp` | placeholder + host egress swap |
234
286
  | `codex` | `codex-acp` | placeholder + host egress swap |
235
287
 
236
- `WORKFLOW.md`:
288
+ `WORKFLOW.yaml`:
237
289
 
238
290
  ```yaml
239
291
  acp:
@@ -269,7 +321,7 @@ holds only the placeholder.
269
321
  On transition into the Done state the orchestrator runs that state's typed
270
322
  `actions:` block — two records, `push_branch` then `create_pr_if_missing` —
271
323
  which push the per-issue branch and open a PR when a GitHub repo is configured:
272
- set `workspace.github_repo: <owner>/<repo>` in `WORKFLOW.md` (or export
324
+ set `workspace.github_repo: <owner>/<repo>` in `WORKFLOW.yaml` (or export
273
325
  `SYMPHONY_REPO=<owner>/<repo>`, which overrides the file). Each action's
274
326
  `if: $repo` predicate short-circuits to a no-op in local-only mode (neither
275
327
  set), so the branch is simply left in the workspace until cleanup; pick the
@@ -286,8 +338,8 @@ and snapshot plumbing replaces the old opaque shell-exit surface: on a
286
338
  rate-limit the `create_pr_if_missing` action surfaces "retrying in 60s" on the
287
339
  dashboard rather than failing silently.
288
340
 
289
- See `states.Done.actions` in [WORKFLOW.md](./WORKFLOW.md) for the canonical
290
- record pair and [WORKFLOW.template.md](./WORKFLOW.template.md) for the
341
+ See `states.Done.actions` in [WORKFLOW.yaml](./WORKFLOW.yaml) for the canonical
342
+ record pair and [WORKFLOW.template.yaml](./WORKFLOW.template.yaml) for the
291
343
  typed-action reference.
292
344
 
293
345
  ## Trust posture
package/SPEC.md CHANGED
@@ -34,7 +34,7 @@ The service solves four operational problems:
34
34
  scripts.
35
35
  - It isolates agent execution in per-issue workspaces so agent commands run
36
36
  only inside per-issue workspace directories.
37
- - It keeps the workflow policy in-repo (`WORKFLOW.md`) so teams version the
37
+ - It keeps the workflow policy in-repo (`WORKFLOW.yaml`) so teams version the
38
38
  agent prompt and runtime settings with their code.
39
39
  - It provides enough observability to operate and debug multiple concurrent
40
40
  agent runs.
@@ -59,7 +59,7 @@ Boundary:
59
59
  - Create deterministic per-issue workspaces and preserve them across runs.
60
60
  - Stop active runs when issue state changes make them ineligible.
61
61
  - Recover from transient failures with exponential backoff.
62
- - Load runtime behavior from a repository-owned `WORKFLOW.md` contract.
62
+ - Load runtime behavior from a repository-owned `WORKFLOW.yaml` contract.
63
63
  - Expose operator-visible observability (at minimum structured logs).
64
64
  - Support tracker/filesystem-driven restart recovery without requiring a
65
65
  persistent database; exact in-memory scheduler state is not restored.
@@ -108,10 +108,12 @@ Fields:
108
108
 
109
109
  #### 3.1.2 Workflow Definition
110
110
 
111
- Parsed `WORKFLOW.md` payload:
111
+ Parsed `WORKFLOW.yaml` payload:
112
112
 
113
- - `config` (map) — YAML front matter root object.
114
- - `prompt_template` (string) Markdown body after front matter, trimmed.
113
+ - `config` (map) — the decoded YAML config root object.
114
+ - `prompt_templates` (map of state name string, optional) — the per-state
115
+ prompt templates the loader assembles from each active state's `prompt_file`
116
+ (wrapped in the shared `prompt.preamble_file`/`footer_file`).
115
117
 
116
118
  #### 3.1.3 Service Config (Typed View)
117
119
 
@@ -160,7 +162,7 @@ attempt dispatches into).
160
162
  Workflow file path precedence:
161
163
 
162
164
  1. Explicit application/runtime setting (set by CLI startup path).
163
- 2. Default: `WORKFLOW.md` in the current process working directory.
165
+ 2. Default: `WORKFLOW.yaml` in the current process working directory.
164
166
 
165
167
  Loader behavior:
166
168
 
@@ -169,22 +171,22 @@ Loader behavior:
169
171
 
170
172
  ### 4.2 File Format
171
173
 
172
- `WORKFLOW.md` is a Markdown file with OPTIONAL YAML front matter.
174
+ `WORKFLOW.yaml` is a pure YAML config file. There is no inline prompt body;
175
+ each active state's prompt lives in its own `prompt_file` (a Liquid template).
173
176
 
174
177
  Parsing rules:
175
178
 
176
- - If file starts with `---`, parse lines until the next `---` as YAML front
177
- matter.
178
- - Remaining lines become the prompt body.
179
- - If front matter is absent, treat the entire file as prompt body and use an
180
- empty config map.
181
- - YAML front matter MUST decode to a map/object; non-map YAML is an error.
182
- - Prompt body is trimmed before use.
179
+ - The whole file decodes as a single YAML document the config map.
180
+ - The decoded YAML MUST be a map/object; a list or bare scalar is an error.
181
+ - An empty/whitespace-only file decodes to an empty config map.
182
+ - A leading `---` YAML document marker is tolerated (decoded as YAML), but
183
+ there is no front-matter fence and no Markdown body.
183
184
 
184
185
  Returned workflow object:
185
186
 
186
- - `config`: front matter root object (not nested under a `config` key).
187
- - `prompt_template`: trimmed Markdown body.
187
+ - `config`: the decoded YAML config root object (not nested under a `config` key).
188
+ - `prompt_templates`: per-state assembled prompt templates (built by the shell
189
+ loader from each active state's `prompt_file`; see §3.1.2).
188
190
 
189
191
  ### 4.3 Front Matter Schema
190
192
 
@@ -192,7 +194,7 @@ Top-level keys: `tracker`, `states`, `polling`, `workspace`, `agent`,
192
194
  `acp`. Unknown keys SHOULD be ignored for forward compatibility. Extensions
193
195
  MAY define additional top-level keys without changing the core schema.
194
196
 
195
- `WORKFLOW.template.md` is the annotated reference for every recognized field;
197
+ `WORKFLOW.template.yaml` is the annotated reference for every recognized field;
196
198
  this section captures the contract the loader enforces.
197
199
 
198
200
  #### 4.3.1 `tracker` (object)
@@ -216,7 +218,7 @@ supported kind.
216
218
 
217
219
  - `root` (path string or `$VAR`, default `<system-temp>/symphony_workspaces`)
218
220
  - `~` is expanded; relative paths are resolved relative to the directory
219
- containing `WORKFLOW.md`. The effective workspace root is normalized to an
221
+ containing `WORKFLOW.yaml`. The effective workspace root is normalized to an
220
222
  absolute path before use.
221
223
 
222
224
  #### 4.3.4 `agent` (object)
@@ -235,7 +237,7 @@ supported kind.
235
237
  Coding-agent launch is mediated by the Agent Client Protocol. The runtime
236
238
  selects an adapter profile and runs it inside the per-issue sandbox; the host
237
239
  opens an authenticated TCP bridge that the in-sandbox proxy dials back over
238
- to carry ACP frames. See `WORKFLOW.template.md` (`acp:` section) for the full
240
+ to carry ACP frames. See `WORKFLOW.template.yaml` (`acp:` section) for the full
239
241
  annotated field list. Adapter credentials are handled out of band of this
240
242
  config — there is no credential-mode knob; see §6.3 for the host credential
241
243
  proxy and identity-staging contract.
@@ -251,7 +253,7 @@ Fields read by the runtime:
251
253
  - `stall_timeout_ms` (integer, default `300000`; `<= 0` disables stall
252
254
  detection)
253
255
  - `bridge` (object) — `bind_host`, `bind_port`, `reach_host`, `reach_url`,
254
- `connect_timeout_ms`; see `WORKFLOW.template.md`.
256
+ `connect_timeout_ms`; see `WORKFLOW.template.yaml`.
255
257
 
256
258
  #### 4.3.6 `states` (map)
257
259
 
@@ -315,7 +317,8 @@ states, not named here.
315
317
 
316
318
  ### 4.4 Prompt Template Contract
317
319
 
318
- The Markdown body of `WORKFLOW.md` is the per-issue prompt template.
320
+ Each active state's `prompt_file` (wrapped in the shared
321
+ `prompt.preamble_file`/`footer_file`) is that state's per-issue prompt template.
319
322
 
320
323
  Rendering requirements:
321
324
 
@@ -332,8 +335,9 @@ Template input variables:
332
335
 
333
336
  Fallback prompt behavior:
334
337
 
335
- - If the workflow prompt body is empty, the runtime MAY use a minimal default
336
- prompt (`You are working on an issue.`).
338
+ - If a dispatched state has no assembled template (no `prompt_file`), or the
339
+ template renders empty, the runtime MAY use a minimal default prompt
340
+ (`You are working on an issue.`).
337
341
  - Workflow file read/parse failures are configuration/validation errors and
338
342
  SHOULD NOT silently fall back to a prompt.
339
343
 
@@ -660,7 +664,12 @@ active → holding); cleanup is driven by the target state's role
660
664
 
661
665
  Inputs to prompt rendering:
662
666
 
663
- - `workflow.prompt_template`
667
+ - `workflow.prompt_templates[issue.state]` — the assembled prompt template for
668
+ the issue's current state, selected from the per-state `prompt_templates` map
669
+ (each entry built by the loader from that state's `prompt_file`, wrapped in
670
+ the shared `prompt.preamble_file`/`footer_file`; see §3.1.2 / §4.2). When no
671
+ template exists for the state (or it is empty), rendering falls back to the
672
+ generic prompt `You are working on an issue.`
664
673
  - normalized `issue` object
665
674
  - OPTIONAL `attempt` integer (retry/continuation metadata)
666
675
 
@@ -0,0 +1,34 @@
1
+ # WORKFLOW.yaml — minimal starter scaffolded by smol-symphony.
2
+ #
3
+ # Run: npx smol-symphony WORKFLOW.yaml --port 8787
4
+ #
5
+ # A workflow file is pure YAML config; each active state's prompt lives in its
6
+ # own `prompt_file`. `npx smol-symphony` scaffolds this file plus prompts/Todo.md
7
+ # next to it. For the full annotated reference — per-state adapters/models, typed
8
+ # action DAGs, egress allowlists, PR autopilot, sleep-cycle reflection, and every
9
+ # other optional power feature — see WORKFLOW.template.yaml:
10
+ # https://github.com/dizk/smol-symphony/blob/main/WORKFLOW.template.yaml
11
+
12
+ tracker:
13
+ kind: local # issues are markdown files under <tracker.root>/<state>/
14
+ # default root: ~/.symphony/trackers/<project> (outside
15
+ # the repo; set tracker.root: to override)
16
+
17
+ states:
18
+ Todo:
19
+ role: active # dispatched — an agent picks the issue up here
20
+ adapter: claude # the coding agent to run (claude | codex)
21
+ prompt_file: prompts/Todo.md # this state's prompt template
22
+ Done:
23
+ role: terminal # transitioning here ends the run and cleans up
24
+ Triage:
25
+ role: holding # propose_issue lands here; never auto-dispatched
26
+
27
+ gondolin:
28
+ # The agent rootfs each per-issue microVM boots. `managed` (the default) FETCHES a
29
+ # prebuilt asset from a published symphony release on first run — no docker, no
30
+ # `npm run build:image`. The image ships only `mise`; node + the agent CLIs are always
31
+ # mise-installed at dispatch (see gondolin.mise in WORKFLOW.template.yaml — mise
32
+ # provisioning is the only toolchain path). To pin your own asset instead, set this to a build id / name:tag from
33
+ # `npm run build:image`, or use gondolin.oci_image for an auto-converted OCI ref.
34
+ image: managed