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,181 @@
1
+ // FCIS rewrite — pure token-usage / runtime-event / tool-call-lifecycle folds.
2
+ //
3
+ // Ported faithfully from the original orchestrator (`reportTokenUsage`,
4
+ // `reportRuntimeEvent`, `reportTurnStarted`, the `detectStalls` in-flight guard)
5
+ // and `src/agent/tool-call-summary.ts:toolCallLifecycle`. The original mutated
6
+ // the live `RunningEntry` map and the aggregate `SessionTotals` in place; here
7
+ // every fold is a pure, SYNCHRONOUS `(data) -> data` returning the next state
8
+ // (and, for the token fold, the per-report delta so the shell can add it into
9
+ // the aggregate SessionTotals). No clock, no randomness, no IO, no Effects —
10
+ // these are in-memory state folds, not side effects. Imports are restricted to
11
+ // src/types.
12
+ //
13
+ // Three responsibilities, one per concern in the original:
14
+ // 1. foldTokenUsage — absolute totals → session deltas (no double counting).
15
+ // 2. foldRuntimeEvent — append into the recent_events ring + last_event/at.
16
+ // 3. tool-call lifecycle — active-tool-call set updates + stall-reaper guard.
17
+ // ─── 1. Token-usage delta accounting ─────────────────────────────────────────
18
+ /**
19
+ * Cap on the recent-events ring buffer. The original kept the last 50 events
20
+ * (`if (e.recent_events.length > 50) e.recent_events.shift()`).
21
+ */
22
+ export const RECENT_EVENTS_CAP = 50;
23
+ /**
24
+ * §9.4 token accounting: prefer the adapter's ABSOLUTE running totals, but only
25
+ * add the per-report DELTA into the aggregate so re-reported totals are not
26
+ * double counted.
27
+ *
28
+ * Mirrors the original `reportTokenUsage`:
29
+ * - `dX = max(0, usage.X - last_reported_X)` (clamped at 0 — a regression /
30
+ * reset in the absolute counter never SUBTRACTS from the aggregate),
31
+ * - the entry's visible totals become the new absolute values,
32
+ * - the baselines advance to the new absolute values.
33
+ *
34
+ * Pure: takes the prior baselines + the new reading, returns the TokenDelta the
35
+ * shell folds. The shell adds `*_delta` into the aggregate SessionTotals (see
36
+ * `addDeltaToTotals`) and stores the new `last_reported_*` + absolute totals on
37
+ * the running entry.
38
+ */
39
+ export function foldTokenUsage(prior, usage) {
40
+ const input_delta = Math.max(0, usage.input_tokens - prior.last_reported_input);
41
+ const output_delta = Math.max(0, usage.output_tokens - prior.last_reported_output);
42
+ const total_delta = Math.max(0, usage.total_tokens - prior.last_reported_total);
43
+ return {
44
+ input_delta,
45
+ output_delta,
46
+ total_delta,
47
+ last_reported_input: usage.input_tokens,
48
+ last_reported_output: usage.output_tokens,
49
+ last_reported_total: usage.total_tokens,
50
+ };
51
+ }
52
+ /**
53
+ * Add a TokenDelta into the aggregate SessionTotals (no double counting — the
54
+ * delta is already de-duplicated by `foldTokenUsage`). `seconds_running` is
55
+ * carried through unchanged; it is accrued elsewhere (on attempt exit). Returns
56
+ * a new SessionTotals; does not mutate the input.
57
+ */
58
+ export function addDeltaToTotals(totals, delta) {
59
+ return {
60
+ input_tokens: totals.input_tokens + delta.input_delta,
61
+ output_tokens: totals.output_tokens + delta.output_delta,
62
+ total_tokens: totals.total_tokens + delta.total_delta,
63
+ seconds_running: totals.seconds_running,
64
+ };
65
+ }
66
+ /**
67
+ * Fold one RuntimeEvent into a running entry's event slice. Mirrors the
68
+ * original `reportRuntimeEvent` (minus the live tool-call-set mutation, which is
69
+ * a separate concern handled by `foldToolCall`): updates `last_event` /
70
+ * `last_event_at` / `last_message` and pushes onto the recent-events ring,
71
+ * trimming the OLDEST when it exceeds `RECENT_EVENTS_CAP`.
72
+ *
73
+ * Pure: returns a new RuntimeEventState (and a fresh `recent_events` array); the
74
+ * input is not mutated.
75
+ */
76
+ export function foldRuntimeEvent(state, ev) {
77
+ const recent_events = [...state.recent_events, ev];
78
+ while (recent_events.length > RECENT_EVENTS_CAP)
79
+ recent_events.shift();
80
+ return {
81
+ last_event: ev.event,
82
+ last_event_at: ev.at,
83
+ last_message: ev.message,
84
+ recent_events,
85
+ };
86
+ }
87
+ // ─── 3. Active-tool-call lifecycle / stall-reaper suppression ─────────────────
88
+ /**
89
+ * Map an ACP tool notification to its effect on the in-flight tool-call set.
90
+ * Ported verbatim from `src/agent/tool-call-summary.ts:toolCallLifecycle`.
91
+ *
92
+ * ACP `ToolCallStatus` is `pending | in_progress | completed | failed`;
93
+ * `completed` / `failed` are terminal. A `tool_call` STARTS a tool (in-flight)
94
+ * unless it already carries a terminal status. A `tool_call_update` acts ONLY on
95
+ * a known status: terminal → ended, pending / in_progress → in-flight; an
96
+ * omitted / null / unknown status is a content-or-title-only delta and must NOT
97
+ * mutate the set (returns `undefined` = "no change").
98
+ */
99
+ export function toolCallLifecycle(event, status) {
100
+ const terminal = status === 'completed' || status === 'failed';
101
+ if (event === 'tool_call')
102
+ return { ended: terminal };
103
+ if (terminal)
104
+ return { ended: true };
105
+ if (status === 'pending' || status === 'in_progress')
106
+ return { ended: false };
107
+ return undefined;
108
+ }
109
+ /**
110
+ * Apply a tool-call lifecycle delta to the in-flight set. Mirrors the original
111
+ * `reportRuntimeEvent` tool branch: a non-terminal delta ADDS the id (in
112
+ * flight), a terminal delta DELETES it (ended). The set is modeled as a sorted,
113
+ * de-duplicated array of ids so core stays free of live `Set` handles and the
114
+ * result is deterministic. Pure: returns a new array; the input is not mutated.
115
+ *
116
+ * Pass `undefined` (the "no change" case from `toolCallLifecycle`) and the set
117
+ * is returned unchanged. An empty `id` is ignored (matches the original guard
118
+ * `if (ev.tool && ev.tool.id)`).
119
+ */
120
+ export function applyToolDelta(active, delta) {
121
+ if (!delta || !delta.id)
122
+ return [...active];
123
+ if (delta.ended)
124
+ return active.filter((id) => id !== delta.id);
125
+ if (active.includes(delta.id))
126
+ return [...active];
127
+ return [...active, delta.id].sort();
128
+ }
129
+ /**
130
+ * Turn-boundary reset of the in-flight set. Mirrors the original
131
+ * `reportTurnStarted`, which `e.active_tool_calls.clear()`s at every turn
132
+ * boundary: the prior turn's `session/prompt` has resolved, so no tool call from
133
+ * it can still be in flight. Clearing here backstops a leaked terminal
134
+ * `tool_call_update` so a stale id can't mask a real mid-turn stall (RCA
135
+ * 2026-06-02). Pure: always returns an empty set.
136
+ */
137
+ export function clearToolCallsAtTurnBoundary() {
138
+ return [];
139
+ }
140
+ /**
141
+ * Whether the no-activity stall reaper should be SUPPRESSED for a running entry.
142
+ * Mirrors the two `continue` guards in the original `detectStalls`:
143
+ * - `steeringRequested` — the agent is intentionally paused while the human
144
+ * composes a reply, which can legitimately exceed `stall_timeout_ms`.
145
+ * - `activeToolCallCount > 0` — a long silent tool (e.g. `… | tail`) produces
146
+ * no ACP frames for its whole duration, so the no-activity timer would reap a
147
+ * legitimately-busy agent merely blocked on the tool.
148
+ *
149
+ * The hard `prompt_timeout_ms` cap (a separate concern) backstops a tool that
150
+ * genuinely hangs, and operator/terminal cancel still applies regardless.
151
+ */
152
+ export function shouldSuppressStallReaper(args) {
153
+ return args.steeringRequested || args.activeToolCallCount > 0;
154
+ }
155
+ /**
156
+ * Whether a running entry has stalled: the no-activity reaper fires when the
157
+ * timeout is positive, the entry is NOT suppressed, and the elapsed time since
158
+ * the last reference point (`last_event_at` ?? `started_at`) exceeds the
159
+ * timeout. Mirrors the body of the original `detectStalls` loop.
160
+ *
161
+ * The clock is INJECTED as `nowMs` (core never reads the wall clock).
162
+ * `lastReferenceMs` is the parsed `last_event_at ?? started_at` epoch ms (the
163
+ * shell parses the ISO timestamp; core stays free of `Date.parse`). A
164
+ * non-finite `lastReferenceMs` is treated as "cannot decide" → not stalled
165
+ * (matches the original `Number.isFinite(elapsed)` guard). Returns the elapsed
166
+ * ms when stalled so the shell can format the terminate reason
167
+ * (`stalled after <elapsed>ms`), or `null` when not stalled.
168
+ */
169
+ export function detectStall(args) {
170
+ if (args.stallTimeoutMs <= 0)
171
+ return { stalled: false };
172
+ if (shouldSuppressStallReaper(args))
173
+ return { stalled: false };
174
+ const elapsed = args.nowMs - args.lastReferenceMs;
175
+ if (!Number.isFinite(elapsed))
176
+ return { stalled: false };
177
+ if (elapsed > args.stallTimeoutMs)
178
+ return { stalled: true, elapsedMs: elapsed };
179
+ return { stalled: false };
180
+ }
181
+ //# sourceMappingURL=token-fold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-fold.js","sourceRoot":"","sources":["../../../../src/core/schedule/token-fold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ // FCIS rewrite — the ONE canonical case-insensitive declared-state-name resolver.
2
+ //
3
+ // Functional core: pure, synchronous (data) -> data. No IO, no clock, no
4
+ // randomness, no node: imports. Imports ONLY from src/types.
5
+ //
6
+ // Collapses what used to be FIVE byte-equivalent copies of the same
7
+ // case-insensitive declared-name lookup (the original spread it across
8
+ // src/issues.ts, src/agent/runner.ts, and src/mcp.ts):
9
+ // - core/states.ts:resolveStateKey (deleted — orphan module)
10
+ // - core/runner/dispatch-config.ts:resolveStateKey (re-points here)
11
+ // - core/mcp/url.ts:canonicalStateName (re-points here)
12
+ // - core/mcp/dispatch.ts:canonicalStateName (re-points to resolveDeclaredName)
13
+ // - core/schedule/eligibility.ts:canonicalStateKey (re-points here)
14
+ // - inlined in core/workflow/derive.ts:resolveActionsForState (re-points here)
15
+ //
16
+ // Resolution contract (ported verbatim from every copy): an exact own-property
17
+ // match wins; failing that, a case-insensitive scan over the declared keys in
18
+ // declaration order (first match wins). Matches the rest of symphony, where
19
+ // eligibility, reconciliation, and the local-tracker directories all compare
20
+ // lowercase, so a workflow that declares `Todo` and a tracker file living under
21
+ // `todo/` still resolves correctly.
22
+ /**
23
+ * Resolve `name` to its canonical declared form given the declared names in
24
+ * declaration order. Exact match wins; otherwise a case-insensitive scan
25
+ * (first match in declaration order). Returns null when no declared name
26
+ * matches.
27
+ *
28
+ * This is the shape-agnostic core: callers that hold a `Record<string,
29
+ * StateConfig>` use {@link resolveStateKey}; callers that hold a precomputed
30
+ * declared-name list (e.g. the MCP `McpStatesView.order`) call this directly.
31
+ */
32
+ export function resolveDeclaredName(order, name) {
33
+ for (const declared of order) {
34
+ if (declared === name)
35
+ return declared;
36
+ }
37
+ const lower = name.toLowerCase();
38
+ for (const declared of order) {
39
+ if (declared.toLowerCase() === lower)
40
+ return declared;
41
+ }
42
+ return null;
43
+ }
44
+ /**
45
+ * Resolve a (possibly differently-cased) state name to its canonical declared
46
+ * key in `states`, or null when no state matches. Thin wrapper over
47
+ * {@link resolveDeclaredName} keyed by `Object.keys(states)` (which is the
48
+ * declaration order). An exact own-property hit short-circuits the scan.
49
+ */
50
+ export function resolveStateKey(states, state) {
51
+ if (Object.prototype.hasOwnProperty.call(states, state))
52
+ return state;
53
+ const lower = state.toLowerCase();
54
+ for (const name of Object.keys(states)) {
55
+ if (name.toLowerCase() === lower)
56
+ return name;
57
+ }
58
+ return null;
59
+ }
60
+ /**
61
+ * Is moving `fromState -> toState` *in-flow* given the from-state's
62
+ * `allowed_transitions`? The ONE definition shared by the agent's hard gate
63
+ * (`decideTransition`, src/core/mcp/dispatch.ts — it rejects an off-flow move
64
+ * with `transition_not_allowed`) and the operator's soft warning
65
+ * (`decideMoveTransition`, src/core/http/decisions.ts — it merely flags
66
+ * `off_flow` and lets the move through). Factoring it here keeps the two from
67
+ * drifting (issue 126).
68
+ *
69
+ * A move is in-flow when ANY of:
70
+ * - it is a self-transition (case-insensitive `from === to`) — always a no-op;
71
+ * - the from-state's `allowed_transitions` is null/undefined — the open
72
+ * default ("any declared state is reachable");
73
+ * - the target is a member of a non-null `allowed_transitions` list
74
+ * (case-insensitive).
75
+ * It is OFF-flow only when the list is non-null and does not include the target.
76
+ * An empty list (`[]`) therefore makes every non-self target off-flow.
77
+ */
78
+ export function isInFlowTransition(allowedTransitions, fromState, toState) {
79
+ if (fromState.toLowerCase() === toState.toLowerCase())
80
+ return true;
81
+ if (allowedTransitions == null)
82
+ return true;
83
+ const wanted = toState.toLowerCase();
84
+ return allowedTransitions.some((s) => s.toLowerCase() === wanted);
85
+ }
86
+ //# sourceMappingURL=state-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-resolve.js","sourceRoot":"","sources":["../../../src/core/state-resolve.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,EAAE;AACF,yEAAyE;AACzE,6DAA6D;AAC7D,EAAE;AACF,oEAAoE;AACpE,uEAAuE;AACvE,uDAAuD;AACvD,0EAA0E;AAC1E,sEAAsE;AACtE,iEAAiE;AACjE,oFAAoF;AACpF,sEAAsE;AACtE,iFAAiF;AACjF,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,gFAAgF;AAChF,oCAAoC;AAIpC;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAwB,EAAE,IAAY;IACxE,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,QAAQ,CAAC;IACzC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,KAAK;YAAE,OAAO,QAAQ,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAmC,EACnC,KAAa;IAEb,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC;IAChD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB,CAChC,kBAAwD,EACxD,SAAiB,EACjB,OAAe;IAEf,IAAI,SAAS,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE;QAAE,OAAO,IAAI,CAAC;IACnE,IAAI,kBAAkB,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,278 @@
1
+ // FCIS rewrite — pure VM safety guards (the *teeth* of the host-only-refresh
2
+ // invariant). These are the createVm-options-building checks the Gondolin
3
+ // dispatch path runs so the guest is enforced-by-construction to hold only
4
+ // placeholders: real refresh / durable tokens never leave the host.
5
+ //
6
+ // 100% PURE + SYNCHRONOUS. No IO, no node: imports, no clock/randomness. POSIX
7
+ // path normalization is done LEXICALLY and inline (the original leaned on
8
+ // `node:path` + an injected `fs.realpath`; core may import neither). The lexical
9
+ // denylist check is *more conservative* than a symlink-resolving one — it cannot
10
+ // be widened by a symlink that resolves out of a denied dir, and a non-existent
11
+ // path can't be mounted anyway.
12
+ //
13
+ // The reference's `realpath` symlink-resolution (codex HIGH) is IO and lives in
14
+ // the shell: the shell canonicalizes the mount source through `fs.realpathSync`
15
+ // and passes BOTH the lexical and resolved forms through assertNoCredentialMounts.
16
+ // This pure core does only the lexical check by design.
17
+ import { CredentialMountError } from '../types/errors.js';
18
+ import { joinPosix } from './path.js';
19
+ // The synthetic guest↔host control-plane vocabulary lives canonically in
20
+ // core/mcp/url.ts (the dedicated MCP/ACP URL module); only MCP_GUEST_BASE_URL is
21
+ // used locally (by guestMcpBaseUrl below) — the rest is re-exported, see the
22
+ // "ACP / MCP guest control-plane URL derivation" section at the bottom.
23
+ import { MCP_GUEST_BASE_URL } from './mcp/url.js';
24
+ // ---------------------------------------------------------------------------
25
+ // Lexical POSIX path helpers. `joinPosix` is the canonical one from core/path.ts
26
+ // (this module's old copy lacked the empty-base/absolute-rel handling that the
27
+ // canonical adopts — behaviour-identical for every call here, which only ever
28
+ // passes a non-empty base + a relative rel). `resolvePosix` (with `.`/`..`
29
+ // collapse) stays local — it is a stronger, security-load-bearing canonicalizer.
30
+ // ---------------------------------------------------------------------------
31
+ const SEP = '/';
32
+ /**
33
+ * Lexically resolve an absolute POSIX path, collapsing `.` / `..` and
34
+ * duplicate separators WITHOUT touching the filesystem. A relative input is
35
+ * resolved against `base` (default the POSIX root `/`), mirroring how the
36
+ * original relied on `path.resolve` to absolutize a relative mount source. We do
37
+ * not consult cwd (that would be ambient state); the shell passes absolute mount
38
+ * sources, and `base` is supplied explicitly for any relative input.
39
+ */
40
+ function resolvePosix(input, base = SEP) {
41
+ // Normalize Windows-style separators defensively, then anchor.
42
+ const raw = input.replace(/\\/g, SEP);
43
+ const anchored = raw.startsWith(SEP) ? raw : joinPosix(base, raw);
44
+ const out = [];
45
+ for (const part of anchored.split(SEP)) {
46
+ if (part === '' || part === '.')
47
+ continue;
48
+ if (part === '..') {
49
+ if (out.length > 0)
50
+ out.pop();
51
+ continue;
52
+ }
53
+ out.push(part);
54
+ }
55
+ return SEP + out.join(SEP);
56
+ }
57
+ /**
58
+ * Lexically canonicalize a host path WITHOUT touching the filesystem: expand a
59
+ * leading `~` / `~/…` against `homeDir`, then lexically resolve (collapse
60
+ * `.`/`..`, make absolute). Mirrors the reference's `canonicalizeHostPath` but
61
+ * uses inline POSIX logic instead of `node:path` so it stays importable from the
62
+ * functional core. We deliberately do NOT `fs.realpath` — the path need not
63
+ * exist, and a symlink-following resolve is IO + a TOCTOU surface; the deny check
64
+ * is a prefix test on the lexical canonical form, which is strictly more
65
+ * conservative.
66
+ */
67
+ export function canonicalizeHostPath(hostPath, homeDir) {
68
+ let p = hostPath;
69
+ if (p === '~') {
70
+ p = homeDir;
71
+ }
72
+ else if (p.startsWith('~/') || p.startsWith('~\\')) {
73
+ p = joinPosix(homeDir, p.slice(2));
74
+ }
75
+ return resolvePosix(p, resolvePosix(homeDir));
76
+ }
77
+ /**
78
+ * True when `child` is `parent` or lies beneath it. Compares canonical absolute
79
+ * paths with a trailing-separator guard so `/home/u/.codexible` does not count as
80
+ * under `/home/u/.codex`.
81
+ */
82
+ function isUnder(child, parent) {
83
+ if (child === parent)
84
+ return true;
85
+ const withSep = parent.endsWith(SEP) ? parent : parent + SEP;
86
+ return child.startsWith(withSep);
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // Credential-mount denylist guard.
90
+ // ---------------------------------------------------------------------------
91
+ /**
92
+ * Built-in credential directories/files, `~`-relative. `~/.claude` and `~/.codex`
93
+ * hold the adapter OAuth credentials; `~/.config`, `~/.ssh`, and `~/.symphony/oauth`
94
+ * round out the denylist.
95
+ */
96
+ const BUILTIN_CRED_RELATIVE = [
97
+ '.claude',
98
+ '.codex',
99
+ '.config',
100
+ '.ssh',
101
+ '.symphony/oauth',
102
+ ];
103
+ /** Resolve the full denylist (built-ins + extras) to canonical absolute paths. */
104
+ function resolveDenylist(homeDir, extra) {
105
+ const home = resolvePosix(homeDir);
106
+ const out = new Set();
107
+ for (const rel of BUILTIN_CRED_RELATIVE)
108
+ out.add(joinPosix(home, rel));
109
+ for (const e of extra)
110
+ out.add(canonicalizeHostPath(e, homeDir));
111
+ return [...out];
112
+ }
113
+ /** Throw if `candidate` is the home root or overlaps any denylist entry. */
114
+ function assertCandidateAllowed(candidate, homeRoot, denylist) {
115
+ // The home root is always denied — mounting it exposes every credential dir at
116
+ // once, and a workspace legitimately lives *under* home so the root can't just
117
+ // go in the per-dir denylist.
118
+ if (candidate === homeRoot) {
119
+ throw new CredentialMountError(`refusing to mount the home directory root ${candidate} into a guest VM ` +
120
+ `(exposes every credential directory at once)`);
121
+ }
122
+ for (const denied of denylist) {
123
+ // Bidirectional overlap: reject if the mount is UNDER a credential dir, IS
124
+ // one, OR is an ANCESTOR that contains one (e.g. mounting `~/.symphony`
125
+ // exposes `~/.symphony/oauth`). Read-only sources are NOT exempt.
126
+ if (isUnder(candidate, denied) || isUnder(denied, candidate)) {
127
+ throw new CredentialMountError(`refusing to mount ${candidate} into a guest VM: it overlaps the credential ` +
128
+ `path ${denied} (mounting it, a parent of it, or a child of it all expose ` +
129
+ `the credential tree; read-only sources are NOT exempt)`);
130
+ }
131
+ }
132
+ }
133
+ /**
134
+ * HARD-FAIL if any mount's host path OVERLAPS a credential directory (the mount
135
+ * is under one, IS one, or is an ancestor that contains one) or is the home-dir
136
+ * root. Lexical-only (see module header). Read-only mounts are NOT exempt. Throws
137
+ * {@link CredentialMountError} on the first offender; returns void on success.
138
+ */
139
+ export function assertNoCredentialMounts(mounts, opts) {
140
+ const homeRoot = resolvePosix(opts.homeDir);
141
+ const denylist = resolveDenylist(opts.homeDir, opts.extraDenylist ?? []);
142
+ for (const m of mounts) {
143
+ const candidate = canonicalizeHostPath(m.host, opts.homeDir);
144
+ assertCandidateAllowed(candidate, homeRoot, denylist);
145
+ }
146
+ }
147
+ // ---------------------------------------------------------------------------
148
+ // assertContained — path-escape guard for workspace restore (critic gap).
149
+ // ---------------------------------------------------------------------------
150
+ /**
151
+ * HARD-FAIL if `target` escapes `root` after lexical normalization. The
152
+ * workspace-restore path materializes agent-named entries under a workspace root;
153
+ * an entry like `../../.ssh/authorized_keys` (or an absolute path) would write
154
+ * outside the sandbox. This guard rejects any `target` that does not resolve to
155
+ * `root` itself or a path strictly beneath it.
156
+ *
157
+ * `target` is resolved RELATIVE TO `root` (so a bare relative path is anchored at
158
+ * the workspace), but an absolute `target` resolves to itself and is rejected
159
+ * unless it already lies under `root`. Returns the canonical contained path on
160
+ * success; throws {@link CredentialMountError} on escape — reused as the typed
161
+ * sandbox-violation error (the closest existing boundary-violation class; no
162
+ * separate `PathEscapeError` exists in src/types).
163
+ */
164
+ export function assertContained(root, target) {
165
+ const canonRoot = resolvePosix(root);
166
+ // An absolute target resolves to itself; a relative one anchors at the root.
167
+ const canonTarget = target.startsWith(SEP)
168
+ ? resolvePosix(target)
169
+ : resolvePosix(joinPosix(canonRoot, target));
170
+ if (!isUnder(canonTarget, canonRoot)) {
171
+ throw new CredentialMountError(`refusing to write ${canonTarget}: it escapes the workspace root ${canonRoot} ` +
172
+ `(path-traversal guard for workspace restore)`);
173
+ }
174
+ return canonTarget;
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Credential env-var stripping.
178
+ // ---------------------------------------------------------------------------
179
+ /**
180
+ * Exact credential env-var names dropped regardless of the family-suffix rules.
181
+ * Covers each adapter's token var plus the GitHub durable-token vars.
182
+ */
183
+ const NAMED_CREDENTIAL_VARS = new Set([
184
+ 'ANTHROPIC_AUTH_TOKEN',
185
+ 'ANTHROPIC_API_KEY',
186
+ 'OPENAI_API_KEY',
187
+ 'GITHUB_TOKEN',
188
+ 'GH_TOKEN',
189
+ ]);
190
+ /**
191
+ * Vendor name prefixes whose entire family is credential-bearing under the strict
192
+ * boot-env policy.
193
+ */
194
+ const CREDENTIAL_NAME_PREFIXES = [
195
+ 'ANTHROPIC_',
196
+ 'OPENAI_',
197
+ 'GITHUB_',
198
+ 'GH_',
199
+ ];
200
+ /** Secret-bearing name suffixes across any vendor (`*_API_KEY` / `*_TOKEN` / `*_SECRET`). */
201
+ const CREDENTIAL_NAME_SUFFIXES = ['_API_KEY', '_TOKEN', '_SECRET'];
202
+ /**
203
+ * True when a name is a *secret-bearing token* by the named-set or the
204
+ * `*_API_KEY`/`*_TOKEN`/`*_SECRET` suffix rule. Deliberately does NOT include the
205
+ * vendor *prefix* families — this is the strip applied to adapter-injected runtime
206
+ * env, which legitimately carries non-secret config like `ANTHROPIC_MODEL` /
207
+ * `OPENAI_BASE_URL`.
208
+ */
209
+ export function isCredentialTokenName(name) {
210
+ const upper = name.toUpperCase();
211
+ if (NAMED_CREDENTIAL_VARS.has(upper))
212
+ return true;
213
+ for (const suffix of CREDENTIAL_NAME_SUFFIXES) {
214
+ if (upper.endsWith(suffix))
215
+ return true;
216
+ }
217
+ return false;
218
+ }
219
+ /**
220
+ * True when an env var name is credential-bearing under ANY rule: the named set,
221
+ * the vendor prefix families, or the secret suffix families. The strict boot-env policy.
222
+ */
223
+ export function isCredentialEnvName(name) {
224
+ if (isCredentialTokenName(name))
225
+ return true;
226
+ const upper = name.toUpperCase();
227
+ for (const prefix of CREDENTIAL_NAME_PREFIXES) {
228
+ if (upper.startsWith(prefix))
229
+ return true;
230
+ }
231
+ return false;
232
+ }
233
+ function stripBy(env, drop) {
234
+ const out = {};
235
+ for (const [k, v] of Object.entries(env)) {
236
+ if (drop(k))
237
+ continue;
238
+ out[k] = v;
239
+ }
240
+ return out;
241
+ }
242
+ /**
243
+ * Return a copy of `env` with every credential-bearing var removed (the strict
244
+ * boot-env policy — named set + vendor prefix families + secret suffixes). Use
245
+ * for the operator-forwarded boot env.
246
+ */
247
+ export function stripCredentialEnv(env) {
248
+ return stripBy(env, isCredentialEnvName);
249
+ }
250
+ /**
251
+ * Return a copy of `env` with only secret-bearing TOKENS removed (named set +
252
+ * secret suffixes), preserving non-secret vendor-prefixed config like
253
+ * `ANTHROPIC_MODEL` / `OPENAI_BASE_URL`. Defense-in-depth for the adapter runtime env.
254
+ */
255
+ export function stripCredentialTokenVars(env) {
256
+ return stripBy(env, isCredentialTokenName);
257
+ }
258
+ // ---------------------------------------------------------------------------
259
+ // ACP / MCP guest control-plane URL derivation.
260
+ // ---------------------------------------------------------------------------
261
+ //
262
+ // The synthetic guest↔host control-plane vocabulary (the `symphony-mcp:7001`
263
+ // tunnel constants + the ACP-URL / tcp.hosts derivations) lives canonically in
264
+ // core/mcp/url.ts — the dedicated MCP/ACP URL module. It is re-exported here so
265
+ // vm-guards importers keep their `vm-guards.js` specifier WITHOUT a second
266
+ // source of truth: a single home for MCP_GUEST_PORT / MCP_SYNTHETIC_HOST means a
267
+ // port changed in one place can't silently desync the `tcp.hosts` rewire from
268
+ // the URLs it's supposed to back. `guestMcpBaseUrl` is vm-guards-only (no
269
+ // equivalent in url.ts) and stays defined here.
270
+ export { MCP_SYNTHETIC_HOST, MCP_GUEST_PORT, MCP_GUEST_BASE_URL, ACP_WS_PATH, ACP_WS_GUEST_URL, acpWsUrlFromExplicit, guestAcpWsUrl, buildMcpTcpHostEntry, } from './mcp/url.js';
271
+ /**
272
+ * The guest MCP base URL: the synthetic-tunnel base unless an explicit host URL
273
+ * is configured (in which case the guest reaches the orchestrator directly).
274
+ */
275
+ export function guestMcpBaseUrl(mcp) {
276
+ return mcp.explicit_host_url ?? MCP_GUEST_BASE_URL;
277
+ }
278
+ //# sourceMappingURL=vm-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vm-guards.js","sourceRoot":"","sources":["../../../src/core/vm-guards.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,0EAA0E;AAC1E,2EAA2E;AAC3E,oEAAoE;AACpE,EAAE;AACF,+EAA+E;AAC/E,0EAA0E;AAC1E,iFAAiF;AACjF,iFAAiF;AACjF,gFAAgF;AAChF,gCAAgC;AAChC,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,mFAAmF;AACnF,wDAAwD;AAGxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,yEAAyE;AACzE,iFAAiF;AACjF,6EAA6E;AAC7E,wEAAwE;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,8EAA8E;AAC9E,iFAAiF;AACjF,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,iFAAiF;AACjF,8EAA8E;AAE9E,MAAM,GAAG,GAAG,GAAG,CAAC;AAEhB;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,KAAa,EAAE,OAAe,GAAG;IACrD,+DAA+D;IAC/D,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,GAAG;YAAE,SAAS;QAC1C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;gBAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,OAAe;IACpE,IAAI,CAAC,GAAG,QAAQ,CAAC;IACjB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACd,CAAC,GAAG,OAAO,CAAC;IACd,CAAC;SAAM,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,YAAY,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,SAAS,OAAO,CAAC,KAAa,EAAE,MAAc;IAC5C,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC;IAC7D,OAAO,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,qBAAqB,GAAsB;IAC/C,SAAS;IACT,QAAQ;IACR,SAAS;IACT,MAAM;IACN,iBAAiB;CAClB,CAAC;AAYF,kFAAkF;AAClF,SAAS,eAAe,CAAC,OAAe,EAAE,KAAwB;IAChE,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,qBAAqB;QAAE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACvE,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;AAClB,CAAC;AAED,4EAA4E;AAC5E,SAAS,sBAAsB,CAC7B,SAAiB,EACjB,QAAgB,EAChB,QAA2B;IAE3B,+EAA+E;IAC/E,+EAA+E;IAC/E,8BAA8B;IAC9B,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,oBAAoB,CAC5B,6CAA6C,SAAS,mBAAmB;YACvE,8CAA8C,CACjD,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,2EAA2E;QAC3E,wEAAwE;QACxE,kEAAkE;QAClE,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,oBAAoB,CAC5B,qBAAqB,SAAS,+CAA+C;gBAC3E,QAAQ,MAAM,6DAA6D;gBAC3E,wDAAwD,CAC3D,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAA0B,EAC1B,IAAiC;IAEjC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IACzE,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7D,sBAAsB,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAc;IAC1D,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,6EAA6E;IAC7E,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QACxC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;QACtB,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,oBAAoB,CAC5B,qBAAqB,WAAW,mCAAmC,SAAS,GAAG;YAC7E,8CAA8C,CACjD,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,qBAAqB,GAAwB,IAAI,GAAG,CAAC;IACzD,sBAAsB;IACtB,mBAAmB;IACnB,gBAAgB;IAChB,cAAc;IACd,UAAU;CACX,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,wBAAwB,GAAsB;IAClD,YAAY;IACZ,SAAS;IACT,SAAS;IACT,KAAK;CACN,CAAC;AAEF,6FAA6F;AAC7F,MAAM,wBAAwB,GAAsB,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,KAAK,MAAM,MAAM,IAAI,wBAAwB,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;IAC1C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,qBAAqB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,KAAK,MAAM,MAAM,IAAI,wBAAwB,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;IAC5C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CACd,GAA2B,EAC3B,IAA+B;IAE/B,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,CAAC,CAAC;YAAE,SAAS;QACtB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAA2B;IAC5D,OAAO,OAAO,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAA2B;IAClE,OAAO,OAAO,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;AAC7C,CAAC;AAED,8EAA8E;AAC9E,gDAAgD;AAChD,8EAA8E;AAC9E,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,gFAAgF;AAChF,2EAA2E;AAC3E,iFAAiF;AACjF,8EAA8E;AAC9E,0EAA0E;AAC1E,gDAAgD;AAEhD,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,GAAyC;IACvE,OAAO,GAAG,CAAC,iBAAiB,IAAI,kBAAkB,CAAC;AACrD,CAAC"}