@bjoernrochel/sevro 0.1.0-rc.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (582) hide show
  1. package/CONTRIBUTING.md +52 -6
  2. package/README.md +12 -7
  3. package/dist/examples/basic/graded.json +13 -0
  4. package/dist/examples/basic/host.js +9 -0
  5. package/dist/examples/basic/host.js.map +1 -0
  6. package/dist/examples/basic/prompt-only.json +7 -0
  7. package/dist/examples/recipes/candidate.js +23 -0
  8. package/dist/examples/recipes/candidate.js.map +1 -0
  9. package/dist/examples/recipes/cases/coding-change.json +21 -0
  10. package/dist/examples/recipes/cases/host-tools.json +21 -0
  11. package/dist/examples/recipes/cases/mise.json +21 -0
  12. package/dist/examples/recipes/cases/node.json +21 -0
  13. package/dist/examples/recipes/cases/python-uv.json +21 -0
  14. package/dist/examples/recipes/cases/semantic.json +17 -0
  15. package/dist/examples/recipes/coding-change/check.js +16 -0
  16. package/dist/examples/recipes/coding-change/check.js.map +1 -0
  17. package/dist/examples/recipes/executable.js +20 -0
  18. package/dist/examples/recipes/executable.js.map +1 -0
  19. package/dist/examples/recipes/extension-artifacts.js +56 -0
  20. package/dist/examples/recipes/extension-artifacts.js.map +1 -0
  21. package/dist/examples/recipes/extension-methods.js +167 -0
  22. package/dist/examples/recipes/extension-methods.js.map +1 -0
  23. package/dist/examples/recipes/extension.js +28 -0
  24. package/dist/examples/recipes/extension.js.map +1 -0
  25. package/dist/examples/recipes/modules.js +9 -0
  26. package/dist/examples/recipes/modules.js.map +1 -0
  27. package/dist/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
  28. package/dist/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
  29. package/dist/examples/recipes/repository-skill/README.md +3 -0
  30. package/dist/examples/recipes/run-inputs.js +144 -0
  31. package/dist/examples/recipes/run-inputs.js.map +1 -0
  32. package/dist/examples/recipes/run-options.js +103 -0
  33. package/dist/examples/recipes/run-options.js.map +1 -0
  34. package/dist/examples/recipes/run.js +62 -0
  35. package/dist/examples/recipes/run.js.map +1 -0
  36. package/dist/examples/recipes/runtime/empty.json +1 -0
  37. package/dist/examples/recipes/runtime/goals.json +1 -0
  38. package/dist/examples/recipes/runtime/mise.json +6 -0
  39. package/dist/examples/recipes/runtime/path.json +1 -0
  40. package/dist/examples/recipes/runtime/plugins.json +4 -0
  41. package/dist/examples/recipes/runtime/python-uv.json +10 -0
  42. package/dist/examples/recipes/semantic-judge.js +27 -0
  43. package/dist/examples/recipes/semantic-judge.js.map +1 -0
  44. package/dist/examples/templates/coding/adapter.js +14 -0
  45. package/dist/examples/templates/coding/adapter.js.map +1 -0
  46. package/dist/examples/templates/coding/case.json +15 -0
  47. package/dist/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
  48. package/dist/examples/templates/repository-skill/extension-data.js +61 -0
  49. package/dist/examples/templates/repository-skill/extension-data.js.map +1 -0
  50. package/dist/examples/templates/repository-skill/extension.js +29 -0
  51. package/dist/examples/templates/repository-skill/extension.js.map +1 -0
  52. package/dist/examples/templates/response/adapter.js +13 -0
  53. package/dist/examples/templates/response/adapter.js.map +1 -0
  54. package/dist/examples/templates/response/case.json +13 -0
  55. package/dist/src/advisory.js +86 -0
  56. package/dist/src/advisory.js.map +1 -0
  57. package/dist/src/candidate-artifacts.js +139 -0
  58. package/dist/src/candidate-artifacts.js.map +1 -0
  59. package/dist/src/candidate-codex-state.js +110 -0
  60. package/dist/src/candidate-codex-state.js.map +1 -0
  61. package/dist/src/case-validation.js +92 -0
  62. package/dist/src/case-validation.js.map +1 -0
  63. package/dist/src/cli/cancellation.js +21 -0
  64. package/dist/src/cli/cancellation.js.map +1 -0
  65. package/dist/src/cli/command.js +60 -0
  66. package/dist/src/cli/command.js.map +1 -0
  67. package/dist/src/cli/completion.js +14 -0
  68. package/dist/src/cli/completion.js.map +1 -0
  69. package/dist/src/cli/demo.js +45 -0
  70. package/dist/src/cli/demo.js.map +1 -0
  71. package/dist/src/cli/evaluation.js +40 -0
  72. package/dist/src/cli/evaluation.js.map +1 -0
  73. package/dist/src/cli/extension.js +54 -0
  74. package/dist/src/cli/extension.js.map +1 -0
  75. package/dist/src/cli/help.js +190 -0
  76. package/dist/src/cli/help.js.map +1 -0
  77. package/dist/src/cli/hosts.js +33 -0
  78. package/dist/src/cli/hosts.js.map +1 -0
  79. package/dist/src/cli/init-settings.js +29 -0
  80. package/dist/src/cli/init-settings.js.map +1 -0
  81. package/dist/src/cli/init.js +82 -0
  82. package/dist/src/cli/init.js.map +1 -0
  83. package/dist/src/cli/invocation.js +431 -0
  84. package/dist/src/cli/invocation.js.map +1 -0
  85. package/dist/src/cli/loading.js +110 -0
  86. package/dist/src/cli/loading.js.map +1 -0
  87. package/dist/src/cli/preparation.js +88 -0
  88. package/dist/src/cli/preparation.js.map +1 -0
  89. package/dist/src/cli/presentation.js +61 -0
  90. package/dist/src/cli/presentation.js.map +1 -0
  91. package/dist/src/cli/progress.js +5 -0
  92. package/dist/src/cli/progress.js.map +1 -0
  93. package/dist/src/cli/run-manifest.js +108 -0
  94. package/dist/src/cli/run-manifest.js.map +1 -0
  95. package/dist/src/cli/run-options.js +367 -0
  96. package/dist/src/cli/run-options.js.map +1 -0
  97. package/dist/src/cli/run-overrides.js +51 -0
  98. package/dist/src/cli/run-overrides.js.map +1 -0
  99. package/dist/src/cli/settings.js +127 -0
  100. package/dist/src/cli/settings.js.map +1 -0
  101. package/dist/src/cli/summary.js +28 -0
  102. package/dist/src/cli/summary.js.map +1 -0
  103. package/dist/src/cli.js +20 -0
  104. package/dist/src/cli.js.map +1 -0
  105. package/dist/src/contract-types.js +2 -0
  106. package/dist/src/contract-types.js.map +1 -0
  107. package/dist/src/engine.js +4 -0
  108. package/dist/src/engine.js.map +1 -0
  109. package/dist/src/evaluation/advisory.js +85 -0
  110. package/dist/src/evaluation/advisory.js.map +1 -0
  111. package/dist/src/evaluation/check-plan.js +292 -0
  112. package/dist/src/evaluation/check-plan.js.map +1 -0
  113. package/dist/src/evaluation/collection.js +61 -0
  114. package/dist/src/evaluation/collection.js.map +1 -0
  115. package/dist/src/evaluation/context.js +2 -0
  116. package/dist/src/evaluation/context.js.map +1 -0
  117. package/dist/src/evaluation/grading-host.js +28 -0
  118. package/dist/src/evaluation/grading-host.js.map +1 -0
  119. package/dist/src/evaluation/grading.js +154 -0
  120. package/dist/src/evaluation/grading.js.map +1 -0
  121. package/dist/src/evaluation/invocation-plan.js +312 -0
  122. package/dist/src/evaluation/invocation-plan.js.map +1 -0
  123. package/dist/src/evaluation/plan.js +376 -0
  124. package/dist/src/evaluation/plan.js.map +1 -0
  125. package/dist/src/evaluation/progress.js +14 -0
  126. package/dist/src/evaluation/progress.js.map +1 -0
  127. package/dist/src/evaluation/resources.js +159 -0
  128. package/dist/src/evaluation/resources.js.map +1 -0
  129. package/dist/src/evaluation/run.js +148 -0
  130. package/dist/src/evaluation/run.js.map +1 -0
  131. package/dist/src/evaluation/scheduler.js +27 -0
  132. package/dist/src/evaluation/scheduler.js.map +1 -0
  133. package/dist/src/evaluation/semantic.js +183 -0
  134. package/dist/src/evaluation/semantic.js.map +1 -0
  135. package/dist/src/evaluation/trial.js +593 -0
  136. package/dist/src/evaluation/trial.js.map +1 -0
  137. package/dist/src/evaluation/types.js +20 -0
  138. package/dist/src/evaluation/types.js.map +1 -0
  139. package/dist/src/evidence/host-results.js +67 -0
  140. package/dist/src/evidence/host-results.js.map +1 -0
  141. package/dist/src/evidence/retained-artifacts.js +17 -0
  142. package/dist/src/evidence/retained-artifacts.js.map +1 -0
  143. package/dist/src/evidence/trial-writer.js +131 -0
  144. package/dist/src/evidence/trial-writer.js.map +1 -0
  145. package/dist/src/evidence/usage.js +14 -0
  146. package/dist/src/evidence/usage.js.map +1 -0
  147. package/dist/src/executable.js +20 -0
  148. package/dist/src/executable.js.map +1 -0
  149. package/dist/src/extension-client.js +212 -0
  150. package/dist/src/extension-client.js.map +1 -0
  151. package/dist/src/extension-session.js +236 -0
  152. package/dist/src/extension-session.js.map +1 -0
  153. package/dist/src/fixtures/advisory.js +206 -0
  154. package/dist/src/fixtures/advisory.js.map +1 -0
  155. package/dist/src/fixtures/bin.js +41 -0
  156. package/dist/src/fixtures/bin.js.map +1 -0
  157. package/dist/src/fixtures/cleanup.js +43 -0
  158. package/dist/src/fixtures/cleanup.js.map +1 -0
  159. package/dist/src/fixtures/create.js +94 -0
  160. package/dist/src/fixtures/create.js.map +1 -0
  161. package/dist/src/fixtures/generated.js +181 -0
  162. package/dist/src/fixtures/generated.js.map +1 -0
  163. package/dist/src/fixtures/git-hooks.js +16 -0
  164. package/dist/src/fixtures/git-hooks.js.map +1 -0
  165. package/dist/src/fixtures/preparation.js +201 -0
  166. package/dist/src/fixtures/preparation.js.map +1 -0
  167. package/dist/src/fixtures/repository.js +255 -0
  168. package/dist/src/fixtures/repository.js.map +1 -0
  169. package/dist/src/fixtures/setup.js +175 -0
  170. package/dist/src/fixtures/setup.js.map +1 -0
  171. package/dist/src/fixtures/tools.js +57 -0
  172. package/dist/src/fixtures/tools.js.map +1 -0
  173. package/dist/src/fixtures/workspace-state.js +155 -0
  174. package/dist/src/fixtures/workspace-state.js.map +1 -0
  175. package/dist/src/generated/cli-result.cjs +2 -0
  176. package/dist/src/generated/extension.cjs +2 -0
  177. package/dist/src/generated/report.cjs +2 -0
  178. package/dist/src/generated/run-evidence.cjs +2 -0
  179. package/dist/src/generated/runtime.cjs +2 -0
  180. package/dist/src/git.js +72 -0
  181. package/dist/src/git.js.map +1 -0
  182. package/dist/src/graders/artifact.js +68 -0
  183. package/dist/src/graders/artifact.js.map +1 -0
  184. package/dist/src/graders/git-head.js +112 -0
  185. package/dist/src/graders/git-head.js.map +1 -0
  186. package/dist/src/graders/output.js +345 -0
  187. package/dist/src/graders/output.js.map +1 -0
  188. package/dist/src/graders/semantic.js +132 -0
  189. package/dist/src/graders/semantic.js.map +1 -0
  190. package/dist/src/graders/shell.js +321 -0
  191. package/dist/src/graders/shell.js.map +1 -0
  192. package/dist/src/host-diagnostic-redaction.js +52 -0
  193. package/dist/src/host-diagnostic-redaction.js.map +1 -0
  194. package/dist/src/host-diagnostics.js +248 -0
  195. package/dist/src/host-diagnostics.js.map +1 -0
  196. package/dist/src/hosts/claude-continuation.js +89 -0
  197. package/dist/src/hosts/claude-continuation.js.map +1 -0
  198. package/dist/src/hosts/claude-credential.js +121 -0
  199. package/dist/src/hosts/claude-credential.js.map +1 -0
  200. package/dist/src/hosts/claude-events.js +136 -0
  201. package/dist/src/hosts/claude-events.js.map +1 -0
  202. package/dist/src/hosts/claude-keychain.js +100 -0
  203. package/dist/src/hosts/claude-keychain.js.map +1 -0
  204. package/dist/src/hosts/claude-login-recovery.js +67 -0
  205. package/dist/src/hosts/claude-login-recovery.js.map +1 -0
  206. package/dist/src/hosts/claude-login-refresh.js +146 -0
  207. package/dist/src/hosts/claude-login-refresh.js.map +1 -0
  208. package/dist/src/hosts/claude-login-store.js +124 -0
  209. package/dist/src/hosts/claude-login-store.js.map +1 -0
  210. package/dist/src/hosts/claude-login.js +74 -0
  211. package/dist/src/hosts/claude-login.js.map +1 -0
  212. package/dist/src/hosts/claude-native-goal.js +138 -0
  213. package/dist/src/hosts/claude-native-goal.js.map +1 -0
  214. package/dist/src/hosts/claude-process.js +10 -0
  215. package/dist/src/hosts/claude-process.js.map +1 -0
  216. package/dist/src/hosts/claude-refresh-lock.js +76 -0
  217. package/dist/src/hosts/claude-refresh-lock.js.map +1 -0
  218. package/dist/src/hosts/claude-repository-invocation.js +229 -0
  219. package/dist/src/hosts/claude-repository-invocation.js.map +1 -0
  220. package/dist/src/hosts/claude-settings.js +156 -0
  221. package/dist/src/hosts/claude-settings.js.map +1 -0
  222. package/dist/src/hosts/claude-skill-activations.js +131 -0
  223. package/dist/src/hosts/claude-skill-activations.js.map +1 -0
  224. package/dist/src/hosts/claude-state.js +237 -0
  225. package/dist/src/hosts/claude-state.js.map +1 -0
  226. package/dist/src/hosts/claude-tool-calls.js +150 -0
  227. package/dist/src/hosts/claude-tool-calls.js.map +1 -0
  228. package/dist/src/hosts/claude.js +373 -0
  229. package/dist/src/hosts/claude.js.map +1 -0
  230. package/dist/src/hosts/codex-app-server.js +764 -0
  231. package/dist/src/hosts/codex-app-server.js.map +1 -0
  232. package/dist/src/hosts/codex-configuration.js +91 -0
  233. package/dist/src/hosts/codex-configuration.js.map +1 -0
  234. package/dist/src/hosts/codex-events.js +104 -0
  235. package/dist/src/hosts/codex-events.js.map +1 -0
  236. package/dist/src/hosts/codex-exec-controls.js +434 -0
  237. package/dist/src/hosts/codex-exec-controls.js.map +1 -0
  238. package/dist/src/hosts/codex-invocation.js +54 -0
  239. package/dist/src/hosts/codex-invocation.js.map +1 -0
  240. package/dist/src/hosts/codex-marketplace.js +185 -0
  241. package/dist/src/hosts/codex-marketplace.js.map +1 -0
  242. package/dist/src/hosts/codex-native-calls.js +516 -0
  243. package/dist/src/hosts/codex-native-calls.js.map +1 -0
  244. package/dist/src/hosts/codex-process.js +10 -0
  245. package/dist/src/hosts/codex-process.js.map +1 -0
  246. package/dist/src/hosts/codex-profile.js +206 -0
  247. package/dist/src/hosts/codex-profile.js.map +1 -0
  248. package/dist/src/hosts/codex-session-files.js +89 -0
  249. package/dist/src/hosts/codex-session-files.js.map +1 -0
  250. package/dist/src/hosts/codex-state.js +310 -0
  251. package/dist/src/hosts/codex-state.js.map +1 -0
  252. package/dist/src/hosts/codex.js +527 -0
  253. package/dist/src/hosts/codex.js.map +1 -0
  254. package/dist/src/hosts/isolation-common.js +43 -0
  255. package/dist/src/hosts/isolation-common.js.map +1 -0
  256. package/dist/src/hosts/isolation-roots.js +64 -0
  257. package/dist/src/hosts/isolation-roots.js.map +1 -0
  258. package/dist/src/hosts/isolation.js +12 -0
  259. package/dist/src/hosts/isolation.js.map +1 -0
  260. package/dist/src/hosts/linux-sandbox.js +127 -0
  261. package/dist/src/hosts/linux-sandbox.js.map +1 -0
  262. package/dist/src/hosts/mac-sandbox.js +137 -0
  263. package/dist/src/hosts/mac-sandbox.js.map +1 -0
  264. package/dist/src/hosts/native-controls.js +151 -0
  265. package/dist/src/hosts/native-controls.js.map +1 -0
  266. package/dist/src/hosts/native-request.js +33 -0
  267. package/dist/src/hosts/native-request.js.map +1 -0
  268. package/dist/src/hosts/process-lifecycle.js +167 -0
  269. package/dist/src/hosts/process-lifecycle.js.map +1 -0
  270. package/dist/src/hosts/protected-worktrees.js +81 -0
  271. package/dist/src/hosts/protected-worktrees.js.map +1 -0
  272. package/dist/src/hosts/skill-hook-catalog.js +100 -0
  273. package/dist/src/hosts/skill-hook-catalog.js.map +1 -0
  274. package/dist/src/hosts/skill-hook-handler.js +228 -0
  275. package/dist/src/hosts/skill-hook-handler.js.map +1 -0
  276. package/dist/src/hosts/skill-hooks.js +423 -0
  277. package/dist/src/hosts/skill-hooks.js.map +1 -0
  278. package/dist/src/hosts/workspace-fingerprint.js +72 -0
  279. package/dist/src/hosts/workspace-fingerprint.js.map +1 -0
  280. package/dist/src/identity.js +167 -0
  281. package/dist/src/identity.js.map +1 -0
  282. package/dist/src/instrumentation.js +83 -0
  283. package/dist/src/instrumentation.js.map +1 -0
  284. package/dist/src/native-transcript-state.js +85 -0
  285. package/dist/src/native-transcript-state.js.map +1 -0
  286. package/dist/src/native-transcript-view.js +65 -0
  287. package/dist/src/native-transcript-view.js.map +1 -0
  288. package/dist/src/native-transcripts.js +208 -0
  289. package/dist/src/native-transcripts.js.map +1 -0
  290. package/dist/src/paths.js +13 -0
  291. package/dist/src/paths.js.map +1 -0
  292. package/dist/src/process-lifecycle.js +101 -0
  293. package/dist/src/process-lifecycle.js.map +1 -0
  294. package/dist/src/provenance.js +263 -0
  295. package/dist/src/provenance.js.map +1 -0
  296. package/dist/src/prune.js +228 -0
  297. package/dist/src/prune.js.map +1 -0
  298. package/dist/src/report.js +276 -0
  299. package/dist/src/report.js.map +1 -0
  300. package/dist/src/resolved-case.js +29 -0
  301. package/dist/src/resolved-case.js.map +1 -0
  302. package/dist/src/results-lock.js +40 -0
  303. package/dist/src/results-lock.js.map +1 -0
  304. package/dist/src/results.js +127 -0
  305. package/dist/src/results.js.map +1 -0
  306. package/dist/src/run-owner.js +283 -0
  307. package/dist/src/run-owner.js.map +1 -0
  308. package/dist/src/runner-paths.js +11 -0
  309. package/dist/src/runner-paths.js.map +1 -0
  310. package/dist/src/runtime/config.js +323 -0
  311. package/dist/src/runtime/config.js.map +1 -0
  312. package/dist/src/runtime/discovery-apple.js +65 -0
  313. package/dist/src/runtime/discovery-apple.js.map +1 -0
  314. package/dist/src/runtime/discovery-providers.js +37 -0
  315. package/dist/src/runtime/discovery-providers.js.map +1 -0
  316. package/dist/src/runtime/discovery.js +40 -0
  317. package/dist/src/runtime/discovery.js.map +1 -0
  318. package/dist/src/runtime/hook-processes.js +81 -0
  319. package/dist/src/runtime/hook-processes.js.map +1 -0
  320. package/dist/src/runtime/hooks.js +304 -0
  321. package/dist/src/runtime/hooks.js.map +1 -0
  322. package/dist/src/runtime/paths.js +244 -0
  323. package/dist/src/runtime/paths.js.map +1 -0
  324. package/dist/src/runtime/query.js +76 -0
  325. package/dist/src/runtime/query.js.map +1 -0
  326. package/dist/src/runtime/seeds.js +98 -0
  327. package/dist/src/runtime/seeds.js.map +1 -0
  328. package/dist/src/runtime/shared-cache.js +81 -0
  329. package/dist/src/runtime/shared-cache.js.map +1 -0
  330. package/dist/src/runtime/state.js +106 -0
  331. package/dist/src/runtime/state.js.map +1 -0
  332. package/dist/src/runtime-process.js +148 -0
  333. package/dist/src/runtime-process.js.map +1 -0
  334. package/dist/src/schema-types.js +2 -0
  335. package/dist/src/schema-types.js.map +1 -0
  336. package/dist/src/schema.js +16 -0
  337. package/dist/src/schema.js.map +1 -0
  338. package/dist/src/shell.js +5 -0
  339. package/dist/src/shell.js.map +1 -0
  340. package/dist/src/sqlite-lock.js +18 -0
  341. package/dist/src/sqlite-lock.js.map +1 -0
  342. package/dist/src/storage.js +21 -0
  343. package/dist/src/storage.js.map +1 -0
  344. package/dist/src/transcript-retention.js +109 -0
  345. package/dist/src/transcript-retention.js.map +1 -0
  346. package/dist/src/value-guards.js +26 -0
  347. package/dist/src/value-guards.js.map +1 -0
  348. package/docs/README.md +19 -15
  349. package/docs/architecture.md +141 -17
  350. package/docs/assets/README.md +5 -4
  351. package/docs/builtin-graders-v1.md +9 -2
  352. package/docs/codex-host.md +155 -57
  353. package/docs/contracts.md +2 -1
  354. package/docs/creating-cases.md +10 -4
  355. package/docs/development-cli.md +197 -24
  356. package/docs/documentation-quality.md +16 -5
  357. package/docs/evaluation-workflow.md +110 -0
  358. package/docs/extension-protocol-v1.md +26 -3
  359. package/docs/getting-started.md +29 -7
  360. package/docs/guide-evaluation.md +34 -2
  361. package/docs/identity-v1.md +29 -3
  362. package/docs/installing.md +35 -17
  363. package/docs/licensing.md +2 -2
  364. package/docs/native-controls.md +76 -5
  365. package/docs/native-hosts.md +197 -8
  366. package/docs/reading-results.md +102 -0
  367. package/docs/recipes.md +490 -0
  368. package/docs/releases.md +48 -13
  369. package/docs/report-v1.md +29 -1
  370. package/docs/results-v1.md +122 -4
  371. package/docs/run-settings-v1.md +147 -0
  372. package/docs/runtime-v1.md +255 -22
  373. package/docs/specs/repository-guide.md +1 -1
  374. package/docs/troubleshooting.md +12 -12
  375. package/docs/typescript-quality.md +106 -26
  376. package/examples/recipes/candidate.ts +26 -0
  377. package/examples/recipes/cases/coding-change.json +21 -0
  378. package/examples/recipes/cases/host-tools.json +21 -0
  379. package/examples/recipes/cases/mise.json +21 -0
  380. package/examples/recipes/cases/node.json +21 -0
  381. package/examples/recipes/cases/python-uv.json +21 -0
  382. package/examples/recipes/cases/semantic.json +17 -0
  383. package/examples/recipes/coding-change/check.ts +23 -0
  384. package/examples/recipes/executable.ts +19 -0
  385. package/examples/recipes/extension-artifacts.ts +65 -0
  386. package/examples/recipes/extension-methods.ts +174 -0
  387. package/examples/recipes/extension.ts +38 -0
  388. package/examples/recipes/modules.ts +9 -0
  389. package/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
  390. package/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
  391. package/examples/recipes/repository-skill/README.md +3 -0
  392. package/examples/recipes/run-inputs.ts +183 -0
  393. package/examples/recipes/run-options.ts +132 -0
  394. package/examples/recipes/run.ts +77 -0
  395. package/examples/recipes/runtime/empty.json +1 -0
  396. package/examples/recipes/runtime/goals.json +1 -0
  397. package/examples/recipes/runtime/mise.json +6 -0
  398. package/examples/recipes/runtime/path.json +1 -0
  399. package/examples/recipes/runtime/plugins.json +4 -0
  400. package/examples/recipes/runtime/python-uv.json +10 -0
  401. package/examples/recipes/semantic-judge.ts +29 -0
  402. package/examples/templates/coding/adapter.ts +17 -0
  403. package/examples/templates/coding/case.json +15 -0
  404. package/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
  405. package/examples/templates/repository-skill/extension-data.ts +64 -0
  406. package/examples/templates/repository-skill/extension.ts +32 -0
  407. package/examples/templates/response/adapter.ts +12 -0
  408. package/examples/templates/response/case.json +13 -0
  409. package/package.json +23 -9
  410. package/schemas/report-v1.schema.json +9 -0
  411. package/schemas/run-evidence-v1.schema.json +2 -1
  412. package/schemas/runtime-v1.schema.json +43 -7
  413. package/src/advisory.ts +2 -2
  414. package/src/candidate-artifacts.ts +42 -11
  415. package/src/candidate-codex-state.ts +185 -0
  416. package/src/case-validation.ts +73 -50
  417. package/src/cli/cancellation.ts +20 -0
  418. package/src/cli/command.ts +87 -0
  419. package/src/cli/completion.ts +15 -0
  420. package/src/cli/demo.ts +61 -0
  421. package/src/cli/evaluation.ts +55 -0
  422. package/src/cli/extension.ts +79 -0
  423. package/src/cli/help.ts +199 -0
  424. package/src/cli/hosts.ts +55 -0
  425. package/src/cli/init-settings.ts +31 -0
  426. package/src/cli/init.ts +112 -0
  427. package/src/{cli-invocation.ts → cli/invocation.ts} +215 -218
  428. package/src/cli/loading.ts +151 -0
  429. package/src/cli/preparation.ts +154 -0
  430. package/src/cli/presentation.ts +93 -0
  431. package/src/cli/progress.ts +6 -0
  432. package/src/cli/run-manifest.ts +128 -0
  433. package/src/cli/run-options.ts +403 -0
  434. package/src/cli/run-overrides.ts +69 -0
  435. package/src/cli/settings.ts +154 -0
  436. package/src/cli/summary.ts +43 -0
  437. package/src/cli.ts +14 -592
  438. package/src/contract-types.ts +94 -0
  439. package/src/engine.ts +9 -5
  440. package/src/evaluation/advisory.ts +150 -0
  441. package/src/{evaluation-check-plan.ts → evaluation/check-plan.ts} +103 -67
  442. package/src/evaluation/collection.ts +88 -0
  443. package/src/evaluation/context.ts +10 -0
  444. package/src/{evaluation-grading-host.ts → evaluation/grading-host.ts} +5 -5
  445. package/src/evaluation/grading.ts +235 -0
  446. package/src/{evaluation-invocation-plan.ts → evaluation/invocation-plan.ts} +147 -58
  447. package/src/{evaluation-plan.ts → evaluation/plan.ts} +208 -141
  448. package/src/evaluation/progress.ts +19 -0
  449. package/src/evaluation/resources.ts +241 -0
  450. package/src/evaluation/run.ts +206 -0
  451. package/src/{evaluation-semantic.ts → evaluation/semantic.ts} +77 -87
  452. package/src/evaluation/trial.ts +800 -0
  453. package/src/{evaluation-types.ts → evaluation/types.ts} +79 -29
  454. package/src/evidence/host-results.ts +85 -0
  455. package/src/evidence/retained-artifacts.ts +18 -0
  456. package/src/evidence/trial-writer.ts +203 -0
  457. package/src/evidence/usage.ts +17 -0
  458. package/src/executable.ts +19 -0
  459. package/src/extension-client.ts +40 -108
  460. package/src/extension-session.ts +24 -48
  461. package/src/{advisory-fixture.ts → fixtures/advisory.ts} +12 -72
  462. package/src/{fixture-bin.ts → fixtures/bin.ts} +1 -1
  463. package/src/{fixture-cleanup.ts → fixtures/cleanup.ts} +13 -7
  464. package/src/fixtures/create.ts +183 -0
  465. package/src/{generated-fixture.ts → fixtures/generated.ts} +10 -53
  466. package/src/{git-hooks.ts → fixtures/git-hooks.ts} +1 -1
  467. package/src/{preparation.ts → fixtures/preparation.ts} +6 -16
  468. package/src/{repository-fixture.ts → fixtures/repository.ts} +30 -64
  469. package/src/{fixture-setup.ts → fixtures/setup.ts} +36 -53
  470. package/src/{fixture-tools.ts → fixtures/tools.ts} +1 -1
  471. package/src/{workspace-state.ts → fixtures/workspace-state.ts} +5 -5
  472. package/src/generated/cli-result.d.cts +2 -1
  473. package/src/generated/extension.d.cts +2 -1
  474. package/src/generated/report.cjs +1 -1
  475. package/src/generated/report.d.cts +2 -1
  476. package/src/generated/run-evidence.cjs +1 -1
  477. package/src/generated/run-evidence.d.cts +2 -1
  478. package/src/generated/runtime.cjs +1 -1
  479. package/src/generated/runtime.d.cts +2 -1
  480. package/src/git.ts +94 -0
  481. package/src/graders/git-head.ts +31 -85
  482. package/src/graders/shell.ts +54 -71
  483. package/src/host-diagnostic-redaction.ts +52 -0
  484. package/src/host-diagnostics.ts +331 -0
  485. package/src/hosts/claude-continuation.ts +57 -40
  486. package/src/hosts/claude-credential.ts +160 -63
  487. package/src/hosts/claude-events.ts +34 -18
  488. package/src/hosts/claude-keychain.ts +79 -21
  489. package/src/hosts/claude-login-recovery.ts +85 -0
  490. package/src/hosts/claude-login-refresh.ts +179 -0
  491. package/src/hosts/claude-login-store.ts +162 -0
  492. package/src/hosts/claude-login.ts +107 -0
  493. package/src/hosts/claude-native-goal.ts +15 -12
  494. package/src/hosts/claude-process.ts +10 -50
  495. package/src/hosts/claude-refresh-lock.ts +82 -0
  496. package/src/hosts/claude-repository-invocation.ts +9 -34
  497. package/src/hosts/claude-settings.ts +46 -9
  498. package/src/hosts/claude-skill-activations.ts +169 -0
  499. package/src/hosts/claude-state.ts +28 -15
  500. package/src/hosts/claude-tool-calls.ts +13 -10
  501. package/src/hosts/claude.ts +121 -81
  502. package/src/hosts/codex-app-server.ts +78 -52
  503. package/src/hosts/codex-configuration.ts +5 -10
  504. package/src/hosts/codex-exec-controls.ts +516 -0
  505. package/src/hosts/codex-marketplace.ts +12 -10
  506. package/src/hosts/codex-native-calls.ts +15 -122
  507. package/src/hosts/codex-process.ts +10 -183
  508. package/src/hosts/codex-profile.ts +36 -21
  509. package/src/hosts/codex-session-files.ts +1 -9
  510. package/src/hosts/codex-state.ts +134 -18
  511. package/src/hosts/codex.ts +210 -183
  512. package/src/hosts/isolation-common.ts +8 -11
  513. package/src/hosts/isolation-roots.ts +5 -4
  514. package/src/hosts/linux-sandbox.ts +15 -2
  515. package/src/hosts/mac-sandbox.ts +87 -18
  516. package/src/hosts/native-controls.ts +72 -22
  517. package/src/hosts/native-request.ts +55 -0
  518. package/src/hosts/process-lifecycle.ts +215 -49
  519. package/src/hosts/protected-worktrees.ts +3 -2
  520. package/src/hosts/skill-hook-catalog.ts +131 -0
  521. package/src/hosts/skill-hook-handler.ts +374 -0
  522. package/src/hosts/skill-hooks.ts +585 -0
  523. package/src/instrumentation.ts +7 -8
  524. package/src/native-transcript-state.ts +22 -3
  525. package/src/native-transcript-view.ts +52 -13
  526. package/src/native-transcripts.ts +26 -11
  527. package/src/paths.ts +22 -0
  528. package/src/process-lifecycle.ts +150 -0
  529. package/src/provenance.ts +34 -13
  530. package/src/prune.ts +300 -0
  531. package/src/report.ts +63 -36
  532. package/src/resolved-case.ts +1 -1
  533. package/src/results-lock.ts +42 -0
  534. package/src/results.ts +14 -18
  535. package/src/run-owner.ts +15 -9
  536. package/src/runner-paths.ts +21 -0
  537. package/src/{runtime-config.ts → runtime/config.ts} +160 -46
  538. package/src/{runtime-discovery-apple.ts → runtime/discovery-apple.ts} +3 -3
  539. package/src/{runtime-discovery-providers.ts → runtime/discovery-providers.ts} +3 -9
  540. package/src/{runtime-discovery.ts → runtime/discovery.ts} +4 -4
  541. package/src/{runtime-hook-processes.ts → runtime/hook-processes.ts} +3 -2
  542. package/src/{runtime-hooks.ts → runtime/hooks.ts} +40 -28
  543. package/src/{runtime-paths.ts → runtime/paths.ts} +5 -19
  544. package/src/{runtime-query.ts → runtime/query.ts} +5 -5
  545. package/src/{runtime-seeds.ts → runtime/seeds.ts} +3 -3
  546. package/src/runtime/shared-cache.ts +130 -0
  547. package/src/{runtime-state.ts → runtime/state.ts} +28 -11
  548. package/src/runtime-process.ts +194 -0
  549. package/src/schema-types.ts +73 -161
  550. package/src/shell.ts +4 -0
  551. package/src/sqlite-lock.ts +25 -0
  552. package/src/transcript-retention.ts +146 -0
  553. package/src/value-guards.ts +22 -0
  554. package/docs/assets/sevro-logo.png +0 -0
  555. package/docs/assets/sevro-symbol.svg +0 -1
  556. package/docs/assets/sevro-wordmark.svg +0 -1
  557. package/docs/cache-ownership-validation.md +0 -49
  558. package/docs/claude-continuation-validation.md +0 -47
  559. package/docs/concurrency-validation.md +0 -86
  560. package/docs/configuration-root-validation.md +0 -70
  561. package/docs/engine-slice.md +0 -114
  562. package/docs/evidence/runtime-startup-30/README.md +0 -185
  563. package/docs/evidence/runtime-startup-30/after.json +0 -319
  564. package/docs/evidence/runtime-startup-30/baseline-timeout.jsonl +0 -2
  565. package/docs/evidence/runtime-startup-30/before.json +0 -403
  566. package/docs/evidence/runtime-startup-30/consumer-smoke.json +0 -63
  567. package/docs/evidence/runtime-startup-30/full-policy-diagnostic.jsonl +0 -3
  568. package/docs/evidence/runtime-startup-30/minimal-policy-diagnostic.jsonl +0 -3
  569. package/docs/evidence/runtime-startup-30/plugin-template-assessment.json +0 -20
  570. package/docs/evidence/runtime-startup-30/seedless-timeout.jsonl +0 -2
  571. package/docs/evidence.md +0 -17
  572. package/docs/fixture-cleanup-validation.md +0 -73
  573. package/docs/guide-verification.json +0 -239
  574. package/src/evaluation-context.ts +0 -259
  575. package/src/evaluation-fixture.ts +0 -302
  576. package/src/evaluation-run.ts +0 -200
  577. package/src/evaluation-trial.ts +0 -1016
  578. package/src/hosts/claude-nested-skills.ts +0 -272
  579. package/src/hosts/codex-command-output.ts +0 -510
  580. package/src/hosts/codex-executor-command.ts +0 -291
  581. package/src/hosts/codex-skill-reads.ts +0 -783
  582. /package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +0 -0
@@ -1,9 +1,10 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
- import { canonicalJson } from "./identity";
4
- import { prepareFixtureBin } from "./fixture-bin";
3
+ import { canonicalJson } from "../identity";
4
+ import { prepareFixtureBin } from "./bin";
5
5
  import { prepareGitHooks } from "./git-hooks";
6
6
  import { fixtureParts } from "./preparation";
7
+ import { runGit } from "../git";
7
8
 
8
9
  const MAX_COMMITS = 128;
9
10
  const MAX_FILES = 1024;
@@ -197,60 +198,16 @@ export function prepareGeneratedFixture(value: unknown): GeneratedFixture {
197
198
  return JSON.parse(canonicalJson(fixture)) as GeneratedFixture;
198
199
  }
199
200
 
200
- function gitEnvironment() {
201
- const nullDevice = process.platform === "win32" ? "NUL" : "/dev/null";
202
- return {
203
- PATH: process.env.PATH ?? "/usr/bin:/bin",
204
- ...(process.env.SystemRoot ? { SystemRoot: process.env.SystemRoot } : {}),
205
- GIT_CONFIG_NOSYSTEM: "1",
206
- GIT_CONFIG_GLOBAL: nullDevice,
207
- GIT_TERMINAL_PROMPT: "0",
208
- GIT_AUTHOR_NAME: "Sevro Fixture",
209
- GIT_AUTHOR_EMAIL: "fixture@sevro.invalid",
210
- GIT_COMMITTER_NAME: "Sevro Fixture",
211
- GIT_COMMITTER_EMAIL: "fixture@sevro.invalid",
212
- GIT_AUTHOR_DATE: "2000-01-01T00:00:00+00:00",
213
- GIT_COMMITTER_DATE: "2000-01-01T00:00:00+00:00",
214
- };
215
- }
216
-
217
201
  async function git(workspace: string, args: string[]): Promise<void> {
218
- async function bounded(stream: ReadableStream<Uint8Array>): Promise<void> {
219
- let size = 0;
220
- for await (const chunk of stream) {
221
- size += chunk.byteLength;
222
- if (size > MAX_GIT_OUTPUT)
223
- throw new Error("generated fixture Git output is too large");
224
- }
225
- }
226
- const proc = Bun.spawn(
227
- [
228
- "git",
229
- "-c",
230
- `core.hooksPath=${process.platform === "win32" ? "NUL" : "/dev/null"}`,
231
- ...args,
232
- ],
233
- {
234
- cwd: workspace,
235
- stdout: "pipe",
236
- stderr: "pipe",
237
- env: gitEnvironment(),
238
- },
239
- );
240
202
  try {
241
- const [, , code] = await Promise.all([
242
- bounded(proc.stdout),
243
- bounded(proc.stderr),
244
- proc.exited,
245
- ]);
246
- if (code !== 0) throw new Error();
203
+ await runGit({
204
+ cwd: workspace,
205
+ args,
206
+ identity: "fixture",
207
+ label: "generated fixture",
208
+ maxOutputBytes: MAX_GIT_OUTPUT,
209
+ });
247
210
  } catch (cause) {
248
- try {
249
- proc.kill("SIGKILL");
250
- } catch {
251
- // The process may have exited before the failure was observed.
252
- }
253
- await proc.exited;
254
211
  throw new Error("generated fixture Git operation failed", { cause });
255
212
  }
256
213
  }
@@ -1,5 +1,5 @@
1
1
  import { join } from "node:path";
2
- import { prepareFixtureTools, installFixtureTools } from "./fixture-tools";
2
+ import { prepareFixtureTools, installFixtureTools } from "./tools";
3
3
 
4
4
  /** Bound hook declarations and keep every name inside Git's hooks directory. */
5
5
  export function prepareGitHooks(value: unknown): Record<string, string> | null {
@@ -1,7 +1,9 @@
1
- import { isMissingFile } from "./fixture-tools";
2
- import { sha256 } from "./identity";
1
+ import { isMissingFile } from "./tools";
2
+ import { sha256 } from "../identity";
3
3
  import { lstat, mkdir, readFile, realpath, stat } from "node:fs/promises";
4
- import { isAbsolute, join, relative, sep } from "node:path";
4
+ import { isAbsolute, join } from "node:path";
5
+ import { insideRoot } from "../paths";
6
+ import { containsControl as containsControlCharacter } from "../value-guards";
5
7
  import { fileURLToPath } from "node:url";
6
8
 
7
9
  const MAX_ARTIFACT_BYTES = 8 * 1024 * 1024;
@@ -114,12 +116,6 @@ function requireArtifactFlags(item: PreparationArtifact): void {
114
116
  if (item.executable !== undefined && typeof item.executable !== "boolean")
115
117
  throw new Error("preparation artifact executable must be boolean");
116
118
  }
117
- function containsControlCharacter(path: string): boolean {
118
- return Array.from(path).some(
119
- (character) =>
120
- character.charCodeAt(0) < 0x20 || character.charCodeAt(0) === 0x7f,
121
- );
122
- }
123
119
  function requireInlineSource(
124
120
  item: PreparationArtifact,
125
121
  ): asserts item is PreparationArtifact & { contentBase64: string } {
@@ -220,13 +216,7 @@ async function preparationSourcePath(url: string): Promise<string> {
220
216
  }
221
217
  }
222
218
  function requireContainedSource(root: string, path: string): void {
223
- const child = relative(root, path);
224
- if (
225
- !child ||
226
- child === ".." ||
227
- child.startsWith(`..${sep}`) ||
228
- isAbsolute(child)
229
- )
219
+ if (root === path || !insideRoot(root, path))
230
220
  throw new Error("preparation source escapes its declared root");
231
221
  }
232
222
  async function preparationSourceSize(path: string): Promise<number> {
@@ -1,10 +1,12 @@
1
- import { isRecord, isStringArray } from "./value-guards";
2
- import { isMissingFile } from "./fixture-tools";
1
+ import { isRecord, isStringArray } from "../value-guards";
2
+ import { isMissingFile } from "./tools";
3
3
  import { lstat, mkdir, realpath, stat, writeFile } from "node:fs/promises";
4
- import { isAbsolute, join, relative, sep } from "node:path";
4
+ import { isAbsolute, join } from "node:path";
5
+ import { insideRoot } from "../paths";
6
+ import { runGit } from "../git";
5
7
  import { fileURLToPath } from "node:url";
6
- import { canonicalJson } from "./identity";
7
- import { prepareFixtureBin } from "./fixture-bin";
8
+ import { canonicalJson } from "../identity";
9
+ import { prepareFixtureBin } from "./bin";
8
10
  import { prepareGitHooks } from "./git-hooks";
9
11
  import type { PreparationSources } from "./preparation";
10
12
  import { fixtureParts } from "./preparation";
@@ -167,53 +169,16 @@ export interface RepositorySource {
167
169
  revision: string;
168
170
  }
169
171
 
170
- async function boundedText(
171
- stream: ReadableStream<Uint8Array>,
172
- ): Promise<string> {
173
- const chunks: Uint8Array[] = [];
174
- let size = 0;
175
- for await (const chunk of stream) {
176
- size += chunk.byteLength;
177
- if (size > MAX_GIT_OUTPUT_BYTES)
178
- throw new Error("repository fixture Git output is too large");
179
- chunks.push(chunk);
180
- }
181
- return new TextDecoder("utf-8", { fatal: true }).decode(
182
- Buffer.concat(chunks),
183
- );
184
- }
185
-
186
172
  async function git(args: string[], cwd: string): Promise<string> {
187
- const proc = Bun.spawn(["git", ...args], {
173
+ const stdout = await runGit({
188
174
  cwd,
189
- stdout: "pipe",
190
- stderr: "pipe",
191
- env: {
192
- ...process.env,
193
- GIT_CONFIG_NOSYSTEM: "1",
194
- GIT_CONFIG_GLOBAL: process.platform === "win32" ? "NUL" : "/dev/null",
195
- GIT_TERMINAL_PROMPT: "0",
196
- GIT_AUTHOR_NAME: "Sevro Fixture",
197
- GIT_AUTHOR_EMAIL: "fixture@sevro.invalid",
198
- GIT_COMMITTER_NAME: "Sevro Fixture",
199
- GIT_COMMITTER_EMAIL: "fixture@sevro.invalid",
200
- GIT_AUTHOR_DATE: "2000-01-01T00:00:00+00:00",
201
- GIT_COMMITTER_DATE: "2000-01-01T00:00:00+00:00",
202
- },
175
+ args,
176
+ identity: "fixture",
177
+ label: "repository fixture",
178
+ maxOutputBytes: MAX_GIT_OUTPUT_BYTES,
179
+ validateUtf8: true,
203
180
  });
204
- try {
205
- const [stdout, , code] = await Promise.all([
206
- boundedText(proc.stdout),
207
- boundedText(proc.stderr),
208
- proc.exited,
209
- ]);
210
- if (code !== 0) throw new Error("repository fixture Git operation failed");
211
- return stdout.trim();
212
- } catch (error) {
213
- proc.kill("SIGKILL");
214
- await proc.exited;
215
- throw error;
216
- }
181
+ return new TextDecoder("utf-8", { fatal: true }).decode(stdout).trim();
217
182
  }
218
183
 
219
184
  /** Resolve a declared local repository without accepting a dirty source tree. */
@@ -261,8 +226,7 @@ async function canonicalRepositorySource(selected: {
261
226
  }
262
227
  }
263
228
  function requireContainedRepository(root: string, path: string): void {
264
- const child = relative(root, path);
265
- if (child === ".." || child.startsWith(`..${sep}`) || isAbsolute(child))
229
+ if (!insideRoot(root, path))
266
230
  throw new Error("repository source escapes its declared root");
267
231
  }
268
232
  async function repositoryCommit(path: string): Promise<string> {
@@ -272,10 +236,18 @@ async function repositoryCommit(path: string): Promise<string> {
272
236
  const revision = await git(["rev-parse", "--verify", "HEAD^{commit}"], path);
273
237
  if (!/^[a-f0-9]{40,64}$/.test(revision))
274
238
  throw new Error("repository source has no valid commit");
275
- if (await git(["status", "--porcelain=v1", "--untracked-files=all"], path))
239
+ if (
240
+ await git(
241
+ [
242
+ "status",
243
+ "--porcelain=v1",
244
+ "--untracked-files=all",
245
+ "--ignore-submodules=none",
246
+ ],
247
+ path,
248
+ )
249
+ )
276
250
  throw new Error("repository source has uncommitted changes");
277
- if (await git(["submodule", "status"], path))
278
- throw new Error("repository submodules are not supported");
279
251
  return revision;
280
252
  }
281
253
  function requireRepositorySnapshot(
@@ -306,6 +278,7 @@ export async function cloneRepositorySource(
306
278
  "--local",
307
279
  "--no-hardlinks",
308
280
  "--no-checkout",
281
+ "--no-recurse-submodules",
309
282
  "--quiet",
310
283
  current.path,
311
284
  workspace,
@@ -375,25 +348,18 @@ export async function applyRepositoryOverlay(
375
348
  });
376
349
  await stageRepositoryOverlay(fixture, workspace, Object.keys(files));
377
350
  }
378
- function disabledHooksArgs(): string[] {
379
- return [
380
- "-c",
381
- `core.hooksPath=${process.platform === "win32" ? "NUL" : "/dev/null"}`,
382
- ];
383
- }
384
351
  async function stageRepositoryOverlay(
385
352
  fixture: RepositoryFixture,
386
353
  workspace: string,
387
354
  paths: string[],
388
355
  ): Promise<void> {
389
- const noHooks = disabledHooksArgs();
390
356
  if (fixture.commitFiles) {
391
- await git([...noHooks, "add", "--", ...paths], workspace);
357
+ await git(["add", "--", ...paths], workspace);
392
358
  await git(
393
- [...noHooks, "commit", "--quiet", "-m", "Add evaluation scaffolding"],
359
+ ["commit", "--quiet", "-m", "Add evaluation scaffolding"],
394
360
  workspace,
395
361
  );
396
362
  }
397
363
  if (fixture.staged?.length)
398
- await git([...noHooks, "add", "--", ...fixture.staged], workspace);
364
+ await git(["add", "--", ...fixture.staged], workspace);
399
365
  }
@@ -1,7 +1,13 @@
1
- import { mkdtemp, rm } from "node:fs/promises";
1
+ import { spawn, type Subprocess } from "../runtime-process";
2
+ import { mkdir, mkdtemp, rm } from "node:fs/promises";
2
3
  import { tmpdir } from "node:os";
3
4
  import { delimiter, isAbsolute, join } from "node:path";
4
- import { isRecord } from "./value-guards";
5
+ import { isRecord } from "../value-guards";
6
+ import { requireCandidateRuntime } from "../candidate-artifacts";
7
+ import {
8
+ ProcessDeadline,
9
+ terminateOwnedProcessGroup,
10
+ } from "../process-lifecycle";
5
11
 
6
12
  const MAX_COMMAND_BYTES = 64 * 1024;
7
13
  const MAX_ENV_BYTES = 16 * 1024;
@@ -103,27 +109,12 @@ export function prepareFixtureSetup(value: unknown): FixtureSetup | null {
103
109
  return { command, environment };
104
110
  }
105
111
 
106
- function stopProcess(proc: Bun.Subprocess): void {
107
- if (process.platform !== "win32") {
108
- try {
109
- process.kill(-proc.pid, "SIGKILL");
110
- return;
111
- } catch {
112
- // The process group may already be gone.
113
- }
114
- }
115
- try {
116
- proc.kill("SIGKILL");
117
- } catch {
118
- // The process already exited.
119
- }
120
- }
121
-
122
112
  interface FixtureSetupOptions {
123
113
  workspace: string;
124
114
  projectRoot: string;
125
115
  fixtureBinDir?: string;
126
116
  signal?: AbortSignal;
117
+ candidateRuntimeRoot?: string;
127
118
  }
128
119
 
129
120
  function setupPath(directory: string | undefined): string {
@@ -146,7 +137,9 @@ function executionEnvironment(
146
137
  );
147
138
  return {
148
139
  PATH: setupPath(options.fixtureBinDir),
149
- HOME: home,
140
+ HOME: options.candidateRuntimeRoot
141
+ ? join(options.candidateRuntimeRoot, "home")
142
+ : home,
150
143
  TMPDIR: home,
151
144
  LANG: process.env.LANG ?? "C",
152
145
  GIT_CONFIG_GLOBAL: process.platform === "win32" ? "NUL" : "/dev/null",
@@ -163,17 +156,27 @@ function executionEnvironment(
163
156
  }
164
157
 
165
158
  class FixtureSetupExecution {
166
- private proc: Bun.Subprocess | undefined;
167
- private timer: ReturnType<typeof setTimeout> | undefined;
168
- private cancel: (() => void) | undefined;
159
+ private proc: Subprocess | undefined;
160
+ private readonly deadline: ProcessDeadline;
169
161
  constructor(
170
162
  private readonly setup: FixtureSetup,
171
163
  private readonly options: FixtureSetupOptions,
172
164
  private readonly home: string,
173
- ) {}
165
+ ) {
166
+ this.deadline = new ProcessDeadline({
167
+ timeoutMs: TIMEOUT_MS,
168
+ signal: options.signal,
169
+ interruption: (reason) =>
170
+ new Error(
171
+ reason === "timeout"
172
+ ? "fixture setup timed out"
173
+ : "fixture setup cancelled",
174
+ ),
175
+ });
176
+ }
174
177
 
175
178
  async run(): Promise<void> {
176
- this.proc = Bun.spawn(this.setup.command, {
179
+ this.proc = spawn(this.setup.command, {
177
180
  cwd: this.options.workspace,
178
181
  env: executionEnvironment(this.setup, this.options, this.home),
179
182
  detached: process.platform !== "win32",
@@ -181,44 +184,18 @@ class FixtureSetupExecution {
181
184
  stdout: "ignore",
182
185
  stderr: "ignore",
183
186
  });
184
- const code = await Promise.race([
185
- this.proc.exited,
186
- this.timeout(),
187
- this.aborted(),
188
- ]);
187
+ const code = await this.deadline.wait(this.proc.exited);
189
188
  if (code !== 0) throw new Error(`fixture setup failed (${code})`);
190
189
  }
191
190
 
192
- private timeout(): Promise<never> {
193
- return new Promise((_resolve, reject) => {
194
- this.timer = setTimeout(() => {
195
- reject(new Error("fixture setup timed out"));
196
- }, TIMEOUT_MS);
197
- });
198
- }
199
-
200
- private aborted(): Promise<never> {
201
- return new Promise((_resolve, reject) => {
202
- const signal = this.options.signal;
203
- if (!signal) return;
204
- this.cancel = () => {
205
- reject(new Error("fixture setup cancelled"));
206
- };
207
- if (signal.aborted) this.cancel();
208
- else signal.addEventListener("abort", this.cancel, { once: true });
209
- });
210
- }
211
-
212
191
  async stop(): Promise<void> {
213
192
  if (!this.proc) return;
214
- stopProcess(this.proc);
193
+ terminateOwnedProcessGroup(this.proc);
215
194
  await this.proc.exited;
216
195
  }
217
196
 
218
197
  async dispose(): Promise<void> {
219
- if (this.timer) clearTimeout(this.timer);
220
- if (this.cancel)
221
- this.options.signal?.removeEventListener("abort", this.cancel);
198
+ this.deadline.dispose();
222
199
  await rm(this.home, { recursive: true, force: true });
223
200
  }
224
201
  }
@@ -229,6 +206,12 @@ export async function runFixtureSetup(
229
206
  options: FixtureSetupOptions,
230
207
  ): Promise<void> {
231
208
  if (options.signal?.aborted) throw new Error("fixture setup cancelled");
209
+ await requireCandidateRuntime(options.candidateRuntimeRoot);
210
+ if (options.candidateRuntimeRoot)
211
+ await mkdir(join(options.candidateRuntimeRoot, "home"), {
212
+ recursive: true,
213
+ mode: 0o700,
214
+ });
232
215
  const home = await mkdtemp(join(tmpdir(), "sevro-setup-"));
233
216
  const execution = new FixtureSetupExecution(setup, options, home);
234
217
  try {
@@ -1,6 +1,6 @@
1
1
  import { chmod, lstat, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { isRecord } from "./value-guards";
3
+ import { isRecord } from "../value-guards";
4
4
 
5
5
  export function isMissingFile(error: unknown): boolean {
6
6
  return error instanceof Error && "code" in error && error.code === "ENOENT";
@@ -17,11 +17,11 @@ import {
17
17
  processIdentity,
18
18
  validProcessIdentity,
19
19
  type ProcessIdentity,
20
- } from "./run-owner";
21
- import { isRecord } from "./value-guards";
22
- import { isMissingFile } from "./fixture-tools";
23
- import { atomicWriteJson } from "./storage";
24
- import { clearFixtureContents } from "./fixture-cleanup";
20
+ } from "../run-owner";
21
+ import { isRecord } from "../value-guards";
22
+ import { isMissingFile } from "./tools";
23
+ import { atomicWriteJson } from "../storage";
24
+ import { clearFixtureContents } from "./cleanup";
25
25
 
26
26
  const RETENTION_MS = 24 * 60 * 60_000;
27
27
  interface WorkspaceOwner {
@@ -1,3 +1,4 @@
1
1
  // Generated by bun run schemas:generate; do not edit.
2
- declare function validate(value: unknown): boolean;
2
+ import type { ValidateFunction } from "ajv";
3
+ declare const validate: ValidateFunction;
3
4
  export = validate;
@@ -1,3 +1,4 @@
1
1
  // Generated by bun run schemas:generate; do not edit.
2
- declare function validate(value: unknown): boolean;
2
+ import type { ValidateFunction } from "ajv";
3
+ declare const validate: ValidateFunction;
3
4
  export = validate;