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
@@ -0,0 +1,338 @@
1
+ // FCIS rewrite — imperative shell: the per-attempt runner loop driver.
2
+ //
3
+ // Ports the original `src/agent/runner.ts:runAttempt` phase pipeline (read for
4
+ // reference, never modified). This is the THIN imperative shell: every routing /
5
+ // precedence / classification DECISION lives in the functional core
6
+ // (src/core/runner/{dispatch-config,injection,vm-plan,turn}.ts and
7
+ // src/core/actions/run-fold.ts). The shell only EXECUTES: it sequences the
8
+ // phases, drives real IO through the injected ports, and owns the per-attempt
9
+ // unwind (teardown safety net).
10
+ //
11
+ // Per the FCIS layout rule, a shell module imports from src/types ONLY (the
12
+ // composition root is the one place core is wired in). So the pure-core decision
13
+ // functions this loop needs are INJECTED through `RunnerLoopCore` — the
14
+ // composition root (src/shell/main.ts) binds the real core fns to it. The ports
15
+ // (WorkspacePort, VmClient, AcpPort, IssueTracker, …) come from src/types/ports.
16
+ //
17
+ // Phase pipeline (faithful to the reference runAttemptCore):
18
+ // 1. resolve dispatch config (core: resolveDispatchConfig — pinned ONCE)
19
+ // 2. workspace setup (WorkspacePort.ensureFor + fetchBaseInWorkspace)
20
+ // 3. adapter prep (AdapterRegistry + core: applyRuntimeInjections)
21
+ // 4. validate ACP transport (core: buildControlPlaneTunnel)
22
+ // 5. VM bring-up from VmPlan (core: buildVmPlan → VmBringUp/GondolinDispatcher)
23
+ // 6. ACP session (AcpPort.sessionNew)
24
+ // 7. turn loop (core: turn deciders) — drives AcpPort.runPrompt
25
+ // 8. terminal actions (core: run-fold) — the per-state cleanup block
26
+ // 9. teardown safety net (close VM + deregister secret manager; idempotent)
27
+ import { runTurnLoop } from './runner-loop-turn.js';
28
+ /** Fail a phase: same shape the reference `failPhase` returned. */
29
+ function fail(reason) {
30
+ return { ok: false, reason, threadId: null, turnsCompleted: 0 };
31
+ }
32
+ /**
33
+ * Drive one attempt for `issue`. Mirrors the reference runAttempt: a strict
34
+ * phase pipeline where any phase failure short-circuits to a RunAttemptResult,
35
+ * and a teardown safety net guarantees the VM + per-VM secret registration are
36
+ * released on every exit path (idempotent — teardown guards re-entry).
37
+ */
38
+ export async function runAttempt(deps, issue, attempt, cancelSignal, runningEntry) {
39
+ const log = deps.log.withIssue(issue.id);
40
+ // Phases 1–5 (config → workspace → injection → VmPlan): all pure failures
41
+ // short-circuit before any VM exists, so no teardown is owed yet.
42
+ const prep = await prepareAttempt(deps, issue, runningEntry, log);
43
+ if (prep.kind === 'fail')
44
+ return fail(prep.reason);
45
+ const { resolved, adapterId, workspacePath, plan, launchEnv } = prep;
46
+ // Bring the VM up through the SINGLE dispatch path (the real GondolinDispatcher:
47
+ // it stages the plan's guest files — INCLUDING the /opt/symphony/vm-agent.mjs
48
+ // launcher — builds the { tcp: { hosts }, dns } tunnel shape, runs the BYO probe +
49
+ // the credential-mount guard, and LAUNCHES the in-VM agent, returning its live
50
+ // exec). After bring-up succeeds ONLY this attempt's teardown can release the
51
+ // handle + the per-VM secret registration, so every post-bring-up exit path runs
52
+ // through `unwind` (reference runSessionOrTeardown).
53
+ let brought;
54
+ try {
55
+ brought = await deps.bringUp.bringUp({
56
+ issue,
57
+ adapterId,
58
+ plan,
59
+ launchEnv,
60
+ workspacePath,
61
+ onStderr: (chunk) => pipeStderrChunk(deps, issue, chunk),
62
+ });
63
+ }
64
+ catch (err) {
65
+ log.emit('error', 'gondolin dispatch failed', { error: err.message });
66
+ return fail('gondolin dispatch error');
67
+ }
68
+ const vm = brought.vm;
69
+ // From here every failure path MUST tear the VM down. `unwind` is idempotent (the
70
+ // bring-up handle's teardown guards re-entry: kill exec + close VM + deregister).
71
+ let teardownDone = false;
72
+ const unwind = async (reason) => {
73
+ if (teardownDone)
74
+ return;
75
+ teardownDone = true;
76
+ deps.runlog.system(issue.id, 'vm_teardown', { reason });
77
+ // Unpark any awaiting steering reply by EMITTING a steering.cancel Effect through the
78
+ // central interpreter (the SAME seam the HTTP reply path uses), never poking the awaiter.
79
+ // Fire-and-forget: the cancel has no reply and execute() never rejects.
80
+ if (runningEntry)
81
+ void deps.performSteering({ family: 'steering', kind: 'cancel', identifier: runningEntry.identifier });
82
+ try {
83
+ await brought.teardown(reason);
84
+ }
85
+ catch (err) {
86
+ log.emit('warn', 'gondolin dispatch teardown threw', { error: err.message });
87
+ }
88
+ };
89
+ try {
90
+ // The in-VM agent is already launched by the bring-up; it dials back the /acp
91
+ // WebSocket and the host AcpPort completes the session over it.
92
+ return await runSession(deps, {
93
+ issue, runningEntry, resolved, adapterId, cancelSignal, attempt, workspacePath, vm, plan, log, unwind,
94
+ });
95
+ }
96
+ catch (err) {
97
+ // A post-bring-up step threw without unwinding. Release the VM before
98
+ // re-propagating (reference's runSessionOrTeardown catch).
99
+ await unwind('post_dispatch_failure');
100
+ throw err;
101
+ }
102
+ }
103
+ /**
104
+ * Phases 1–5 minus createVm: resolve dispatch config, set up the workspace,
105
+ * stage runtime injections + fake creds, and assemble the VmPlan. Every failure
106
+ * is returned as data (no VM exists yet, so no teardown is owed).
107
+ */
108
+ async function prepareAttempt(deps, issue, runningEntry, log) {
109
+ // ── Phase 1: dispatch config (pinned ONCE; reload can't redirect it) ────────
110
+ const resolved = deps.core.resolveDispatchConfig(deps.cfg, issue.state);
111
+ if (resolved instanceof Error) {
112
+ log.emit('error', 'dispatch resolution failed', { error: resolved.message, state: issue.state });
113
+ return { kind: 'fail', reason: 'dispatch resolution error' };
114
+ }
115
+ if (!deps.adapters.isKnown(resolved.adapter)) {
116
+ log.emit('error', 'unknown acp adapter for state', { adapter: resolved.adapter, state: issue.state });
117
+ return { kind: 'fail', reason: 'unknown acp adapter' };
118
+ }
119
+ const adapterId = resolved.adapter;
120
+ // ── Phase 2: workspace setup (ensureFor + pre-dispatch base fetch) ──────────
121
+ // Use repo/base pinned at dispatch so a mid-run WORKFLOW.yaml reload can't
122
+ // retarget the workspace origin / PR base (reference setupSnapshot).
123
+ const githubRepo = runningEntry?.github_repo_at_dispatch || deps.cfg.workspace.github_repo;
124
+ const baseBranch = runningEntry?.base_branch_at_dispatch || deps.cfg.workspace.base_branch;
125
+ const ws = await setupWorkspace(deps, issue, baseBranch, githubRepo, log);
126
+ if (ws === null)
127
+ return { kind: 'fail', reason: 'workspace error' };
128
+ if (ws.fetchFailed)
129
+ return { kind: 'fail', reason: 'pre-dispatch base fetch failed' };
130
+ // ── Phase 3+4+5: injections → fake creds → VmPlan ───────────────────────────
131
+ const built = await buildPlan(deps, issue, resolved, adapterId, ws.path, log);
132
+ if (built.kind === 'fail')
133
+ return built;
134
+ return { kind: 'ok', resolved, adapterId, workspacePath: ws.path, plan: built.plan, launchEnv: built.launchEnv };
135
+ }
136
+ /**
137
+ * Phases 3–5: stage the model/effort injections (pure fold) and per-adapter fake
138
+ * creds (host reads), then assemble the VmPlan in core. validateAcpTransport
139
+ * collapses into the plan's tunnel: a null acpWsGuestUrl means no reachable
140
+ * control plane → fail fast. Failures are returned as data.
141
+ */
142
+ async function buildPlan(deps, issue, resolved, adapterId, workspacePath, log) {
143
+ let injected;
144
+ let fakeCreds;
145
+ try {
146
+ injected = deps.core.applyRuntimeInjections(deps.adapters.profile(adapterId), { model: resolved.model, effort: resolved.effort });
147
+ }
148
+ catch (err) {
149
+ log.emit('error', 'runtime injection staging failed', { adapter: adapterId, error: err.message });
150
+ return { kind: 'fail', reason: 'runtime injection staging error' };
151
+ }
152
+ try {
153
+ fakeCreds = await deps.credStager.stageFakeCreds(adapterId);
154
+ }
155
+ catch (err) {
156
+ log.emit('error', 'fake-cred staging failed', { adapter: adapterId, error: err.message });
157
+ return { kind: 'fail', reason: 'credential staging error' };
158
+ }
159
+ const { plan, launchEnv } = deps.core.buildVmPlan({
160
+ cfg: deps.cfg,
161
+ resolved,
162
+ identifier: issue.identifier,
163
+ workspacePath,
164
+ adapterBin: injected.adapterBin,
165
+ adapterArgs: injected.effectiveAdapterArgs,
166
+ runtimeEnv: injected.runtimeEnv,
167
+ runtimeExtraFiles: injected.runtimeExtraFiles,
168
+ fakeCreds,
169
+ launcherSource: deps.launcherSource,
170
+ // The symphony-bundled mise SYSTEM config (issue 209); core always stages it at
171
+ // /etc/mise/config.toml (mise provisioning is unconditional, issue 233).
172
+ miseSystemConfigSource: deps.miseSystemConfigSource,
173
+ // The SAME token the dispatch slice registered with the AcpWsRegistry BEFORE
174
+ // bring-up — so the launch env bearer matches the pending registration the guest
175
+ // dials back against (NOT a second, divergent `random.newToken()`).
176
+ acpToken: deps.acpToken,
177
+ resolvedNodeBin: deps.resolvedNodeBin,
178
+ boundMcpPort: deps.boundMcpPort,
179
+ allowWebSockets: deps.allowWebSockets(adapterId),
180
+ // The asset auto-converted from `gondolin.oci_image` (issue 206); core uses it
181
+ // as the boot imagePath only when the `gondolin.image` escape hatch is unset.
182
+ convertedImageSelector: deps.convertedImageSelector ?? null,
183
+ readEnv: deps.readEnv,
184
+ });
185
+ if (plan.tunnel.acpWsGuestUrl === null) {
186
+ log.emit('error', 'acp ws has no reachable guest dial-back URL', {
187
+ mcp_enabled: deps.cfg.mcp.enabled,
188
+ explicit_host_url: deps.cfg.mcp.explicit_host_url,
189
+ });
190
+ return { kind: 'fail', reason: 'acp ws url unavailable' };
191
+ }
192
+ return { kind: 'ok', plan, launchEnv };
193
+ }
194
+ /** Workspace ensure + pre-dispatch base fetch; null = ensure failed. */
195
+ async function setupWorkspace(deps, issue, baseBranch, githubRepo, log) {
196
+ let path;
197
+ try {
198
+ path = (await deps.workspaces.ensureFor(issue.identifier, { baseBranch, githubRepo })).path;
199
+ }
200
+ catch (err) {
201
+ log.emit('error', 'workspace error', { error: err.message });
202
+ return null;
203
+ }
204
+ try {
205
+ await deps.workspaces.fetchBaseInWorkspace(path, baseBranch);
206
+ deps.runlog.system(issue.id, 'pre_dispatch_base_fetch_ok', { base_branch: baseBranch });
207
+ }
208
+ catch (err) {
209
+ log.emit('error', 'pre-dispatch base fetch failed; aborting attempt', {
210
+ base_branch: baseBranch,
211
+ error: err.message,
212
+ });
213
+ deps.runlog.system(issue.id, 'pre_dispatch_base_fetch_failed', {
214
+ base_branch: baseBranch,
215
+ error: err.message,
216
+ });
217
+ return { path, fetchFailed: true };
218
+ }
219
+ return { path, fetchFailed: false };
220
+ }
221
+ /** Phases 6–9: open the ACP session, run the turn loop, run terminal actions, tear down. */
222
+ async function runSession(deps, a) {
223
+ // ── Phase 6: ACP session over the /acp WebSocket (dial-back) ────────────────
224
+ let sessionId;
225
+ try {
226
+ sessionId = (await deps.acp.sessionNew(a.vm.id, { mcpEnabled: deps.cfg.mcp.enabled })).sessionId;
227
+ deps.runlog.system(a.issue.id, 'acp_ws_connected', { acp_url: a.plan.tunnel.acpWsGuestUrl });
228
+ }
229
+ catch (err) {
230
+ a.log.emit('error', 'acp init failed', { error: err.message, adapter: a.adapterId });
231
+ await a.unwind('init_failed');
232
+ return fail('agent session startup error');
233
+ }
234
+ // ── Phase 7: autonomous turn loop ───────────────────────────────────────────
235
+ const activeStates = new Set(deps.core.activeStateNames(deps.cfg.states).map((s) => s.toLowerCase()));
236
+ const loop = await runTurnLoop(deps, {
237
+ issue: a.issue,
238
+ runningEntry: a.runningEntry,
239
+ resolved: a.resolved,
240
+ adapterId: a.adapterId,
241
+ cancelSignal: a.cancelSignal,
242
+ attempt: a.attempt,
243
+ sessionId,
244
+ activeStates,
245
+ log: a.log,
246
+ });
247
+ // ── Phase 8: terminal-state actions (cleanup block; VM still alive) ─────────
248
+ const nonRouted = a.runningEntry ? await runTerminalActions(deps, a, a.runningEntry) : null;
249
+ // ── Phase 9: teardown + compose result ──────────────────────────────────────
250
+ await a.unwind(loop.kind === 'mid_failure' ? loop.cleanupReason : loop.lastReason);
251
+ if (loop.kind === 'mid_failure') {
252
+ return { ok: false, reason: loop.publicReason, threadId: sessionId, turnsCompleted: loop.turnsCompleted };
253
+ }
254
+ return deps.core.decideAttemptOutcome({
255
+ agentFailure: loop.agentFailure,
256
+ nonRoutedActionFailureReason: nonRouted,
257
+ lastReason: loop.lastReason,
258
+ sessionId,
259
+ turnsCompleted: loop.turnsCompleted,
260
+ });
261
+ }
262
+ /**
263
+ * Phase 8: run the issue's state `actions:` block (the VM is still alive so a
264
+ * `run_in_vm` action can exec into it), then RETAIN the workspace on any failed
265
+ * handoff. Returns the non-routed (abort) failure reason for the attempt outcome;
266
+ * a route — the issue already moved out into the HandoffFailed holding state (235) —
267
+ * returns null (a clean attempt). The workspace is marked for retention (234's
268
+ * handoff-pending marker) whenever the handoff failed at all, routed OR aborted, so
269
+ * the only copy of the completed commit survives for a manual push.
270
+ */
271
+ async function runTerminalActions(deps, a, entry) {
272
+ const actionState = entry.issue.state ?? a.issue.state;
273
+ let nonRouted = null;
274
+ let markHandoffReason = null;
275
+ try {
276
+ const run = await deps.actions.runStateActions({ state: actionState, entry, workspacePath: a.workspacePath, vm: a.vm });
277
+ nonRouted = run.nonRouted;
278
+ markHandoffReason = run.markHandoffReason;
279
+ }
280
+ catch (err) {
281
+ nonRouted = err.message;
282
+ markHandoffReason = nonRouted;
283
+ }
284
+ if (markHandoffReason !== null)
285
+ await markHandoffIfTerminal(deps, a, actionState, markHandoffReason);
286
+ return nonRouted;
287
+ }
288
+ /**
289
+ * On a terminal-state phase-8 handoff FAILURE, drop the workspace's handoff-pending
290
+ * marker so the janitor RETAINS the dir (the only copy of the completed commit lives
291
+ * there) instead of reaping it ~5 min later — turning a recoverable push failure into
292
+ * permanent loss (issue 234). No-op for a non-terminal state (its workspace is desired,
293
+ * never reaped). Best-effort: a marker-write failure never changes the attempt outcome.
294
+ */
295
+ async function markHandoffIfTerminal(deps, a, state, reason) {
296
+ if (!isTerminalState(deps.cfg, state))
297
+ return;
298
+ try {
299
+ await deps.workspaces.markHandoffPending(a.issue.identifier, reason);
300
+ deps.runlog.system(a.issue.id, 'handoff_marker_written', { state, reason });
301
+ }
302
+ catch (err) {
303
+ a.log.emit('warn', 'failed to write handoff-pending marker', { error: err.message });
304
+ }
305
+ }
306
+ /** Case-insensitive terminal-role check: the issue's front-matter state may differ in
307
+ * casing from the declared state key (mirrors core/state-resolve.ts's resolution). */
308
+ function isTerminalState(cfg, state) {
309
+ const exact = cfg.states[state];
310
+ if (exact)
311
+ return exact.role === 'terminal';
312
+ const lower = state.toLowerCase();
313
+ for (const [name, sc] of Object.entries(cfg.states)) {
314
+ if (name.toLowerCase() === lower)
315
+ return sc.role === 'terminal';
316
+ }
317
+ return false;
318
+ }
319
+ /**
320
+ * The diagnostic-stderr sink: fold ONE chunk of the in-VM agent's stderr into the
321
+ * run log. Mirrors the reference `onAgentStderr` (truncated runtime event + run-log
322
+ * record). The bring-up (GondolinDispatcher) owns the stream tap and hands each
323
+ * chunk here. Fire-and-forget — failures here never fail the attempt.
324
+ */
325
+ function pipeStderrChunk(deps, issue, chunk) {
326
+ try {
327
+ const entry = { channel: 'stderr', text: chunk };
328
+ deps.runlog.record(issue.id, entry);
329
+ const text = chunk.trim();
330
+ if (text.length === 0)
331
+ return;
332
+ deps.log.withIssue(issue.id).emit('info', 'agent stderr', { text: text.slice(0, 500) });
333
+ }
334
+ catch {
335
+ // Best-effort tap; a malformed chunk just yields no record.
336
+ }
337
+ }
338
+ //# sourceMappingURL=runner-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-loop.js","sourceRoot":"","sources":["../../../src/shell/runner-loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ // FCIS rewrite — node:http transport adapter (kind: server).
2
+ //
3
+ // THIN imperative shell for the unified HTTP server. Implements `HttpServerPort`
4
+ // (bind/stop) and does ONE job per request: read the wire (method, headers, body)
5
+ // into an `HttpRequestView`, hand it to the injected `handle` (wired in the
6
+ // composition root to core http/routes + http/decisions + http/views + http/render),
7
+ // then write the `HttpResponseSpec` core returns. EVERY domain decision — route
8
+ // matching, CSRF gating, create-issue validation, triage transitions, all HTML
9
+ // rendering — lives in core; this file only moves bytes.
10
+ //
11
+ // It also hosts the two non-request concerns that are legitimately transport:
12
+ // • the `/acp` WebSocket `Upgrade` the in-VM agent dials back on (forwarded to
13
+ // the injected AcpWsRegistry.handleUpgrade — see src/shell/interp/acp-ws.ts);
14
+ // • `clientError` (a malformed request line / oversized header) → a raw
15
+ // `400 Bad Request` on the socket;
16
+ // • a malformed `Host`/request-URL that would otherwise throw inside `new URL`
17
+ // → a structured `400` JSON body (the critic gap the reference guards against
18
+ // at src/http.ts handleRequest).
19
+ //
20
+ // The preview asset (`.impeccable/preview/dashboard.html`) is served by the
21
+ // injected `handle` itself: reading that file is async IO the composition-root
22
+ // wiring performs, so the route stays core-owned while the read stays in the shell.
23
+ //
24
+ // Reference (read-only, do not edit): src/http.ts — startHttpServer / handleRequest.
25
+ import { createServer } from 'node:http';
26
+ const DEFAULT_MAX_BODY_BYTES = 1_000_000;
27
+ /** A JSON error body in the reference's `{ error: { code, message } }` shape. */
28
+ function jsonError(status, code, message) {
29
+ return {
30
+ status,
31
+ contentType: 'application/json; charset=utf-8',
32
+ body: JSON.stringify({ error: { code, message } }),
33
+ };
34
+ }
35
+ /** Drain the request body to a UTF-8 string, capping at `maxBytes`. Rejects on
36
+ * overflow (the reference destroys the socket + surfaces "request body too
37
+ * large"); core decides what an empty body means. */
38
+ function readRawBody(req, maxBytes) {
39
+ return new Promise((resolve, reject) => {
40
+ const chunks = [];
41
+ let size = 0;
42
+ req.on('data', (chunk) => {
43
+ size += chunk.length;
44
+ if (size > maxBytes) {
45
+ req.destroy();
46
+ reject(new Error('request body too large'));
47
+ return;
48
+ }
49
+ chunks.push(chunk);
50
+ });
51
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
52
+ req.on('error', reject);
53
+ });
54
+ }
55
+ /** Flatten node's `string | string[] | undefined` header values to a lowercased
56
+ * single-string map (array headers collapse to their first value — none of the
57
+ * headers core inspects are legitimately repeated). */
58
+ function viewHeaders(req) {
59
+ const out = {};
60
+ for (const [k, v] of Object.entries(req.headers)) {
61
+ out[k.toLowerCase()] = Array.isArray(v) ? v[0] : v;
62
+ }
63
+ return out;
64
+ }
65
+ /** Write a `HttpResponseSpec` to the live `ServerResponse`. Sets content-type +
66
+ * content-length and any extra headers core asked for (e.g. cache-control). */
67
+ function writeSpec(res, spec) {
68
+ res.statusCode = spec.status;
69
+ res.setHeader('content-type', spec.contentType);
70
+ if (spec.headers) {
71
+ for (const [k, v] of Object.entries(spec.headers))
72
+ res.setHeader(k, v);
73
+ }
74
+ res.setHeader('content-length', Buffer.byteLength(spec.body));
75
+ res.end(spec.body);
76
+ }
77
+ /** Parse the request pathname, defending the listener against a malformed
78
+ * `Host`/request-target that would throw inside `new URL` (the critic gap). */
79
+ function parsePathname(req) {
80
+ try {
81
+ return new URL(req.url ?? '/', 'http://symphony.local').pathname;
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ }
87
+ async function handleRequest(req, res, deps, maxBytes) {
88
+ const pathname = parsePathname(req);
89
+ if (pathname === null) {
90
+ writeSpec(res, jsonError(400, 'bad_request', 'invalid request URL'));
91
+ return;
92
+ }
93
+ // Body is drained for every method; core ignores it for GET/HEAD. An overflow
94
+ // is the one read failure the transport owns — map it to a structured 400.
95
+ let rawBody;
96
+ try {
97
+ rawBody = await readRawBody(req, maxBytes);
98
+ }
99
+ catch (err) {
100
+ writeSpec(res, jsonError(400, 'bad_request', err.message));
101
+ return;
102
+ }
103
+ const view = {
104
+ method: (req.method ?? 'GET').toUpperCase(),
105
+ pathname,
106
+ headers: viewHeaders(req),
107
+ rawBody,
108
+ };
109
+ const spec = await deps.handle(view);
110
+ writeSpec(res, spec);
111
+ }
112
+ /**
113
+ * Build the node:http server adapter implementing `HttpServerPort`. Construction
114
+ * does not bind; `bind` listens (resolving the actually-bound port, relevant for
115
+ * a `--port 0` request) and `stop` closes the listener + tears down any pending
116
+ * `/acp` socket via the registry's own `stop` (the registry, not this file, owns
117
+ * upgraded-socket lifecycle).
118
+ */
119
+ export function createHttpServer(deps) {
120
+ const maxBytes = deps.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
121
+ let server = null;
122
+ function build() {
123
+ const s = createServer((req, res) => {
124
+ void handleRequest(req, res, deps, maxBytes).catch((err) => {
125
+ deps.log.emit('error', 'http handler error', { error: err.message });
126
+ try {
127
+ writeSpec(res, jsonError(500, 'internal_error', err.message));
128
+ }
129
+ catch {
130
+ /* response already started — nothing safe to write */
131
+ }
132
+ });
133
+ });
134
+ // A malformed request line / oversized header never reaches handleRequest;
135
+ // node emits clientError instead. Mirror the reference: raw 400 on the wire.
136
+ s.on('clientError', (err, socket) => {
137
+ deps.log.emit('debug', 'http client error', { error: err.message });
138
+ try {
139
+ socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
140
+ }
141
+ catch {
142
+ /* socket may already be closed */
143
+ }
144
+ });
145
+ // The in-VM agent dials `ws://…/acp`; the registry completes the RFC-6455
146
+ // handshake + first-message bearer auth. No registry ⇒ refuse the upgrade by
147
+ // destroying the socket (an un-answered upgrade would otherwise hang the peer).
148
+ s.on('upgrade', (req, socket, head) => {
149
+ // Node types the upgrade socket as a bare Duplex; at runtime it is the
150
+ // underlying net.Socket the registry needs for setNoDelay / remote-address.
151
+ const sock = socket;
152
+ if (deps.acpUpgrade)
153
+ deps.acpUpgrade(req, sock, head);
154
+ else
155
+ sock.destroy();
156
+ });
157
+ return s;
158
+ }
159
+ return {
160
+ async bind(requestedPort, host) {
161
+ const s = build();
162
+ server = s;
163
+ const listenPort = requestedPort ?? 0;
164
+ await new Promise((resolve, reject) => {
165
+ const onError = (err) => {
166
+ s.removeListener('listening', onListening);
167
+ reject(err);
168
+ };
169
+ const onListening = () => {
170
+ s.removeListener('error', onError);
171
+ resolve();
172
+ };
173
+ s.once('error', onError);
174
+ s.once('listening', onListening);
175
+ s.listen(listenPort, host);
176
+ });
177
+ // After a clean bind, swap the fatal bind-error listener for a permanent
178
+ // one so later runtime socket faults (ENOTCONN, resets) log instead of
179
+ // crashing the process.
180
+ s.on('error', (err) => {
181
+ deps.log.emit('warn', 'http server error', { error: err.message });
182
+ });
183
+ const addr = s.address();
184
+ const port = typeof addr === 'object' && addr ? addr.port : listenPort;
185
+ deps.log.emit('info', 'http server listening', { host, port });
186
+ return { port };
187
+ },
188
+ async stop() {
189
+ const s = server;
190
+ if (!s)
191
+ return;
192
+ server = null;
193
+ // Force-close the registry's upgraded `/acp` sockets FIRST: server.close()
194
+ // only refuses new connections and resolves once existing ones drain, so a
195
+ // live WebSocket would otherwise hang the close() callback forever. The
196
+ // registry's stop() rejects pending registrations + destroys every tracked
197
+ // socket, letting the listener drain cleanly. Best-effort (never block the
198
+ // listener teardown on a registry fault).
199
+ if (deps.acpStop) {
200
+ await deps.acpStop().catch((err) => {
201
+ deps.log.emit('warn', 'acp ws registry stop failed', { error: err.message });
202
+ });
203
+ }
204
+ await new Promise((resolve) => s.close(() => resolve()));
205
+ },
206
+ };
207
+ }
208
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../../src/shell/server/http.ts"],"names":[],"mappings":"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"}