@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,25 +1,38 @@
1
1
  import { lstat, readFile, realpath } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
+ import type { ErrorObject } from "ajv";
3
4
  import {
4
5
  declaredRuntimeRoots,
5
6
  optionalRuntimeRoots,
6
7
  runtimePathDirectories,
7
8
  runtimeInheritedPath,
8
9
  requireRuntimeReadRoots,
9
- } from "./runtime-paths";
10
- import validate from "./generated/runtime.cjs";
10
+ } from "./paths";
11
+ import validate from "../generated/runtime.cjs";
11
12
  import {
12
13
  requireArtifactDirectories,
13
14
  type RuntimeArtifactDirectory,
14
- } from "./candidate-artifacts";
15
- import { runtimeSeedDigest } from "./runtime-seeds";
15
+ } from "../candidate-artifacts";
16
+ import { runtimeSeedDigest } from "./seeds";
17
+ import {
18
+ resolveSharedCaches,
19
+ requireSharedCachePolicy,
20
+ type SharedCacheDirectory,
21
+ } from "./shared-cache";
16
22
  import {
17
23
  discoverRuntimeSupport,
18
24
  type RuntimeDiscoverySource,
19
- } from "./runtime-discovery";
25
+ } from "./discovery";
20
26
 
21
- export type RuntimeRole =
22
- "candidate" | "checks" | "hooks" | "semantic" | "advisory";
27
+ /** Canonical roles; schemas:generate projects this list into the runtime schema. */
28
+ export const RUNTIME_ROLES = [
29
+ "candidate",
30
+ "checks",
31
+ "hooks",
32
+ "semantic",
33
+ "advisory",
34
+ ] as const;
35
+ export type RuntimeRole = (typeof RUNTIME_ROLES)[number];
23
36
  export interface RuntimeSeed {
24
37
  source: string;
25
38
  target: string;
@@ -27,11 +40,14 @@ export interface RuntimeSeed {
27
40
  }
28
41
  export interface RuntimeConfiguration {
29
42
  format: "sevro.runtime.v1";
43
+ codexState?: boolean;
44
+ network?: { localHttp?: boolean };
30
45
  nativeTranscripts?: boolean;
31
46
  environment?: { inherit?: string[]; set?: Record<string, string> };
32
47
  filesystem?: { readOnlyRoots?: string[]; optionalReadOnlyRoots?: string[] };
33
48
  runtime?: {
34
49
  seedDirectories?: RuntimeSeed[];
50
+ sharedCacheDirectories?: SharedCacheDirectory[];
35
51
  artifactDirectories?: RuntimeArtifactDirectory[];
36
52
  };
37
53
  hooks?: { nativeGoal?: boolean; plugins?: string[] };
@@ -39,6 +55,8 @@ export interface RuntimeConfiguration {
39
55
 
40
56
  export interface RuntimePolicy {
41
57
  format: "sevro.runtime.v1";
58
+ codexState?: boolean;
59
+ network?: { localHttp?: boolean };
42
60
  artifactDirectories?: RuntimeArtifactDirectory[];
43
61
  nativeTranscripts?: boolean;
44
62
  environment: Record<string, string>;
@@ -48,9 +66,18 @@ export interface RuntimePolicy {
48
66
  /** Original source denials retained when a derived role policy omits seeds. */
49
67
  seedReadDenyRoots?: string[];
50
68
  seeds?: (RuntimeSeed & { sha256: string })[];
69
+ sharedCacheDirectories?: SharedCacheDirectory[];
51
70
  hooks?: { nativeGoal?: boolean; plugins?: string[] };
52
71
  }
53
72
 
73
+ export function runtimeLocalHttpEnabled(
74
+ policy: RuntimePolicy | undefined,
75
+ role: RuntimeRole,
76
+ ): boolean {
77
+ const network = policy?.network;
78
+ return network?.localHttp === true && ["candidate", "checks"].includes(role);
79
+ }
80
+
54
81
  export function runtimeNativeGoalEnabled(
55
82
  policy: RuntimePolicy | undefined,
56
83
  ): boolean {
@@ -58,28 +85,64 @@ export function runtimeNativeGoalEnabled(
58
85
  return hooks?.nativeGoal === true;
59
86
  }
60
87
 
88
+ const validatedPolicies = new WeakSet<RuntimePolicy>();
89
+
90
+ export function runtimePolicySnapshot(policy: RuntimePolicy): RuntimePolicy;
91
+ export function runtimePolicySnapshot(
92
+ policy: RuntimePolicy | undefined,
93
+ ): RuntimePolicy | undefined;
61
94
  export function runtimePolicySnapshot(
62
95
  policy: RuntimePolicy | undefined,
63
96
  ): RuntimePolicy | undefined {
64
97
  if (!policy) return undefined;
65
- requireRuntimeEnvironment(policy.environment);
66
98
  const snapshot = structuredClone(policy);
99
+ if (!validatedPolicies.has(policy)) requireRuntimePolicy(snapshot);
100
+ Object.freeze(snapshot.network);
67
101
  freezeArtifactDirectories(snapshot);
68
102
  Object.freeze(snapshot.environment);
69
103
  Object.freeze(snapshot.readOnlyRoots);
70
104
  freezeDiscovery(snapshot);
71
- for (const seed of snapshot.seeds ?? []) {
72
- Object.freeze(seed.roles);
73
- Object.freeze(seed);
74
- }
75
- Object.freeze(snapshot.seeds);
105
+ freezeRuntimeCaches(snapshot);
76
106
  Object.freeze(snapshot.seedReadDenyRoots);
77
107
  const hooks = snapshot.hooks;
78
108
  if (hooks) {
79
109
  Object.freeze(hooks.plugins);
80
110
  Object.freeze(hooks);
81
111
  }
82
- return Object.freeze(snapshot);
112
+ Object.freeze(snapshot);
113
+ validatedPolicies.add(snapshot);
114
+ return snapshot;
115
+ }
116
+
117
+ /** Loaded snapshots are already validated; mutable direct API inputs still need validation. */
118
+ export function requireRuntimePolicy(policy: RuntimePolicy): void {
119
+ if (validatedPolicies.has(policy)) return;
120
+ snapshotEnvironment([], policy.environment);
121
+ requireRuntimeCaches(policy.seeds ?? [], policy.sharedCacheDirectories ?? []);
122
+ requireSharedCachePolicy(policy);
123
+ requireArtifactDirectories(policy.artifactDirectories ?? []);
124
+ }
125
+
126
+ function requireRuntimeCaches(
127
+ seeds: RuntimeSeed[],
128
+ caches: SharedCacheDirectory[],
129
+ ): void {
130
+ requireRuntimeSeedTargets([...seeds, ...caches]);
131
+ for (const seed of seeds)
132
+ if (seed.roles !== undefined) requireRuntimeRoles(seed.roles, "seed");
133
+ for (const cache of caches) requireRuntimeRoles(cache.roles, "shared cache");
134
+ }
135
+
136
+ function freezeRuntimeCaches(snapshot: RuntimePolicy): void {
137
+ for (const seed of [
138
+ ...(snapshot.seeds ?? []),
139
+ ...(snapshot.sharedCacheDirectories ?? []),
140
+ ]) {
141
+ Object.freeze(seed.roles);
142
+ Object.freeze(seed);
143
+ }
144
+ Object.freeze(snapshot.seeds);
145
+ Object.freeze(snapshot.sharedCacheDirectories);
83
146
  }
84
147
 
85
148
  function freezeDiscovery(snapshot: RuntimePolicy): void {
@@ -93,7 +156,6 @@ function freezeDiscovery(snapshot: RuntimePolicy): void {
93
156
 
94
157
  function freezeArtifactDirectories(snapshot: RuntimePolicy): void {
95
158
  const directories = snapshot.artifactDirectories ?? [];
96
- requireArtifactDirectories(directories);
97
159
  for (const directory of directories) Object.freeze(directory);
98
160
  Object.freeze(snapshot.artifactDirectories);
99
161
  }
@@ -101,11 +163,27 @@ function freezeArtifactDirectories(snapshot: RuntimePolicy): void {
101
163
  function assertRuntimeConfiguration(
102
164
  value: unknown,
103
165
  ): asserts value is RuntimeConfiguration {
104
- if (!validate(value)) throw new Error("invalid runtime configuration schema");
166
+ if (!validate(value)) {
167
+ // Ajv always populates errors when validation fails.
168
+ const issue = (validate.errors as [ErrorObject, ...ErrorObject[]])[0];
169
+ throw new Error(
170
+ `runtime configuration schema ${runtimeSchemaPath(issue)}: ${issue.message}`,
171
+ );
172
+ }
173
+ }
174
+
175
+ function runtimeSchemaPath(issue: ErrorObject): string {
176
+ const params = issue.params as Record<string, unknown>;
177
+ const property = params.additionalProperty ?? params.missingProperty;
178
+ const suffix =
179
+ typeof property === "string"
180
+ ? "/" + property.replaceAll("~", "~0").replaceAll("/", "~1")
181
+ : "";
182
+ return safeFilesystemPath(issue.instancePath + suffix || "/");
105
183
  }
106
184
 
107
185
  const RESERVED_ENVIRONMENT =
108
- /^(HOME|TMPDIR|TMP|TEMP|CODEX_HOME|CODEX_THREAD_ID|CLAUDE_CONFIG_DIR|CLAUDE_EFFORT|BASH_ENV|ENV|ZDOTDIR|NODE_OPTIONS|BUN_OPTIONS|UV_OFFLINE|GIT_CONFIG.*|LD_.*|DYLD_.*|CLAUDE_CODE_.*|SEVRO_NATIVE_.*|SEVRO_CANDIDATE_.*)$/i;
186
+ /^(HOME|TMPDIR|TMPPREFIX|TMP|TEMP|CODEX_HOME|CODEX_THREAD_ID|CLAUDE_CONFIG_DIR|CLAUDE_EFFORT|BASH_ENV|ENV|ZDOTDIR|NODE_OPTIONS|BUN_OPTIONS|UV_OFFLINE|GIT_CONFIG.*|LD_.*|DYLD_.*|CLAUDE_CODE_.*|SEVRO_CODEX_.*|SEVRO_NATIVE_.*|SEVRO_CANDIDATE_.*)$/i;
109
187
 
110
188
  function requireEnvironmentName(name: string): void {
111
189
  if (!/^[A-Za-z_][A-Za-z0-9_]{0,127}$/.test(name))
@@ -139,16 +217,7 @@ function snapshotEnvironment(
139
217
  return environment;
140
218
  }
141
219
 
142
- export function requireRuntimeEnvironment(
143
- environment: Record<string, string>,
144
- ): void {
145
- snapshotEnvironment([], environment);
146
- }
147
-
148
- export function requireRuntimeSeedTargets(
149
- seeds: NonNullable<RuntimePolicy["seeds"]>,
150
- ): void {
151
- for (const seed of seeds) requireRuntimeSeedRoles(seed.roles);
220
+ function requireRuntimeSeedTargets(seeds: RuntimeSeed[]): void {
152
221
  const targets = seeds.map((seed) => seed.target);
153
222
  if (
154
223
  targets.some(
@@ -175,13 +244,29 @@ export async function loadRuntimeConfiguration(
175
244
  const source = await readFile(canonical, "utf8");
176
245
  if (Buffer.byteLength(source) > 65536)
177
246
  throw new Error("runtime configuration exceeds 64 KiB");
178
- return await resolveRuntimeConfiguration(
179
- JSON.parse(source),
180
- dirname(canonical),
181
- protectedRoots,
247
+ return runtimePolicySnapshot(
248
+ await resolveRuntimeConfiguration(
249
+ parseRuntimeConfiguration(source),
250
+ dirname(canonical),
251
+ protectedRoots,
252
+ ),
182
253
  );
183
254
  } catch (cause) {
184
- throw new Error(runtimeConfigurationDiagnostic(cause), { cause });
255
+ throw new Error(
256
+ `${runtimeConfigurationDiagnostic(cause)} at ${safeFilesystemPath(path)}`,
257
+ { cause },
258
+ );
259
+ }
260
+ }
261
+
262
+ function parseRuntimeConfiguration(source: string): unknown {
263
+ try {
264
+ return JSON.parse(source);
265
+ } catch (cause) {
266
+ throw new Error(
267
+ "runtime configuration $: invalid JSON; check the JSON syntax",
268
+ { cause },
269
+ );
185
270
  }
186
271
  }
187
272
 
@@ -256,7 +341,7 @@ async function resolvedSeeds(
256
341
  environment: Record<string, string>,
257
342
  base: string,
258
343
  ) {
259
- const resolved = await Promise.all(
344
+ return Promise.all(
260
345
  seeds.map(async (seed) => {
261
346
  const roots = await declaredRuntimeRoots(
262
347
  [seed.source],
@@ -274,8 +359,6 @@ async function resolvedSeeds(
274
359
  };
275
360
  }),
276
361
  );
277
- requireRuntimeSeedTargets(resolved);
278
- return resolved;
279
362
  }
280
363
 
281
364
  async function resolveRuntimeConfiguration(
@@ -308,19 +391,53 @@ async function resolveRuntimeConfiguration(
308
391
  requireRuntimeReadRoots(readOnlyRoots, protectedRoots);
309
392
  return {
310
393
  format: value.format,
394
+ ...selectedRuntimeCapabilities(value),
311
395
  ...artifactConfiguration(value.runtime),
312
- ...(value.nativeTranscripts === undefined
313
- ? {}
314
- : { nativeTranscripts: value.nativeTranscripts }),
315
396
  environment,
316
397
  readOnlyRoots: [...new Set(readOnlyRoots)].sort(),
317
398
  discovery: discovery.sources,
318
399
  skippedOptionalReadOnlyRoots: optional.skipped,
319
- seeds: await resolvedSeeds(configurationSeeds(value), environment, base),
400
+ ...(await resolvedRuntimeCaches(value, environment, base, [
401
+ ...protectedRoots,
402
+ ...readOnlyRoots,
403
+ ])),
320
404
  hooks: resolvedHooks(value.hooks),
321
405
  };
322
406
  }
323
407
 
408
+ async function resolvedRuntimeCaches(
409
+ value: RuntimeConfiguration,
410
+ environment: Record<string, string>,
411
+ base: string,
412
+ protectedRoots: string[],
413
+ ) {
414
+ const seeds = await resolvedSeeds(
415
+ configurationSeeds(value),
416
+ environment,
417
+ base,
418
+ );
419
+ const caches = await resolveSharedCaches(
420
+ value.runtime?.sharedCacheDirectories ?? [],
421
+ environment,
422
+ base,
423
+ [...protectedRoots, ...seeds.map((seed) => seed.source)],
424
+ );
425
+ return {
426
+ seeds,
427
+ ...(caches.length ? { sharedCacheDirectories: caches } : {}),
428
+ };
429
+ }
430
+
431
+ function selectedRuntimeCapabilities(value: RuntimeConfiguration) {
432
+ return {
433
+ ...(value.network === undefined ? {} : { network: value.network }),
434
+ ...(value.codexState === undefined ? {} : { codexState: value.codexState }),
435
+ ...(value.nativeTranscripts === undefined
436
+ ? {}
437
+ : { nativeTranscripts: value.nativeTranscripts }),
438
+ };
439
+ }
440
+
324
441
  async function resolvedRuntimeEnvironment(value: RuntimeConfiguration) {
325
442
  const { inherit, set } = configurationEnvironment(value);
326
443
  const environment = snapshotEnvironment(inherit, set);
@@ -339,7 +456,6 @@ function configurationEnvironment(value: RuntimeConfiguration) {
339
456
  function artifactConfiguration(runtime: RuntimeConfiguration["runtime"]) {
340
457
  const directories = runtime?.artifactDirectories;
341
458
  if (directories === undefined) return {};
342
- requireArtifactDirectories(directories);
343
459
  return { artifactDirectories: directories };
344
460
  }
345
461
  function configurationReadRoots(value: RuntimeConfiguration): string[] {
@@ -356,20 +472,18 @@ function resolvedHooks(hooks: RuntimeConfiguration["hooks"]) {
356
472
  };
357
473
  }
358
474
 
359
- function requireRuntimeSeedRoles(roles: RuntimeRole[] | undefined): void {
360
- if (roles === undefined) return;
361
- const allowed = ["candidate", "checks", "hooks", "semantic", "advisory"];
475
+ function requireRuntimeRoles(roles: RuntimeRole[], kind: string): void {
362
476
  if (
363
477
  !validRoleArray(roles) ||
364
478
  new Set(roles).size !== roles.length ||
365
- roles.some((role) => !allowed.includes(role))
479
+ roles.some((role) => !RUNTIME_ROLES.includes(role))
366
480
  )
367
- throw new Error("runtime seed roles are invalid");
481
+ throw new Error(`runtime ${kind} roles are invalid`);
368
482
  }
369
483
 
370
484
  export function runtimeRoleSeeds(policy: RuntimePolicy, role: RuntimeRole) {
371
485
  return (policy.seeds ?? []).filter(
372
- (seed) => seed.roles === undefined || seed.roles.includes(role),
486
+ (seed) => seed.roles?.includes(role) ?? role !== "checks",
373
487
  );
374
488
  }
375
489
 
@@ -1,13 +1,13 @@
1
1
  import { realpath } from "node:fs/promises";
2
2
  import { dirname } from "node:path";
3
- import { RuntimeMetadataQueryError } from "./runtime-query";
4
- import { optionalRuntimeRoots, requireRuntimeReadRoots } from "./runtime-paths";
3
+ import { RuntimeMetadataQueryError } from "./query";
4
+ import { optionalRuntimeRoots, requireRuntimeReadRoots } from "./paths";
5
5
  import {
6
6
  providerExecutable,
7
7
  query,
8
8
  requireProvider,
9
9
  type RuntimeDiscoverySource,
10
- } from "./runtime-discovery-providers";
10
+ } from "./discovery-providers";
11
11
 
12
12
  export async function discoverApple(
13
13
  path: string,
@@ -1,8 +1,9 @@
1
1
  import { access, realpath } from "node:fs/promises";
2
2
  import { constants } from "node:fs";
3
3
  import { delimiter, isAbsolute, join } from "node:path";
4
- import { runtimeMetadataQuery } from "./runtime-query";
5
- import { requireRuntimeReadRoots } from "./runtime-paths";
4
+ import { runtimeMetadataQuery } from "./query";
5
+ import { requireRuntimeReadRoots } from "./paths";
6
+ import { containsControl } from "../value-guards";
6
7
 
7
8
  export interface RuntimeDiscoverySource {
8
9
  provider: "homebrew" | "apple-developer";
@@ -45,13 +46,6 @@ export async function query(
45
46
  }
46
47
  }
47
48
 
48
- function containsControl(value: string): boolean {
49
- return Array.from(value).some(
50
- (character) =>
51
- character.charCodeAt(0) < 0x20 || character.charCodeAt(0) === 0x7f,
52
- );
53
- }
54
-
55
49
  export async function requireProvider(
56
50
  executable: string,
57
51
  protectedRoots: string[],
@@ -4,14 +4,14 @@ import {
4
4
  insideRuntimeRoot,
5
5
  optionalRuntimeRoots,
6
6
  requireRuntimeReadRoots,
7
- } from "./runtime-paths";
7
+ } from "./paths";
8
8
  import {
9
9
  providerExecutable,
10
10
  query,
11
11
  requireProvider,
12
12
  type RuntimeDiscoverySource,
13
- } from "./runtime-discovery-providers";
14
- export type { RuntimeDiscoverySource } from "./runtime-discovery-providers";
13
+ } from "./discovery-providers";
14
+ export type { RuntimeDiscoverySource } from "./discovery-providers";
15
15
 
16
16
  async function homebrew(
17
17
  executable: string,
@@ -63,7 +63,7 @@ export async function discoverRuntimeSupport(
63
63
  });
64
64
  }
65
65
  if (process.platform === "darwin") {
66
- const { discoverApple } = await import("./runtime-discovery-apple");
66
+ const { discoverApple } = await import("./discovery-apple");
67
67
  await discoverApple(path, environment, sources, protectedRoots);
68
68
  }
69
69
  return { sources, excludedPrefixes };
@@ -1,6 +1,7 @@
1
+ import { spawn } from "../runtime-process";
1
2
  import { readFile, readdir, writeFile } from "node:fs/promises";
2
3
  import { basename, dirname, join } from "node:path";
3
- import { isRecord } from "./value-guards";
4
+ import { isRecord } from "../value-guards";
4
5
 
5
6
  export async function hookExecutions(
6
7
  receipts: string,
@@ -22,7 +23,7 @@ export async function hookExecutions(
22
23
  }
23
24
 
24
25
  async function processOutput(argv: string[]): Promise<string> {
25
- const child = Bun.spawn(argv, { stdout: "pipe", stderr: "ignore" });
26
+ const child = spawn(argv, { stdout: "pipe", stderr: "ignore" });
26
27
  const output = await new Response(child.stdout).text();
27
28
  await child.exited;
28
29
  if (Buffer.byteLength(output) > 1024 * 1024)
@@ -1,3 +1,5 @@
1
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
2
+ import { existsSync } from "node:fs";
1
3
  import {
2
4
  cp,
3
5
  mkdir,
@@ -7,19 +9,21 @@ import {
7
9
  writeFile,
8
10
  } from "node:fs/promises";
9
11
  import { join } from "node:path";
10
- import type { RuntimePolicy } from "./runtime-config";
11
- import { insideRuntimeRoot, requireRuntimeReadRoots } from "./runtime-paths";
12
- import { runtimeSeedDigest } from "./runtime-seeds";
13
- import { prepareRuntimeState } from "./runtime-state";
14
- import { macSandboxProfile } from "./hosts/mac-sandbox";
15
- import type { IsolatedCommand } from "./hosts/mac-sandbox";
16
- import { prepareLinuxSandboxCommand } from "./hosts/linux-sandbox";
17
- import { isRecord, isUnknownArray } from "./value-guards";
18
- import { hookExecutions, releaseHookProcesses } from "./runtime-hook-processes";
12
+ import { shellQuote as quote } from "../shell";
13
+ import type { RuntimePolicy } from "./config";
14
+ import { insideRuntimeRoot, requireRuntimeReadRoots } from "./paths";
15
+ import { runtimeSeedDigest } from "./seeds";
16
+ import { prepareRuntimeState } from "./state";
17
+ import { sharedCacheDenyRoots, sharedCacheRoots } from "./shared-cache";
18
+ import { macSandboxProfile } from "../hosts/mac-sandbox";
19
+ import type { IsolatedCommand } from "../hosts/mac-sandbox";
20
+ import { prepareLinuxSandboxCommand } from "../hosts/linux-sandbox";
21
+ import { isRecord, isUnknownArray } from "../value-guards";
22
+ import { hookExecutions, releaseHookProcesses } from "./hook-processes";
19
23
  import {
20
24
  nativeStateParent,
21
25
  requireNativeHookRoots,
22
- } from "./native-transcript-state";
26
+ } from "../native-transcript-state";
23
27
 
24
28
  export interface HookMounts {
25
29
  directories: string[];
@@ -61,10 +65,6 @@ function object(value: unknown): Record<string, unknown> {
61
65
  return value;
62
66
  }
63
67
 
64
- function quote(value: string): string {
65
- return `'${value.replaceAll("'", `'"'"'`)}'`;
66
- }
67
-
68
68
  /** Materialize immutable mounts; only declared plugin hooks reach the host. */
69
69
  export async function prepareHookMounts(options: {
70
70
  workspace: string;
@@ -156,7 +156,7 @@ function lazyHookExecution(
156
156
  options,
157
157
  index,
158
158
  readRoots,
159
- runtime.root,
159
+ runtime,
160
160
  );
161
161
  if (boundary.isolation) isolation.push(boundary.isolation);
162
162
  return {
@@ -175,31 +175,43 @@ async function prepareHookIsolation(
175
175
  options: Parameters<typeof prepareHookMounts>[0],
176
176
  index: number,
177
177
  roots: { ordinary: string[]; curated: string[] },
178
- runtimeRoot: string,
178
+ runtime: Awaited<ReturnType<typeof prepareRuntimeState>>,
179
179
  ): Promise<{ profile?: string; isolation?: IsolatedCommand }> {
180
+ const cacheRoots = await sharedCacheRoots(
181
+ options.policy,
182
+ "hooks",
183
+ options.protectedRoots,
184
+ );
185
+ const protectedRoots = [
186
+ ...options.protectedRoots,
187
+ ...sharedCacheDenyRoots(options.policy, "hooks"),
188
+ ];
180
189
  if (process.platform === "linux")
181
190
  return {
182
191
  isolation: await prepareLinuxSandboxCommand({
183
192
  argv: ["/bin/true"],
184
193
  workspace: options.workspace,
185
- protectedRoots: options.protectedRoots,
194
+ protectedRoots,
186
195
  privateStateRoot: options.privateRoot,
187
196
  denyNetwork: true,
188
197
  readOnlyRoots: roots.ordinary,
189
198
  hookReadRoots: roots.curated,
190
- writableRuntimeRoot: runtimeRoot,
199
+ writableRuntimeRoot: runtime.root,
200
+ writableCacheRoots: cacheRoots,
191
201
  }),
192
202
  };
193
203
  const profile = join(options.privateRoot, `hooks-${index}.sb`);
194
204
  await writeFile(
195
205
  profile,
196
206
  macSandboxProfile(
197
- options.protectedRoots,
207
+ protectedRoots,
198
208
  true,
199
209
  roots.ordinary,
200
- runtimeRoot,
210
+ runtime.root,
201
211
  roots.curated,
202
212
  options.workspace,
213
+ undefined,
214
+ cacheRoots,
203
215
  ) + "\n(deny process-info* (require-not (target self)))\n",
204
216
  { mode: 0o600 },
205
217
  );
@@ -217,7 +229,7 @@ async function hookReadRoots(
217
229
  ];
218
230
  const curated = trusted ? [root] : [];
219
231
  requireRuntimeReadRoots(ordinary, options.protectedRoots);
220
- await requireNativeHookRoots(curated);
232
+ await requireNativeHookRoots(curated, options.privateRoot);
221
233
  return { ordinary, curated };
222
234
  }
223
235
 
@@ -243,23 +255,23 @@ async function rewritePlugin(
243
255
  manifest: Record<string, unknown>,
244
256
  state: HookRewrite,
245
257
  ): Promise<void> {
246
- await requireHookOnlyPlugin(state.root);
258
+ requireHookOnlyPlugin(state.root);
247
259
  await rewriteManifest(manifest, state, ".claude-plugin/plugin.json");
248
260
  const native = join(state.root, ".codex-plugin/plugin.json");
249
- if (await Bun.file(native).exists())
261
+ if (existsSync(native))
250
262
  await rewriteManifest(
251
263
  object(JSON.parse(await readFile(native, "utf8"))),
252
264
  state,
253
265
  ".codex-plugin/plugin.json",
254
266
  );
255
267
  const standard = join(state.root, "hooks/hooks.json");
256
- if (await Bun.file(standard).exists()) await hookFile(standard, state);
268
+ if (existsSync(standard)) await hookFile(standard, state);
257
269
  await rewriteFrontmatter(state.root, state);
258
270
  }
259
271
 
260
- async function requireHookOnlyPlugin(root: string): Promise<void> {
272
+ function requireHookOnlyPlugin(root: string): void {
261
273
  for (const name of [".mcp.json", ".lsp.json"])
262
- if (await Bun.file(join(root, name)).exists())
274
+ if (existsSync(join(root, name)))
263
275
  throw new Error("runtime auxiliary plugin execution is unsupported");
264
276
  }
265
277
 
@@ -422,7 +434,7 @@ async function rewriteMarkdown(
422
434
  else delete metadata.hooks;
423
435
  await writeFile(
424
436
  path,
425
- `---\n${Bun.YAML.stringify(metadata)}---\n${body.slice(header[0].length)}`,
437
+ `---\n${stringifyYaml(metadata)}\n---\n${body.slice(header[0].length)}`,
426
438
  );
427
439
  }
428
440
 
@@ -430,7 +442,7 @@ function hookFrontmatter(
430
442
  header: string | undefined,
431
443
  ): Record<string, unknown> | undefined {
432
444
  if (!header?.includes("hooks")) return undefined;
433
- const metadata = object(Bun.YAML.parse(header));
445
+ const metadata = object(parseYaml(header));
434
446
  return metadata.hooks === undefined ? undefined : metadata;
435
447
  }
436
448
 
@@ -8,27 +8,20 @@ import {
8
8
  } from "node:fs/promises";
9
9
  import { constants, lstatSync, readlinkSync, realpathSync } from "node:fs";
10
10
  import { homedir, userInfo } from "node:os";
11
- import { nativeStateProtectedRoots } from "./native-transcript-state";
12
- import { workspaceStatePath } from "./workspace-state";
11
+ import { nativeStateProtectedRoots } from "../native-transcript-state";
12
+ import { workspaceStatePath } from "../fixtures/workspace-state";
13
+ import { insideRoot as insideRuntimeRoot } from "../paths";
14
+ import { containsControl } from "../value-guards";
15
+ export { insideRoot as insideRuntimeRoot } from "../paths";
13
16
  import {
14
17
  basename,
15
18
  delimiter,
16
19
  dirname,
17
20
  isAbsolute,
18
21
  join,
19
- relative,
20
22
  resolve,
21
- sep,
22
23
  } from "node:path";
23
24
 
24
- export function insideRuntimeRoot(root: string, path: string): boolean {
25
- const child = relative(root, path);
26
- return (
27
- child === "" ||
28
- (!child.startsWith(`..${sep}`) && child !== ".." && !isAbsolute(child))
29
- );
30
- }
31
-
32
25
  export function isRuntimeHomeRoot(root: string): boolean {
33
26
  return [homedir(), userInfo().homedir]
34
27
  .map((home) => resolve(home))
@@ -195,13 +188,6 @@ export async function runtimePathDirectories(
195
188
  return [...new Set(roots)].sort();
196
189
  }
197
190
 
198
- function containsControl(value: string): boolean {
199
- return Array.from(value).some(
200
- (character) =>
201
- character.charCodeAt(0) < 0x20 || character.charCodeAt(0) === 0x7f,
202
- );
203
- }
204
-
205
191
  function requirePathEntry(entry: string): void {
206
192
  if (!isAbsolute(entry) || containsControl(entry))
207
193
  throw new Error("runtime PATH entries must be absolute and nonempty");
@@ -1,5 +1,6 @@
1
1
  import { spawn, type ChildProcess } from "node:child_process";
2
2
  import { homedir } from "node:os";
3
+ import { terminateOwnedProcessGroup } from "../process-lifecycle";
3
4
 
4
5
  export class RuntimeMetadataQueryError extends Error {
5
6
  constructor(
@@ -25,11 +26,10 @@ function exitError(
25
26
 
26
27
  function stopQuery(child: ChildProcess): void {
27
28
  if (child.pid === undefined) return;
28
- try {
29
- process.kill(-child.pid, "SIGKILL");
30
- } catch {
31
- child.kill("SIGKILL");
32
- }
29
+ terminateOwnedProcessGroup(
30
+ { pid: child.pid, kill: (signal) => child.kill(signal) },
31
+ { alwaysGroup: true, fallbackError: "propagate" },
32
+ );
33
33
  }
34
34
 
35
35
  /** Bound both output streams and stop every descendant of this metadata query. */