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,171 @@
1
+ // FCIS rewrite — PURE builder of the guest fake-creds file set (placeholders only).
2
+ //
3
+ // Ported faithfully from the reference `src/agent/gondolin-creds-staging.ts`
4
+ // (`buildGondolinFakeCreds`, `buildClaudeFiles`, `buildCodexFiles`).
5
+ //
6
+ // This is the credential-MODEL half of the Gondolin backend: there is NO proxy
7
+ // server and NO base-URL injection. The in-VM client dials its REAL upstream in
8
+ // its NATIVE mode with a token-shaped PLACEHOLDER as its bearer; Gondolin
9
+ // substitutes the real access token into the outbound request at egress
10
+ // (TLS-MITM) by EXACT string match on the `Authorization` header. So the bearer
11
+ // the guest sends MUST equal the placeholder Gondolin holds — we therefore stage
12
+ // `input.placeholder` VERBATIM as the staged file's bearer field (claude
13
+ // `claudeAiOauth.accessToken`, codex `tokens.access_token`/`id_token`). The real
14
+ // refresh/durable token NEVER enters the guest (the invariant).
15
+ //
16
+ // FCIS shape: in the reference the only IO was reading the host `~/.claude.json`
17
+ // and `~/.codex/auth.json` for the NON-SECRET identity/metadata (oauthAccount
18
+ // UUIDs; codex account_id / auth_mode / last_refresh). In this clean-room rewrite
19
+ // that IO lives in the SHELL: the shell reads + extracts the already-validated
20
+ // `ClaudeIdentity` / `CodexIdentity` and hands them to this core as plain data.
21
+ // This module is 100% synchronous, has ZERO IO, and imports ONLY from src/types.
22
+ //
23
+ // Defense-in-depth (codex review, HIGH, preserved from the reference): even
24
+ // though the shell extractor is expected to validate, this STAGING chokepoint
25
+ // re-validates the codex `accountId` (must be a UUID — a real token/`sk-…`/JWT
26
+ // never matches), `authMode` (closed set), and `lastRefresh` (ISO-timestamp
27
+ // shape) before embedding them into the staged auth.json. A token-shaped value is
28
+ // OMITTED regardless of which producer handed it to us.
29
+ // SHARED account_id guard (codex review HIGH) — the ONE definition. Re-exported
30
+ // so this module's importers keep their specifier.
31
+ import { validAccountId } from './account-id.js';
32
+ export { validAccountId };
33
+ // ---------------------------------------------------------------------------
34
+ // Constants (mirrors the reference guest paths + magic values).
35
+ // ---------------------------------------------------------------------------
36
+ // Guest paths the fake native creds land at (the VM runs as root). These mirror
37
+ // the runner's `stageAdapterExtras` guest paths so a client finds its creds in
38
+ // exactly the place its native mode looks.
39
+ const CLAUDE_CREDENTIALS_GUEST_PATH = '/root/.claude/.credentials.json';
40
+ const CLAUDE_CONFIG_GUEST_PATH = '/root/.claude.json';
41
+ const CODEX_AUTH_GUEST_PATH = '/root/.codex/auth.json';
42
+ // Creds files are 0600.
43
+ const CRED_FILE_MODE = 0o600;
44
+ // Far-future expiry (2100-01-01T00:00:00Z, ms since epoch) so the claude client
45
+ // never proactively refreshes the placeholder (a refresh attempt would be
46
+ // egress-blocked and is pure waste). Matches the spike's `4102444800000`.
47
+ const FAR_FUTURE_MS = 4_102_444_800_000;
48
+ // A junk refresh token: token-SHAPED but explicitly never a real token. The guest
49
+ // has nothing to rotate (the real refresh token stays host-side).
50
+ const JUNK_REFRESH = 'JUNK-PLACEHOLDER-REFRESH-not-a-real-token';
51
+ // ---------------------------------------------------------------------------
52
+ // Validation guards (defense-in-depth; SHARED, codex review HIGH).
53
+ // `validAccountId` + its UUID_RE live in ./account-id.js (imported above).
54
+ // ---------------------------------------------------------------------------
55
+ /** codex auth modes are a tiny closed set. */
56
+ const KNOWN_AUTH_MODES = new Set(['chatgpt', 'apikey']);
57
+ /** `last_refresh` is an ISO-8601 timestamp: digits + `-:.TZ+`, bounded length. */
58
+ const ISO_TIMESTAMP_RE = /^[0-9T:.Z+-]{1,40}$/;
59
+ function validAuthMode(v) {
60
+ return v !== null && KNOWN_AUTH_MODES.has(v) ? v : null;
61
+ }
62
+ function validLastRefresh(v) {
63
+ return v !== null && ISO_TIMESTAMP_RE.test(v) ? v : null;
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Entry point.
67
+ // ---------------------------------------------------------------------------
68
+ /**
69
+ * Build the fake native creds + env additions for `input.adapter`. The
70
+ * placeholder (a fake, token-shaped value) is what the guest sees as its bearer;
71
+ * Gondolin substitutes the real token at egress by EXACT string match. The
72
+ * returned `env` is always the single-entry `{ [secretName]: placeholder }` so a
73
+ * client reading its bearer from env (not a file) still gets the placeholder.
74
+ *
75
+ * 100% synchronous, pure: identity inputs (`claudeIdentity`/`codexIdentity`) are
76
+ * supplied already-resolved by the shell. No IO.
77
+ */
78
+ export function buildGondolinFakeCreds(input) {
79
+ const env = { [input.secretName]: input.placeholder };
80
+ switch (input.adapter) {
81
+ case 'claude':
82
+ return { files: buildClaudeFiles(input.placeholder, input.claudeIdentity), env };
83
+ case 'codex':
84
+ return { files: buildCodexFiles(input.placeholder, input.codexIdentity), env };
85
+ default: {
86
+ // Exhaustive over AcpAdapterId (closed union claude|codex): the compiler
87
+ // proves `input.adapter` is `never` here. Kept as a total function.
88
+ const unreachable = input.adapter;
89
+ throw new Error(`buildGondolinFakeCreds: unhandled adapter ${String(unreachable)}`);
90
+ }
91
+ }
92
+ }
93
+ // ---------------------------------------------------------------------------
94
+ // Per-adapter builders.
95
+ // ---------------------------------------------------------------------------
96
+ /**
97
+ * claude fake `~/.claude/.credentials.json` = `{ claudeAiOauth: { accessToken:
98
+ * <placeholder>, refreshToken: <junk>, expiresAt: <far future ms> } }` (spike B5).
99
+ * Far-future expiry ⇒ no proactive refresh. ALSO stage the scrubbed
100
+ * `~/.claude.json` identity (oauthAccount UUIDs only — the real accountUuid /
101
+ * organizationUuid are identifiers, NOT secrets) when one is supplied; absent
102
+ * identity is non-fatal (best-effort).
103
+ */
104
+ export function buildClaudeFiles(placeholder, identity) {
105
+ const credsContent = JSON.stringify({
106
+ claudeAiOauth: {
107
+ accessToken: placeholder,
108
+ refreshToken: JUNK_REFRESH,
109
+ expiresAt: FAR_FUTURE_MS,
110
+ },
111
+ });
112
+ const files = [credFile(CLAUDE_CREDENTIALS_GUEST_PATH, credsContent)];
113
+ if (identity !== null) {
114
+ const configContent = JSON.stringify({
115
+ hasCompletedOnboarding: true,
116
+ oauthAccount: { accountUuid: identity.accountUuid, organizationUuid: identity.organizationUuid },
117
+ projects: {},
118
+ });
119
+ files.push(credFile(CLAUDE_CONFIG_GUEST_PATH, configContent));
120
+ }
121
+ return files;
122
+ }
123
+ /**
124
+ * codex fake `~/.codex/auth.json`, shaped to be COMPLETE for codex 0.135.
125
+ *
126
+ * codex 0.135's local auth manager runs a COMPLETENESS check on auth.json BEFORE
127
+ * it will send the `Authorization` bearer. A too-minimal `{ tokens: {…} }` is
128
+ * judged "credentials incomplete" → no bearer → 401 → blocked refresh → refusal.
129
+ * The proven-working shape (spike C7) carries the non-secret top-level
130
+ * completeness fields `auth_mode` + `last_refresh` (and `OPENAI_API_KEY: null`)
131
+ * alongside the tokens block.
132
+ *
133
+ * SAFETY-FIRST: we do NOT spread any host auth.json into the staged file. We
134
+ * read ONLY an ALLOWLIST of non-secret metadata (supplied as `CodexIdentity`) and
135
+ * BUILD a fresh object from scratch, re-validating each field at this chokepoint
136
+ * (defense-in-depth). The placeholder is staged as both `access_token` (codex's
137
+ * bearer; Gondolin substitutes the real token at egress) and `id_token`; the
138
+ * refresh token is JUNK; `account_id` is the non-secret routing identifier.
139
+ */
140
+ export function buildCodexFiles(placeholder, identity) {
141
+ // Re-validate at this STAGING chokepoint: a custom/buggy/hostile producer could
142
+ // hand us a non-UUID `accountId` (or out-of-allowlist `authMode`/`lastRefresh`).
143
+ // The shared guards run again so a token-shaped value is OMITTED from the staged
144
+ // auth.json regardless of which producer made it.
145
+ const accountId = validAccountId(identity?.accountId ?? null);
146
+ const authMode = validAuthMode(identity?.authMode ?? null);
147
+ const lastRefresh = validLastRefresh(identity?.lastRefresh ?? null);
148
+ const tokens = {
149
+ access_token: placeholder,
150
+ id_token: placeholder,
151
+ refresh_token: JUNK_REFRESH,
152
+ ...(accountId !== null ? { account_id: accountId } : {}),
153
+ };
154
+ // Top-level non-secret completeness fields. `OPENAI_API_KEY: null` mirrors the
155
+ // host (codex stores the OAuth tokens block, NOT an api key); `auth_mode` /
156
+ // `last_refresh` are the markers codex 0.135's completeness check requires.
157
+ const auth = {
158
+ OPENAI_API_KEY: null,
159
+ ...(authMode !== null ? { auth_mode: authMode } : {}),
160
+ tokens,
161
+ ...(lastRefresh !== null ? { last_refresh: lastRefresh } : {}),
162
+ };
163
+ return [credFile(CODEX_AUTH_GUEST_PATH, JSON.stringify(auth))];
164
+ }
165
+ // ---------------------------------------------------------------------------
166
+ // Helpers.
167
+ // ---------------------------------------------------------------------------
168
+ function credFile(guestPath, content) {
169
+ return { guestPath, content, mode: CRED_FILE_MODE };
170
+ }
171
+ //# sourceMappingURL=fake-creds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-creds.js","sourceRoot":"","sources":["../../../../src/core/credential/fake-creds.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ // FCIS rewrite — pure host-identity EXTRACTORS over already-parsed JSON.
2
+ //
3
+ // Functional core: every export is a pure, SYNCHRONOUS (data) -> data function —
4
+ // no IO, no async/Promise, no clock/random, no node: imports; imports ONLY
5
+ // src/types. Ports the PURE half of src/agent/gondolin-creds-staging.ts verbatim
6
+ // in behavior. The original READ the host files itself; a pure core cannot touch
7
+ // fs/os, so the read is a `credential.read_identity` Effect the shell interprets,
8
+ // handing the PARSED JSON (or null when missing/malformed) to these extractors.
9
+ //
10
+ // SECURITY INVARIANT (codex review): the codex auth.json bytes the shell parses DO
11
+ // contain real tokens. These extractors read ONLY non-secret identity by an
12
+ // explicit key allowlist (claude oauthAccount UUIDs; codex `tokens.account_id` /
13
+ // top-level `auth_mode` / `last_refresh`) and NEVER touch
14
+ // `tokens.{access,id,refresh}_token` / a real `OPENAI_API_KEY`. The guards below
15
+ // re-validate at the staging chokepoint so a hostile/buggy reader cannot smuggle a
16
+ // token-shaped value into the placeholder-JWT `chatgpt_account_id` claim (the guest
17
+ // BEARER) or the staged metadata: a non-UUID `account_id`, out-of-allowlist
18
+ // `auth_mode`, or non-ISO `last_refresh` is OMITTED (the SAFE failure), not embedded.
19
+ // SHARED account_id guard (codex review, HIGH) — the ONE definition. Both
20
+ // account_id flows MUST validate through it so a hostile/malformed host
21
+ // `~/.codex/auth.json` cannot smuggle a token-shaped value into either sink:
22
+ // (1) the placeholder JWT's `chatgpt_account_id` claim (the guest BEARER), and
23
+ // (2) the staged `~/.codex/auth.json` `tokens.account_id`. Re-exported so this
24
+ // module's importers keep their specifier.
25
+ import { validAccountId } from './account-id.js';
26
+ export { validAccountId };
27
+ // ---------------------------------------------------------------------------
28
+ // Allowlist format guards (the staging-chokepoint re-validation).
29
+ // ---------------------------------------------------------------------------
30
+ /** codex auth modes are a tiny closed set. */
31
+ const KNOWN_AUTH_MODES = new Set(['chatgpt', 'apikey']);
32
+ /** `last_refresh` is an ISO-8601 timestamp: digits + `-:.TZ+`, bounded length. */
33
+ const ISO_TIMESTAMP_RE = /^[0-9T:.Z+-]{1,40}$/;
34
+ /** Guard the non-secret top-level `auth_mode` against the tiny closed set. */
35
+ export function validAuthMode(v) {
36
+ return v !== null && KNOWN_AUTH_MODES.has(v) ? v : null;
37
+ }
38
+ /** Guard the non-secret top-level `last_refresh` against the ISO-timestamp shape. */
39
+ export function validLastRefresh(v) {
40
+ return v !== null && ISO_TIMESTAMP_RE.test(v) ? v : null;
41
+ }
42
+ // ---------------------------------------------------------------------------
43
+ // Extractors over already-parsed JSON (the `credential.read_identity` Effect
44
+ // result the shell hands in).
45
+ // ---------------------------------------------------------------------------
46
+ /**
47
+ * Pure: pull ONLY the non-secret oauthAccount UUIDs out of a parsed `~/.claude.json`.
48
+ * Mirrors the original `extractOauthAccountIdentity` — no token, no device/session
49
+ * id, no local config. Returns null when the file was missing/malformed (parsed is
50
+ * null/non-object) or the oauthAccount UUIDs are absent.
51
+ */
52
+ export function extractClaudeIdentity(parsed) {
53
+ const acct = pickObject(parsed, 'oauthAccount');
54
+ if (acct === null)
55
+ return null;
56
+ const accountUuid = pickString(acct, 'accountUuid');
57
+ const organizationUuid = pickString(acct, 'organizationUuid');
58
+ if (accountUuid === null || organizationUuid === null)
59
+ return null;
60
+ return { accountUuid, organizationUuid };
61
+ }
62
+ /**
63
+ * Pure: pull ONLY the non-secret `account_id` out of a parsed `~/.codex/auth.json`
64
+ * `tokens` block. The parsed object also holds the real access/refresh tokens (the
65
+ * shell parsed the whole file), but this reads + returns ONLY `account_id` — the
66
+ * tokens are never returned or emitted.
67
+ *
68
+ * SAFETY-CRITICAL (codex review, HIGH): this value flows into the placeholder JWT's
69
+ * `chatgpt_account_id` claim, and that JWT IS the guest's staged
70
+ * `tokens.access_token` BEARER. So we validate through the SHARED {@link
71
+ * validAccountId} UUID guard here: a hostile/malformed `account_id` (a token /
72
+ * `sk-…` / JWT string) is NOT a UUID → returns null → the claim is OMITTED from the
73
+ * bearer (the SAFE failure), never embedded.
74
+ */
75
+ export function extractCodexAccountId(parsed) {
76
+ const tokens = pickObject(parsed, 'tokens');
77
+ if (tokens === null)
78
+ return null;
79
+ return validAccountId(pickString(tokens, 'account_id'));
80
+ }
81
+ /**
82
+ * Pure: pull ONLY the allowlisted NON-SECRET codex completeness metadata out of a
83
+ * parsed `~/.codex/auth.json`. SAFETY-CRITICAL: reads three explicit non-secret
84
+ * keys by name (`tokens.account_id`, top-level `auth_mode`, `last_refresh`) and
85
+ * NEVER touches `tokens.access_token` / `tokens.id_token` / `tokens.refresh_token`
86
+ * / a real `OPENAI_API_KEY` — even though the parsed object holds them. Returns
87
+ * null only when the file is entirely missing/unparseable (parsed === null / not an
88
+ * object); a present-but-sparse auth.json yields a struct with null fields (each
89
+ * omitted downstream). Every non-null field is validated through the shared guards
90
+ * so a real token (JWT / `sk-…` / refresh) cannot pass as identity/metadata.
91
+ */
92
+ export function extractCodexMetadata(parsed) {
93
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
94
+ return null;
95
+ const top = parsed;
96
+ const tokens = pickObject(parsed, 'tokens');
97
+ return {
98
+ accountId: validAccountId(tokens !== null ? pickString(tokens, 'account_id') : null),
99
+ authMode: validAuthMode(pickString(top, 'auth_mode')),
100
+ lastRefresh: validLastRefresh(pickString(top, 'last_refresh')),
101
+ };
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // Tiny shape pickers (pure).
105
+ // ---------------------------------------------------------------------------
106
+ /** Return `value[key]` when both `value` and the child are plain objects, else null. */
107
+ function pickObject(value, key) {
108
+ if (!value || typeof value !== 'object' || Array.isArray(value))
109
+ return null;
110
+ const v = value[key];
111
+ if (!v || typeof v !== 'object' || Array.isArray(v))
112
+ return null;
113
+ return v;
114
+ }
115
+ /** Return `obj[key]` when it is a non-empty string, else null. */
116
+ function pickString(obj, key) {
117
+ const v = obj[key];
118
+ return typeof v === 'string' && v.length > 0 ? v : null;
119
+ }
120
+ // NOTE (boundary, settled): the original `safeReadClaudeIdentity` /
121
+ // `safeReadCodexMetadata` are async try/catch wrappers (fs read + warn-on-failure)
122
+ // around the IO readers. They are IO+async by nature, so they live in the shell
123
+ // interpreter for the `credential.read_identity` Effect — porting them here would
124
+ // break the core async-ban. This module is the PURE extraction half only.
125
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../../src/core/credential/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,230 @@
1
+ // FCIS rewrite — PURE credential ASSEMBLY (the "shape" half of the original
2
+ // src/agent/credential-secrets.ts).
3
+ //
4
+ // Functional core: every export here is a pure, synchronous (data) -> data
5
+ // function. No IO, no clock, no randomness read off the wall (the placeholder
6
+ // signature/random segments come from an INJECTED RandomSource port), no node:
7
+ // imports, no process/env read, no Promise. Imports ONLY from src/types.
8
+ //
9
+ // This module owns the *shape* of the credential output, NOT its lifecycle:
10
+ // - assemblePlaceholderJwt(...) + PLACEHOLDER_JWT_EXP_SECONDS
11
+ // the JWT-shaped placeholder codex's native mode reads as its (non-expiring)
12
+ // bearer; the host `chatgpt_account_id` is embedded (UUID-guarded) so codex
13
+ // does not attempt an egress-blocked mid-turn refresh.
14
+ // - buildAdapterPlaceholder(adapter, rng, accountId?)
15
+ // the token-shaped placeholder string for an adapter (sk-ant- / JWT / gho_).
16
+ // - buildAdapterCredentialSpec(adapter, placeholder)
17
+ // the per-adapter AdapterCredentialSpec (secretName + substitutionHosts +
18
+ // placeholder), faithful to the original's static per-adapter config.
19
+ // - codexUpstreamRoute(token)
20
+ // the ChatGPT-backend upstream-route decision + chatgpt-account-id header
21
+ // policy (routes ChatGPT-OAuth subscription tokens off the metered platform
22
+ // API onto chatgpt.com/backend-api/codex). Pure decision object; the shell
23
+ // applies it at egress.
24
+ // - buildAdapterHooksConfig(specs, egressAllowlist)
25
+ // the egress-allowlist UNION (every adapter's substitutionHosts ∪
26
+ // egress.allowed_hosts) → AdapterHooksConfig. createHttpHooks ITSELF stays
27
+ // in the shell; this returns the decided config it is constructed from.
28
+ //
29
+ // The original mixed these pure decisions with host IO (file reads, flock,
30
+ // refresher spawns, the live SecretManager registry, createHttpHooks). All of
31
+ // that is now the shell's job; the SHELL constructs createHttpHooks from the
32
+ // AdapterHooksConfig this core returns, registers the SecretManager, and performs
33
+ // the credential.{probe,refresh,push_to_all} Effects.
34
+ // SHARED account_id UUID guard (codex review HIGH) — the ONE definition.
35
+ // Re-exported so this module's importers keep their specifier.
36
+ import { validAccountId } from './account-id.js';
37
+ export { validAccountId };
38
+ import { nonEmptyString } from './strings.js';
39
+ // ─── per-adapter static config (secret name + substitution hosts) ────────────
40
+ //
41
+ // The env var / secret name each adapter's placeholder is keyed under — the SAME
42
+ // name the in-VM client reads its bearer from (claude `ANTHROPIC_AUTH_TOKEN`,
43
+ // codex `OPENAI_API_KEY`).
44
+ export const CLAUDE_SECRET_NAME = 'ANTHROPIC_AUTH_TOKEN';
45
+ export const CODEX_SECRET_NAME = 'OPENAI_API_KEY';
46
+ // The hosts each adapter's real token may be substituted onto at egress (its
47
+ // credential validity scope — NOT the general firewall; see buildAdapterHooksConfig).
48
+ export const CLAUDE_UPSTREAM_HOST = 'api.anthropic.com';
49
+ // codex ChatGPT-OAuth subscription tokens are honored on the ChatGPT backend
50
+ // (chatgpt.com/backend-api/codex), never the metered platform API.
51
+ export const CODEX_UPSTREAM_HOST = 'chatgpt.com';
52
+ /**
53
+ * Far-future JWT `exp` (seconds since epoch — 2100-01-01T00:00:00Z) baked into
54
+ * the codex placeholder so codex's native mode treats it as a long-lived,
55
+ * unexpired token and never attempts a refresh (egress-blocked → wasteful 403).
56
+ * Exported so the fake-creds staging + tests can assert the same instant.
57
+ */
58
+ export const PLACEHOLDER_JWT_EXP_SECONDS = 4_102_444_800;
59
+ // The CHATGPT-backend route the codexUpstreamRoute decision targets.
60
+ const CHATGPT_BACKEND_HOST = 'chatgpt.com';
61
+ // ─── placeholder JWT assembly (codex) ────────────────────────────────────────
62
+ /**
63
+ * Assemble a structurally-valid (but cryptographically meaningless) JWT-shaped
64
+ * placeholder: `base64url(header).base64url(payload).<signature>`. codex never
65
+ * verifies the signature — it reads `exp` (far-future, so it never tries to
66
+ * refresh) and the `https://api.openai.com/auth.chatgpt_account_id` claim (which
67
+ * it uses to route + to consider the token complete; a missing claim triggers an
68
+ * egress-blocked refresh). The real token replaces this whole string at egress.
69
+ * The `signature` segment is the caller's high-entropy random string (from the
70
+ * injected RandomSource), making each VM's placeholder unique + exact-matchable
71
+ * by Gondolin's header substitution.
72
+ *
73
+ * SAFETY-CRITICAL: this JWT becomes the guest's staged BEARER, so this is the
74
+ * LAST chokepoint before a host `account_id` lands in a bearer slot. The id is
75
+ * re-validated through the shared {@link validAccountId} UUID guard (defense in
76
+ * depth): a non-UUID / token-shaped value is NOT embedded; the claim is simply
77
+ * OMITTED (the well-formed, SAFE failure). A real token (JWT / `sk-…` / refresh)
78
+ * never matches a UUID, so it can never reach the `chatgpt_account_id` claim.
79
+ */
80
+ export function assemblePlaceholderJwt(signature, accountId = null) {
81
+ const safeAccountId = validAccountId(accountId);
82
+ const header = base64urlJson({ alg: 'RS256', typ: 'JWT' });
83
+ const payload = base64urlJson({
84
+ exp: PLACEHOLDER_JWT_EXP_SECONDS,
85
+ ...(safeAccountId !== null
86
+ ? { 'https://api.openai.com/auth': { chatgpt_account_id: safeAccountId } }
87
+ : {}),
88
+ });
89
+ return `${header}.${payload}.${signature}`;
90
+ }
91
+ // ─── per-adapter placeholder strings ─────────────────────────────────────────
92
+ /**
93
+ * Build the token-shaped placeholder STRING for an adapter. The original used
94
+ * Gondolin's `makePlaceholderFunc` (shell) called once at createHttpHooks() time;
95
+ * here the random material comes from the injected RandomSource (a pure value to
96
+ * the core) so this stays synchronous + deterministic under test.
97
+ *
98
+ * - claude → `sk-ant-<random>` (claude validates the `sk-ant-` shape)
99
+ * - codex → a JWT-shaped placeholder (header.payload.<random-sig>) with a
100
+ * far-future `exp` + (when known + UUID-valid) the account-id claim
101
+ *
102
+ * `accountId` is consulted ONLY for codex; null/undefined elsewhere.
103
+ */
104
+ export function buildAdapterPlaceholder(adapter, rng, accountId = null) {
105
+ switch (adapter) {
106
+ case 'claude':
107
+ return `sk-ant-${rng.newToken()}`;
108
+ case 'codex':
109
+ // The signature segment is high-entropy random material (base64url-safe).
110
+ return assemblePlaceholderJwt(rng.newToken(), accountId);
111
+ }
112
+ }
113
+ // ─── per-adapter credential spec ─────────────────────────────────────────────
114
+ /**
115
+ * Build the per-adapter {@link AdapterCredentialSpec}: the secret/env name the
116
+ * placeholder is keyed under, the substitution hosts (the credential's validity
117
+ * scope — where the real token may be substituted onto an outbound request), and
118
+ * the placeholder string. Faithful to the original's static per-adapter config.
119
+ *
120
+ * SECURITY: `substitutionHosts` is the credential VALIDITY scope, NOT the general
121
+ * egress firewall — only these are wired into `secrets[].hosts` by the shell, so a
122
+ * general egress host (from egress.allowed_hosts) never receives a real token.
123
+ */
124
+ export function buildAdapterCredentialSpec(adapter, placeholder) {
125
+ switch (adapter) {
126
+ case 'claude':
127
+ return {
128
+ adapter,
129
+ placeholder,
130
+ secretName: CLAUDE_SECRET_NAME,
131
+ substitutionHosts: [CLAUDE_UPSTREAM_HOST],
132
+ };
133
+ case 'codex':
134
+ return {
135
+ adapter,
136
+ placeholder,
137
+ secretName: CODEX_SECRET_NAME,
138
+ substitutionHosts: [CODEX_UPSTREAM_HOST],
139
+ };
140
+ }
141
+ }
142
+ /**
143
+ * Convenience: assemble both halves (placeholder + spec) for an adapter in one
144
+ * call, drawing placeholder randomness from the injected RandomSource. The
145
+ * `accountId` is only consulted for codex (embedded in the placeholder JWT's auth
146
+ * claim, UUID-guarded).
147
+ */
148
+ export function buildAdapterCredentialSpecWithPlaceholder(adapter, rng, accountId = null) {
149
+ return buildAdapterCredentialSpec(adapter, buildAdapterPlaceholder(adapter, rng, accountId));
150
+ }
151
+ /**
152
+ * Decide the codex upstream route for a credential. ChatGPT-OAuth subscription
153
+ * tokens are accepted ONLY by OpenAI's ChatGPT backend
154
+ * (chatgpt.com/backend-api/codex), NOT the metered platform API (api.openai.com/v1,
155
+ * which 401s "Missing scopes: api.responses.write" — the subscription token carries
156
+ * only openid/profile/email/offline_access). So for a ChatGPT-OAuth credential we
157
+ * swap host → chatgpt.com, rewrite `/v1/*` → `/backend-api/codex/*`, and add the
158
+ * `chatgpt-account-id` header WHEN we have it.
159
+ *
160
+ * Routing keys on `chatgptOAuth`, NOT the account id — an OAuth token WITHOUT an
161
+ * account id still must avoid the platform API (codex review finding). API-key
162
+ * credentials (`chatgptOAuth` falsy) get null: they keep the default
163
+ * api.openai.com/v1 route unchanged.
164
+ */
165
+ export function codexUpstreamRoute(token) {
166
+ if (!token.chatgptOAuth)
167
+ return null;
168
+ // The account id is the routing CONTEXT the backend expects, but it is not the
169
+ // routing TRIGGER: send the header only when present.
170
+ const accountId = nonEmptyString(token.chatgptAccountId ?? null);
171
+ const extraHeaders = accountId !== null ? { 'chatgpt-account-id': accountId } : {};
172
+ return { host: CHATGPT_BACKEND_HOST, rewritePath: rewriteCodexBackendPath, extraHeaders };
173
+ }
174
+ /** `/v1/<rest>` → `/backend-api/codex/<rest>`; non-`/v1` paths pass through unchanged. */
175
+ export function rewriteCodexBackendPath(pathname) {
176
+ return pathname.replace(/^\/v1(?=\/|$|\?)/, '/backend-api/codex');
177
+ }
178
+ // ─── egress-allowlist union → hooks config ───────────────────────────────────
179
+ /**
180
+ * Build the per-VM {@link AdapterHooksConfig} from the per-adapter specs plus the
181
+ * general workspace egress allowlist.
182
+ *
183
+ * The egress firewall (`allowedHosts`) = the general workspace dev-tooling
184
+ * allowlist (`egress.allowed_hosts` from WORKFLOW.yaml — npm/git/CDNs) UNION every
185
+ * adapter's `substitutionHosts` (you must be able to reach the host whose token you
186
+ * substitute on). Deduplicated, order-stable (egress hosts first, then each spec's
187
+ * substitution hosts in order).
188
+ *
189
+ * SECURITY: only `substitutionHosts` are wired (by the shell) into `secrets[].hosts`,
190
+ * so the real token is NEVER substituted for a general egress host — those receive
191
+ * plain network egress only. The FIREWALL is the union; the SUBSTITUTION scope is not.
192
+ */
193
+ export function buildAdapterHooksConfig(specs, egressAllowlist = []) {
194
+ const substitution = specs.flatMap((s) => s.substitutionHosts);
195
+ const allowedHosts = dedupe([...egressAllowlist, ...substitution]);
196
+ return {
197
+ specs: specs.map((s) => ({ ...s, substitutionHosts: [...s.substitutionHosts] })),
198
+ allowedHosts,
199
+ };
200
+ }
201
+ // ─── internal helpers ────────────────────────────────────────────────────────
202
+ // nonEmptyString is the shared credential helper from ./strings.js (imported above).
203
+ /** Order-stable de-duplication (first occurrence wins). */
204
+ function dedupe(values) {
205
+ const seen = new Set();
206
+ const out = [];
207
+ for (const v of values) {
208
+ if (seen.has(v))
209
+ continue;
210
+ seen.add(v);
211
+ out.push(v);
212
+ }
213
+ return out;
214
+ }
215
+ /**
216
+ * base64url-encode a JSON-serialized object WITHOUT node:buffer (core may not
217
+ * import node builtins). Mirrors the extract.ts convention (which uses the WHATWG
218
+ * `atob` for decoding): here we JSON-stringify, UTF-8 encode via
219
+ * `unescape(encodeURIComponent(...))` (the inverse of extract.ts's decode), base64
220
+ * via the WHATWG `btoa`, then translate base64 → base64url (strip padding,
221
+ * `+`→`-`, `/`→`_`).
222
+ */
223
+ function base64urlJson(obj) {
224
+ const json = JSON.stringify(obj);
225
+ // UTF-8 encode the string into a Latin-1 "binary string" btoa accepts.
226
+ const binary = unescape(encodeURIComponent(json));
227
+ const b64 = btoa(binary);
228
+ return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
229
+ }
230
+ //# sourceMappingURL=shape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.js","sourceRoot":"","sources":["../../../../src/core/credential/shape.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ // FCIS rewrite — shared credential string helpers (the ONE home).
2
+ //
3
+ // `nonEmptyString` was inlined across the credential modules (extract.ts /
4
+ // shape.ts / availability.ts), and availability.ts's copy had DRIFTED to a
5
+ // boolean return while the others returned the string value. The canonical
6
+ // (and strictly more useful — the boolean is just `!== null`) form is the
7
+ // string-valued one; availability.ts's boolean call sites adapt with a
8
+ // `!== null` check. This collapses all three onto one definition.
9
+ //
10
+ // 100% PURE + SYNCHRONOUS. No IO, no node: imports, no clock/randomness.
11
+ /** The value iff it is a non-empty string, else null. (`!== null` ⇒ "is set".) */
12
+ export function nonEmptyString(v) {
13
+ return typeof v === 'string' && v.length > 0 ? v : null;
14
+ }
15
+ //# sourceMappingURL=strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.js","sourceRoot":"","sources":["../../../../src/core/credential/strings.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,0EAA0E;AAC1E,uEAAuE;AACvE,kEAAkE;AAClE,EAAE;AACF,yEAAyE;AAEzE,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,CAAU;IACvC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1D,CAAC"}