@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,10 +1,15 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
+ import { gunzipSync } from "node:zlib";
3
4
  import { allocateNativeState } from "./native-transcript-state";
4
- import { fixtureParts } from "./preparation";
5
+ import { fixtureParts } from "./fixtures/preparation";
5
6
  import { isRecord, isUnknownArray } from "./value-guards";
6
7
  import { sha256 } from "./identity";
7
8
 
9
+ const MAX_NATIVE_BYTES = 5 * 1024 * 1024;
10
+ type NativeFormat =
11
+ "sevro.native-transcripts.v1" | "sevro.native-transcripts.v2";
12
+
8
13
  export async function materializeNativeTranscriptView(
9
14
  bytes: Uint8Array,
10
15
  ): Promise<string> {
@@ -12,19 +17,33 @@ export async function materializeNativeTranscriptView(
12
17
  const bundle = nativeBundle(value);
13
18
  const root = await allocateNativeState("view-");
14
19
  await writeFile(join(root, "index.json"), bytes, { flag: "wx", mode: 0o600 });
20
+ const filesRoot = join(root, bundle.host);
21
+ let remainingBytes = MAX_NATIVE_BYTES;
15
22
  for (const item of bundle.files)
16
- await materializeNativeFile(root, bundle.host, item);
23
+ remainingBytes -= await materializeNativeFile(
24
+ filesRoot,
25
+ item,
26
+ bundle.format,
27
+ remainingBytes,
28
+ );
17
29
  return root;
18
30
  }
19
31
 
20
32
  function nativeBundle(value: unknown) {
21
- if (!isRecord(value) || value.format !== "sevro.native-transcripts.v1")
33
+ if (!isRecord(value) || !nativeFormat(value.format))
22
34
  throw new Error("invalid native transcript bundle");
23
35
  if (!nativeHost(value.host))
24
36
  throw new Error("invalid native transcript host");
25
37
  if (!isUnknownArray(value.files))
26
38
  throw new Error("invalid native transcript files");
27
- return { host: value.host, files: value.files };
39
+ return { host: value.host, files: value.files, format: value.format };
40
+ }
41
+
42
+ function nativeFormat(value: unknown): value is NativeFormat {
43
+ return (
44
+ value === "sevro.native-transcripts.v1" ||
45
+ value === "sevro.native-transcripts.v2"
46
+ );
28
47
  }
29
48
 
30
49
  function nativeHost(value: unknown): value is "codex" | "claude" {
@@ -33,19 +52,39 @@ function nativeHost(value: unknown): value is "codex" | "claude" {
33
52
 
34
53
  async function materializeNativeFile(
35
54
  root: string,
36
- host: string,
37
55
  value: unknown,
38
- ): Promise<void> {
39
- if (
40
- !isRecord(value) ||
41
- typeof value.path !== "string" ||
42
- typeof value.bytesBase64 !== "string"
43
- )
56
+ format: NativeFormat,
57
+ remainingBytes: number,
58
+ ): Promise<number> {
59
+ if (!isRecord(value) || typeof value.path !== "string")
44
60
  throw new Error("invalid native transcript file");
45
- const path = join(root, host, ...fixtureParts(value.path));
46
- const bytes = Buffer.from(value.bytesBase64, "base64");
61
+ const path = join(root, ...fixtureParts(value.path));
62
+ const bytes = nativeFileBytes(value, format, remainingBytes);
63
+ if (bytes.length > remainingBytes)
64
+ throw new Error("native transcript byte limit exceeded");
47
65
  if (sha256(bytes) !== value.sha256)
48
66
  throw new Error("native transcript hash mismatch");
49
67
  await mkdir(dirname(path), { recursive: true, mode: 0o700 });
50
68
  await writeFile(path, bytes, { flag: "wx", mode: 0o600 });
69
+ return bytes.length;
70
+ }
71
+
72
+ function nativeFileBytes(
73
+ value: Record<string, unknown>,
74
+ format: NativeFormat,
75
+ remainingBytes: number,
76
+ ): Buffer {
77
+ const encoded =
78
+ format === "sevro.native-transcripts.v1"
79
+ ? value.bytesBase64
80
+ : value.gzipBase64;
81
+ if (typeof encoded !== "string")
82
+ throw new Error("invalid native transcript file");
83
+ const bytes = Buffer.from(encoded, "base64");
84
+ if (format === "sevro.native-transcripts.v1") return bytes;
85
+ try {
86
+ return gunzipSync(bytes, { maxOutputLength: Math.max(1, remainingBytes) });
87
+ } catch (cause) {
88
+ throw new Error("invalid native transcript gzip", { cause });
89
+ }
51
90
  }
@@ -1,11 +1,15 @@
1
1
  import { lstat, readdir, readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
+ import { gzipSync } from "node:zlib";
3
4
  import { sha256 } from "./identity";
4
- import type { HostResult } from "./evaluation-types";
5
- import type { RuntimeRole } from "./runtime-state";
6
- import type { RuntimePolicy } from "./runtime-config";
5
+ import { HostExecutionFailure, type HostResult } from "./evaluation/types";
6
+ import type { RuntimeRole } from "./runtime/state";
7
+ import type { RuntimePolicy } from "./runtime/config";
7
8
  import { isRecord } from "./value-guards";
8
- import { CodexProcessFailure } from "./hosts/codex-process";
9
+ import {
10
+ rethrowDiagnosticPersistenceError,
11
+ type HostDiagnostics,
12
+ } from "./host-diagnostics";
9
13
 
10
14
  export function candidateTranscriptRoots(root: string | undefined): string[] {
11
15
  return root ? [root] : [];
@@ -48,11 +52,13 @@ export async function failedNativeTranscripts(
48
52
  policy: RuntimePolicy | undefined,
49
53
  root: string,
50
54
  host: "codex" | "claude",
51
- role?: RuntimeRole,
55
+ role: RuntimeRole | undefined,
56
+ diagnostics: HostDiagnostics,
52
57
  ): Promise<HostResult> {
53
- if (policy?.nativeTranscripts !== true) throw cause;
58
+ rethrowDiagnosticPersistenceError(cause);
59
+ requireFailureCapture(cause, policy, diagnostics);
54
60
  const result: HostResult =
55
- cause instanceof CodexProcessFailure
61
+ cause instanceof HostExecutionFailure
56
62
  ? cause.result
57
63
  : {
58
64
  finalMessage: null,
@@ -60,14 +66,23 @@ export async function failedNativeTranscripts(
60
66
  executionFailed: true,
61
67
  actualCondition: "passive",
62
68
  };
63
- await retainNativeTranscripts(result, root, host, role);
69
+ await diagnostics.retain(result, cause);
70
+ await retainEnabledNativeTranscripts(result, policy, root, host, role);
64
71
  return result;
65
72
  }
66
73
 
74
+ function requireFailureCapture(
75
+ cause: unknown,
76
+ policy: RuntimePolicy | undefined,
77
+ diagnostics: HostDiagnostics,
78
+ ): void {
79
+ if (policy?.nativeTranscripts !== true && !diagnostics.enabled) throw cause;
80
+ }
81
+
67
82
  const MAX_FILES = 4096;
68
83
  const MAX_BYTES = 5 * 1024 * 1024;
69
84
  const MAX_ENCODED_FILES_BYTES = 7 * 1024 * 1024;
70
- type NativeFile = { path: string; sha256: string; bytesBase64: string };
85
+ type NativeFile = { path: string; sha256: string; gzipBase64: string };
71
86
  type Capture = {
72
87
  files: NativeFile[];
73
88
  bytes: number;
@@ -99,7 +114,7 @@ export async function retainNativeTranscripts(
99
114
  observeCaptureRoot(capture, rootSessionId, host);
100
115
  const completeness = captureCompleteness(capture, result);
101
116
  const bundle = {
102
- format: "sevro.native-transcripts.v1",
117
+ format: "sevro.native-transcripts.v2",
103
118
  host,
104
119
  role,
105
120
  rootSessionId,
@@ -212,7 +227,7 @@ async function captureFile(
212
227
  const file = {
213
228
  path,
214
229
  sha256: sha256(bytes),
215
- bytesBase64: bytes.toString("base64"),
230
+ gzipBase64: gzipSync(bytes).toString("base64"),
216
231
  };
217
232
  const issue = nativeFileIssue(path, bytes);
218
233
  if (issue && !capture.issues.includes(issue)) capture.issues.push(issue);
package/src/paths.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { isAbsolute, relative, sep } from "node:path";
2
+
3
+ /** Lexical containment includes the root itself; callers resolve symlinks first. */
4
+ export function insideRoot(root: string, path: string): boolean {
5
+ const child = relative(root, path);
6
+ return (
7
+ child === "" ||
8
+ (child !== ".." && !child.startsWith(`..${sep}`) && !isAbsolute(child))
9
+ );
10
+ }
11
+
12
+ /** Keep outermost roots in input order, retaining the first equivalent spelling. */
13
+ export function minimalRoots(roots: string[]): string[] {
14
+ return roots.filter(
15
+ (root, index) =>
16
+ !roots.some(
17
+ (other, otherIndex) =>
18
+ insideRoot(other, root) &&
19
+ (!insideRoot(root, other) || otherIndex < index),
20
+ ),
21
+ );
22
+ }
@@ -0,0 +1,150 @@
1
+ export type ProcessInterruptionReason = "timeout" | "cancelled";
2
+
3
+ interface DeadlineOptions {
4
+ timeoutMs: number;
5
+ signal?: AbortSignal;
6
+ interruption: (reason: ProcessInterruptionReason) => Error;
7
+ }
8
+
9
+ /** Keep the deadline active until the caller has finished failure cleanup. */
10
+ export class ProcessDeadline {
11
+ private timer: ReturnType<typeof setTimeout> | undefined;
12
+ private cancel: (() => void) | undefined;
13
+
14
+ constructor(private readonly options: DeadlineOptions) {}
15
+
16
+ wait<T>(completed: Promise<T> | (() => Promise<T>)): Promise<T> {
17
+ const timeout = this.timeout();
18
+ const aborted = this.aborted();
19
+ const completion =
20
+ typeof completed === "function" ? completed() : completed;
21
+ return Promise.race([completion, timeout, aborted]);
22
+ }
23
+
24
+ private timeout(): Promise<never> {
25
+ return new Promise((_resolve, reject) => {
26
+ this.timer = setTimeout(() => {
27
+ reject(this.options.interruption("timeout"));
28
+ }, this.options.timeoutMs);
29
+ });
30
+ }
31
+
32
+ private aborted(): Promise<never> {
33
+ return new Promise((_resolve, reject) => {
34
+ const signal = this.options.signal;
35
+ if (!signal) return;
36
+ this.cancel = () => {
37
+ reject(this.options.interruption("cancelled"));
38
+ };
39
+ if (signal.aborted) this.cancel();
40
+ else signal.addEventListener("abort", this.cancel, { once: true });
41
+ });
42
+ }
43
+
44
+ dispose(): void {
45
+ if (this.timer) clearTimeout(this.timer);
46
+ if (this.cancel)
47
+ this.options.signal?.removeEventListener("abort", this.cancel);
48
+ }
49
+ }
50
+
51
+ interface OwnedProcess {
52
+ pid: number;
53
+ kill: (signal: "SIGKILL") => unknown;
54
+ }
55
+
56
+ interface TerminationOptions {
57
+ alwaysGroup?: boolean;
58
+ fallbackError?: "ignore" | "propagate";
59
+ }
60
+
61
+ function killGroup(pid: number): boolean {
62
+ try {
63
+ process.kill(-pid, "SIGKILL");
64
+ return true;
65
+ } catch {
66
+ // The owned process group may already be gone.
67
+ return false;
68
+ }
69
+ }
70
+
71
+ function useProcessGroup(options: TerminationOptions): boolean {
72
+ return options.alwaysGroup === true || process.platform !== "win32";
73
+ }
74
+
75
+ function killOwnedProcess(
76
+ proc: OwnedProcess,
77
+ options: TerminationOptions,
78
+ ): void {
79
+ if (options.fallbackError === "propagate") {
80
+ proc.kill("SIGKILL");
81
+ return;
82
+ }
83
+ try {
84
+ proc.kill("SIGKILL");
85
+ } catch {
86
+ // The owned process may already have exited.
87
+ }
88
+ }
89
+
90
+ /** Only use for children spawned in a new, runner-owned process group. */
91
+ export function terminateOwnedProcessGroup(
92
+ proc: OwnedProcess,
93
+ options: TerminationOptions = {},
94
+ ): void {
95
+ if (useProcessGroup(options) && killGroup(proc.pid)) return;
96
+ killOwnedProcess(proc, options);
97
+ }
98
+
99
+ type RejectedCapture = {
100
+ overflow: "reject";
101
+ exceeded: () => Error;
102
+ };
103
+
104
+ interface CaptureOptions {
105
+ limit: number;
106
+ observe?: (bytes: Uint8Array) => void;
107
+ cancelOnError?: boolean;
108
+ }
109
+
110
+ type ByteCaptureOptions = CaptureOptions &
111
+ (RejectedCapture | { overflow: "truncate" });
112
+
113
+ function retainedChunk(
114
+ bytes: Uint8Array,
115
+ size: number,
116
+ options: ByteCaptureOptions,
117
+ ): Uint8Array {
118
+ if (options.overflow === "reject" && size + bytes.byteLength > options.limit)
119
+ throw options.exceeded();
120
+ return bytes.subarray(0, Math.max(0, options.limit - size));
121
+ }
122
+
123
+ /** Truncation retains a byte prefix while still draining the entire stream. */
124
+ export async function captureBoundedBytes(
125
+ stream: ReadableStream<Uint8Array>,
126
+ options: ByteCaptureOptions,
127
+ ): Promise<{ bytes: Uint8Array; truncated: boolean }> {
128
+ const chunks: Uint8Array[] = [];
129
+ let size = 0;
130
+ let truncated = false;
131
+ for await (const bytes of stream.values({
132
+ preventCancel: !options.cancelOnError,
133
+ })) {
134
+ options.observe?.(bytes);
135
+ const retained = retainedChunk(bytes, size, options);
136
+ if (retained.byteLength) chunks.push(retained);
137
+ size += retained.byteLength;
138
+ truncated ||= retained.byteLength !== bytes.byteLength;
139
+ }
140
+ return { bytes: Buffer.concat(chunks), truncated };
141
+ }
142
+
143
+ /** Reject oversize output before strictly decoding the complete UTF-8 stream. */
144
+ export async function captureBoundedText(
145
+ stream: ReadableStream<Uint8Array>,
146
+ options: CaptureOptions & RejectedCapture,
147
+ ): Promise<string> {
148
+ const { bytes } = await captureBoundedBytes(stream, options);
149
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
150
+ }
package/src/provenance.ts CHANGED
@@ -1,10 +1,14 @@
1
+ import { runnerRoot, sourceRuntime } from "./runner-paths";
2
+ import { spawnSync } from "./runtime-process";
1
3
  import type { Stats } from "node:fs";
2
4
  import { lstat, readFile, readdir, readlink, realpath } from "node:fs/promises";
3
5
  import { tmpdir } from "node:os";
4
- import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
6
+ import { dirname, join, relative, resolve, sep } from "node:path";
7
+ import { insideRoot } from "./paths";
5
8
  import { pathToFileURL } from "node:url";
6
- import packageJson from "../package.json";
9
+ import packageJson from "../package.json" with { type: "json" };
7
10
  import { hashJson, sha256 } from "./identity";
11
+ import { insideRuntimeRoot } from "./runtime/paths";
8
12
 
9
13
  const MAX_DIRTY_BYTES = 32 * 1024 * 1024;
10
14
  const MAX_BUILD_BYTES = 64 * 1024 * 1024;
@@ -47,9 +51,7 @@ class BuildSnapshot {
47
51
  }
48
52
 
49
53
  /** Digest the packaged runtime and public contract files in path order. */
50
- export async function packageBuildDigest(
51
- root = join(import.meta.dir, ".."),
52
- ): Promise<string> {
54
+ export async function packageBuildDigest(root = runnerRoot): Promise<string> {
53
55
  const snapshot = new BuildSnapshot(await realpath(root));
54
56
  for (const path of [
55
57
  "package.json",
@@ -58,6 +60,7 @@ export async function packageBuildDigest(
58
60
  "examples",
59
61
  "schemas",
60
62
  "src",
63
+ ...(!sourceRuntime ? ["dist"] : []),
61
64
  ])
62
65
  await snapshot.collect(path);
63
66
  return hashJson({
@@ -136,7 +139,7 @@ export async function projectIdentityDigest(
136
139
  }
137
140
 
138
141
  function git(root: string, ...arguments_: string[]): Buffer {
139
- const result = Bun.spawnSync(["git", "-C", root, ...arguments_], {
142
+ const result = spawnSync(["git", "-C", root, ...arguments_], {
140
143
  env: { PATH: process.env.PATH ?? "/usr/bin:/bin", LC_ALL: "C" },
141
144
  stdout: "pipe",
142
145
  stderr: "ignore",
@@ -147,7 +150,10 @@ function git(root: string, ...arguments_: string[]): Buffer {
147
150
  return Buffer.from(result.stdout);
148
151
  }
149
152
 
150
- async function dirtyPatchDigest(gitRoot: string): Promise<string | null> {
153
+ async function dirtyPatchDigest(
154
+ gitRoot: string,
155
+ excludedRoots: string[],
156
+ ): Promise<string | null> {
151
157
  const trackedPatch = git(gitRoot, "diff", "--binary", "HEAD", "--");
152
158
  const untrackedPaths = git(
153
159
  gitRoot,
@@ -159,6 +165,12 @@ async function dirtyPatchDigest(gitRoot: string): Promise<string | null> {
159
165
  .toString("utf8")
160
166
  .split("\0")
161
167
  .filter(Boolean)
168
+ .filter(
169
+ (path) =>
170
+ !excludedRoots.some((root) =>
171
+ insideRuntimeRoot(root, resolve(gitRoot, path)),
172
+ ),
173
+ )
162
174
  .sort();
163
175
  let dirtyBytes = trackedPatch.byteLength;
164
176
  const untracked: { path: string; sha256: string }[] = [];
@@ -175,8 +187,7 @@ async function dirtyPatchDigest(gitRoot: string): Promise<string | null> {
175
187
  }
176
188
 
177
189
  function requireSafeUntrackedPath(root: string, absolute: string): void {
178
- const path = relative(root, absolute);
179
- if (isAbsolute(path) || path === ".." || path.startsWith(`..${sep}`))
190
+ if (!insideRoot(root, absolute))
180
191
  throw new Error("Git checkout has an unsafe untracked path");
181
192
  }
182
193
  async function untrackedIdentityBytes(
@@ -209,7 +220,7 @@ export async function checkoutProvenance(root: string, buildDigest: string) {
209
220
  source: "checkout" as const,
210
221
  root: pathToFileURL(canonicalRoot).href,
211
222
  revision,
212
- dirtyPatchDigest: await dirtyPatchDigest(canonicalRoot),
223
+ dirtyPatchDigest: await dirtyPatchDigest(canonicalRoot, []),
213
224
  buildDigest,
214
225
  };
215
226
  }
@@ -249,7 +260,10 @@ async function emptyTemporaryGitPlaceholder(
249
260
  );
250
261
  }
251
262
 
252
- export async function projectProvenance(root: string) {
263
+ export async function projectProvenance(
264
+ root: string,
265
+ excludedRoots?: string[],
266
+ ) {
253
267
  const canonicalRoot = await realpath(root);
254
268
  const gitEntryRoot = await enclosingGitRoot(canonicalRoot);
255
269
  if (!gitEntryRoot)
@@ -279,16 +293,23 @@ export async function projectProvenance(root: string) {
279
293
  return {
280
294
  root: pathToFileURL(canonicalRoot).href,
281
295
  revision,
282
- dirtyPatchDigest: await dirtyPatchDigest(gitRoot),
296
+ dirtyPatchDigest: await projectDirtyDigest(gitRoot, excludedRoots),
283
297
  };
284
298
  }
285
299
 
300
+ async function projectDirtyDigest(
301
+ root: string,
302
+ excludedRoots: string[] | undefined,
303
+ ) {
304
+ return dirtyPatchDigest(root, excludedRoots ?? []);
305
+ }
306
+
286
307
  export async function runnerProvenance(
287
308
  buildDigest: string,
288
309
  checkoutRoot?: string,
289
310
  ) {
290
311
  if (checkoutRoot) {
291
- const actualRoot = await realpath(join(import.meta.dir, ".."));
312
+ const actualRoot = await realpath(runnerRoot);
292
313
  if ((await realpath(checkoutRoot)) !== actualRoot)
293
314
  throw new Error(
294
315
  "local Sevro checkout root does not match the running package",