@interf/compiler 0.7.3 → 0.9.3

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 (418) hide show
  1. package/README.md +124 -90
  2. package/TRADEMARKS.md +1 -1
  3. package/agent-skills/interf-actions/SKILL.md +74 -0
  4. package/agent-skills/interf-actions/references/cli.md +190 -0
  5. package/{builtin-workflows/interf → builtin-methods/interf-default}/README.md +9 -9
  6. package/{builtin-workflows/interf → builtin-methods/interf-default}/compile/stages/shape/SKILL.md +4 -4
  7. package/{builtin-workflows/interf → builtin-methods/interf-default}/compile/stages/structure/SKILL.md +1 -1
  8. package/builtin-methods/interf-default/improve/SKILL.md +18 -0
  9. package/{builtin-workflows/interf/workflow.json → builtin-methods/interf-default/method.json} +9 -9
  10. package/{builtin-workflows/interf/workflow.schema.json → builtin-methods/interf-default/method.schema.json} +3 -3
  11. package/{builtin-workflows/interf → builtin-methods/interf-default}/use/query/SKILL.md +1 -1
  12. package/dist/cli/commands/check-draft.d.ts +11 -10
  13. package/dist/cli/commands/check-draft.js +21 -20
  14. package/dist/cli/commands/compile-controller.d.ts +10 -7
  15. package/dist/cli/commands/compile-controller.js +84 -79
  16. package/dist/cli/commands/compile.d.ts +3 -3
  17. package/dist/cli/commands/compile.js +101 -43
  18. package/dist/cli/commands/compiled-flow.d.ts +14 -11
  19. package/dist/cli/commands/compiled-flow.js +38 -33
  20. package/dist/cli/commands/control-path.d.ts +11 -0
  21. package/dist/cli/commands/control-path.js +72 -0
  22. package/dist/cli/commands/create-method-wizard.d.ts +76 -0
  23. package/dist/cli/commands/create-method-wizard.js +465 -0
  24. package/dist/cli/commands/create.d.ts +3 -3
  25. package/dist/cli/commands/create.js +81 -68
  26. package/dist/cli/commands/default.js +4 -3
  27. package/dist/cli/commands/doctor.js +5 -5
  28. package/dist/cli/commands/executor-flow.d.ts +6 -6
  29. package/dist/cli/commands/executor-flow.js +2 -2
  30. package/dist/cli/commands/init.d.ts +2 -2
  31. package/dist/cli/commands/init.js +415 -144
  32. package/dist/cli/commands/list.js +16 -14
  33. package/dist/cli/commands/preparation-selection.d.ts +6 -0
  34. package/dist/cli/commands/preparation-selection.js +11 -0
  35. package/dist/cli/commands/reset.js +3 -3
  36. package/dist/cli/commands/source-config-wizard.d.ts +12 -11
  37. package/dist/cli/commands/source-config-wizard.js +206 -228
  38. package/dist/cli/commands/status.js +152 -17
  39. package/dist/cli/commands/test-flow.d.ts +16 -16
  40. package/dist/cli/commands/test-flow.js +53 -243
  41. package/dist/cli/commands/test.d.ts +6 -2
  42. package/dist/cli/commands/test.js +136 -100
  43. package/dist/cli/commands/verify.js +13 -13
  44. package/dist/cli/commands/web.d.ts +11 -0
  45. package/dist/cli/commands/web.js +386 -0
  46. package/dist/cli/index.d.ts +2 -1
  47. package/dist/cli/index.js +3 -1
  48. package/dist/compiler-ui/404.html +1 -0
  49. package/dist/compiler-ui/__next.__PAGE__.txt +10 -0
  50. package/dist/compiler-ui/__next._full.txt +20 -0
  51. package/dist/compiler-ui/__next._head.txt +5 -0
  52. package/dist/compiler-ui/__next._index.txt +5 -0
  53. package/dist/compiler-ui/__next._tree.txt +5 -0
  54. package/dist/compiler-ui/_next/static/chunks/03~yq9q893hmn.js +1 -0
  55. package/dist/compiler-ui/_next/static/chunks/06yhdspx~ca5-.js +5 -0
  56. package/dist/compiler-ui/_next/static/chunks/06z~l3kwb891e.js +1 -0
  57. package/dist/compiler-ui/_next/static/chunks/08g7lvje.te.u.js +1 -0
  58. package/dist/compiler-ui/_next/static/chunks/08m7vf5asqlsm.js +91 -0
  59. package/dist/compiler-ui/_next/static/chunks/0_i-3_5l9t2qe.js +1 -0
  60. package/dist/compiler-ui/_next/static/chunks/0b-ywny_j0g~0.js +1 -0
  61. package/dist/compiler-ui/_next/static/chunks/0b52v41o1gixx.js +1 -0
  62. package/dist/compiler-ui/_next/static/chunks/0c9mu7yldxyyg.css +3 -0
  63. package/dist/compiler-ui/_next/static/chunks/0gpzgsv0w.q~m.js +31 -0
  64. package/dist/compiler-ui/_next/static/chunks/0ilwfezfvu6~-.js +1 -0
  65. package/dist/compiler-ui/_next/static/chunks/0n51hrfoufc7g.js +1 -0
  66. package/dist/compiler-ui/_next/static/chunks/0xxmf45eskdt~.css +1 -0
  67. package/dist/compiler-ui/_next/static/chunks/0y5z3t-z1c8ks.js.map +5 -0
  68. package/dist/compiler-ui/_next/static/chunks/14wtz~vq25~qq.js +1 -0
  69. package/dist/compiler-ui/_next/static/chunks/15mks7ry_cupt.js +118 -0
  70. package/dist/compiler-ui/_next/static/chunks/turbopack-0.uq1k8c0j4s..js +1 -0
  71. package/dist/compiler-ui/_next/static/chunks/turbopack-10e~t1yzi4svj.js +1 -0
  72. package/dist/compiler-ui/_next/static/chunks/turbopack-worker-0sjn--fhq~1cg.js +1 -0
  73. package/dist/compiler-ui/_next/static/media/GeistMono_Variable.p.17jn9btb_52pq.woff2 +0 -0
  74. package/dist/compiler-ui/_next/static/media/Geist_Variable-s.p.0-te~ja_gpvcf.woff2 +0 -0
  75. package/dist/compiler-ui/_next/static/media/worker.102zas1s52_pf.js +109 -0
  76. package/dist/compiler-ui/_next/static/pIZnDsV3Je6hdC3cOsGdK/_buildManifest.js +11 -0
  77. package/dist/compiler-ui/_next/static/pIZnDsV3Je6hdC3cOsGdK/_clientMiddlewareManifest.js +1 -0
  78. package/dist/compiler-ui/_next/static/pIZnDsV3Je6hdC3cOsGdK/_ssgManifest.js +1 -0
  79. package/dist/compiler-ui/_not-found/__next._full.txt +15 -0
  80. package/dist/compiler-ui/_not-found/__next._head.txt +5 -0
  81. package/dist/compiler-ui/_not-found/__next._index.txt +5 -0
  82. package/dist/compiler-ui/_not-found/__next._not-found.__PAGE__.txt +5 -0
  83. package/dist/compiler-ui/_not-found/__next._not-found.txt +5 -0
  84. package/dist/compiler-ui/_not-found/__next._tree.txt +2 -0
  85. package/dist/compiler-ui/_not-found.html +1 -0
  86. package/dist/compiler-ui/_not-found.txt +15 -0
  87. package/dist/compiler-ui/index.html +1 -0
  88. package/dist/compiler-ui/index.txt +20 -0
  89. package/dist/index.d.ts +11 -7
  90. package/dist/index.js +8 -4
  91. package/dist/packages/agents/index.d.ts +1 -1
  92. package/dist/packages/agents/lib/args.d.ts +2 -2
  93. package/dist/packages/agents/lib/compiled-bootstrap.js +7 -6
  94. package/dist/packages/agents/lib/execution-profile.d.ts +5 -5
  95. package/dist/packages/agents/lib/execution-profile.js +7 -6
  96. package/dist/packages/agents/lib/execution.js +4 -2
  97. package/dist/packages/agents/lib/executors.d.ts +14 -13
  98. package/dist/packages/agents/lib/executors.js +1 -0
  99. package/dist/packages/agents/lib/preflight.d.ts +1 -0
  100. package/dist/packages/agents/lib/preflight.js +32 -9
  101. package/dist/packages/agents/lib/render.d.ts +2 -2
  102. package/dist/packages/agents/lib/render.js +10 -9
  103. package/dist/packages/agents/lib/shells.d.ts +27 -34
  104. package/dist/packages/agents/lib/shells.js +191 -235
  105. package/dist/packages/agents/lib/types.d.ts +3 -2
  106. package/dist/packages/compiler/artifact-counts.d.ts +1 -0
  107. package/dist/packages/compiler/artifact-counts.js +30 -0
  108. package/dist/packages/compiler/compiled-paths.d.ts +5 -5
  109. package/dist/packages/compiler/compiled-paths.js +10 -10
  110. package/dist/packages/compiler/compiled-pipeline.d.ts +18 -12
  111. package/dist/packages/compiler/compiled-pipeline.js +34 -23
  112. package/dist/packages/compiler/compiled-schema.d.ts +20 -20
  113. package/dist/packages/compiler/compiled-schema.js +29 -29
  114. package/dist/packages/compiler/compiled-stage-plan.d.ts +4 -4
  115. package/dist/packages/compiler/compiled-stage-plan.js +11 -11
  116. package/dist/packages/compiler/compiled-stage-runner.d.ts +10 -5
  117. package/dist/packages/compiler/compiled-stage-runner.js +56 -8
  118. package/dist/packages/compiler/compiled-target.d.ts +5 -5
  119. package/dist/packages/compiler/compiled-target.js +5 -5
  120. package/dist/packages/compiler/index.d.ts +3 -3
  121. package/dist/packages/compiler/index.js +2 -2
  122. package/dist/packages/compiler/lib/schema.d.ts +68 -93
  123. package/dist/packages/compiler/lib/schema.js +57 -89
  124. package/dist/packages/compiler/{workflows.d.ts → method-runs.d.ts} +4 -4
  125. package/dist/packages/compiler/{workflows.js → method-runs.js} +4 -3
  126. package/dist/packages/compiler/raw-snapshot.d.ts +3 -3
  127. package/dist/packages/compiler/raw-snapshot.js +0 -1
  128. package/dist/packages/compiler/reset.js +3 -3
  129. package/dist/packages/compiler/runtime-acceptance.js +9 -16
  130. package/dist/packages/compiler/runtime-contracts.js +9 -9
  131. package/dist/packages/compiler/runtime-prompt.js +9 -9
  132. package/dist/packages/compiler/runtime-reconcile.d.ts +2 -2
  133. package/dist/packages/compiler/runtime-reconcile.js +3 -3
  134. package/dist/packages/compiler/runtime-runs.js +12 -9
  135. package/dist/packages/compiler/runtime-types.d.ts +9 -7
  136. package/dist/packages/compiler/state-health.js +26 -35
  137. package/dist/packages/compiler/state-view.js +6 -6
  138. package/dist/packages/compiler/validate-compiled.d.ts +5 -5
  139. package/dist/packages/compiler/validate-compiled.js +56 -62
  140. package/dist/packages/compiler/validate.d.ts +2 -2
  141. package/dist/packages/compiler/validate.js +22 -14
  142. package/dist/packages/contracts/index.d.ts +2 -0
  143. package/dist/packages/contracts/index.js +1 -0
  144. package/dist/packages/contracts/lib/schema.d.ts +205 -0
  145. package/dist/packages/contracts/lib/schema.js +101 -0
  146. package/dist/packages/execution/adapters.d.ts +15 -0
  147. package/dist/packages/execution/adapters.js +1 -0
  148. package/dist/packages/execution/events.d.ts +8 -0
  149. package/dist/packages/execution/events.js +16 -0
  150. package/dist/packages/execution/index.d.ts +9 -0
  151. package/dist/packages/execution/index.js +6 -0
  152. package/dist/packages/execution/lib/schema.d.ts +1551 -0
  153. package/dist/packages/execution/lib/schema.js +296 -0
  154. package/dist/packages/local-service/action-values.d.ts +22 -0
  155. package/dist/packages/local-service/action-values.js +30 -0
  156. package/dist/packages/local-service/client.d.ts +119 -0
  157. package/dist/packages/local-service/client.js +356 -0
  158. package/dist/packages/local-service/index.d.ts +15 -0
  159. package/dist/packages/local-service/index.js +11 -0
  160. package/dist/packages/local-service/lib/schema.d.ts +6917 -0
  161. package/dist/packages/local-service/lib/schema.js +519 -0
  162. package/dist/packages/local-service/routes.d.ts +27 -0
  163. package/dist/packages/local-service/routes.js +32 -0
  164. package/dist/packages/local-service/run-observability.d.ts +6 -0
  165. package/dist/packages/local-service/run-observability.js +592 -0
  166. package/dist/packages/local-service/runtime.d.ts +130 -0
  167. package/dist/packages/local-service/runtime.js +2263 -0
  168. package/dist/packages/local-service/server.d.ts +18 -0
  169. package/dist/packages/local-service/server.js +577 -0
  170. package/dist/packages/method-authoring/index.d.ts +4 -0
  171. package/dist/packages/method-authoring/index.js +4 -0
  172. package/dist/packages/{workflow-authoring/lib/workflow-edit-utils.d.ts → method-authoring/lib/method-edit-utils.d.ts} +3 -3
  173. package/dist/packages/method-authoring/method-authoring.d.ts +24 -0
  174. package/dist/packages/method-authoring/method-authoring.js +116 -0
  175. package/dist/packages/method-authoring/method-edit-session.d.ts +18 -0
  176. package/dist/packages/method-authoring/method-edit-session.js +125 -0
  177. package/dist/packages/method-authoring/method-improvement.d.ts +23 -0
  178. package/dist/packages/{workflow-authoring/workflow-improvement.js → method-authoring/method-improvement.js} +65 -64
  179. package/dist/packages/{workflow-package/builtin-compiled-workflow.d.ts → method-package/builtin-compiled-method.d.ts} +1 -1
  180. package/dist/packages/{workflow-package/builtin-compiled-workflow.js → method-package/builtin-compiled-method.js} +17 -17
  181. package/dist/packages/{workflow-package → method-package}/context-interface.d.ts +12 -12
  182. package/dist/packages/{workflow-package → method-package}/context-interface.js +20 -20
  183. package/dist/packages/method-package/index.d.ts +11 -0
  184. package/dist/packages/method-package/index.js +11 -0
  185. package/dist/packages/method-package/interf-method-package.d.ts +31 -0
  186. package/dist/packages/method-package/interf-method-package.js +496 -0
  187. package/dist/packages/{workflow-package → method-package}/lib/package-root.js +1 -1
  188. package/dist/packages/method-package/local-methods.d.ts +64 -0
  189. package/dist/packages/method-package/local-methods.js +466 -0
  190. package/dist/packages/method-package/method-definitions.d.ts +83 -0
  191. package/dist/packages/method-package/method-definitions.js +205 -0
  192. package/dist/packages/{workflow-package/workflow-helpers.d.ts → method-package/method-helpers.d.ts} +10 -10
  193. package/dist/packages/{workflow-package/workflow-helpers.js → method-package/method-helpers.js} +27 -27
  194. package/dist/packages/method-package/method-review-paths.d.ts +10 -0
  195. package/dist/packages/{workflow-package/workflow-review-paths.js → method-package/method-review-paths.js} +4 -4
  196. package/dist/packages/{workflow-package/workflow-stage-runner.d.ts → method-package/method-stage-runner.d.ts} +13 -11
  197. package/dist/packages/{workflow-package/workflow-stage-runner.js → method-package/method-stage-runner.js} +8 -6
  198. package/dist/packages/methods/index.d.ts +2 -0
  199. package/dist/packages/methods/index.js +2 -0
  200. package/dist/packages/methods/method-resolution.d.ts +6 -0
  201. package/dist/packages/methods/method-resolution.js +7 -0
  202. package/dist/packages/project-model/index.d.ts +2 -4
  203. package/dist/packages/project-model/index.js +1 -3
  204. package/dist/packages/project-model/interf-detect.d.ts +3 -3
  205. package/dist/packages/project-model/interf-detect.js +18 -14
  206. package/dist/packages/project-model/interf-scaffold.d.ts +2 -2
  207. package/dist/packages/project-model/interf-scaffold.js +40 -38
  208. package/dist/packages/project-model/interf.d.ts +1 -2
  209. package/dist/packages/project-model/interf.js +1 -2
  210. package/dist/packages/project-model/lib/schema.d.ts +24 -14
  211. package/dist/packages/project-model/lib/schema.js +22 -30
  212. package/dist/packages/project-model/project-paths.d.ts +9 -10
  213. package/dist/packages/project-model/project-paths.js +14 -17
  214. package/dist/packages/project-model/source-config.d.ts +19 -17
  215. package/dist/packages/project-model/source-config.js +144 -145
  216. package/dist/packages/project-model/source-folders.d.ts +11 -0
  217. package/dist/packages/project-model/source-folders.js +110 -0
  218. package/dist/packages/testing/index.d.ts +2 -2
  219. package/dist/packages/testing/index.js +1 -1
  220. package/dist/packages/testing/lib/schema.d.ts +11 -11
  221. package/dist/packages/testing/lib/schema.js +8 -9
  222. package/dist/packages/testing/readiness-check-run.d.ts +67 -0
  223. package/dist/packages/testing/readiness-check-run.js +258 -0
  224. package/dist/packages/testing/test-execution.d.ts +3 -3
  225. package/dist/packages/testing/test-execution.js +8 -8
  226. package/dist/packages/testing/test-paths.js +7 -9
  227. package/dist/packages/testing/test-profile-presets.js +2 -2
  228. package/dist/packages/testing/test-sandbox.js +10 -11
  229. package/dist/packages/testing/test-targets.d.ts +1 -1
  230. package/dist/packages/testing/test-targets.js +8 -7
  231. package/dist/packages/testing/test-types.d.ts +1 -1
  232. package/package.json +29 -30
  233. package/builtin-workflows/interf/improve/SKILL.md +0 -18
  234. package/dist/cli/commands/create-workflow-wizard.d.ts +0 -70
  235. package/dist/cli/commands/create-workflow-wizard.js +0 -361
  236. package/dist/cli/commands/dataset-selection.d.ts +0 -6
  237. package/dist/cli/commands/dataset-selection.js +0 -11
  238. package/dist/lib/agent-args.d.ts +0 -1
  239. package/dist/lib/agent-args.js +0 -1
  240. package/dist/lib/agent-constants.d.ts +0 -1
  241. package/dist/lib/agent-constants.js +0 -1
  242. package/dist/lib/agent-detection.d.ts +0 -1
  243. package/dist/lib/agent-detection.js +0 -1
  244. package/dist/lib/agent-execution.d.ts +0 -1
  245. package/dist/lib/agent-execution.js +0 -1
  246. package/dist/lib/agent-logs.d.ts +0 -1
  247. package/dist/lib/agent-logs.js +0 -1
  248. package/dist/lib/agent-preflight.d.ts +0 -1
  249. package/dist/lib/agent-preflight.js +0 -1
  250. package/dist/lib/agent-render.d.ts +0 -1
  251. package/dist/lib/agent-render.js +0 -1
  252. package/dist/lib/agent-shells.d.ts +0 -1
  253. package/dist/lib/agent-shells.js +0 -1
  254. package/dist/lib/agent-status.d.ts +0 -1
  255. package/dist/lib/agent-status.js +0 -1
  256. package/dist/lib/agent-types.d.ts +0 -1
  257. package/dist/lib/agent-types.js +0 -1
  258. package/dist/lib/agents.d.ts +0 -1
  259. package/dist/lib/agents.js +0 -1
  260. package/dist/lib/builtin-compiled-workflow.d.ts +0 -1
  261. package/dist/lib/builtin-compiled-workflow.js +0 -1
  262. package/dist/lib/chart-guidance.d.ts +0 -1
  263. package/dist/lib/chart-guidance.js +0 -1
  264. package/dist/lib/compiled-compile.d.ts +0 -1
  265. package/dist/lib/compiled-compile.js +0 -1
  266. package/dist/lib/compiled-paths.d.ts +0 -1
  267. package/dist/lib/compiled-paths.js +0 -3
  268. package/dist/lib/compiled-raw.d.ts +0 -1
  269. package/dist/lib/compiled-raw.js +0 -3
  270. package/dist/lib/compiled-reset.d.ts +0 -1
  271. package/dist/lib/compiled-reset.js +0 -3
  272. package/dist/lib/compiled-schema.d.ts +0 -1
  273. package/dist/lib/compiled-schema.js +0 -1
  274. package/dist/lib/discovery.d.ts +0 -1
  275. package/dist/lib/discovery.js +0 -1
  276. package/dist/lib/execution-profile.d.ts +0 -1
  277. package/dist/lib/execution-profile.js +0 -1
  278. package/dist/lib/executors.d.ts +0 -1
  279. package/dist/lib/executors.js +0 -1
  280. package/dist/lib/filesystem.d.ts +0 -1
  281. package/dist/lib/filesystem.js +0 -1
  282. package/dist/lib/interf-bootstrap.d.ts +0 -1
  283. package/dist/lib/interf-bootstrap.js +0 -3
  284. package/dist/lib/interf-detect.d.ts +0 -1
  285. package/dist/lib/interf-detect.js +0 -3
  286. package/dist/lib/interf-scaffold.d.ts +0 -1
  287. package/dist/lib/interf-scaffold.js +0 -3
  288. package/dist/lib/interf-workflow-package.d.ts +0 -1
  289. package/dist/lib/interf-workflow-package.js +0 -1
  290. package/dist/lib/interf.d.ts +0 -1
  291. package/dist/lib/interf.js +0 -3
  292. package/dist/lib/local-workflows.d.ts +0 -1
  293. package/dist/lib/local-workflows.js +0 -1
  294. package/dist/lib/logger.d.ts +0 -1
  295. package/dist/lib/logger.js +0 -1
  296. package/dist/lib/package-root.d.ts +0 -1
  297. package/dist/lib/package-root.js +0 -1
  298. package/dist/lib/parse.d.ts +0 -1
  299. package/dist/lib/parse.js +0 -1
  300. package/dist/lib/project-paths.d.ts +0 -1
  301. package/dist/lib/project-paths.js +0 -3
  302. package/dist/lib/runtime-acceptance.d.ts +0 -1
  303. package/dist/lib/runtime-acceptance.js +0 -1
  304. package/dist/lib/runtime-contracts.d.ts +0 -1
  305. package/dist/lib/runtime-contracts.js +0 -1
  306. package/dist/lib/runtime-inventory.d.ts +0 -1
  307. package/dist/lib/runtime-inventory.js +0 -1
  308. package/dist/lib/runtime-paths.d.ts +0 -1
  309. package/dist/lib/runtime-paths.js +0 -1
  310. package/dist/lib/runtime-prompt.d.ts +0 -1
  311. package/dist/lib/runtime-prompt.js +0 -1
  312. package/dist/lib/runtime-reconcile.d.ts +0 -1
  313. package/dist/lib/runtime-reconcile.js +0 -1
  314. package/dist/lib/runtime-runs.d.ts +0 -1
  315. package/dist/lib/runtime-runs.js +0 -1
  316. package/dist/lib/runtime-types.d.ts +0 -1
  317. package/dist/lib/runtime-types.js +0 -1
  318. package/dist/lib/runtime.d.ts +0 -1
  319. package/dist/lib/runtime.js +0 -1
  320. package/dist/lib/schema.d.ts +0 -4
  321. package/dist/lib/schema.js +0 -6
  322. package/dist/lib/source-config.d.ts +0 -1
  323. package/dist/lib/source-config.js +0 -3
  324. package/dist/lib/state-artifacts.d.ts +0 -1
  325. package/dist/lib/state-artifacts.js +0 -1
  326. package/dist/lib/state-health.d.ts +0 -1
  327. package/dist/lib/state-health.js +0 -1
  328. package/dist/lib/state-io.d.ts +0 -1
  329. package/dist/lib/state-io.js +0 -1
  330. package/dist/lib/state-paths.d.ts +0 -1
  331. package/dist/lib/state-paths.js +0 -1
  332. package/dist/lib/state-view.d.ts +0 -1
  333. package/dist/lib/state-view.js +0 -1
  334. package/dist/lib/state.d.ts +0 -1
  335. package/dist/lib/state.js +0 -1
  336. package/dist/lib/test-execution.d.ts +0 -1
  337. package/dist/lib/test-execution.js +0 -3
  338. package/dist/lib/test-matrices.d.ts +0 -1
  339. package/dist/lib/test-matrices.js +0 -3
  340. package/dist/lib/test-paths.d.ts +0 -1
  341. package/dist/lib/test-paths.js +0 -3
  342. package/dist/lib/test-profile-presets.d.ts +0 -1
  343. package/dist/lib/test-profile-presets.js +0 -3
  344. package/dist/lib/test-sandbox.d.ts +0 -1
  345. package/dist/lib/test-sandbox.js +0 -3
  346. package/dist/lib/test-specs.d.ts +0 -1
  347. package/dist/lib/test-specs.js +0 -3
  348. package/dist/lib/test-targets.d.ts +0 -1
  349. package/dist/lib/test-targets.js +0 -3
  350. package/dist/lib/test-types.d.ts +0 -1
  351. package/dist/lib/test-types.js +0 -3
  352. package/dist/lib/test.d.ts +0 -1
  353. package/dist/lib/test.js +0 -3
  354. package/dist/lib/util.d.ts +0 -1
  355. package/dist/lib/util.js +0 -1
  356. package/dist/lib/validate-compiled.d.ts +0 -1
  357. package/dist/lib/validate-compiled.js +0 -1
  358. package/dist/lib/validate-helpers.d.ts +0 -1
  359. package/dist/lib/validate-helpers.js +0 -1
  360. package/dist/lib/validate.d.ts +0 -1
  361. package/dist/lib/validate.js +0 -1
  362. package/dist/lib/workflow-authoring.d.ts +0 -1
  363. package/dist/lib/workflow-authoring.js +0 -1
  364. package/dist/lib/workflow-definitions.d.ts +0 -1
  365. package/dist/lib/workflow-definitions.js +0 -1
  366. package/dist/lib/workflow-edit-session.d.ts +0 -1
  367. package/dist/lib/workflow-edit-session.js +0 -1
  368. package/dist/lib/workflow-edit-utils.d.ts +0 -1
  369. package/dist/lib/workflow-edit-utils.js +0 -1
  370. package/dist/lib/workflow-helpers.d.ts +0 -1
  371. package/dist/lib/workflow-helpers.js +0 -1
  372. package/dist/lib/workflow-improvement.d.ts +0 -1
  373. package/dist/lib/workflow-improvement.js +0 -1
  374. package/dist/lib/workflow-primitives.d.ts +0 -1
  375. package/dist/lib/workflow-primitives.js +0 -1
  376. package/dist/lib/workflow-review-paths.d.ts +0 -1
  377. package/dist/lib/workflow-review-paths.js +0 -1
  378. package/dist/lib/workflow-stage-policy.d.ts +0 -1
  379. package/dist/lib/workflow-stage-policy.js +0 -1
  380. package/dist/lib/workflow-stage-runner.d.ts +0 -1
  381. package/dist/lib/workflow-stage-runner.js +0 -1
  382. package/dist/lib/workflows.d.ts +0 -1
  383. package/dist/lib/workflows.js +0 -1
  384. package/dist/packages/project-model/compiled-paths.d.ts +0 -1
  385. package/dist/packages/project-model/compiled-paths.js +0 -1
  386. package/dist/packages/project-model/compiled-raw.d.ts +0 -1
  387. package/dist/packages/project-model/compiled-raw.js +0 -1
  388. package/dist/packages/project-model/compiled-reset.d.ts +0 -1
  389. package/dist/packages/project-model/compiled-reset.js +0 -1
  390. package/dist/packages/shared/index.d.ts +0 -7
  391. package/dist/packages/shared/index.js +0 -7
  392. package/dist/packages/shared/util.d.ts +0 -3
  393. package/dist/packages/shared/util.js +0 -3
  394. package/dist/packages/testing/test-matrices.d.ts +0 -90
  395. package/dist/packages/testing/test-matrices.js +0 -96
  396. package/dist/packages/workflow-authoring/index.d.ts +0 -4
  397. package/dist/packages/workflow-authoring/index.js +0 -4
  398. package/dist/packages/workflow-authoring/workflow-authoring.d.ts +0 -26
  399. package/dist/packages/workflow-authoring/workflow-authoring.js +0 -123
  400. package/dist/packages/workflow-authoring/workflow-edit-session.d.ts +0 -16
  401. package/dist/packages/workflow-authoring/workflow-edit-session.js +0 -60
  402. package/dist/packages/workflow-authoring/workflow-improvement.d.ts +0 -23
  403. package/dist/packages/workflow-package/index.d.ts +0 -11
  404. package/dist/packages/workflow-package/index.js +0 -11
  405. package/dist/packages/workflow-package/interf-workflow-package.d.ts +0 -25
  406. package/dist/packages/workflow-package/interf-workflow-package.js +0 -389
  407. package/dist/packages/workflow-package/local-workflows.d.ts +0 -64
  408. package/dist/packages/workflow-package/local-workflows.js +0 -441
  409. package/dist/packages/workflow-package/workflow-definitions.d.ts +0 -82
  410. package/dist/packages/workflow-package/workflow-definitions.js +0 -210
  411. package/dist/packages/workflow-package/workflow-review-paths.d.ts +0 -10
  412. /package/{builtin-workflows/interf → builtin-methods/interf-default}/compile/stages/summarize/SKILL.md +0 -0
  413. /package/dist/packages/compiler/{workflow-primitives.d.ts → method-primitives.d.ts} +0 -0
  414. /package/dist/packages/compiler/{workflow-primitives.js → method-primitives.js} +0 -0
  415. /package/dist/packages/{workflow-authoring/lib/workflow-edit-utils.js → method-authoring/lib/method-edit-utils.js} +0 -0
  416. /package/dist/packages/{workflow-package → method-package}/lib/package-root.d.ts +0 -0
  417. /package/dist/packages/{workflow-package/workflow-stage-policy.d.ts → method-package/method-stage-policy.d.ts} +0 -0
  418. /package/dist/packages/{workflow-package/workflow-stage-policy.js → method-package/method-stage-policy.js} +0 -0
@@ -0,0 +1,2263 @@
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { CompileRunSchema, } from "../execution/lib/schema.js";
4
+ import { createRunEventId, createRunEventTimestamp, } from "../execution/events.js";
5
+ import { compiledRuntimeRunHistoryPath, compiledRuntimeRoot, testRootForCompiled, } from "../compiler/compiled-paths.js";
6
+ import { loadState, } from "../compiler/state.js";
7
+ import { RuntimeRunSchema, } from "../compiler/lib/schema.js";
8
+ import { ReadinessStateSchema, } from "../contracts/lib/schema.js";
9
+ import { discoverSourceFiles, } from "../compiler/discovery.js";
10
+ import { ensurePortableContextScaffold, readInterfConfig, } from "../project-model/interf.js";
11
+ import { findSourcePreparationConfig, fingerprintReadinessChecks, listSourcePreparationConfigs, loadSourceFolderConfig, DEFAULT_METHOD_ID, methodIdForSourcePreparationConfig, resolveConfiguredSourceFolderPath, resolveSourcePreparationPath, syncCompiledInterfConfigFromSourcePreparationConfig, upsertSourcePreparationConfig, } from "../project-model/source-config.js";
12
+ import { defaultPreparationNameForPath, listSourceFolderChoices, normalizeSourcePreparationPathForConfig, } from "../project-model/source-folders.js";
13
+ import { portableContextPath, } from "../project-model/project-paths.js";
14
+ import { getCompiledMethod, listCompiledMethodChoices, } from "../method-package/method-definitions.js";
15
+ import { resolveMethodPackageSourcePath, } from "../method-package/local-methods.js";
16
+ import { resolveAgent, detectAgents, supportsAutomatedRuns, } from "../agents/lib/detection.js";
17
+ import { AGENTS, } from "../agents/lib/constants.js";
18
+ import { loadUserConfig, saveUserConfig, } from "../agents/lib/user-config.js";
19
+ import { readSavedReadinessCheckRun, } from "../testing/readiness-check-run.js";
20
+ import { createCompiledTestTarget, } from "../testing/test-targets.js";
21
+ import { ActionProposalApprovalRequestSchema, ActionProposalCreateRequestSchema, ActionProposalPlanSchema, ActionProposalResourceSchema, CompileRunCreateRequestSchema, CompileRunResourceSchema, MethodResourceSchema, LocalExecutorStatusSchema, LocalExecutorSelectRequestSchema, LocalServiceHealthSchema, PreparationReadinessStateSchema, LocalRunHandlerResultSchema, LocalJobEventAppendRequestSchema, LocalJobRunCreateRequestSchema, LocalJobRunResourceSchema, SourceFileResourceSchema, WorkspaceFileResourceSchema, PortableContextResourceSchema, PreparationSetupCreateRequestSchema, PreparationResourceSchema, ReadinessCheckDraftCreateRequestSchema, ReadinessCheckDraftResultSchema, TestRunCreateRequestSchema, TestRunResourceSchema, MethodAuthoringCreateRequestSchema, MethodAuthoringResultSchema, } from "./lib/schema.js";
22
+ import { buildLocalServiceUrl, } from "./routes.js";
23
+ import { methodAuthoringTaskPrompt, MethodAuthoringActionValuesSchema, PreparationSetupActionValuesSchema, } from "./action-values.js";
24
+ import { compileRunToObservability, jobRunToObservability, testRunToObservability, uniqueArtifacts, } from "./run-observability.js";
25
+ function createRunId(prefix) {
26
+ return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
27
+ }
28
+ function createActionProposalId() {
29
+ return `action_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
30
+ }
31
+ const ACTION_PLANNER_CLARIFICATION_MESSAGE = "I can help with this Interf Workspace. Ask a question about Interf, or ask me to create a Preparation, prepare, check readiness, improve, or draft a Method and I will prepare an approval proposal.";
32
+ function readJsonFile(filePath) {
33
+ try {
34
+ return JSON.parse(readFileSync(filePath, "utf8"));
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ function writeJsonFile(filePath, value) {
41
+ mkdirSync(dirname(filePath), { recursive: true });
42
+ writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
43
+ }
44
+ function sanitizeActionProposalPlan(value) {
45
+ if (!value || typeof value !== "object" || Array.isArray(value))
46
+ return value;
47
+ const plan = { ...value };
48
+ for (const key of ["preparation", "method", "title", "summary", "assistant_message", "command_preview"]) {
49
+ const current = plan[key];
50
+ if (current === null || current === undefined) {
51
+ delete plan[key];
52
+ continue;
53
+ }
54
+ if (typeof current === "string" && current.trim().length === 0) {
55
+ delete plan[key];
56
+ }
57
+ }
58
+ return plan;
59
+ }
60
+ function compileRunsRoot(compiledPath) {
61
+ return join(compiledRuntimeRoot(compiledPath), "compile-runs");
62
+ }
63
+ function compileRunPath(compiledPath, runId) {
64
+ return join(compileRunsRoot(compiledPath), `${runId}.json`);
65
+ }
66
+ function testRunsRoot(compiledPath) {
67
+ return join(testRootForCompiled(compiledPath), "service-runs");
68
+ }
69
+ function testRunPath(compiledPath, runId) {
70
+ return join(testRunsRoot(compiledPath), `${runId}.json`);
71
+ }
72
+ function localJobsRoot(rootPath) {
73
+ return join(rootPath, "interf", ".service", "jobs");
74
+ }
75
+ function localJobPath(rootPath, runId) {
76
+ return join(localJobsRoot(rootPath), `${runId}.json`);
77
+ }
78
+ function actionProposalsRoot(rootPath) {
79
+ return join(rootPath, "interf", ".service", "action-proposals");
80
+ }
81
+ function actionProposalPath(rootPath, proposalId) {
82
+ return join(actionProposalsRoot(rootPath), `${proposalId}.json`);
83
+ }
84
+ function listJsonFiles(dirPath) {
85
+ if (!existsSync(dirPath))
86
+ return [];
87
+ try {
88
+ if (!statSync(dirPath).isDirectory())
89
+ return [];
90
+ }
91
+ catch {
92
+ return [];
93
+ }
94
+ return readdirSync(dirPath)
95
+ .filter((entry) => entry.endsWith(".json"))
96
+ .map((entry) => join(dirPath, entry));
97
+ }
98
+ function readCompileRunAt(filePath) {
99
+ const parsed = CompileRunSchema.safeParse(readJsonFile(filePath));
100
+ return parsed.success ? parsed.data : null;
101
+ }
102
+ function readRuntimeRunHistory(compiledPath) {
103
+ const historyPath = compiledRuntimeRunHistoryPath(compiledPath);
104
+ if (!existsSync(historyPath))
105
+ return [];
106
+ try {
107
+ return readFileSync(historyPath, "utf8")
108
+ .split(/\r?\n/)
109
+ .map((line) => line.trim())
110
+ .filter((line) => line.length > 0)
111
+ .map((line) => {
112
+ try {
113
+ return RuntimeRunSchema.safeParse(JSON.parse(line));
114
+ }
115
+ catch {
116
+ return { success: false };
117
+ }
118
+ })
119
+ .filter((parsed) => parsed.success)
120
+ .map((parsed) => parsed.data);
121
+ }
122
+ catch {
123
+ return [];
124
+ }
125
+ }
126
+ function readTestRunAt(filePath) {
127
+ const parsed = TestRunResourceSchema.safeParse(readJsonFile(filePath));
128
+ return parsed.success ? parsed.data : null;
129
+ }
130
+ function readLocalJobRunAt(filePath) {
131
+ const parsed = LocalJobRunResourceSchema.safeParse(readJsonFile(filePath));
132
+ return parsed.success ? parsed.data : null;
133
+ }
134
+ function readActionProposalAt(filePath) {
135
+ const parsed = ActionProposalResourceSchema.safeParse(readJsonFile(filePath));
136
+ return parsed.success ? parsed.data : null;
137
+ }
138
+ function newestFirst(items) {
139
+ return [...items].sort((left, right) => {
140
+ const leftTime = Date.parse(left.started_at ?? left.finished_at ?? "");
141
+ const rightTime = Date.parse(right.started_at ?? right.finished_at ?? "");
142
+ return (Number.isFinite(rightTime) ? rightTime : 0) - (Number.isFinite(leftTime) ? leftTime : 0);
143
+ });
144
+ }
145
+ function newestJobFirst(items) {
146
+ return [...items].sort((left, right) => Date.parse(right.created_at) - Date.parse(left.created_at));
147
+ }
148
+ function newestActionProposalFirst(items) {
149
+ return [...items].sort((left, right) => Date.parse(right.created_at) - Date.parse(left.created_at));
150
+ }
151
+ function newestCompileFirst(items) {
152
+ return [...items].sort((left, right) => Date.parse(right.created_at) - Date.parse(left.created_at));
153
+ }
154
+ function configuredAgentName() {
155
+ const config = loadUserConfig();
156
+ if (!config)
157
+ return null;
158
+ const configured = AGENTS.find((agent) => agent.command === config.agentCommand) ??
159
+ AGENTS.find((agent) => agent.name === config.agent) ??
160
+ AGENTS.find((agent) => agent.displayName === config.agent);
161
+ return configured?.name ?? null;
162
+ }
163
+ function detectedExecutorOptions(currentAgentName) {
164
+ return detectAgents()
165
+ .filter(supportsAutomatedRuns)
166
+ .map((agent) => ({
167
+ name: agent.name,
168
+ display_name: agent.displayName,
169
+ command: agent.command,
170
+ current: agent.name === currentAgentName,
171
+ }));
172
+ }
173
+ function stageArtifactRefs(stageId, artifacts) {
174
+ return (artifacts ?? []).map((path) => ({
175
+ path,
176
+ role: "output",
177
+ stage_id: stageId,
178
+ label: path,
179
+ }));
180
+ }
181
+ function proofForStage(options) {
182
+ return {
183
+ id: `${options.runId}-${options.stageId}-proof`,
184
+ run_id: options.runId,
185
+ stage_id: options.stageId,
186
+ generated_at: options.stageState.finished_at ?? new Date().toISOString(),
187
+ summary: options.summary ?? `${options.stageId} produced stage evidence.`,
188
+ files_processed: options.stageState.counts?.source_total,
189
+ artifacts: options.artifacts,
190
+ checks: [
191
+ {
192
+ id: `${options.stageId}-status`,
193
+ label: "stage completed",
194
+ ok: options.stageState.status === "succeeded",
195
+ ...(options.stageState.status === "succeeded"
196
+ ? {}
197
+ : { detail: options.stageState.summary ?? "Stage did not complete successfully." }),
198
+ },
199
+ {
200
+ id: `${options.stageId}-artifacts`,
201
+ label: "artifacts recorded",
202
+ ok: options.artifacts.length > 0,
203
+ ...(options.artifacts.length > 0
204
+ ? {}
205
+ : { detail: "No stage artifacts were recorded." }),
206
+ },
207
+ ],
208
+ };
209
+ }
210
+ function logsForStageRun(stageState) {
211
+ const runId = stageState?.run_id;
212
+ if (!runId)
213
+ return undefined;
214
+ return {
215
+ prompt_path: `.interf/runtime/logs/${runId}.prompt.txt`,
216
+ event_stream_path: `.interf/runtime/logs/${runId}.events.ndjson`,
217
+ status_path: `.interf/runtime/logs/${runId}.status.log`,
218
+ contract_path: `.interf/runtime/logs/${runId}.stage-contract.json`,
219
+ };
220
+ }
221
+ function logsForRuntimeRun(run) {
222
+ if (!run)
223
+ return undefined;
224
+ return {
225
+ ...(run.logs?.prompt_path ? { prompt_path: run.logs.prompt_path } : {}),
226
+ ...(run.logs?.event_stream_path ? { event_stream_path: run.logs.event_stream_path } : {}),
227
+ ...(run.logs?.status_path ? { status_path: run.logs.status_path } : {}),
228
+ contract_path: run.contract_path,
229
+ };
230
+ }
231
+ function timestampKey(value) {
232
+ const parsed = Date.parse(value ?? "");
233
+ return Number.isFinite(parsed) ? parsed : 0;
234
+ }
235
+ function applyEventToCompileRun(run, event) {
236
+ const now = event.timestamp;
237
+ const stageFor = (stageId) => {
238
+ const existing = run.stages.find((stage) => stage.stage_id === stageId);
239
+ if (existing)
240
+ return existing;
241
+ const created = {
242
+ run_id: run.run_id,
243
+ stage_id: stageId,
244
+ status: "queued",
245
+ artifacts: [],
246
+ };
247
+ run.stages.push(created);
248
+ return created;
249
+ };
250
+ const updateStage = (stageId, patch) => {
251
+ const current = stageFor(stageId);
252
+ Object.assign(current, patch);
253
+ };
254
+ switch (event.type) {
255
+ case "run.started":
256
+ return {
257
+ ...run,
258
+ status: "running",
259
+ started_at: run.started_at ?? now,
260
+ events: [...run.events, event],
261
+ };
262
+ case "stage.started":
263
+ updateStage(event.stage_id, {
264
+ status: "running",
265
+ started_at: now,
266
+ stage_index: event.stage_index,
267
+ stage_total: event.stage_total,
268
+ });
269
+ break;
270
+ case "artifact.written": {
271
+ const stage = stageFor(event.stage_id);
272
+ updateStage(event.stage_id, {
273
+ artifacts: uniqueArtifacts([...(stage.artifacts ?? []), event.artifact]),
274
+ });
275
+ break;
276
+ }
277
+ case "proof.updated":
278
+ if (event.stage_id) {
279
+ updateStage(event.stage_id, {
280
+ latest_proof: event.proof,
281
+ });
282
+ }
283
+ return {
284
+ ...run,
285
+ latest_proof: event.proof,
286
+ events: [...run.events, event],
287
+ };
288
+ case "log.appended":
289
+ break;
290
+ case "stage.passed":
291
+ updateStage(event.stage_id, {
292
+ status: "succeeded",
293
+ finished_at: now,
294
+ summary: event.summary ?? null,
295
+ failure: null,
296
+ });
297
+ break;
298
+ case "stage.failed":
299
+ updateStage(event.stage_id, {
300
+ status: "failed",
301
+ finished_at: now,
302
+ summary: event.error,
303
+ failure: event.error,
304
+ });
305
+ break;
306
+ case "run.completed":
307
+ return {
308
+ ...run,
309
+ status: "succeeded",
310
+ finished_at: run.finished_at ?? now,
311
+ events: [...run.events, event],
312
+ };
313
+ case "run.failed":
314
+ return {
315
+ ...run,
316
+ status: "failed",
317
+ finished_at: run.finished_at ?? now,
318
+ events: [...run.events, event],
319
+ };
320
+ default:
321
+ break;
322
+ }
323
+ return {
324
+ ...run,
325
+ events: [...run.events, event],
326
+ };
327
+ }
328
+ function applyEventToLocalJob(run, event) {
329
+ const stepFor = (stepId) => {
330
+ const existing = run.steps.find((step) => step.id === stepId);
331
+ if (existing)
332
+ return existing;
333
+ const created = {
334
+ id: stepId,
335
+ label: stepId,
336
+ status: "queued",
337
+ };
338
+ run.steps.push(created);
339
+ return created;
340
+ };
341
+ const updateStep = (stepId, patch) => {
342
+ if (!stepId)
343
+ return;
344
+ Object.assign(stepFor(stepId), patch);
345
+ };
346
+ switch (event.type) {
347
+ case "job.started":
348
+ return {
349
+ ...run,
350
+ status: "running",
351
+ started_at: run.started_at ?? event.timestamp,
352
+ events: [...run.events, event],
353
+ };
354
+ case "step.started":
355
+ updateStep(event.step_id, {
356
+ status: "running",
357
+ started_at: event.timestamp,
358
+ ...(event.input ? { input: event.input } : {}),
359
+ });
360
+ break;
361
+ case "step.completed":
362
+ updateStep(event.step_id, {
363
+ status: "succeeded",
364
+ finished_at: event.timestamp,
365
+ summary: event.message ?? null,
366
+ ...(event.output ? { output: event.output } : {}),
367
+ });
368
+ break;
369
+ case "step.failed":
370
+ updateStep(event.step_id, {
371
+ status: "failed",
372
+ finished_at: event.timestamp,
373
+ summary: event.message ?? null,
374
+ ...(event.output ? { output: event.output } : {}),
375
+ });
376
+ break;
377
+ case "job.completed":
378
+ return {
379
+ ...run,
380
+ status: "succeeded",
381
+ finished_at: run.finished_at ?? event.timestamp,
382
+ events: [...run.events, event],
383
+ };
384
+ case "job.failed":
385
+ return {
386
+ ...run,
387
+ status: "failed",
388
+ finished_at: run.finished_at ?? event.timestamp,
389
+ error: event.message ?? "Job failed.",
390
+ events: [...run.events, event],
391
+ };
392
+ case "artifact.written":
393
+ case "log.appended":
394
+ break;
395
+ default:
396
+ break;
397
+ }
398
+ return {
399
+ ...run,
400
+ events: [...run.events, event],
401
+ };
402
+ }
403
+ function slugFromText(value) {
404
+ const slug = value
405
+ .toLowerCase()
406
+ .replace(/[^a-z0-9]+/g, "-")
407
+ .replace(/^-+|-+$/g, "")
408
+ .slice(0, 42)
409
+ .replace(/-+$/g, "");
410
+ return slug || "custom";
411
+ }
412
+ function stringValue(values, key) {
413
+ const value = values?.[key];
414
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
415
+ }
416
+ function numberValue(values, key) {
417
+ const value = values?.[key];
418
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
419
+ }
420
+ function testModeFromValues(values) {
421
+ const value = stringValue(values, "mode") ?? stringValue(values, "target");
422
+ if (value === "source-files")
423
+ return "raw";
424
+ if (value === "portable-context")
425
+ return "compiled";
426
+ return value === "raw" || value === "compiled" || value === "both" ? value : null;
427
+ }
428
+ function testModeValue(values, defaultMode = "both") {
429
+ return testModeFromValues(values) ?? defaultMode;
430
+ }
431
+ function testModeCliTarget(mode) {
432
+ if (mode === "raw")
433
+ return "source-files";
434
+ if (mode === "compiled")
435
+ return "portable-context";
436
+ return "both";
437
+ }
438
+ function methodIdForProposal(message, values) {
439
+ const explicit = stringValue(values, "method_id") ??
440
+ stringValue(values, "method");
441
+ return explicit ?? `custom-${slugFromText(message)}`;
442
+ }
443
+ function actionValueMethodTaskPrompt(values) {
444
+ const parsed = MethodAuthoringActionValuesSchema.safeParse(values);
445
+ return parsed.success ? methodAuthoringTaskPrompt(parsed.data) : null;
446
+ }
447
+ function preparationSetupPathValue(values) {
448
+ return stringValue(values, "path") ??
449
+ stringValue(values, "source_folder_path") ??
450
+ stringValue(values, "source_path") ??
451
+ stringValue(values, "source_folder") ??
452
+ stringValue(values, "folder");
453
+ }
454
+ function preparationSetupNameValue(values) {
455
+ const parsed = PreparationSetupActionValuesSchema.safeParse(values);
456
+ return parsed.success ? parsed.data.name : stringValue(values, "name") ??
457
+ stringValue(values, "preparation") ??
458
+ stringValue(values, "preparation_name");
459
+ }
460
+ function actionCommandPreview(actionType, preparationName, methodId, values) {
461
+ if (actionType === "preparation-setup") {
462
+ const preparationPart = preparationName ? ` # Preparation: ${preparationName}` : "";
463
+ const pathPart = preparationSetupPathValue(values);
464
+ return pathPart ? `interf init # source: ${pathPart}${preparationPart}` : `interf init${preparationPart}`;
465
+ }
466
+ if (actionType === "compile") {
467
+ const methodSuffix = methodId ? ` # Method: ${methodId}` : "";
468
+ return preparationName
469
+ ? `interf compile --preparation ${preparationName}${methodSuffix}`
470
+ : `interf compile${methodSuffix}`;
471
+ }
472
+ if (actionType === "test") {
473
+ const mode = testModeCliTarget(testModeValue(values));
474
+ return preparationName
475
+ ? `interf test --preparation ${preparationName} --target ${mode}`
476
+ : `interf test --target ${mode}`;
477
+ }
478
+ if (actionType === "readiness-check-draft") {
479
+ return "interf # choose Auto-create readiness checks";
480
+ }
481
+ if (actionType === "method-authoring" || actionType === "method-improvement") {
482
+ return "interf create method";
483
+ }
484
+ return "Try: create a Preparation, prepare, check readiness, draft readiness checks, or draft a Method.";
485
+ }
486
+ function hasCompiledTestTarget(sourcePath, preparationConfig) {
487
+ const compiledPath = portableContextPath(sourcePath, preparationConfig.name);
488
+ if (!existsSync(compiledPath))
489
+ return false;
490
+ return createCompiledTestTarget(compiledPath, preparationConfig.name, methodIdForSourcePreparationConfig(preparationConfig) ?? DEFAULT_METHOD_ID).eligible;
491
+ }
492
+ function actionAssistantMessage(actionType, preparationName, commandPreview) {
493
+ const preparationSuffix = preparationName ? ` for Preparation "${preparationName}"` : "";
494
+ if (actionType === "preparation-setup") {
495
+ return `Interf prepared a Preparation setup proposal${preparationSuffix}. Approve to save the source folder and create the portable-context scaffold. CLI equivalent: ${commandPreview}`;
496
+ }
497
+ if (actionType === "compile") {
498
+ return `Interf prepared a prepare-run proposal${preparationSuffix}. Approve to submit it through the local Interf service and watch the run in Interf. CLI equivalent: ${commandPreview}`;
499
+ }
500
+ if (actionType === "test") {
501
+ return `Interf prepared a readiness-check proposal${preparationSuffix}. Approve to run the requested target against saved readiness checks. CLI equivalent: ${commandPreview}`;
502
+ }
503
+ if (actionType === "readiness-check-draft") {
504
+ return `Interf prepared a readiness-check draft proposal${preparationSuffix}. Approve to ask the configured local executor to draft checks as a visible run. CLI equivalent: ${commandPreview}`;
505
+ }
506
+ if (actionType === "method-authoring" || actionType === "method-improvement") {
507
+ return `Interf prepared a Method draft proposal${preparationSuffix}. Approve to draft a reusable local Method as a visible run. CLI equivalent: ${commandPreview}`;
508
+ }
509
+ return "I could not map that to a safe Interf action. Ask for one action in plain English, such as create a Preparation, prepare the data, check readiness, draft readiness checks, or draft a Method.";
510
+ }
511
+ function passRate(passed, total) {
512
+ if (total <= 0)
513
+ return null;
514
+ return Math.round((passed / total) * 100);
515
+ }
516
+ function readinessTargetResult(summary, currentFingerprint, comparisonFingerprint) {
517
+ if (!summary)
518
+ return null;
519
+ const resultFingerprint = comparisonFingerprint ?? null;
520
+ return {
521
+ passed: summary.passed_cases,
522
+ total: summary.total_cases,
523
+ pass_rate: passRate(summary.passed_cases, summary.total_cases),
524
+ checks_fingerprint: resultFingerprint,
525
+ stale: Boolean(currentFingerprint && resultFingerprint && currentFingerprint !== resultFingerprint),
526
+ run_id: null,
527
+ run_path: summary.run_path,
528
+ };
529
+ }
530
+ function readinessSummaryForStatus(status) {
531
+ if (status === "ready")
532
+ return "Ready for agent work.";
533
+ if (status === "not-ready")
534
+ return "Readiness checks did not pass.";
535
+ if (status === "stale")
536
+ return "Readiness checks are stale for the current saved checks.";
537
+ if (status === "checking")
538
+ return "Readiness checks are running.";
539
+ if (status === "building")
540
+ return "Portable context is building.";
541
+ if (status === "built")
542
+ return "Portable context is built; readiness has not been proven yet.";
543
+ if (status === "not-built")
544
+ return "Portable context has not been built yet.";
545
+ if (status === "not-configured")
546
+ return "No readiness checks are configured.";
547
+ return "Latest preparation failed.";
548
+ }
549
+ function readinessStateToPreparationReadiness(readiness) {
550
+ return PreparationReadinessStateSchema.parse({
551
+ ...readiness,
552
+ checks: readiness.checks.map((check) => ({ ...check })),
553
+ });
554
+ }
555
+ function buildPreparationResource(rootPath, preparation, readiness, latestCompileRunId, latestTestRunId) {
556
+ const methodId = methodIdForSourcePreparationConfig(preparation);
557
+ return PreparationResourceSchema.parse({
558
+ id: preparation.name,
559
+ name: preparation.name,
560
+ preparation,
561
+ source_path: resolveSourcePreparationPath(rootPath, preparation),
562
+ method_id: methodId,
563
+ checks: preparation.checks,
564
+ portable_context: {
565
+ preparation: preparation.name,
566
+ path: readiness.portable_context_path,
567
+ exists: readiness.portable_context_path !== null,
568
+ method_id: methodId,
569
+ latest_compile_run_id: latestCompileRunId,
570
+ latest_test_run_id: latestTestRunId,
571
+ },
572
+ portable_context_path: readiness.portable_context_path,
573
+ readiness: readinessStateToPreparationReadiness(readiness),
574
+ runs: {
575
+ latest_compile_run_id: latestCompileRunId,
576
+ latest_test_run_id: latestTestRunId,
577
+ },
578
+ latest_compile_run_id: latestCompileRunId,
579
+ latest_test_run_id: latestTestRunId,
580
+ });
581
+ }
582
+ function buildMethodResource(resource) {
583
+ return MethodResourceSchema.parse({
584
+ id: resource.id,
585
+ method_id: resource.id,
586
+ path: resource.path,
587
+ ...(resource.label ? { label: resource.label } : {}),
588
+ ...(resource.hint ? { hint: resource.hint } : {}),
589
+ source_kind: resource.source_kind,
590
+ built_in: resource.built_in,
591
+ active_for_preparations: resource.active_for_preparations,
592
+ stages: resource.stages,
593
+ });
594
+ }
595
+ export class LocalServiceRuntime {
596
+ rootPath;
597
+ host;
598
+ port;
599
+ startedAt;
600
+ packageVersion;
601
+ handlers;
602
+ constructor(options) {
603
+ this.rootPath = resolve(options.rootPath);
604
+ this.host = options.host;
605
+ this.port = options.port;
606
+ this.startedAt = options.startedAt ?? new Date().toISOString();
607
+ this.packageVersion = options.packageVersion;
608
+ this.handlers = options.handlers ?? {};
609
+ }
610
+ health() {
611
+ const sourceFolderPath = resolveConfiguredSourceFolderPath(this.rootPath);
612
+ return LocalServiceHealthSchema.parse({
613
+ kind: "interf-local-service-health",
614
+ version: 1,
615
+ status: "ok",
616
+ host: this.host,
617
+ port: this.port,
618
+ service_url: buildLocalServiceUrl({ host: this.host, port: this.port }),
619
+ control_path: this.rootPath,
620
+ source_folder_path: sourceFolderPath,
621
+ started_at: this.startedAt,
622
+ ...(this.packageVersion ? { package_version: this.packageVersion } : {}),
623
+ });
624
+ }
625
+ listPreparations() {
626
+ const config = loadSourceFolderConfig(this.rootPath);
627
+ return listSourcePreparationConfigs(config).map((preparation) => {
628
+ const compileRuns = this.listCompileRunsForPreparation(preparation.name);
629
+ const testRuns = this.listTestRunsForPreparation(preparation.name);
630
+ const readiness = this.computePreparationReadiness(preparation);
631
+ return buildPreparationResource(this.rootPath, preparation, readiness, compileRuns[0]?.run_id ?? null, testRuns[0]?.run_id ?? null);
632
+ });
633
+ }
634
+ getPreparation(preparationName) {
635
+ return this.listPreparations().find((preparation) => preparation.name === preparationName) ?? null;
636
+ }
637
+ listPreparationReadiness() {
638
+ return this.listReadiness().map(readinessStateToPreparationReadiness);
639
+ }
640
+ getPreparationReadiness(preparationName) {
641
+ const readiness = this.getReadiness(preparationName);
642
+ return readiness ? readinessStateToPreparationReadiness(readiness) : null;
643
+ }
644
+ listReadiness() {
645
+ const config = loadSourceFolderConfig(this.rootPath);
646
+ return listSourcePreparationConfigs(config).map((preparation) => this.computePreparationReadiness(preparation));
647
+ }
648
+ getReadiness(preparationName) {
649
+ const preparation = findSourcePreparationConfig(loadSourceFolderConfig(this.rootPath), preparationName);
650
+ return preparation ? this.computePreparationReadiness(preparation) : null;
651
+ }
652
+ computePreparationReadiness(preparation) {
653
+ const generatedAt = new Date().toISOString();
654
+ const compiledPath = portableContextPath(this.rootPath, preparation.name);
655
+ const contextExists = existsSync(compiledPath);
656
+ const compiledTarget = createCompiledTestTarget(compiledPath, preparation.name, methodIdForSourcePreparationConfig(preparation) ?? DEFAULT_METHOD_ID);
657
+ const contextReady = compiledTarget.eligible;
658
+ const compileRun = this.listCompileRunsForPreparation(preparation.name)[0] ?? null;
659
+ const testRun = this.listTestRunsForPreparation(preparation.name)[0] ?? null;
660
+ const comparison = this.readLatestComparison(preparation.name);
661
+ const configuredChecks = preparation.checks.length;
662
+ const currentFingerprint = configuredChecks > 0 ? fingerprintReadinessChecks(preparation.checks) : null;
663
+ const comparisonFingerprint = comparison?.checks_fingerprint ?? null;
664
+ const sourceResult = readinessTargetResult(comparison?.raw, currentFingerprint, comparisonFingerprint);
665
+ const contextResult = readinessTargetResult(comparison?.compiled, currentFingerprint, comparisonFingerprint);
666
+ const checksStale = Boolean(currentFingerprint && comparisonFingerprint && currentFingerprint !== comparisonFingerprint);
667
+ const compileCheck = (() => {
668
+ if (!compileRun) {
669
+ return {
670
+ gate: "compile-run",
671
+ ok: false,
672
+ status: "not-built",
673
+ summary: "No compile run has built portable context yet.",
674
+ artifact_path: contextReady ? compiledPath : null,
675
+ };
676
+ }
677
+ if (compileRun.status === "succeeded") {
678
+ return {
679
+ gate: "compile-run",
680
+ ok: contextReady,
681
+ status: contextReady ? "built" : "failed",
682
+ summary: contextReady
683
+ ? "Latest compile run built portable context."
684
+ : "Latest compile run finished, but portable context is missing.",
685
+ run_id: compileRun.run_id,
686
+ artifact_path: contextReady ? compiledPath : null,
687
+ };
688
+ }
689
+ if (compileRun.status === "queued" || compileRun.status === "running") {
690
+ return {
691
+ gate: "compile-run",
692
+ ok: false,
693
+ status: "building",
694
+ summary: "Latest compile run is still building portable context.",
695
+ run_id: compileRun.run_id,
696
+ artifact_path: contextExists ? compiledPath : null,
697
+ };
698
+ }
699
+ return {
700
+ gate: "compile-run",
701
+ ok: false,
702
+ status: "failed",
703
+ summary: compileRun.status === "cancelled"
704
+ ? "Latest compile run was cancelled."
705
+ : "Latest compile run failed.",
706
+ run_id: compileRun.run_id,
707
+ artifact_path: contextReady ? compiledPath : null,
708
+ };
709
+ })();
710
+ const checks = [
711
+ {
712
+ gate: "preparation-config",
713
+ ok: true,
714
+ summary: "Preparation is saved in this control plane folder.",
715
+ },
716
+ {
717
+ gate: "portable-context",
718
+ ok: contextReady,
719
+ status: contextReady ? "built" : "not-built",
720
+ summary: contextReady
721
+ ? "Portable context is built."
722
+ : "Portable context has not been built.",
723
+ artifact_path: contextReady ? compiledPath : null,
724
+ },
725
+ compileCheck,
726
+ {
727
+ gate: "readiness-checks",
728
+ ok: configuredChecks > 0,
729
+ status: configuredChecks > 0 ? "built" : "not-configured",
730
+ summary: configuredChecks > 0
731
+ ? `${configuredChecks} readiness check${configuredChecks === 1 ? "" : "s"} configured.`
732
+ : "No readiness checks are configured.",
733
+ },
734
+ {
735
+ gate: "checks-current",
736
+ ok: !checksStale,
737
+ status: checksStale ? "stale" : "built",
738
+ summary: checksStale
739
+ ? "Latest readiness result is stale for the current saved checks."
740
+ : "Latest readiness result matches the current saved checks.",
741
+ },
742
+ ];
743
+ const status = (() => {
744
+ if (compileRun?.status === "queued" || compileRun?.status === "running")
745
+ return "building";
746
+ if (testRun?.status === "queued" || testRun?.status === "running")
747
+ return "checking";
748
+ if (compileRun?.status === "failed" || compileRun?.status === "cancelled")
749
+ return "failed";
750
+ if (!compileRun || !contextReady)
751
+ return "not-built";
752
+ if (configuredChecks === 0)
753
+ return "not-configured";
754
+ if (checksStale)
755
+ return "stale";
756
+ if (!contextResult)
757
+ return "built";
758
+ return contextResult.total > 0 && contextResult.passed === contextResult.total ? "ready" : "not-ready";
759
+ })();
760
+ const ready = status === "ready";
761
+ return ReadinessStateSchema.parse({
762
+ kind: "interf-readiness-state",
763
+ version: 1,
764
+ generated_at: generatedAt,
765
+ preparation: preparation.name,
766
+ status,
767
+ ready,
768
+ summary: readinessSummaryForStatus(status),
769
+ portable_context_path: contextReady ? compiledPath : null,
770
+ latest_compile_run_id: compileRun?.run_id ?? null,
771
+ latest_test_run_id: testRun?.run_id ?? null,
772
+ compile: compileCheck,
773
+ check_results: {
774
+ configured: configuredChecks,
775
+ fingerprint: currentFingerprint,
776
+ source_files: sourceResult,
777
+ portable_context: contextResult,
778
+ delta: comparison?.summary.pass_rate_delta ?? null,
779
+ },
780
+ checks,
781
+ });
782
+ }
783
+ listSourceFiles(preparationName) {
784
+ const preparations = listSourcePreparationConfigs(loadSourceFolderConfig(this.rootPath))
785
+ .filter((preparation) => !preparationName || preparation.name === preparationName);
786
+ return preparations.flatMap((preparation) => {
787
+ const sourceFolderPath = resolveSourcePreparationPath(this.rootPath, preparation);
788
+ const compiledPath = portableContextPath(this.rootPath, preparation.name);
789
+ return discoverSourceFiles(sourceFolderPath, compiledPath).sourceFiles.map((relativePath) => {
790
+ const absolutePath = join(sourceFolderPath, relativePath);
791
+ let sizeBytes = 0;
792
+ let modifiedAt = null;
793
+ try {
794
+ const stat = statSync(absolutePath);
795
+ sizeBytes = stat.size;
796
+ modifiedAt = stat.mtime.toISOString();
797
+ }
798
+ catch {
799
+ sizeBytes = 0;
800
+ modifiedAt = null;
801
+ }
802
+ return SourceFileResourceSchema.parse({
803
+ preparation: preparation.name,
804
+ path: relativePath,
805
+ absolute_path: absolutePath,
806
+ size_bytes: sizeBytes,
807
+ modified_at: modifiedAt,
808
+ source_folder_path: sourceFolderPath,
809
+ });
810
+ });
811
+ });
812
+ }
813
+ listWorkspaceFiles() {
814
+ const sourceFolderPath = resolveConfiguredSourceFolderPath(this.rootPath) ?? this.rootPath;
815
+ return discoverSourceFiles(sourceFolderPath, join(this.rootPath, "interf")).sourceFiles.map((relativePath) => {
816
+ const absolutePath = join(sourceFolderPath, relativePath);
817
+ let sizeBytes = 0;
818
+ let modifiedAt = null;
819
+ try {
820
+ const stat = statSync(absolutePath);
821
+ sizeBytes = stat.size;
822
+ modifiedAt = stat.mtime.toISOString();
823
+ }
824
+ catch {
825
+ sizeBytes = 0;
826
+ modifiedAt = null;
827
+ }
828
+ return WorkspaceFileResourceSchema.parse({
829
+ path: relativePath,
830
+ absolute_path: absolutePath,
831
+ size_bytes: sizeBytes,
832
+ modified_at: modifiedAt,
833
+ });
834
+ });
835
+ }
836
+ listMethods() {
837
+ const preparations = listSourcePreparationConfigs(loadSourceFolderConfig(this.rootPath));
838
+ const choices = listCompiledMethodChoices(this.rootPath);
839
+ return choices.map((method) => {
840
+ const activeForPreparations = preparations
841
+ .filter((preparation) => (methodIdForSourcePreparationConfig(preparation) ?? DEFAULT_METHOD_ID) === method.id)
842
+ .map((preparation) => preparation.name);
843
+ return buildMethodResource({
844
+ id: method.id,
845
+ path: resolveMethodPackageSourcePath(this.rootPath, method.id) ?? method.id,
846
+ label: method.label,
847
+ hint: method.hint,
848
+ source_kind: method.scope === "builtin" ? "builtin" : "local",
849
+ built_in: method.scope === "builtin",
850
+ active_for_preparations: activeForPreparations,
851
+ stages: method.stages.map((stage) => ({
852
+ id: stage.id,
853
+ label: stage.label,
854
+ description: stage.description,
855
+ contract_type: stage.contractType,
856
+ skill_dir: stage.skillDir,
857
+ reads: stage.reads,
858
+ writes: stage.writes,
859
+ ...(stage.acceptance ? { acceptance: stage.acceptance } : {}),
860
+ })),
861
+ });
862
+ });
863
+ }
864
+ getMethod(methodId) {
865
+ return this.listMethods().find((method) => method.id === methodId) ?? null;
866
+ }
867
+ listJobs() {
868
+ return newestJobFirst(listJsonFiles(localJobsRoot(this.rootPath))
869
+ .map(readLocalJobRunAt)
870
+ .filter((run) => run !== null));
871
+ }
872
+ getJob(runId) {
873
+ return this.listJobs().find((run) => run.run_id === runId) ?? null;
874
+ }
875
+ getJobEvents(runId) {
876
+ return this.getJob(runId)?.events ?? null;
877
+ }
878
+ getExecutorStatus() {
879
+ const checkedAt = new Date().toISOString();
880
+ try {
881
+ const resolved = resolveAgent();
882
+ const currentName = resolved.agent?.name ?? configuredAgentName();
883
+ const availableExecutors = detectedExecutorOptions(currentName);
884
+ if (!resolved.agent) {
885
+ return LocalExecutorStatusSchema.parse({
886
+ kind: "interf-local-executor-status",
887
+ version: 1,
888
+ status: "unavailable",
889
+ checked_at: checkedAt,
890
+ executor: null,
891
+ available_executors: availableExecutors,
892
+ message: resolved.error ?? "No supported local coding agent is configured.",
893
+ });
894
+ }
895
+ return LocalExecutorStatusSchema.parse({
896
+ kind: "interf-local-executor-status",
897
+ version: 1,
898
+ status: "connected",
899
+ checked_at: checkedAt,
900
+ executor: {
901
+ name: resolved.agent.name,
902
+ display_name: resolved.agent.displayName,
903
+ command: resolved.agent.command,
904
+ },
905
+ available_executors: availableExecutors.length > 0
906
+ ? availableExecutors
907
+ : [{
908
+ name: resolved.agent.name,
909
+ display_name: resolved.agent.displayName,
910
+ command: resolved.agent.command,
911
+ current: true,
912
+ }],
913
+ message: `${resolved.agent.displayName} is configured for local Interf actions.`,
914
+ });
915
+ }
916
+ catch (error) {
917
+ const currentName = configuredAgentName();
918
+ return LocalExecutorStatusSchema.parse({
919
+ kind: "interf-local-executor-status",
920
+ version: 1,
921
+ status: "unavailable",
922
+ checked_at: checkedAt,
923
+ executor: null,
924
+ available_executors: detectedExecutorOptions(currentName),
925
+ message: error instanceof Error ? error.message : String(error),
926
+ });
927
+ }
928
+ }
929
+ selectExecutor(requestValue) {
930
+ const request = LocalExecutorSelectRequestSchema.parse(requestValue);
931
+ const selected = detectAgents()
932
+ .filter(supportsAutomatedRuns)
933
+ .find((agent) => agent.name === request.agent);
934
+ if (!selected) {
935
+ throw new Error(`Local agent "${request.agent}" is not detected or cannot run Interf runs.`);
936
+ }
937
+ const current = loadUserConfig();
938
+ saveUserConfig({
939
+ agent: selected.name,
940
+ agentCommand: selected.command,
941
+ skillsInstalled: current?.skillsInstalled ?? false,
942
+ initialized: current?.initialized ?? new Date().toISOString(),
943
+ });
944
+ return this.getExecutorStatus();
945
+ }
946
+ listActionProposals() {
947
+ return newestActionProposalFirst(listJsonFiles(actionProposalsRoot(this.rootPath))
948
+ .map(readActionProposalAt)
949
+ .filter((proposal) => proposal !== null));
950
+ }
951
+ getActionProposal(proposalId) {
952
+ return this.listActionProposals().find((proposal) => proposal.proposal_id === proposalId) ?? null;
953
+ }
954
+ async createActionProposal(requestValue) {
955
+ const request = ActionProposalCreateRequestSchema.parse(requestValue);
956
+ const proposal = await this.buildActionProposal(request);
957
+ this.writeActionProposal(proposal);
958
+ return proposal;
959
+ }
960
+ async decideActionProposal(proposalId, requestValue) {
961
+ const decision = ActionProposalApprovalRequestSchema.parse(requestValue);
962
+ const current = this.getActionProposal(proposalId);
963
+ if (!current)
964
+ return null;
965
+ if (current.status !== "awaiting_approval") {
966
+ throw new Error(`Action proposal "${proposalId}" is already ${current.status}.`);
967
+ }
968
+ const now = new Date().toISOString();
969
+ const decided = ActionProposalResourceSchema.parse({
970
+ ...current,
971
+ status: decision.approved ? "approved" : "denied",
972
+ updated_at: now,
973
+ approval: {
974
+ approved: decision.approved,
975
+ decided_at: now,
976
+ ...(decision.note ? { note: decision.note } : {}),
977
+ },
978
+ });
979
+ this.writeActionProposal(decided);
980
+ if (!decision.approved)
981
+ return decided;
982
+ try {
983
+ const submission = await this.submitActionProposal(decided);
984
+ const submitted = ActionProposalResourceSchema.parse({
985
+ ...decided,
986
+ status: "submitted",
987
+ updated_at: new Date().toISOString(),
988
+ submitted_run_id: submission.runId,
989
+ submitted_run_type: submission.runType,
990
+ });
991
+ this.writeActionProposal(submitted);
992
+ return submitted;
993
+ }
994
+ catch (error) {
995
+ const failed = ActionProposalResourceSchema.parse({
996
+ ...decided,
997
+ status: "failed",
998
+ updated_at: new Date().toISOString(),
999
+ error: error instanceof Error ? error.message : String(error),
1000
+ });
1001
+ this.writeActionProposal(failed);
1002
+ return failed;
1003
+ }
1004
+ }
1005
+ listRunObservability() {
1006
+ return [
1007
+ ...this.listCompileRuns().map((resource) => compileRunToObservability(resource.run)),
1008
+ ...this.listTestRuns().map(testRunToObservability),
1009
+ ...this.listJobs().map(jobRunToObservability),
1010
+ ].sort((left, right) => {
1011
+ const leftTime = timestampKey(left.started_at ?? left.created_at ?? left.finished_at);
1012
+ const rightTime = timestampKey(right.started_at ?? right.created_at ?? right.finished_at);
1013
+ return rightTime - leftTime;
1014
+ });
1015
+ }
1016
+ getRunObservability(runId) {
1017
+ return this.listRunObservability().find((run) => run.run_id === runId) ?? null;
1018
+ }
1019
+ createJobRun(requestValue) {
1020
+ const request = LocalJobRunCreateRequestSchema.parse(requestValue);
1021
+ const runId = createRunId("job");
1022
+ const now = new Date().toISOString();
1023
+ const run = LocalJobRunResourceSchema.parse({
1024
+ kind: "interf-local-job-run",
1025
+ version: 1,
1026
+ run_id: runId,
1027
+ job_type: request.job_type,
1028
+ status: "running",
1029
+ title: request.title,
1030
+ ...(request.preparation !== undefined ? { preparation: request.preparation } : {}),
1031
+ ...(request.method !== undefined ? { method: request.method } : {}),
1032
+ ...(request.source_path !== undefined ? { source_path: request.source_path } : {}),
1033
+ ...(request.output_path !== undefined ? { output_path: request.output_path } : {}),
1034
+ ...(request.agent !== undefined ? { agent: request.agent } : {}),
1035
+ created_at: now,
1036
+ started_at: now,
1037
+ steps: request.steps.map((step) => ({
1038
+ ...step,
1039
+ status: "queued",
1040
+ })),
1041
+ events: [
1042
+ {
1043
+ type: "job.started",
1044
+ event_id: createRunEventId("event"),
1045
+ run_id: runId,
1046
+ timestamp: now,
1047
+ message: request.title,
1048
+ },
1049
+ ],
1050
+ });
1051
+ this.writeJobRun(run);
1052
+ return run;
1053
+ }
1054
+ appendJobRunEvent(runId, requestValue) {
1055
+ const request = LocalJobEventAppendRequestSchema.parse(requestValue);
1056
+ const current = this.getJob(runId);
1057
+ if (!current)
1058
+ return null;
1059
+ const event = {
1060
+ type: request.type,
1061
+ event_id: createRunEventId("event"),
1062
+ run_id: runId,
1063
+ timestamp: new Date().toISOString(),
1064
+ ...(request.step_id ? { step_id: request.step_id } : {}),
1065
+ ...(request.message ? { message: request.message } : {}),
1066
+ ...(request.artifact ? { artifact: request.artifact } : {}),
1067
+ ...(request.input ? { input: request.input } : {}),
1068
+ ...(request.output ? { output: request.output } : {}),
1069
+ };
1070
+ const next = LocalJobRunResourceSchema.parse(applyEventToLocalJob(current, event));
1071
+ this.writeJobRun(next);
1072
+ return next;
1073
+ }
1074
+ async createReadinessCheckDraftRun(requestValue) {
1075
+ const request = ReadinessCheckDraftCreateRequestSchema.parse(requestValue);
1076
+ const job = this.createJobRun({
1077
+ job_type: "readiness-check-draft",
1078
+ title: `Draft readiness checks for ${request.preparation}`,
1079
+ preparation: request.preparation,
1080
+ source_path: request.source_folder_path,
1081
+ steps: [
1082
+ {
1083
+ id: "read-source",
1084
+ label: "Read source files",
1085
+ input: {
1086
+ preparation: request.preparation,
1087
+ source_folder_path: request.source_folder_path,
1088
+ },
1089
+ },
1090
+ {
1091
+ id: "agent-draft",
1092
+ label: "Draft readiness checks",
1093
+ input: {
1094
+ about: request.about ?? null,
1095
+ target_count: request.target_count,
1096
+ },
1097
+ },
1098
+ {
1099
+ id: "normalize-checks",
1100
+ label: "Normalize saved readiness checks",
1101
+ },
1102
+ ],
1103
+ });
1104
+ this.appendJobRunEvent(job.run_id, {
1105
+ type: "step.started",
1106
+ step_id: "read-source",
1107
+ message: "Reading source files for readiness-check evidence.",
1108
+ input: {
1109
+ preparation: request.preparation,
1110
+ source_folder_path: request.source_folder_path,
1111
+ },
1112
+ });
1113
+ this.appendJobRunEvent(job.run_id, {
1114
+ type: "step.completed",
1115
+ step_id: "read-source",
1116
+ message: "Source folder is ready for readiness-check drafting.",
1117
+ output: {
1118
+ preparation: request.preparation,
1119
+ source_folder_path: request.source_folder_path,
1120
+ },
1121
+ });
1122
+ this.appendJobRunEvent(job.run_id, {
1123
+ type: "step.started",
1124
+ step_id: "agent-draft",
1125
+ message: "Drafting saved readiness checks from the source files.",
1126
+ input: {
1127
+ about: request.about ?? null,
1128
+ target_count: request.target_count,
1129
+ },
1130
+ });
1131
+ void this.runReadinessCheckDraftInBackground(request, job.run_id);
1132
+ return this.getJob(job.run_id) ?? job;
1133
+ }
1134
+ async createPreparationSetupRun(requestValue) {
1135
+ const request = PreparationSetupCreateRequestSchema.parse(requestValue);
1136
+ const preparationConfig = request.preparation;
1137
+ const methodId = methodIdForSourcePreparationConfig(preparationConfig) ?? "interf-default";
1138
+ const normalizedPreparationConfig = {
1139
+ ...preparationConfig,
1140
+ method: methodId,
1141
+ };
1142
+ const sourceFolderPath = resolveSourcePreparationPath(this.rootPath, preparationConfig);
1143
+ const outputPath = portableContextPath(this.rootPath, preparationConfig.name);
1144
+ const job = this.createJobRun({
1145
+ job_type: "preparation-setup",
1146
+ title: `Create Preparation ${preparationConfig.name}`,
1147
+ preparation: preparationConfig.name,
1148
+ method: methodId,
1149
+ source_path: sourceFolderPath,
1150
+ output_path: outputPath,
1151
+ agent: this.getExecutorStatus().executor,
1152
+ steps: [
1153
+ {
1154
+ id: "validate-source",
1155
+ label: "Validate source folder",
1156
+ input: {
1157
+ preparation: preparationConfig.name,
1158
+ path: preparationConfig.path,
1159
+ },
1160
+ },
1161
+ {
1162
+ id: "write-config",
1163
+ label: "Save Preparation config",
1164
+ input: {
1165
+ config_path: join(this.rootPath, "interf", "interf.json"),
1166
+ },
1167
+ },
1168
+ {
1169
+ id: "prepare-scaffold",
1170
+ label: "Prepare portable context",
1171
+ input: {
1172
+ output_path: outputPath,
1173
+ method: methodId,
1174
+ },
1175
+ },
1176
+ ],
1177
+ });
1178
+ let activeStep = "validate-source";
1179
+ try {
1180
+ this.appendJobRunEvent(job.run_id, {
1181
+ type: "step.started",
1182
+ step_id: "validate-source",
1183
+ message: "Validating source folder.",
1184
+ input: {
1185
+ path: preparationConfig.path,
1186
+ source_folder_path: sourceFolderPath,
1187
+ },
1188
+ });
1189
+ if (!existsSync(sourceFolderPath) || !statSync(sourceFolderPath).isDirectory()) {
1190
+ throw new Error(`Source folder "${preparationConfig.path}" is not available.`);
1191
+ }
1192
+ this.appendJobRunEvent(job.run_id, {
1193
+ type: "step.completed",
1194
+ step_id: "validate-source",
1195
+ message: "Source folder is available.",
1196
+ output: {
1197
+ source_folder_path: sourceFolderPath,
1198
+ },
1199
+ });
1200
+ activeStep = "write-config";
1201
+ this.appendJobRunEvent(job.run_id, {
1202
+ type: "step.started",
1203
+ step_id: "write-config",
1204
+ message: "Saving Preparation in the control plane config.",
1205
+ input: {
1206
+ preparation: preparationConfig.name,
1207
+ path: preparationConfig.path,
1208
+ },
1209
+ });
1210
+ upsertSourcePreparationConfig(this.rootPath, normalizedPreparationConfig);
1211
+ this.appendJobRunEvent(job.run_id, {
1212
+ type: "step.completed",
1213
+ step_id: "write-config",
1214
+ message: "Preparation config saved.",
1215
+ output: {
1216
+ config_path: join(this.rootPath, "interf", "interf.json"),
1217
+ preparation: preparationConfig.name,
1218
+ },
1219
+ });
1220
+ activeStep = "prepare-scaffold";
1221
+ this.appendJobRunEvent(job.run_id, {
1222
+ type: "step.started",
1223
+ step_id: "prepare-scaffold",
1224
+ message: "Preparing portable-context scaffold.",
1225
+ input: {
1226
+ output_path: outputPath,
1227
+ method: methodId,
1228
+ },
1229
+ });
1230
+ const compiledPath = ensurePortableContextScaffold(this.rootPath, normalizedPreparationConfig.name, methodId);
1231
+ syncCompiledInterfConfigFromSourcePreparationConfig(compiledPath, normalizedPreparationConfig);
1232
+ this.appendJobRunEvent(job.run_id, {
1233
+ type: "step.completed",
1234
+ step_id: "prepare-scaffold",
1235
+ message: "Portable-context scaffold is ready.",
1236
+ output: {
1237
+ portable_context_path: compiledPath,
1238
+ },
1239
+ });
1240
+ this.setJobRunResult(job.run_id, {
1241
+ preparation: normalizedPreparationConfig,
1242
+ source_folder_path: sourceFolderPath,
1243
+ portable_context_path: compiledPath,
1244
+ });
1245
+ this.appendJobRunEvent(job.run_id, {
1246
+ type: "job.completed",
1247
+ message: `Preparation ${preparationConfig.name} is ready for Interf runs.`,
1248
+ });
1249
+ }
1250
+ catch (error) {
1251
+ const message = error instanceof Error ? error.message : String(error);
1252
+ this.appendJobRunEvent(job.run_id, {
1253
+ type: "step.failed",
1254
+ step_id: activeStep,
1255
+ message,
1256
+ output: {
1257
+ error: message,
1258
+ },
1259
+ });
1260
+ this.appendJobRunEvent(job.run_id, {
1261
+ type: "job.failed",
1262
+ message,
1263
+ });
1264
+ }
1265
+ return this.getJob(job.run_id) ?? job;
1266
+ }
1267
+ async createMethodAuthoringRun(requestValue) {
1268
+ const request = MethodAuthoringCreateRequestSchema.parse(requestValue);
1269
+ const job = this.createJobRun({
1270
+ job_type: "method-authoring",
1271
+ title: `Draft Method ${request.method_id}`,
1272
+ preparation: request.preparation ?? null,
1273
+ method: request.method_id,
1274
+ source_path: request.source_folder_path,
1275
+ output_path: join(this.rootPath, "interf", "methods", request.method_id),
1276
+ steps: [
1277
+ {
1278
+ id: "inspect-source",
1279
+ label: "Inspect source files",
1280
+ input: {
1281
+ preparation: request.preparation ?? null,
1282
+ source_folder_path: request.source_folder_path,
1283
+ checks: request.checks.length,
1284
+ },
1285
+ },
1286
+ {
1287
+ id: "draft-package",
1288
+ label: "Draft Method package",
1289
+ input: {
1290
+ method_id: request.method_id,
1291
+ label: request.label,
1292
+ task_prompt: request.task_prompt,
1293
+ },
1294
+ },
1295
+ {
1296
+ id: "validate-package",
1297
+ label: "Validate Method package",
1298
+ input: {
1299
+ method_id: request.method_id,
1300
+ },
1301
+ },
1302
+ ],
1303
+ });
1304
+ this.appendJobRunEvent(job.run_id, {
1305
+ type: "step.started",
1306
+ step_id: "inspect-source",
1307
+ message: "Inspecting source files for Method drafting.",
1308
+ input: {
1309
+ preparation: request.preparation ?? null,
1310
+ source_folder_path: request.source_folder_path,
1311
+ checks: request.checks.length,
1312
+ },
1313
+ });
1314
+ this.appendJobRunEvent(job.run_id, {
1315
+ type: "step.completed",
1316
+ step_id: "inspect-source",
1317
+ message: "Source context is ready.",
1318
+ output: {
1319
+ source_folder_path: request.source_folder_path,
1320
+ checks: request.checks.length,
1321
+ },
1322
+ });
1323
+ this.appendJobRunEvent(job.run_id, {
1324
+ type: "step.started",
1325
+ step_id: "draft-package",
1326
+ message: "Drafting Method package.",
1327
+ input: {
1328
+ method_id: request.method_id,
1329
+ label: request.label,
1330
+ task_prompt: request.task_prompt,
1331
+ },
1332
+ });
1333
+ void this.runMethodAuthoringInBackground(request, job.run_id);
1334
+ return this.getJob(job.run_id) ?? job;
1335
+ }
1336
+ listPortableContexts() {
1337
+ return listSourcePreparationConfigs(loadSourceFolderConfig(this.rootPath))
1338
+ .map((preparation) => this.getPortableContext(preparation.name))
1339
+ .filter((context) => context !== null);
1340
+ }
1341
+ getPortableContext(preparationName) {
1342
+ const preparation = findSourcePreparationConfig(loadSourceFolderConfig(this.rootPath), preparationName);
1343
+ if (!preparation)
1344
+ return null;
1345
+ const path = portableContextPath(this.rootPath, preparation.name);
1346
+ const config = readInterfConfig(path);
1347
+ const compileRuns = this.listCompileRunsForPreparation(preparation.name);
1348
+ const testRuns = this.listTestRunsForPreparation(preparation.name);
1349
+ const readiness = this.computePreparationReadiness(preparation);
1350
+ const method = config?.method ?? methodIdForSourcePreparationConfig(preparation);
1351
+ return PortableContextResourceSchema.parse({
1352
+ preparation: preparation.name,
1353
+ path,
1354
+ exists: existsSync(path),
1355
+ readiness,
1356
+ method,
1357
+ latest_compile_run_id: compileRuns[0]?.run_id ?? null,
1358
+ latest_test_run_id: testRuns[0]?.run_id ?? null,
1359
+ artifacts: uniqueArtifacts(compileRuns[0]?.stages.flatMap((stage) => stage.artifacts) ?? []),
1360
+ });
1361
+ }
1362
+ listCompileRuns() {
1363
+ return newestCompileFirst(listSourcePreparationConfigs(loadSourceFolderConfig(this.rootPath))
1364
+ .flatMap((preparation) => this.listCompileRunsForPreparation(preparation.name))).map((run) => CompileRunResourceSchema.parse({ run }));
1365
+ }
1366
+ listCompileRunsForPreparation(preparationName) {
1367
+ const compiledPath = portableContextPath(this.rootPath, preparationName);
1368
+ return newestCompileFirst(listJsonFiles(compileRunsRoot(compiledPath))
1369
+ .map(readCompileRunAt)
1370
+ .filter((run) => run !== null));
1371
+ }
1372
+ getCompileRun(runId) {
1373
+ for (const resource of this.listCompileRuns()) {
1374
+ if (resource.run.run_id === runId)
1375
+ return resource;
1376
+ }
1377
+ return null;
1378
+ }
1379
+ getCompileRunEvents(runId) {
1380
+ return this.getCompileRun(runId)?.run.events ?? null;
1381
+ }
1382
+ getCompileRunProof(runId) {
1383
+ const run = this.getCompileRun(runId)?.run;
1384
+ if (!run)
1385
+ return null;
1386
+ return run.stages
1387
+ .map((stage) => stage.latest_proof ?? null)
1388
+ .filter((proof) => proof !== null);
1389
+ }
1390
+ getCompileRunArtifacts(runId) {
1391
+ const run = this.getCompileRun(runId)?.run;
1392
+ if (!run)
1393
+ return null;
1394
+ return uniqueArtifacts(run.stages.flatMap((stage) => stage.artifacts));
1395
+ }
1396
+ async createCompileRun(requestValue) {
1397
+ const request = CompileRunCreateRequestSchema.parse(requestValue);
1398
+ const preparationConfig = this.resolvePreparationConfig(request.preparation, {
1399
+ method: request.method,
1400
+ max_attempts: request.max_attempts,
1401
+ max_loops: request.max_loops,
1402
+ });
1403
+ const compiledPath = this.ensureCompiledForRun(preparationConfig);
1404
+ const runId = createRunId("compile");
1405
+ const now = new Date().toISOString();
1406
+ const method = getCompiledMethod(methodIdForSourcePreparationConfig(preparationConfig) ?? DEFAULT_METHOD_ID, {
1407
+ sourcePath: this.rootPath,
1408
+ });
1409
+ const stageTotal = method.stages.length;
1410
+ const run = CompileRunSchema.parse({
1411
+ kind: "interf-compile-run",
1412
+ version: 1,
1413
+ run_id: runId,
1414
+ status: "running",
1415
+ preparation: preparationConfig.name,
1416
+ method: method.id,
1417
+ backend: "native",
1418
+ source_path: resolveSourcePreparationPath(this.rootPath, preparationConfig),
1419
+ portable_context_path: compiledPath,
1420
+ created_at: now,
1421
+ started_at: now,
1422
+ stages: method.stages
1423
+ .map((stage, index) => {
1424
+ return {
1425
+ run_id: runId,
1426
+ stage_id: stage.id,
1427
+ stage_label: stage.label,
1428
+ stage_index: index,
1429
+ stage_total: stageTotal,
1430
+ status: "queued",
1431
+ contract: {
1432
+ stage_label: stage.label,
1433
+ stage_index: index,
1434
+ stage_total: stageTotal,
1435
+ reads: stage.reads,
1436
+ writes: stage.writes,
1437
+ ...(stage.acceptance ? { acceptance: stage.acceptance } : {}),
1438
+ },
1439
+ artifacts: [],
1440
+ };
1441
+ }),
1442
+ events: [],
1443
+ });
1444
+ this.writeCompileRun(compiledPath, run);
1445
+ await this.recordCompileRunEvent(compiledPath, runId, {
1446
+ type: "run.started",
1447
+ event_id: createRunEventId("event"),
1448
+ run_id: runId,
1449
+ timestamp: now,
1450
+ preparation: preparationConfig.name,
1451
+ method: method.id,
1452
+ portable_context_path: compiledPath,
1453
+ backend: "native",
1454
+ });
1455
+ const sink = {
1456
+ emit: (event) => this.recordCompileRunEvent(compiledPath, runId, event),
1457
+ };
1458
+ void this.runCompileInBackground(request, {
1459
+ runId,
1460
+ sourcePath: this.rootPath,
1461
+ compiledPath,
1462
+ preparationConfig,
1463
+ events: sink,
1464
+ });
1465
+ const saved = this.readCompileRun(compiledPath, runId) ?? run;
1466
+ return CompileRunResourceSchema.parse({ run: saved });
1467
+ }
1468
+ listTestRuns() {
1469
+ return newestFirst(listSourcePreparationConfigs(loadSourceFolderConfig(this.rootPath))
1470
+ .flatMap((preparation) => this.listTestRunsForPreparation(preparation.name)));
1471
+ }
1472
+ listTestRunsForPreparation(preparationName) {
1473
+ const compiledPath = portableContextPath(this.rootPath, preparationName);
1474
+ return newestFirst(listJsonFiles(testRunsRoot(compiledPath))
1475
+ .map(readTestRunAt)
1476
+ .filter((run) => run !== null));
1477
+ }
1478
+ getTestRun(runId) {
1479
+ return this.listTestRuns().find((run) => run.run_id === runId) ?? null;
1480
+ }
1481
+ async createTestRun(requestValue) {
1482
+ const request = TestRunCreateRequestSchema.parse(requestValue);
1483
+ const preparationConfig = this.resolvePreparationConfig(request.preparation);
1484
+ const compiledPath = portableContextPath(this.rootPath, preparationConfig.name);
1485
+ const compiledTarget = createCompiledTestTarget(compiledPath, preparationConfig.name, methodIdForSourcePreparationConfig(preparationConfig) ?? DEFAULT_METHOD_ID);
1486
+ const runId = createRunId("test");
1487
+ const now = new Date().toISOString();
1488
+ const initial = TestRunResourceSchema.parse({
1489
+ run_id: runId,
1490
+ status: "running",
1491
+ preparation: preparationConfig.name,
1492
+ mode: request.mode,
1493
+ source_path: this.rootPath,
1494
+ portable_context_path: compiledTarget.eligible ? compiledPath : null,
1495
+ started_at: now,
1496
+ comparison: null,
1497
+ events: [],
1498
+ });
1499
+ this.writeTestRun(compiledPath, initial);
1500
+ void this.runTestInBackground(request, {
1501
+ runId,
1502
+ sourcePath: this.rootPath,
1503
+ compiledPath,
1504
+ preparationConfig,
1505
+ }, initial);
1506
+ return initial;
1507
+ }
1508
+ async runCompileInBackground(request, context) {
1509
+ try {
1510
+ if (!this.handlers.createCompileRun) {
1511
+ throw new Error("No compile-run handler is configured for this local service.");
1512
+ }
1513
+ const result = LocalRunHandlerResultSchema.parse(await this.handlers.createCompileRun(request, context));
1514
+ this.refreshCompileRunFromRuntime(context.compiledPath, context.runId);
1515
+ await this.emitRuntimeDerivedEvents(context.compiledPath, context.runId);
1516
+ if (!result.ok) {
1517
+ await this.recordCompileRunEvent(context.compiledPath, context.runId, {
1518
+ type: "run.failed",
1519
+ event_id: createRunEventId("event"),
1520
+ run_id: context.runId,
1521
+ timestamp: createRunEventTimestamp(),
1522
+ error: result.error ?? "Compile run failed.",
1523
+ });
1524
+ }
1525
+ else {
1526
+ await this.recordCompileRunEvent(context.compiledPath, context.runId, {
1527
+ type: "run.completed",
1528
+ event_id: createRunEventId("event"),
1529
+ run_id: context.runId,
1530
+ timestamp: createRunEventTimestamp(),
1531
+ summary: "Portable context ready.",
1532
+ });
1533
+ }
1534
+ }
1535
+ catch (error) {
1536
+ await this.recordCompileRunEvent(context.compiledPath, context.runId, {
1537
+ type: "run.failed",
1538
+ event_id: createRunEventId("event"),
1539
+ run_id: context.runId,
1540
+ timestamp: createRunEventTimestamp(),
1541
+ error: error instanceof Error ? error.message : String(error),
1542
+ });
1543
+ }
1544
+ }
1545
+ async runTestInBackground(request, context, initial) {
1546
+ try {
1547
+ if (!this.handlers.createTestRun) {
1548
+ throw new Error("No test-run handler is configured for this local service.");
1549
+ }
1550
+ const result = LocalRunHandlerResultSchema.parse(await this.handlers.createTestRun(request, context));
1551
+ const comparison = result.comparison ?? this.readLatestComparison(context.preparationConfig.name);
1552
+ const resultEvent = comparison
1553
+ ? this.checksEvaluatedEvent(context.runId, comparison)
1554
+ : null;
1555
+ const nextWithoutReadiness = TestRunResourceSchema.parse({
1556
+ ...initial,
1557
+ status: result.ok ? "succeeded" : "failed",
1558
+ finished_at: new Date().toISOString(),
1559
+ comparison,
1560
+ events: resultEvent ? [resultEvent] : [],
1561
+ ...(!result.ok ? { error: result.error ?? "Readiness check failed." } : {}),
1562
+ });
1563
+ this.writeTestRun(context.compiledPath, nextWithoutReadiness);
1564
+ const readiness = this.computePreparationReadiness(context.preparationConfig);
1565
+ const next = TestRunResourceSchema.parse({
1566
+ ...nextWithoutReadiness,
1567
+ readiness,
1568
+ events: [
1569
+ ...nextWithoutReadiness.events,
1570
+ this.readinessUpdatedEvent(context.runId, context.preparationConfig.name, readiness),
1571
+ ],
1572
+ });
1573
+ this.writeTestRun(context.compiledPath, next);
1574
+ }
1575
+ catch (error) {
1576
+ const failedWithoutReadiness = TestRunResourceSchema.parse({
1577
+ ...initial,
1578
+ status: "failed",
1579
+ finished_at: new Date().toISOString(),
1580
+ error: error instanceof Error ? error.message : String(error),
1581
+ });
1582
+ this.writeTestRun(context.compiledPath, failedWithoutReadiness);
1583
+ const readiness = this.computePreparationReadiness(context.preparationConfig);
1584
+ const next = TestRunResourceSchema.parse({
1585
+ ...failedWithoutReadiness,
1586
+ readiness,
1587
+ events: [this.readinessUpdatedEvent(context.runId, context.preparationConfig.name, readiness)],
1588
+ });
1589
+ this.writeTestRun(context.compiledPath, next);
1590
+ }
1591
+ }
1592
+ async runReadinessCheckDraftInBackground(request, runId) {
1593
+ try {
1594
+ if (!this.handlers.createReadinessCheckDraft) {
1595
+ throw new Error("No readiness-check-draft handler is configured for this local service.");
1596
+ }
1597
+ const result = ReadinessCheckDraftResultSchema.parse(await this.handlers.createReadinessCheckDraft(request, this.jobRunContext(runId)));
1598
+ this.appendJobRunEvent(runId, {
1599
+ type: "step.completed",
1600
+ step_id: "agent-draft",
1601
+ message: `Drafted ${result.checks.length} readiness checks.`,
1602
+ output: {
1603
+ checks: result.checks,
1604
+ },
1605
+ });
1606
+ this.appendJobRunEvent(runId, {
1607
+ type: "step.started",
1608
+ step_id: "normalize-checks",
1609
+ message: "Normalizing readiness-check draft into saved check records.",
1610
+ input: {
1611
+ checks: result.checks.length,
1612
+ },
1613
+ });
1614
+ this.appendJobRunEvent(runId, {
1615
+ type: "step.completed",
1616
+ step_id: "normalize-checks",
1617
+ message: `${result.checks.length} readiness checks ready for review.`,
1618
+ output: {
1619
+ checks: result.checks.length,
1620
+ },
1621
+ });
1622
+ this.setJobRunResult(runId, result);
1623
+ this.appendJobRunEvent(runId, {
1624
+ type: "job.completed",
1625
+ message: `Drafted ${result.checks.length} readiness checks.`,
1626
+ });
1627
+ }
1628
+ catch (error) {
1629
+ const message = error instanceof Error ? error.message : String(error);
1630
+ this.appendJobRunEvent(runId, {
1631
+ type: "step.failed",
1632
+ step_id: "agent-draft",
1633
+ message,
1634
+ output: {
1635
+ error: message,
1636
+ },
1637
+ });
1638
+ this.appendJobRunEvent(runId, {
1639
+ type: "job.failed",
1640
+ message,
1641
+ });
1642
+ }
1643
+ }
1644
+ async runMethodAuthoringInBackground(request, runId) {
1645
+ try {
1646
+ if (!this.handlers.createMethodAuthoringRun) {
1647
+ throw new Error("No Method-authoring handler is configured for this local service.");
1648
+ }
1649
+ const result = MethodAuthoringResultSchema.parse(await this.handlers.createMethodAuthoringRun(request, this.jobRunContext(runId)));
1650
+ this.setJobRunResult(runId, result);
1651
+ this.appendJobRunEvent(runId, {
1652
+ type: result.status === "executor-failed" ? "step.failed" : "step.completed",
1653
+ step_id: "draft-package",
1654
+ message: result.summary,
1655
+ output: {
1656
+ status: result.status,
1657
+ changed: result.changed,
1658
+ method_path: result.method_path,
1659
+ shell_path: result.shell_path,
1660
+ },
1661
+ });
1662
+ this.appendJobRunEvent(runId, {
1663
+ type: "step.started",
1664
+ step_id: "validate-package",
1665
+ message: "Validating Method package structure and stage contract.",
1666
+ input: {
1667
+ method_path: result.method_path,
1668
+ },
1669
+ });
1670
+ if (result.status === "updated" || result.status === "no-change") {
1671
+ this.appendJobRunEvent(runId, {
1672
+ type: "step.completed",
1673
+ step_id: "validate-package",
1674
+ message: result.summary,
1675
+ output: {
1676
+ status: result.status,
1677
+ validation: result.validation ?? null,
1678
+ },
1679
+ });
1680
+ this.appendJobRunEvent(runId, {
1681
+ type: "job.completed",
1682
+ message: result.summary,
1683
+ });
1684
+ }
1685
+ else {
1686
+ this.appendJobRunEvent(runId, {
1687
+ type: "step.failed",
1688
+ step_id: "validate-package",
1689
+ message: result.summary,
1690
+ output: {
1691
+ status: result.status,
1692
+ validation: result.validation ?? null,
1693
+ },
1694
+ });
1695
+ this.appendJobRunEvent(runId, {
1696
+ type: "job.failed",
1697
+ message: result.summary,
1698
+ });
1699
+ }
1700
+ }
1701
+ catch (error) {
1702
+ const message = error instanceof Error ? error.message : String(error);
1703
+ this.appendJobRunEvent(runId, {
1704
+ type: "step.failed",
1705
+ step_id: "draft-package",
1706
+ message,
1707
+ output: {
1708
+ error: message,
1709
+ },
1710
+ });
1711
+ this.appendJobRunEvent(runId, {
1712
+ type: "job.failed",
1713
+ message,
1714
+ });
1715
+ }
1716
+ }
1717
+ jobRunContext(runId) {
1718
+ return {
1719
+ runId,
1720
+ sourcePath: this.rootPath,
1721
+ emit: (event) => {
1722
+ this.appendJobRunEvent(runId, event);
1723
+ },
1724
+ };
1725
+ }
1726
+ defaultPreparationName() {
1727
+ const preparation = listSourcePreparationConfigs(loadSourceFolderConfig(this.rootPath))[0];
1728
+ if (!preparation) {
1729
+ throw new Error("No Preparation is saved in this control plane folder.");
1730
+ }
1731
+ return preparation.name;
1732
+ }
1733
+ async planActionProposal(request) {
1734
+ if (!this.handlers.planActionProposal) {
1735
+ return ActionProposalPlanSchema.parse({
1736
+ action_type: "clarification",
1737
+ ...(request.preparation ? { preparation: request.preparation } : {}),
1738
+ assistant_message: "No local action planner is configured for this Interf Workspace.",
1739
+ });
1740
+ }
1741
+ const preparations = listSourcePreparationConfigs(loadSourceFolderConfig(this.rootPath));
1742
+ let rawPlan;
1743
+ try {
1744
+ rawPlan = await this.handlers.planActionProposal(request, {
1745
+ sourcePath: this.rootPath,
1746
+ preparations,
1747
+ preparationHealth: preparations.map((preparation) => {
1748
+ const readinessChecks = preparation.checks?.length ?? 0;
1749
+ const portableContextReady = hasCompiledTestTarget(this.rootPath, preparation);
1750
+ return {
1751
+ name: preparation.name,
1752
+ readiness_checks: readinessChecks,
1753
+ portable_context_ready: portableContextReady,
1754
+ can_check_readiness: readinessChecks > 0 && portableContextReady,
1755
+ recommended_next_actions: portableContextReady
1756
+ ? readinessChecks > 0
1757
+ ? ["check readiness", "improve", "prepare again"]
1758
+ : ["draft readiness checks", "prepare again"]
1759
+ : ["prepare"],
1760
+ };
1761
+ }),
1762
+ sourceFolders: listSourceFolderChoices(this.rootPath),
1763
+ recentProposals: this.listActionProposals().slice(0, 5),
1764
+ });
1765
+ }
1766
+ catch {
1767
+ return ActionProposalPlanSchema.parse({
1768
+ action_type: "clarification",
1769
+ ...(request.preparation ? { preparation: request.preparation } : {}),
1770
+ assistant_message: ACTION_PLANNER_CLARIFICATION_MESSAGE,
1771
+ });
1772
+ }
1773
+ const parsed = ActionProposalPlanSchema.safeParse(sanitizeActionProposalPlan(rawPlan));
1774
+ if (parsed.success)
1775
+ return parsed.data;
1776
+ return ActionProposalPlanSchema.parse({
1777
+ action_type: "clarification",
1778
+ ...(request.preparation ? { preparation: request.preparation } : {}),
1779
+ assistant_message: ACTION_PLANNER_CLARIFICATION_MESSAGE,
1780
+ });
1781
+ }
1782
+ buildPreparationSetupRequest(request, plan, values) {
1783
+ const sourceFolderChoices = listSourceFolderChoices(this.rootPath);
1784
+ const selectedPath = preparationSetupPathValue(values) ??
1785
+ (sourceFolderChoices.length === 1 ? sourceFolderChoices[0].value : null);
1786
+ if (!selectedPath) {
1787
+ return {
1788
+ error: "Tell Interf which source folder to use for the Preparation.",
1789
+ };
1790
+ }
1791
+ let normalizedPath;
1792
+ try {
1793
+ normalizedPath = normalizeSourcePreparationPathForConfig(this.rootPath, selectedPath);
1794
+ }
1795
+ catch (error) {
1796
+ return {
1797
+ error: error instanceof Error ? error.message : String(error),
1798
+ };
1799
+ }
1800
+ const explicitName = preparationSetupNameValue(values) ?? plan.preparation ?? request.preparation;
1801
+ const preparationName = explicitName
1802
+ ? slugFromText(explicitName)
1803
+ : defaultPreparationNameForPath(normalizedPath);
1804
+ const requestMethodId = stringValue(request.values, "method");
1805
+ const valueMethodId = stringValue(values, "method");
1806
+ const methodId = requestMethodId ?? plan.method ?? valueMethodId ?? "interf-default";
1807
+ try {
1808
+ return {
1809
+ preparationName,
1810
+ methodId,
1811
+ request: PreparationSetupCreateRequestSchema.parse({
1812
+ preparation: {
1813
+ name: preparationName,
1814
+ path: normalizedPath,
1815
+ about: stringValue(values, "about") ?? stringValue(values, "task_prompt") ?? request.message,
1816
+ method: methodId,
1817
+ checks: [],
1818
+ },
1819
+ }),
1820
+ };
1821
+ }
1822
+ catch (error) {
1823
+ return {
1824
+ error: error instanceof Error ? error.message : String(error),
1825
+ };
1826
+ }
1827
+ }
1828
+ async buildActionProposal(request) {
1829
+ const plan = await this.planActionProposal(request);
1830
+ const actionType = plan.action_type;
1831
+ const now = new Date().toISOString();
1832
+ if (actionType === "clarification") {
1833
+ return ActionProposalResourceSchema.parse({
1834
+ kind: "interf-action-proposal",
1835
+ version: 1,
1836
+ proposal_id: createActionProposalId(),
1837
+ status: "needs_clarification",
1838
+ action_type: actionType,
1839
+ title: plan.title ?? "Clarify Interf action",
1840
+ summary: plan.summary ?? "No local run was proposed because the request did not resolve to a confirmed Interf action.",
1841
+ assistant_message: plan.assistant_message ?? ACTION_PLANNER_CLARIFICATION_MESSAGE,
1842
+ ...(plan.command_preview ? { command_preview: plan.command_preview } : {}),
1843
+ message: request.message,
1844
+ preparation: plan.preparation ?? request.preparation ?? null,
1845
+ method: plan.method ?? null,
1846
+ request: {
1847
+ message: request.message,
1848
+ ...(plan.values ? { values: plan.values } : {}),
1849
+ },
1850
+ created_at: now,
1851
+ updated_at: now,
1852
+ proposed_by_executor: this.getExecutorStatus().executor,
1853
+ approval: null,
1854
+ submitted_run_id: null,
1855
+ submitted_run_type: null,
1856
+ error: null,
1857
+ });
1858
+ }
1859
+ const proposalValues = {
1860
+ ...(plan.values ?? {}),
1861
+ ...(request.values ?? {}),
1862
+ };
1863
+ if (actionType === "preparation-setup") {
1864
+ const setup = this.buildPreparationSetupRequest(request, plan, proposalValues);
1865
+ if ("error" in setup) {
1866
+ return ActionProposalResourceSchema.parse({
1867
+ kind: "interf-action-proposal",
1868
+ version: 1,
1869
+ proposal_id: createActionProposalId(),
1870
+ status: "needs_clarification",
1871
+ action_type: "clarification",
1872
+ title: "Clarify Preparation setup",
1873
+ summary: "Interf needs a source folder before it can save a Preparation.",
1874
+ assistant_message: setup.error,
1875
+ message: request.message,
1876
+ preparation: plan.preparation ?? request.preparation ?? null,
1877
+ method: plan.method ?? null,
1878
+ request: {
1879
+ message: request.message,
1880
+ ...(proposalValues ? { values: proposalValues } : {}),
1881
+ },
1882
+ created_at: now,
1883
+ updated_at: now,
1884
+ proposed_by_executor: this.getExecutorStatus().executor,
1885
+ approval: null,
1886
+ submitted_run_id: null,
1887
+ submitted_run_type: null,
1888
+ error: null,
1889
+ });
1890
+ }
1891
+ const commandPreview = plan.command_preview ??
1892
+ actionCommandPreview(actionType, setup.preparationName, setup.methodId, {
1893
+ ...proposalValues,
1894
+ path: setup.request.preparation.path,
1895
+ });
1896
+ return ActionProposalResourceSchema.parse({
1897
+ kind: "interf-action-proposal",
1898
+ version: 1,
1899
+ proposal_id: createActionProposalId(),
1900
+ status: "awaiting_approval",
1901
+ action_type: actionType,
1902
+ title: plan.title ?? `Create Preparation ${setup.preparationName}`,
1903
+ summary: plan.summary ?? "Save this source folder as an Interf Preparation.",
1904
+ assistant_message: plan.assistant_message ?? actionAssistantMessage(actionType, setup.preparationName, commandPreview),
1905
+ command_preview: commandPreview,
1906
+ message: request.message,
1907
+ preparation: setup.preparationName,
1908
+ method: setup.methodId,
1909
+ request: setup.request,
1910
+ created_at: now,
1911
+ updated_at: now,
1912
+ proposed_by_executor: this.getExecutorStatus().executor,
1913
+ approval: null,
1914
+ submitted_run_id: null,
1915
+ submitted_run_type: null,
1916
+ error: null,
1917
+ });
1918
+ }
1919
+ const preparationConfig = this.resolvePreparationConfig(plan.preparation ?? request.preparation ?? this.defaultPreparationName());
1920
+ const preparationPath = resolveSourcePreparationPath(this.rootPath, preparationConfig);
1921
+ const requestedMethodId = stringValue(request.values, "method_id") ??
1922
+ stringValue(request.values, "method");
1923
+ const plannedMethodId = plan.method ??
1924
+ stringValue(plan.values, "method_id") ??
1925
+ stringValue(plan.values, "method");
1926
+ const methodId = actionType === "method-authoring"
1927
+ ? requestedMethodId ?? plannedMethodId ?? methodIdForProposal(request.message, proposalValues)
1928
+ : requestedMethodId ?? plannedMethodId ?? methodIdForSourcePreparationConfig(preparationConfig);
1929
+ const clarifyResolvedAction = (options) => ActionProposalResourceSchema.parse({
1930
+ kind: "interf-action-proposal",
1931
+ version: 1,
1932
+ proposal_id: createActionProposalId(),
1933
+ status: "needs_clarification",
1934
+ action_type: "clarification",
1935
+ title: options.title,
1936
+ summary: options.summary,
1937
+ assistant_message: options.assistantMessage,
1938
+ message: request.message,
1939
+ preparation: preparationConfig.name,
1940
+ method: methodId ?? null,
1941
+ request: {
1942
+ message: request.message,
1943
+ ...(proposalValues ? { values: proposalValues } : {}),
1944
+ },
1945
+ created_at: now,
1946
+ updated_at: now,
1947
+ proposed_by_executor: this.getExecutorStatus().executor,
1948
+ approval: null,
1949
+ submitted_run_id: null,
1950
+ submitted_run_type: null,
1951
+ error: null,
1952
+ });
1953
+ if (actionType === "test") {
1954
+ const requestedMode = testModeFromValues(proposalValues);
1955
+ const hasReadinessChecks = (preparationConfig.checks ?? []).length > 0;
1956
+ const portableContextReady = hasCompiledTestTarget(this.rootPath, preparationConfig);
1957
+ if (!hasReadinessChecks) {
1958
+ return clarifyResolvedAction({
1959
+ title: `Add readiness checks for ${preparationConfig.name}`,
1960
+ summary: "Readiness cannot be checked until this Preparation has saved checks.",
1961
+ assistantMessage: `Preparation "${preparationConfig.name}" does not have saved readiness checks yet. Ask me to draft readiness checks after the Source Folder is prepared, or add readiness guidance first.`,
1962
+ });
1963
+ }
1964
+ if (!portableContextReady && requestedMode !== "raw") {
1965
+ return clarifyResolvedAction({
1966
+ title: `Prepare ${preparationConfig.name} first`,
1967
+ summary: "Readiness checks need portable context unless you explicitly ask for a source-files-only baseline.",
1968
+ assistantMessage: `Preparation "${preparationConfig.name}" has no prepared portable context yet. Prepare it first; after that Interf can check readiness. If you specifically want a source-files-only baseline, ask for source files only.`,
1969
+ });
1970
+ }
1971
+ }
1972
+ const actionRequest = (() => {
1973
+ if (actionType === "compile") {
1974
+ return {
1975
+ preparation: preparationConfig.name,
1976
+ ...(methodId ? { method: methodId } : {}),
1977
+ };
1978
+ }
1979
+ if (actionType === "test") {
1980
+ const defaultMode = hasCompiledTestTarget(this.rootPath, preparationConfig) ? "both" : "raw";
1981
+ return {
1982
+ preparation: preparationConfig.name,
1983
+ mode: testModeValue(proposalValues, defaultMode),
1984
+ };
1985
+ }
1986
+ if (actionType === "readiness-check-draft") {
1987
+ return {
1988
+ preparation: preparationConfig.name,
1989
+ source_folder_path: preparationPath,
1990
+ about: stringValue(proposalValues, "about") ?? preparationConfig.about ?? request.message,
1991
+ target_count: Math.max(1, Math.min(8, Math.round(numberValue(proposalValues, "target_count") ?? 4))),
1992
+ };
1993
+ }
1994
+ return {
1995
+ preparation: preparationConfig.name,
1996
+ source_folder_path: preparationPath,
1997
+ method_id: methodId,
1998
+ label: stringValue(proposalValues, "label") ?? `Custom ${preparationConfig.name}`,
1999
+ hint: stringValue(proposalValues, "hint") ?? request.message,
2000
+ task_prompt: actionValueMethodTaskPrompt(proposalValues) ?? stringValue(proposalValues, "task_prompt") ?? request.message,
2001
+ checks: preparationConfig.checks ?? [],
2002
+ };
2003
+ })();
2004
+ const title = (() => {
2005
+ if (plan.title)
2006
+ return plan.title;
2007
+ if (actionType === "compile")
2008
+ return `Prepare ${preparationConfig.name}`;
2009
+ if (actionType === "test")
2010
+ return `Check readiness for ${preparationConfig.name}`;
2011
+ if (actionType === "readiness-check-draft")
2012
+ return `Draft readiness checks for ${preparationConfig.name}`;
2013
+ return `Draft Method ${methodId}`;
2014
+ })();
2015
+ const summary = (() => {
2016
+ if (plan.summary)
2017
+ return plan.summary;
2018
+ if (actionType === "compile")
2019
+ return "Build portable context agents can use.";
2020
+ if (actionType === "test")
2021
+ return "Run readiness checks against source files and portable context.";
2022
+ if (actionType === "readiness-check-draft")
2023
+ return "Ask the configured local executor to draft saved readiness checks.";
2024
+ return "Ask the configured local executor to create a reusable local Method.";
2025
+ })();
2026
+ const previewValues = actionType === "test"
2027
+ ? { mode: actionRequest.mode }
2028
+ : proposalValues;
2029
+ const commandPreview = plan.command_preview ?? actionCommandPreview(actionType, preparationConfig.name, methodId, previewValues);
2030
+ return ActionProposalResourceSchema.parse({
2031
+ kind: "interf-action-proposal",
2032
+ version: 1,
2033
+ proposal_id: createActionProposalId(),
2034
+ status: "awaiting_approval",
2035
+ action_type: actionType,
2036
+ title,
2037
+ summary,
2038
+ assistant_message: plan.assistant_message ?? actionAssistantMessage(actionType, preparationConfig.name, commandPreview),
2039
+ command_preview: commandPreview,
2040
+ message: request.message,
2041
+ preparation: preparationConfig.name,
2042
+ method: methodId,
2043
+ request: actionRequest,
2044
+ created_at: now,
2045
+ updated_at: now,
2046
+ proposed_by_executor: this.getExecutorStatus().executor,
2047
+ approval: null,
2048
+ submitted_run_id: null,
2049
+ submitted_run_type: null,
2050
+ error: null,
2051
+ });
2052
+ }
2053
+ async submitActionProposal(proposal) {
2054
+ if (proposal.action_type === "clarification") {
2055
+ throw new Error("Clarification proposals cannot be submitted.");
2056
+ }
2057
+ if (proposal.action_type === "compile") {
2058
+ const resource = await this.createCompileRun(proposal.request);
2059
+ return {
2060
+ runId: resource.run.run_id,
2061
+ runType: "compile-run",
2062
+ };
2063
+ }
2064
+ if (proposal.action_type === "test") {
2065
+ const resource = await this.createTestRun(proposal.request);
2066
+ return {
2067
+ runId: resource.run_id,
2068
+ runType: "test-run",
2069
+ };
2070
+ }
2071
+ if (proposal.action_type === "preparation-setup") {
2072
+ const job = await this.createPreparationSetupRun(proposal.request);
2073
+ return {
2074
+ runId: job.run_id,
2075
+ runType: "job-run",
2076
+ };
2077
+ }
2078
+ if (proposal.action_type === "readiness-check-draft") {
2079
+ const job = await this.createReadinessCheckDraftRun(proposal.request);
2080
+ return {
2081
+ runId: job.run_id,
2082
+ runType: "job-run",
2083
+ };
2084
+ }
2085
+ const job = await this.createMethodAuthoringRun(proposal.request);
2086
+ return {
2087
+ runId: job.run_id,
2088
+ runType: "job-run",
2089
+ };
2090
+ }
2091
+ resolvePreparationConfig(preparationName, overrides = {}) {
2092
+ const preparation = findSourcePreparationConfig(loadSourceFolderConfig(this.rootPath), preparationName);
2093
+ if (!preparation) {
2094
+ throw new Error(`Preparation "${preparationName}" is not saved in this control plane folder.`);
2095
+ }
2096
+ const method = overrides.method ?? methodIdForSourcePreparationConfig(preparation) ?? undefined;
2097
+ return {
2098
+ ...preparation,
2099
+ ...(method ? { method } : {}),
2100
+ ...(typeof overrides.max_attempts === "number" ? { max_attempts: overrides.max_attempts } : {}),
2101
+ ...(typeof overrides.max_loops === "number" ? { max_loops: overrides.max_loops } : {}),
2102
+ };
2103
+ }
2104
+ ensureCompiledForRun(preparationConfig) {
2105
+ const methodId = methodIdForSourcePreparationConfig(preparationConfig) ?? DEFAULT_METHOD_ID;
2106
+ const compiledPath = ensurePortableContextScaffold(this.rootPath, preparationConfig.name, methodId);
2107
+ syncCompiledInterfConfigFromSourcePreparationConfig(compiledPath, preparationConfig);
2108
+ return compiledPath;
2109
+ }
2110
+ readCompileRun(compiledPath, runId) {
2111
+ return readCompileRunAt(compileRunPath(compiledPath, runId));
2112
+ }
2113
+ writeCompileRun(compiledPath, run) {
2114
+ mkdirSync(compileRunsRoot(compiledPath), { recursive: true });
2115
+ writeJsonFile(compileRunPath(compiledPath, run.run_id), CompileRunSchema.parse(run));
2116
+ }
2117
+ writeJobRun(run) {
2118
+ mkdirSync(localJobsRoot(this.rootPath), { recursive: true });
2119
+ writeJsonFile(localJobPath(this.rootPath, run.run_id), LocalJobRunResourceSchema.parse(run));
2120
+ }
2121
+ writeActionProposal(proposal) {
2122
+ mkdirSync(actionProposalsRoot(this.rootPath), { recursive: true });
2123
+ writeJsonFile(actionProposalPath(this.rootPath, proposal.proposal_id), ActionProposalResourceSchema.parse(proposal));
2124
+ }
2125
+ setJobRunResult(runId, result) {
2126
+ const current = this.getJob(runId);
2127
+ if (!current)
2128
+ return;
2129
+ const normalizedResult = result && typeof result === "object" && !Array.isArray(result)
2130
+ ? result
2131
+ : { value: result };
2132
+ this.writeJobRun(LocalJobRunResourceSchema.parse({
2133
+ ...current,
2134
+ result: normalizedResult,
2135
+ }));
2136
+ }
2137
+ async recordCompileRunEvent(compiledPath, runId, event) {
2138
+ const current = this.readCompileRun(compiledPath, runId);
2139
+ if (!current)
2140
+ return;
2141
+ this.writeCompileRun(compiledPath, applyEventToCompileRun(current, event));
2142
+ if (event.type === "stage.passed" || event.type === "stage.failed") {
2143
+ this.refreshCompileRunFromRuntime(compiledPath, runId);
2144
+ }
2145
+ }
2146
+ refreshCompileRunFromRuntime(compiledPath, runId) {
2147
+ const current = this.readCompileRun(compiledPath, runId);
2148
+ if (!current)
2149
+ return;
2150
+ const state = loadState(compiledPath);
2151
+ if (!state?.stages)
2152
+ return;
2153
+ const historyByStage = new Map();
2154
+ for (const run of readRuntimeRunHistory(compiledPath)) {
2155
+ if (run.target_name !== current.preparation)
2156
+ continue;
2157
+ const existing = historyByStage.get(run.stage);
2158
+ if (!existing || timestampKey(run.updated_at) >= timestampKey(existing.updated_at)) {
2159
+ historyByStage.set(run.stage, run);
2160
+ }
2161
+ }
2162
+ const next = {
2163
+ ...current,
2164
+ stages: current.stages.map((stage) => {
2165
+ const stageState = state.stages?.[stage.stage_id];
2166
+ if (!stageState)
2167
+ return stage;
2168
+ const runtimeRun = historyByStage.get(stage.stage_id);
2169
+ const artifacts = uniqueArtifacts([
2170
+ ...(stage.artifacts ?? []),
2171
+ ...stageArtifactRefs(stage.stage_id, stageState.artifacts),
2172
+ ]);
2173
+ const proof = stage.latest_proof ?? proofForStage({
2174
+ runId,
2175
+ stageId: stage.stage_id,
2176
+ summary: stageState.summary,
2177
+ stageState,
2178
+ artifacts,
2179
+ });
2180
+ return {
2181
+ ...stage,
2182
+ started_at: stage.started_at ?? stageState.started_at,
2183
+ finished_at: stage.finished_at ?? stageState.finished_at,
2184
+ summary: stage.summary ?? stageState.summary ?? null,
2185
+ executor: stage.executor ?? runtimeRun?.executor ?? null,
2186
+ artifacts,
2187
+ logs: stage.logs ?? logsForRuntimeRun(runtimeRun) ?? logsForStageRun(stageState),
2188
+ latest_proof: proof,
2189
+ };
2190
+ }),
2191
+ };
2192
+ next.latest_proof = [...next.stages].reverse().find((stage) => Boolean(stage.latest_proof))?.latest_proof ?? next.latest_proof;
2193
+ this.writeCompileRun(compiledPath, next);
2194
+ }
2195
+ async emitRuntimeDerivedEvents(compiledPath, runId) {
2196
+ const state = loadState(compiledPath);
2197
+ const run = this.readCompileRun(compiledPath, runId);
2198
+ if (!state?.stages || !run)
2199
+ return;
2200
+ for (const stage of run.stages) {
2201
+ const stageState = state.stages[stage.stage_id];
2202
+ if (!stageState)
2203
+ continue;
2204
+ const artifacts = stageArtifactRefs(stage.stage_id, stageState.artifacts);
2205
+ for (const artifact of artifacts) {
2206
+ await this.recordCompileRunEvent(compiledPath, runId, {
2207
+ type: "artifact.written",
2208
+ event_id: createRunEventId("event"),
2209
+ run_id: runId,
2210
+ timestamp: stageState.finished_at ?? createRunEventTimestamp(),
2211
+ stage_id: stage.stage_id,
2212
+ artifact,
2213
+ });
2214
+ }
2215
+ await this.recordCompileRunEvent(compiledPath, runId, {
2216
+ type: "proof.updated",
2217
+ event_id: createRunEventId("event"),
2218
+ run_id: runId,
2219
+ timestamp: stageState.finished_at ?? createRunEventTimestamp(),
2220
+ stage_id: stage.stage_id,
2221
+ proof: proofForStage({
2222
+ runId,
2223
+ stageId: stage.stage_id,
2224
+ summary: stageState.summary,
2225
+ stageState,
2226
+ artifacts,
2227
+ }),
2228
+ });
2229
+ }
2230
+ }
2231
+ readLatestComparison(preparationName) {
2232
+ return readSavedReadinessCheckRun(this.rootPath, preparationName);
2233
+ }
2234
+ checksEvaluatedEvent(runId, comparison) {
2235
+ const target = comparison.compiled ?? comparison.raw;
2236
+ return {
2237
+ type: "checks.evaluated",
2238
+ event_id: createRunEventId("event"),
2239
+ run_id: runId,
2240
+ timestamp: createRunEventTimestamp(),
2241
+ passed: target?.passed_cases ?? 0,
2242
+ total: target?.total_cases ?? 0,
2243
+ test_run_id: runId,
2244
+ };
2245
+ }
2246
+ readinessUpdatedEvent(runId, preparation, readiness) {
2247
+ return {
2248
+ type: "readiness.updated",
2249
+ event_id: createRunEventId("event"),
2250
+ run_id: runId,
2251
+ timestamp: createRunEventTimestamp(),
2252
+ preparation,
2253
+ readiness,
2254
+ };
2255
+ }
2256
+ writeTestRun(compiledPath, run) {
2257
+ mkdirSync(testRunsRoot(compiledPath), { recursive: true });
2258
+ writeJsonFile(testRunPath(compiledPath, run.run_id), TestRunResourceSchema.parse(run));
2259
+ }
2260
+ }
2261
+ export function createLocalServiceRuntime(options) {
2262
+ return new LocalServiceRuntime(options);
2263
+ }