@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,14 +1,12 @@
1
1
  import { isRecord, isUnknownArray } from "../value-guards";
2
- import { nativeCommandOutputs } from "./codex-command-output";
2
+ import {
3
+ codexExecCallReceipts,
4
+ type ExecCallReceipt,
5
+ } from "./codex-exec-controls";
3
6
  import {
4
7
  readNativeSession,
5
- readNativeSessionText,
6
8
  locateNativeSession as sessionPath,
7
9
  } from "./codex-session-files";
8
- import {
9
- codexNativeReadDiagnostic,
10
- type NativeReadDiagnostic,
11
- } from "./codex-skill-reads";
12
10
 
13
11
  const MAX_SESSION_ENTRIES = 10_000;
14
12
  const MAX_RETAINED_CALLS = 128;
@@ -63,7 +61,6 @@ interface ChildSession {
63
61
  threadId: string;
64
62
  status: "available" | "unavailable" | "ambiguous" | "partial";
65
63
  resultStatus?: "completed" | "unavailable";
66
- readDiagnostics?: NativeReadDiagnostic;
67
64
  nestedSpawns?: NestedSpawn[];
68
65
  requestsTruncated?: boolean;
69
66
  }
@@ -81,9 +78,7 @@ interface NestedSpawn {
81
78
  readerResultStatus: "completed" | "unavailable";
82
79
  }
83
80
 
84
- interface NativeSkillContext {
85
- workspace: string;
86
- installedPluginRoots: string[];
81
+ interface NativeCallContext {
87
82
  followUpPrompt?: string;
88
83
  }
89
84
 
@@ -95,9 +90,9 @@ interface NativeCallObservation {
95
90
  calls: NativeCall[];
96
91
  toolCalls: NativeToolCall[];
97
92
  submittedExecCalls: number;
93
+ execCalls?: ExecCallReceipt[];
98
94
  acceptedSpawns: AcceptedSpawn[];
99
95
  feedbackCalls: NativeFeedbackCall[];
100
- parentReadDiagnostics?: NativeReadDiagnostic;
101
96
  childSessions: ChildSession[];
102
97
  childrenTruncated: boolean;
103
98
  };
@@ -531,6 +526,9 @@ function sessionObservation(
531
526
  calls: state.calls,
532
527
  toolCalls: state.toolCalls,
533
528
  submittedExecCalls: state.submittedExecCalls,
529
+ ...(state.submittedExecCalls > 0
530
+ ? { execCalls: codexExecCallReceipts(state.entries) }
531
+ : {}),
534
532
  ...sessionReceipts(state, followUpPrompt),
535
533
  childSessions: [],
536
534
  childrenTruncated: false,
@@ -696,7 +694,6 @@ async function childSessionStatus(
696
694
  home: string,
697
695
  parentThread: string,
698
696
  threadId: string,
699
- skillContext?: NativeSkillContext,
700
697
  rootThread?: string,
701
698
  ): Promise<ChildSession> {
702
699
  if (threadId === parentThread) return { threadId, status: "partial" };
@@ -705,41 +702,21 @@ async function childSessionStatus(
705
702
  try {
706
703
  const text = await readNativeSession(located.path);
707
704
  if (text === null) return { threadId, status: "partial" };
708
- return await availableChildSession(
709
- home,
710
- threadId,
711
- text,
712
- skillContext,
713
- rootThread,
714
- );
705
+ return await availableChildSession(home, threadId, text, rootThread);
715
706
  } catch {
716
707
  return { threadId, status: "partial" };
717
708
  }
718
709
  }
719
710
 
720
- async function readDiagnostics(
721
- entries: NativeEntry[],
722
- context: NativeSkillContext | undefined,
723
- ) {
724
- return context
725
- ? codexNativeReadDiagnostic(
726
- entries,
727
- context.workspace,
728
- context.installedPluginRoots,
729
- )
730
- : undefined;
731
- }
732
711
  async function availableChildSession(
733
712
  home: string,
734
713
  threadId: string,
735
714
  text: string,
736
- context: NativeSkillContext | undefined,
737
715
  rootThread: string | undefined,
738
716
  ): Promise<ChildSession> {
739
717
  const parsed = parseSession(text);
740
718
  if (parsed.observation.completeness !== "complete")
741
719
  return { threadId, status: "partial" };
742
- const diagnostics = await readDiagnostics(parsed.entries, context);
743
720
  const nested = rootThread
744
721
  ? await nestedSpawnReceipts(home, rootThread, threadId, parsed.entries)
745
722
  : undefined;
@@ -749,7 +726,6 @@ async function availableChildSession(
749
726
  resultStatus: childResultCompleted(parsed.entries)
750
727
  ? "completed"
751
728
  : "unavailable",
752
- ...(diagnostics ? { readDiagnostics: diagnostics } : {}),
753
729
  ...nested,
754
730
  };
755
731
  }
@@ -779,7 +755,7 @@ function lastSessionOrdinal(text: string): number | null {
779
755
  export async function codexNativeCallObservation(
780
756
  home: string,
781
757
  threadId: string,
782
- skillContext?: NativeSkillContext,
758
+ context?: NativeCallContext,
783
759
  ): Promise<NativeCallObservation> {
784
760
  const located = await sessionPath(home, threadId);
785
761
  if (located.status !== "found")
@@ -791,7 +767,7 @@ export async function codexNativeCallObservation(
791
767
  home,
792
768
  threadId,
793
769
  located.path,
794
- skillContext,
770
+ context,
795
771
  );
796
772
  } catch {
797
773
  return unavailable("partial");
@@ -802,109 +778,26 @@ async function nativeSessionObservation(
802
778
  home: string,
803
779
  threadId: string,
804
780
  path: string,
805
- skillContext: NativeSkillContext | undefined,
781
+ context: NativeCallContext | undefined,
806
782
  ): Promise<NativeCallObservation> {
807
783
  const text = await readNativeSession(path);
808
784
  if (text === null) return unavailable("partial");
809
- const { observation, entries } = parseSession(
810
- text,
811
- skillContext?.followUpPrompt,
812
- );
785
+ const { observation } = parseSession(text, context?.followUpPrompt);
813
786
  if (observation.completeness !== "complete") return observation;
814
- const parentReadDiagnostics = await readDiagnostics(entries, skillContext);
815
787
  const children = [
816
788
  ...new Set(observation.data.acceptedSpawns.map((spawn) => spawn.threadId)),
817
789
  ];
818
790
  const childSessions = await Promise.all(
819
791
  children
820
792
  .slice(0, MAX_CHILD_SESSIONS)
821
- .map((child) =>
822
- childSessionStatus(home, threadId, child, skillContext, threadId),
823
- ),
793
+ .map((child) => childSessionStatus(home, threadId, child, threadId)),
824
794
  );
825
795
  return {
826
796
  ...observation,
827
797
  data: {
828
798
  ...observation.data,
829
- ...(parentReadDiagnostics ? { parentReadDiagnostics } : {}),
830
799
  childSessions,
831
800
  childrenTruncated: children.length > MAX_CHILD_SESSIONS,
832
801
  },
833
802
  };
834
803
  }
835
-
836
- /** Actor-local recovery stays in host memory and never enters public observations. */
837
- export async function codexNativeSkillReadRecovery(
838
- home: string,
839
- threadId: string,
840
- ): Promise<Map<string, { command: string; output: string }>> {
841
- const found = await sessionPath(home, threadId);
842
- if (found.status !== "found") return new Map();
843
- try {
844
- const text = await readNativeSessionText(found.path);
845
- if (text === null) return new Map();
846
- const parsed = parseSession(text);
847
- if (parsed.observation.completeness !== "complete") return new Map();
848
- return recoveredSessionReads(parsed.entries);
849
- } catch {
850
- return new Map();
851
- }
852
- }
853
-
854
- function completedCommandItem(
855
- payload: Record<string, unknown>,
856
- ): Record<string, unknown> | null {
857
- if (payload.type !== "item_completed") return null;
858
- if (!isRecord(payload.item) || payload.item.type !== "CommandExecution")
859
- return null;
860
- return payload.item;
861
- }
862
- function commandIdentityCounts(entries: NativeEntry[]): Map<string, number> {
863
- const counts = new Map<string, number>();
864
- for (const { payload } of entries) {
865
- const item = completedCommandItem(payload);
866
- if (typeof item?.id === "string")
867
- counts.set(item.id, (counts.get(item.id) ?? 0) + 1);
868
- }
869
- return counts;
870
- }
871
- function uniqueRecoveryItem(
872
- payload: Record<string, unknown>,
873
- counts: Map<string, number>,
874
- ) {
875
- const item = completedCommandItem(payload);
876
- if (!item || typeof item.id !== "string" || counts.get(item.id) !== 1)
877
- return null;
878
- return { id: item.id, command: item.command };
879
- }
880
- function recoveredLiteralCommand(command: unknown): string | null {
881
- if (!isUnknownArray(command) || command.length !== 3) return null;
882
- if (
883
- !["-c", "-lc"].includes(String(command[1])) ||
884
- typeof command[2] !== "string"
885
- )
886
- return null;
887
- return command[2];
888
- }
889
- function recoveredSessionReads(
890
- entries: NativeEntry[],
891
- ): Map<string, { command: string; output: string }> {
892
- const output = nativeCommandOutputs(entries);
893
- const counts = commandIdentityCounts(entries);
894
- const recovered = new Map<string, { command: string; output: string }>();
895
- for (const { ordinal, payload } of entries) {
896
- const item = uniqueRecoveryItem(payload, counts);
897
- if (!item) continue;
898
- const read = recoveredCommandRead(
899
- item.command,
900
- output.get(ordinal)?.output,
901
- );
902
- if (read) recovered.set(item.id, read);
903
- }
904
- return recovered;
905
- }
906
- function recoveredCommandRead(value: unknown, output: string | undefined) {
907
- if (output === undefined) return null;
908
- const command = recoveredLiteralCommand(value);
909
- return command === null ? null : { command, output };
910
- }
@@ -1,190 +1,17 @@
1
1
  import {
2
- awaitHostProcess,
3
- boundedProcessText,
4
- MAX_EVENT_BYTES,
5
- HostProcessInterruption,
2
+ HostProcessFailure,
3
+ runHostProcess,
4
+ type HostProcessOptions,
5
+ type HostProcessResult,
6
+ type Phase,
6
7
  } from "./process-lifecycle";
7
- import type { HostResult } from "../evaluation-types";
8
8
 
9
- type Phase = NonNullable<HostResult["processFailure"]>["phase"];
10
- type Result = {
11
- code: number;
12
- out: string;
13
- stderr: Uint8Array;
14
- stderrTruncated: boolean;
15
- signal: string | null;
16
- durationMs: number;
17
- };
18
-
19
- export function codexFailureMessage(result: HostResult): string | undefined {
20
- const failure = result.processFailure;
21
- if (!failure) return undefined;
22
- const labels = {
23
- "isolation-preflight": "Codex isolation preflight",
24
- "executable-preflight": "Codex executable preflight",
25
- execution: "Codex run",
26
- };
27
- if (!Object.hasOwn(labels, failure.phase)) return undefined;
28
- return `${labels[failure.phase]} ${failureSuffix(failure)}`;
29
- }
30
-
31
- function validTimeout(timeoutMs: number): boolean {
32
- return (
33
- Number.isSafeInteger(timeoutMs) && timeoutMs > 0 && timeoutMs <= 30 * 60_000
34
- );
35
- }
36
-
37
- function failureSuffix(
38
- failure: NonNullable<HostResult["processFailure"]>,
39
- ): string {
40
- if (failure.reason === "timeout" && validTimeout(failure.timeoutMs))
41
- return `timed out after ${failure.timeoutMs / 1000} s`;
42
- return failure.reason === "cancelled" ? "cancelled" : "failed";
43
- }
44
-
45
- export class CodexProcessFailure extends Error {
46
- readonly result: HostResult;
47
- constructor(
48
- phase: Phase,
49
- process: Result,
50
- reason: NonNullable<HostResult["processFailure"]>["reason"] = "exit",
51
- timeoutMs = 60_000,
52
- ) {
53
- const failure = { phase, reason, timeoutMs };
54
- super(
55
- codexFailureMessage({
56
- finalMessage: null,
57
- complete: false,
58
- processFailure: failure,
59
- }),
60
- );
61
- this.result = {
62
- finalMessage: null,
63
- complete: false,
64
- executionFailed: true,
65
- actualCondition: "passive",
66
- processFailure: failure,
67
- artifacts: [
68
- {
69
- id: "codex.process",
70
- bytes: Buffer.from(
71
- JSON.stringify({
72
- ...failure,
73
- code: process.code,
74
- signal: process.signal,
75
- durationMs: process.durationMs,
76
- stderrTruncated: process.stderrTruncated,
77
- }),
78
- ),
79
- },
80
- { id: "codex.stderr", bytes: process.stderr },
81
- ],
82
- };
83
- }
84
- }
85
-
86
- /** Drain stderr even after the retained 64 KiB prefix is full. */
87
- async function captureStderr(stream: ReadableStream<Uint8Array>) {
88
- const chunks: Uint8Array[] = [];
89
- let size = 0;
90
- let truncated = false;
91
- for await (const bytes of stream) {
92
- const retained = bytes.subarray(0, Math.max(0, 64 * 1024 - size));
93
- if (retained.byteLength) chunks.push(retained);
94
- size += retained.byteLength;
95
- truncated ||= retained.byteLength !== bytes.byteLength;
9
+ export class CodexProcessFailure extends HostProcessFailure {
10
+ constructor(phase: Phase, result: HostProcessResult) {
11
+ super("Codex", phase, result);
96
12
  }
97
- return { bytes: Buffer.concat(chunks), truncated };
98
13
  }
99
14
 
100
- function stopProcess(proc: Bun.Subprocess): void {
101
- if (process.platform !== "win32") {
102
- try {
103
- process.kill(-proc.pid, "SIGKILL");
104
- return;
105
- } catch {
106
- // The group may have exited before cancellation.
107
- }
108
- }
109
- try {
110
- proc.kill("SIGKILL");
111
- } catch {
112
- // The process already exited.
113
- }
114
- }
115
-
116
- interface CodexProcessOptions {
117
- argv: string[];
118
- cwd: string;
119
- env: Record<string, string>;
120
- input?: string;
121
- timeoutMs: number;
122
- signal?: AbortSignal;
123
- phase?: Phase;
124
- }
125
-
126
- async function writeCodexInput(
127
- proc: Bun.Subprocess,
128
- input?: string,
129
- ): Promise<void> {
130
- if (input === undefined) return;
131
- if (!proc.stdin || typeof proc.stdin === "number")
132
- throw new Error("Codex input pipe unavailable");
133
- await proc.stdin.write(input);
134
- await proc.stdin.end();
135
- }
136
-
137
- function spawnCodexProcess(options: CodexProcessOptions) {
138
- return Bun.spawn(options.argv, {
139
- cwd: options.cwd,
140
- env: options.env,
141
- detached: process.platform !== "win32",
142
- stdin: options.input === undefined ? "ignore" : "pipe",
143
- stdout: "pipe",
144
- stderr: "pipe",
145
- });
146
- }
147
-
148
- function processPhase(options: CodexProcessOptions): Phase {
149
- return options.phase ?? "execution";
150
- }
151
-
152
- export async function runCodexProcess(
153
- options: CodexProcessOptions,
154
- ): Promise<Result> {
155
- if (options.signal?.aborted) throw new Error("Codex run cancelled");
156
- const started = performance.now();
157
- const proc = spawnCodexProcess(options);
158
- const completed = Promise.all([
159
- boundedProcessText(
160
- proc.stdout,
161
- MAX_EVENT_BYTES,
162
- "Codex event stream exceeds the size limit",
163
- ),
164
- proc.exited,
165
- captureStderr(proc.stderr),
166
- writeCodexInput(proc, options.input),
167
- ]).then(([out, code, stderr]) => ({
168
- out,
169
- code,
170
- stderr: stderr.bytes,
171
- stderrTruncated: stderr.truncated,
172
- signal: proc.signalCode ?? null,
173
- durationMs: performance.now() - started,
174
- }));
175
- try {
176
- return await awaitHostProcess(proc, completed, {
177
- ...options,
178
- host: "Codex",
179
- stop: stopProcess,
180
- });
181
- } catch (cause) {
182
- if (!(cause instanceof HostProcessInterruption)) throw cause;
183
- throw new CodexProcessFailure(
184
- processPhase(options),
185
- await completed,
186
- cause.reason,
187
- options.timeoutMs,
188
- );
189
- }
15
+ export function runCodexProcess(options: Omit<HostProcessOptions, "host">) {
16
+ return runHostProcess({ ...options, host: "Codex" });
190
17
  }
@@ -1,6 +1,8 @@
1
- import { isAbsolute, sep } from "node:path";
2
- import { insideRuntimeRoot, isRuntimeHomeRoot } from "../runtime-paths";
3
- import { workspaceBoundaryException } from "../workspace-state";
1
+ import { isAbsolute, join, sep } from "node:path";
2
+ import { minimalRoots as minimalProtectedRoots } from "../paths";
3
+ import { containsControl } from "../value-guards";
4
+ import { insideRuntimeRoot, isRuntimeHomeRoot } from "../runtime/paths";
5
+ import { workspaceBoundaryException } from "../fixtures/workspace-state";
4
6
  import {
5
7
  nativeStatePath,
6
8
  nativeStateProtectedRoots,
@@ -18,12 +20,7 @@ const LINUX_MINIMAL_READ_ROOTS = [
18
20
  ];
19
21
 
20
22
  function toml(value: string): string {
21
- if (
22
- Array.from(value).some(
23
- (character) =>
24
- character.charCodeAt(0) < 0x20 || character.charCodeAt(0) === 0x7f,
25
- )
26
- )
23
+ if (containsControl(value))
27
24
  throw new Error("Codex profile value contains a control character");
28
25
  return JSON.stringify(value);
29
26
  }
@@ -40,7 +37,9 @@ export function codexPermissionProfile(options: {
40
37
  commandEnvironment?: Record<string, string>;
41
38
  runtimeReadRoots?: string[];
42
39
  nativeReadRoots?: string[];
40
+ nativeWriteRoots?: string[];
43
41
  runtimeWriteRoot?: string;
42
+ localHttp?: boolean;
44
43
  }): string {
45
44
  if (!/^[a-z][a-z0-9_]*$/.test(options.id))
46
45
  throw new Error("invalid Codex permission profile ID");
@@ -51,8 +50,7 @@ export function codexPermissionProfile(options: {
51
50
  `default_permissions = ${toml(name)}`,
52
51
  'approval_policy = "never"',
53
52
  "allow_login_shell = false",
54
- "[features]",
55
- "hooks = false",
53
+ ...codexFeatureLines(options.localHttp),
56
54
  "",
57
55
  "[shell_environment_policy]",
58
56
  'inherit = "none"',
@@ -65,6 +63,7 @@ export function codexPermissionProfile(options: {
65
63
  ),
66
64
  `HOME = ${toml(options.commandHome)}`,
67
65
  `TMPDIR = ${toml(options.commandTemp)}`,
66
+ `TMPPREFIX = ${toml(join(options.commandTemp, sep))}`,
68
67
  "",
69
68
  `[permissions.${name}]`,
70
69
  'extends = ":workspace"',
@@ -79,30 +78,55 @@ export function codexPermissionProfile(options: {
79
78
  .sort()
80
79
  .map((root) => `${toml(root)} = "deny"`),
81
80
  ...readRootLines(options),
81
+ ...(options.nativeWriteRoots ?? []).map(
82
+ (root) => `${toml(root)} = "write"`,
83
+ ),
82
84
  `${toml(options.commandHome)} = "write"`,
83
85
  `${toml(options.commandTemp)} = "write"`,
84
86
  ...optionalRootLines(options.runtimeWriteRoot, "write"),
87
+ // Override Codex's metadata carveout only for this isolated fixture.
88
+ `${toml(join(options.workspace, ".git"))} = "write"`,
85
89
  "",
86
90
  `[permissions.${name}.filesystem.":workspace_roots"]`,
87
91
  '"." = "write"',
88
92
  "",
89
93
  `[permissions.${name}.network]`,
90
- "enabled = false",
94
+ ...networkProfile(options.localHttp),
91
95
  "",
92
96
  ].join("\n");
93
97
  }
94
98
 
99
+ function codexFeatureLines(localHttp: boolean | undefined): string[] {
100
+ return [
101
+ "[features]",
102
+ "hooks = false",
103
+ ...(localHttp ? ["network_proxy = true"] : []),
104
+ ];
105
+ }
106
+
107
+ function networkProfile(localHttp: boolean | undefined): string[] {
108
+ if (!localHttp) return ["enabled = false"];
109
+ return [
110
+ "enabled = true",
111
+ "allow_local_binding = true",
112
+ "allow_upstream_proxy = false",
113
+ 'domains = { "localhost" = "allow", "127.0.0.1" = "allow", "::1" = "allow" }',
114
+ ];
115
+ }
116
+
95
117
  function profileProtectedRoots(
96
118
  options: Parameters<typeof codexPermissionProfile>[0],
97
119
  ): string[] {
98
120
  const readRoots = profileReadRoots(options);
99
121
  const trustedRoots = [
100
122
  ...readRoots,
123
+ ...(options.nativeWriteRoots ?? []),
101
124
  ...(options.runtimeWriteRoot ? [options.runtimeWriteRoot] : []),
102
125
  ];
103
126
  const baselines = [
104
127
  ...LINUX_MINIMAL_READ_ROOTS,
105
128
  ...readRoots,
129
+ ...(options.nativeWriteRoots ?? []),
106
130
  options.workspace,
107
131
  options.commandHome,
108
132
  options.commandTemp,
@@ -192,15 +216,6 @@ function implicitLinuxHomeBoundary(
192
216
  );
193
217
  }
194
218
 
195
- function minimalProtectedRoots(roots: string[]): string[] {
196
- return [...new Set(roots)].filter(
197
- (root) =>
198
- !roots.some(
199
- (other) => other !== root && root.startsWith(`${other}${sep}`),
200
- ),
201
- );
202
- }
203
-
204
219
  function commandEnvironmentLines(
205
220
  environment: Record<string, string> = {},
206
221
  executableReadRoots: string[],
@@ -1,7 +1,7 @@
1
1
  import type { Dirent } from "node:fs";
2
2
  import { lstat, readFile, readdir, stat } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
- import { isMissingFile } from "../fixture-tools";
4
+ import { isMissingFile } from "../fixtures/tools";
5
5
 
6
6
  const MAX_SESSION_BYTES = 8 * 1024 * 1024;
7
7
  const MAX_SESSION_FILES = 1024;
@@ -104,11 +104,3 @@ export async function readNativeSession(path: string): Promise<string | null> {
104
104
  if (bytes.byteLength > MAX_SESSION_BYTES) return null;
105
105
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
106
106
  }
107
-
108
- export async function readNativeSessionText(
109
- path: string,
110
- ): Promise<string | null> {
111
- if ((await stat(path)).size > MAX_SESSION_BYTES) return null;
112
- const text = await readFile(path, "utf8");
113
- return Buffer.byteLength(text) > MAX_SESSION_BYTES ? null : text;
114
- }