@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
package/src/prune.ts ADDED
@@ -0,0 +1,300 @@
1
+ import { lstat, readFile, readdir, realpath, rm, stat } from "node:fs/promises";
2
+ import { basename, dirname, join, resolve } from "node:path";
3
+ import { parseArgs } from "node:util";
4
+ import { assertCliResult, assertRunEvidence } from "./schema";
5
+ import type { CliResultData, RunEvidenceData } from "./schema-types";
6
+ import { createReport } from "./report";
7
+ import { atomicWriteJson } from "./storage";
8
+ import { isRecord } from "./value-guards";
9
+ import {
10
+ acquireResultsLock,
11
+ retainedFile,
12
+ withResultsLock,
13
+ } from "./results-lock";
14
+ import { pruneNativeTranscripts } from "./transcript-retention";
15
+
16
+ interface RetainedResult {
17
+ directory: string;
18
+ result: CliResultData;
19
+ evidence: RunEvidenceData;
20
+ time: number;
21
+ }
22
+
23
+ interface RetainedStorage {
24
+ directories: string[];
25
+ roots: string[];
26
+ releases: (() => void)[];
27
+ }
28
+
29
+ type RetentionPolicy =
30
+ { keep: number; cutoff: null } | { keep: null; cutoff: number };
31
+
32
+ const durationUnits: Record<string, number> = {
33
+ ms: 1,
34
+ s: 1000,
35
+ m: 60_000,
36
+ h: 3_600_000,
37
+ d: 86_400_000,
38
+ w: 604_800_000,
39
+ };
40
+
41
+ function duration(value: string): number {
42
+ const match = /^([1-9]\d*)(ms|s|m|h|d|w)$/.exec(value);
43
+ if (!match)
44
+ throw new Error(
45
+ "--older-than requires a positive integer and ms, s, m, h, d or w",
46
+ );
47
+ const amount =
48
+ Number.parseInt(value, 10) *
49
+ Number(durationUnits[value.replace(/^\d+/, "")]);
50
+ if (!Number.isSafeInteger(amount))
51
+ throw new Error("--older-than exceeds the safe duration range");
52
+ return amount;
53
+ }
54
+
55
+ function count(value: string): number {
56
+ const amount = Number(value);
57
+ if (!/^[1-9]\d*$/.test(value) || !Number.isSafeInteger(amount))
58
+ throw new Error("--keep must be a positive safe integer");
59
+ return amount;
60
+ }
61
+
62
+ function parseInvocation(args: string[]) {
63
+ const { values } = parseArgs({
64
+ args,
65
+ strict: true,
66
+ options: {
67
+ "results-root": { type: "string" },
68
+ keep: { type: "string" },
69
+ latest: { type: "boolean" },
70
+ "older-than": { type: "string" },
71
+ "native-transcripts": { type: "boolean" },
72
+ },
73
+ });
74
+ return values;
75
+ }
76
+
77
+ function policy(values: ReturnType<typeof parseInvocation>): RetentionPolicy {
78
+ if (values.latest) return { keep: 1, cutoff: null };
79
+ if (values["older-than"] !== undefined)
80
+ return { keep: null, cutoff: Date.now() - duration(values["older-than"]) };
81
+ if (values.keep !== undefined)
82
+ return { keep: count(values.keep), cutoff: null };
83
+ return { keep: values["native-transcripts"] ? 0 : 10, cutoff: null };
84
+ }
85
+
86
+ function invocation(args: string[]) {
87
+ const values = parseInvocation(args);
88
+ const policies = [values.latest, values.keep, values["older-than"]].filter(
89
+ (value) => value !== undefined,
90
+ );
91
+ if (policies.length > 1) throw new Error("retention policies are exclusive");
92
+ if (values["results-root"] === "")
93
+ throw new Error("--results-root must not be empty");
94
+ return {
95
+ root: resolve(values["results-root"] ?? ".sevro/results"),
96
+ policy: policy(values),
97
+ nativeTranscripts: values["native-transcripts"] === true,
98
+ };
99
+ }
100
+
101
+ async function retainedResults(
102
+ root: string,
103
+ directories: string[],
104
+ ): Promise<RetainedResult[]> {
105
+ const results: RetainedResult[] = [];
106
+ for (const directory of directories) {
107
+ const path = join(directory, "result.json");
108
+ await retainedFile(path);
109
+ const result: unknown = JSON.parse(await readFile(path, "utf8"));
110
+ assertCliResult(result);
111
+ if (!(await finalizedAncestors(root, directory, result.runId))) continue;
112
+ if (result.evidencePath !== join(directory, "run.json"))
113
+ throw new Error(
114
+ `retained result references evidence outside its directory: ${path}`,
115
+ );
116
+ await retainedFile(result.evidencePath);
117
+ const evidence: unknown = JSON.parse(
118
+ await readFile(result.evidencePath, "utf8"),
119
+ );
120
+ assertRunEvidence(evidence);
121
+ await createReport([path]);
122
+ results.push({
123
+ directory,
124
+ result,
125
+ evidence,
126
+ time: (await stat(path)).mtimeMs,
127
+ });
128
+ }
129
+ return results.sort(
130
+ (left, right) =>
131
+ right.time - left.time || left.directory.localeCompare(right.directory),
132
+ );
133
+ }
134
+
135
+ async function resultDirectories(
136
+ parent: string,
137
+ storage: RetainedStorage,
138
+ ): Promise<void> {
139
+ let children = await resultChildren(parent);
140
+ if (
141
+ !storage.roots.includes(parent) &&
142
+ ((await resultsRoot(parent)) || children.results.length > 0)
143
+ ) {
144
+ storage.releases.push(await acquireResultsLock(parent));
145
+ storage.roots.push(parent);
146
+ children = await resultChildren(parent);
147
+ }
148
+ storage.directories.push(...children.results);
149
+ for (const directory of children.containers)
150
+ await resultDirectories(directory, storage);
151
+ }
152
+
153
+ async function resultChildren(parent: string) {
154
+ const results: string[] = [];
155
+ const containers: string[] = [];
156
+ const entries = await readdir(parent, { withFileTypes: true });
157
+ for (const entry of entries.sort((left, right) =>
158
+ left.name.localeCompare(right.name),
159
+ )) {
160
+ if (!entry.isDirectory()) continue;
161
+ const directory = join(parent, entry.name);
162
+ if (await retainedFile(join(directory, "result.json")))
163
+ results.push(directory);
164
+ else containers.push(directory);
165
+ }
166
+ return { results, containers };
167
+ }
168
+
169
+ async function resultsRoot(directory: string): Promise<boolean> {
170
+ const active = await lstat(join(directory, "active")).catch(
171
+ (cause: unknown) => {
172
+ if ((cause as NodeJS.ErrnoException).code === "ENOENT") return null;
173
+ throw cause;
174
+ },
175
+ );
176
+ if (active && !active.isDirectory())
177
+ throw new Error(`retained ownership must be a directory: ${directory}`);
178
+ return Boolean(
179
+ active || (await retainedFile(join(directory, ".retention-lock.sqlite"))),
180
+ );
181
+ }
182
+
183
+ async function finalized(root: string, runId: string | null): Promise<boolean> {
184
+ if (!runId || basename(runId) !== runId) return false;
185
+ const path = join(root, "active", `${runId}.json`);
186
+ if (!(await retainedFile(path))) return true;
187
+ const value: unknown = JSON.parse(await readFile(path, "utf8"));
188
+ if (!isRecord(value)) return false;
189
+ return finalizedRecord(value, runId);
190
+ }
191
+
192
+ async function finalizedAncestors(
193
+ root: string,
194
+ directory: string,
195
+ runId: string | null,
196
+ ): Promise<boolean> {
197
+ let ancestor = dirname(directory);
198
+ while (ancestor !== dirname(root)) {
199
+ if (!(await finalized(ancestor, runId))) return false;
200
+ ancestor = dirname(ancestor);
201
+ }
202
+ return true;
203
+ }
204
+
205
+ function finalizedRecord(
206
+ value: Record<string, unknown>,
207
+ runId: string,
208
+ ): boolean {
209
+ return (
210
+ value.format === "sevro.active-run.v1" &&
211
+ value.runId === runId &&
212
+ ["complete", "interrupted", "diagnostic"].includes(String(value.status))
213
+ );
214
+ }
215
+
216
+ function retainedByPolicy(results: RetainedResult[], policy: RetentionPolicy) {
217
+ const cutoff = policy.cutoff;
218
+ return cutoff === null
219
+ ? results.slice(0, policy.keep)
220
+ : results.filter((result) => result.time >= cutoff);
221
+ }
222
+
223
+ async function pruneResults(
224
+ root: string,
225
+ policy: RetentionPolicy,
226
+ storage: RetainedStorage,
227
+ ) {
228
+ const results = await retainedResults(root, storage.directories);
229
+ const remaining = retainedByPolicy(results, policy);
230
+ for (const resultsRoot of storage.roots) {
231
+ const latest = remaining.find((item) =>
232
+ item.directory.startsWith(`${resultsRoot}/`),
233
+ );
234
+ if (latest)
235
+ await atomicWriteJson(join(resultsRoot, "latest.json"), latest.result);
236
+ else await rm(join(resultsRoot, "latest.json"), { force: true });
237
+ }
238
+ const removed = results.filter((result) => !remaining.includes(result));
239
+ for (const result of removed) await rm(result.directory, { recursive: true });
240
+ return { removed: removed.length, kept: remaining.length };
241
+ }
242
+
243
+ async function pruneTranscripts(
244
+ root: string,
245
+ policy: RetentionPolicy,
246
+ directories: string[],
247
+ ) {
248
+ const results = await retainedResults(root, directories);
249
+ const preserved = retainedByPolicy(results, policy);
250
+ let removed = 0;
251
+ for (const { evidence } of results.filter(
252
+ (item) => !preserved.includes(item),
253
+ )) {
254
+ removed += await pruneNativeTranscripts(evidence);
255
+ }
256
+ return { removed, kept: results.length };
257
+ }
258
+
259
+ async function prune(options: ReturnType<typeof invocation>) {
260
+ const root = await realpath(options.root).catch((cause: unknown) => {
261
+ if ((cause as NodeJS.ErrnoException).code === "ENOENT") return null;
262
+ throw cause;
263
+ });
264
+ if (root === null) return { removed: 0, kept: 0 };
265
+ return withResultsLock(root, async () => {
266
+ const storage: RetainedStorage = {
267
+ directories: [],
268
+ roots: [root],
269
+ releases: [],
270
+ };
271
+ try {
272
+ await resultDirectories(root, storage);
273
+ return options.nativeTranscripts
274
+ ? await pruneTranscripts(root, options.policy, storage.directories)
275
+ : await pruneResults(root, options.policy, storage);
276
+ } finally {
277
+ for (const release of storage.releases.reverse()) release();
278
+ }
279
+ });
280
+ }
281
+
282
+ /** Explicitly remove old retained runs while keeping report's latest index usable. */
283
+ export async function pruneCommand(args: string[]): Promise<number> {
284
+ try {
285
+ const options = invocation(args);
286
+ const result = await prune(options);
287
+ const unit = options.nativeTranscripts
288
+ ? "native transcript bundle(s)"
289
+ : "result(s)";
290
+ process.stdout.write(
291
+ `Removed ${result.removed} ${unit}; kept ${result.kept}${options.nativeTranscripts ? " result(s)" : ""}.\n`,
292
+ );
293
+ return 0;
294
+ } catch (error) {
295
+ process.stderr.write(
296
+ `sevro prune: ${error instanceof Error ? error.message : "pruning failed"}\n`,
297
+ );
298
+ return 64;
299
+ }
300
+ }
package/src/report.ts CHANGED
@@ -1,38 +1,22 @@
1
- import type { CliResultData, RunEvidenceData } from "./schema-types";
1
+ import type {
2
+ CliResultData,
3
+ ReportData,
4
+ RunEvidenceData,
5
+ } from "./schema-types";
2
6
  import { readFile } from "node:fs/promises";
3
- import { isAbsolute } from "node:path";
7
+ import { isAbsolute, join, resolve } from "node:path";
4
8
  import { parseArgs } from "node:util";
5
9
  import { canonicalJson } from "./identity";
6
10
  import { assertCliResult, assertReport, assertRunEvidence } from "./schema";
11
+ import { canonicalRuntimeRoot } from "./runtime/paths";
12
+ import { nativeTranscriptRetention } from "./transcript-retention";
7
13
 
8
14
  type CliResult = CliResultData;
9
15
  type Evidence = RunEvidenceData;
10
16
  type Case = CliResult["cases"][number];
11
17
  type Trial = Case["trials"][number];
12
18
 
13
- export type ReportRow = {
14
- resultFile: string;
15
- evidencePath: string | null;
16
- runId: string | null;
17
- caseId: string;
18
- execution: string;
19
- grading: string;
20
- task: string;
21
- exitCode: number;
22
- trialCount: number;
23
- taskPassRate: number | null;
24
- candidateDurationMs: number | null;
25
- inputTokens: number | null;
26
- outputTokens: number | null;
27
- costUsd: number | null;
28
- runnerBuildDigest: string | null;
29
- evaluationDigest: string | null;
30
- requestedCondition: string | null;
31
- actualCondition: string | null;
32
- candidateRoute: { host: string; model: string; effort: string } | null;
33
- routes: Array<{ role: string; host: string; model: string; effort: string }>;
34
- domainOutcomes: Array<{ trial: number; id: string; status: string }>;
35
- };
19
+ export type ReportRow = ReportData["rows"][number];
36
20
 
37
21
  function sumKnown(values: Array<number | null | undefined>): number | null {
38
22
  return values.length && values.every((value) => value != null)
@@ -113,6 +97,7 @@ function reportRow(
113
97
  result: CliResult,
114
98
  selected: Case,
115
99
  evidence: Evidence | null,
100
+ transcripts: Awaited<ReturnType<typeof nativeTranscriptRetention>>,
116
101
  ): ReportRow {
117
102
  const retained = trialEvidence(selected.caseId, selected.trials, evidence);
118
103
  const candidateRoute = retainedCandidateRoute(evidence);
@@ -134,6 +119,14 @@ function reportRow(
134
119
  ...usage,
135
120
  ...retainedIdentity(evidence),
136
121
  candidateRoute,
122
+ nativeTranscripts: {
123
+ retained: transcripts.filter(
124
+ (item) => item.caseId === selected.caseId && !item.pruned,
125
+ ).length,
126
+ pruned: transcripts.filter(
127
+ (item) => item.caseId === selected.caseId && item.pruned,
128
+ ).length,
129
+ },
137
130
  domainOutcomes: selected.trials.flatMap((trial) =>
138
131
  (trial.domainOutcomes ?? []).map((outcome) => ({
139
132
  trial: trial.trial,
@@ -191,17 +184,11 @@ export async function createReport(paths: string[]) {
191
184
  if (!paths.length || new Set(paths).size !== paths.length)
192
185
  throw new Error("report needs distinct result files");
193
186
  const rows: ReportRow[] = [];
194
- const inputs: Array<{
195
- resultFile: string;
196
- execution: string;
197
- grading: string;
198
- task: string;
199
- exitCode: number;
200
- caseCount: number;
201
- }> = [];
187
+ const inputs: ReportData["inputs"] = [];
202
188
  for (const path of paths) {
203
189
  const result = await loadResult(path);
204
190
  const evidence = await loadEvidence(result);
191
+ const transcripts = await nativeTranscriptRetention(evidence);
205
192
  inputs.push({
206
193
  resultFile: path,
207
194
  execution: result.execution.status,
@@ -211,7 +198,7 @@ export async function createReport(paths: string[]) {
211
198
  caseCount: result.cases.length,
212
199
  });
213
200
  for (const selected of result.cases)
214
- rows.push(reportRow(path, result, selected, evidence));
201
+ rows.push(reportRow(path, result, selected, evidence, transcripts));
215
202
  }
216
203
  const report = {
217
204
  format: "sevro.report.v1",
@@ -268,7 +255,8 @@ export function renderReport(
268
255
  "## Retained evidence",
269
256
  "",
270
257
  ...report.rows.map(
271
- (row) => `- ${cell(row.caseId)}: ${row.evidencePath ?? "unavailable"}`,
258
+ (row) =>
259
+ `- ${cell(row.caseId)}: ${row.evidencePath ?? "unavailable"}${transcriptSummary(row)}`,
272
260
  ),
273
261
  "",
274
262
  ];
@@ -305,6 +293,11 @@ export function renderReport(
305
293
  return lines.join("\n");
306
294
  }
307
295
 
296
+ function transcriptSummary(row: ReportRow): string {
297
+ if (!row.nativeTranscripts) return "";
298
+ return `; native transcripts: ${row.nativeTranscripts.retained} retained, ${row.nativeTranscripts.pruned} pruned`;
299
+ }
300
+
308
301
  function passRateCell(rate: number | null): string {
309
302
  return rate === null ? "unknown" : `${(rate * 100).toFixed(0)}%`;
310
303
  }
@@ -326,7 +319,7 @@ function caseOutcomeLine(row: ReportRow): string {
326
319
  export async function reportCommand(argv: string[]): Promise<number> {
327
320
  try {
328
321
  const values = reportInvocation(argv);
329
- const report = await createReport(values["result-file"] ?? []);
322
+ const report = await createReport(await reportPaths(values));
330
323
  process.stdout.write(
331
324
  values.json ? `${JSON.stringify(report)}\n` : renderReport(report),
332
325
  );
@@ -345,12 +338,46 @@ function reportInvocation(argv: string[]) {
345
338
  options: {
346
339
  json: { type: "boolean" },
347
340
  "result-file": { type: "string", multiple: true },
341
+ latest: { type: "boolean" },
342
+ "results-root": { type: "string" },
348
343
  },
349
344
  });
350
345
  if (positionals.length !== 1 || positionals[0] !== "report")
351
346
  throw new Error("expected the report command");
352
347
  return values;
353
348
  }
349
+
350
+ async function reportPaths(
351
+ values: ReturnType<typeof reportInvocation>,
352
+ ): Promise<string[]> {
353
+ validateReportSource(values);
354
+ const paths = selectedReportPaths(values);
355
+ if (paths.some((path) => !path.trim()))
356
+ throw new Error("--result-file must name a readable retained result file");
357
+ return Promise.all(paths.map((path) => canonicalRuntimeRoot(resolve(path))));
358
+ }
359
+
360
+ function validateReportSource(
361
+ values: ReturnType<typeof reportInvocation>,
362
+ ): void {
363
+ if (values.latest && values["result-file"] !== undefined)
364
+ throw new Error("--latest and --result-file are exclusive");
365
+ if (values["results-root"] !== undefined && !values.latest)
366
+ throw new Error("--results-root requires --latest");
367
+ }
368
+
369
+ function selectedReportPaths(
370
+ values: ReturnType<typeof reportInvocation>,
371
+ ): string[] {
372
+ return values.latest
373
+ ? [
374
+ join(
375
+ values["results-root"] ?? join(process.cwd(), ".sevro", "results"),
376
+ "latest.json",
377
+ ),
378
+ ]
379
+ : (values["result-file"] ?? []);
380
+ }
354
381
  function reportErrorMessage(error: unknown): string {
355
382
  return error instanceof Error ? error.message : "invalid report input";
356
383
  }
@@ -1,5 +1,5 @@
1
1
  import type { ExtensionCase } from "./extension-session";
2
- import type { RepositoryFixture } from "./repository-fixture";
2
+ import type { RepositoryFixture } from "./fixtures/repository";
3
3
 
4
4
  function repositoryOverlay(fixture: RepositoryFixture) {
5
5
  return {
@@ -0,0 +1,42 @@
1
+ import { openLockDatabase } from "./sqlite-lock";
2
+ import { join } from "node:path";
3
+ import { lstat } from "node:fs/promises";
4
+
5
+ export async function retainedFile(path: string) {
6
+ const info = await lstat(path).catch((cause: unknown) => {
7
+ if ((cause as NodeJS.ErrnoException).code === "ENOENT") return null;
8
+ throw cause;
9
+ });
10
+ if (info && !info.isFile())
11
+ throw new Error(`retained storage must be a regular file: ${path}`);
12
+ return info;
13
+ }
14
+
15
+ /** Serialize result publication and pruning across CLI processes. Closing rolls back the lock transaction. */
16
+ export async function withResultsLock<T>(
17
+ root: string,
18
+ action: () => Promise<T>,
19
+ ): Promise<T> {
20
+ const release = await acquireResultsLock(root);
21
+ try {
22
+ return await action();
23
+ } finally {
24
+ release();
25
+ }
26
+ }
27
+
28
+ /** Hold a root lock while discovering and validating additional nested roots. */
29
+ export async function acquireResultsLock(root: string): Promise<() => void> {
30
+ await retainedFile(join(root, ".retention-lock.sqlite"));
31
+ const database = openLockDatabase(join(root, ".retention-lock.sqlite"));
32
+ try {
33
+ database.exec("PRAGMA busy_timeout = 5000");
34
+ database.exec("BEGIN IMMEDIATE");
35
+ return () => {
36
+ database.close();
37
+ };
38
+ } catch (cause) {
39
+ database.close();
40
+ throw cause;
41
+ }
42
+ }
package/src/results.ts CHANGED
@@ -1,21 +1,17 @@
1
- export type ExecutionStatus = "completed" | "failed" | "cancelled" | "not_run";
2
- export type GradingStatus =
3
- "completed" | "error" | "unavailable" | "not_requested";
4
- export type TaskVerdict = "passed" | "failed" | "not_assessed";
5
-
6
- export interface CheckOutcome {
7
- id: string;
8
- grader: string;
9
- status: "passed" | "failed" | "unavailable";
10
- detail?: string;
11
- evidenceRefs?: string[];
12
- }
13
-
14
- export interface Assessment {
15
- execution: { status: ExecutionStatus };
16
- grading: { status: GradingStatus };
17
- task: { verdict: TaskVerdict };
18
- }
1
+ import type {
2
+ Assessment,
3
+ CheckOutcome,
4
+ ExecutionStatus,
5
+ GradingStatus,
6
+ TaskVerdict,
7
+ } from "./contract-types";
8
+ export type {
9
+ Assessment,
10
+ CheckOutcome,
11
+ ExecutionStatus,
12
+ GradingStatus,
13
+ TaskVerdict,
14
+ } from "./contract-types";
19
15
 
20
16
  export interface TrialInput {
21
17
  execution: ExecutionStatus;
package/src/run-owner.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import { spawnSync } from "./runtime-process";
1
2
  import { isRecord } from "./value-guards";
2
- import { Database } from "bun:sqlite";
3
+ import { openLockDatabase } from "./sqlite-lock";
3
4
  import { randomUUID } from "node:crypto";
4
5
  import {
5
6
  mkdirSync,
@@ -115,11 +116,16 @@ function atomicJson(path: string, value: unknown): void {
115
116
  function withClaimLock<T>(claimPath: string, action: () => T): T {
116
117
  const locks = join(dirname(dirname(claimPath)), "locks");
117
118
  mkdirSync(locks, { recursive: true, mode: 0o700 });
118
- const database = new Database(join(locks, `${basename(claimPath)}.sqlite`));
119
+ const database = openLockDatabase(
120
+ join(locks, `${basename(claimPath)}.sqlite`),
121
+ );
119
122
  try {
120
- database.run("PRAGMA busy_timeout = 5000");
121
- database.run("CREATE TABLE IF NOT EXISTS mutex (id INTEGER PRIMARY KEY)");
122
- return database.transaction(action).immediate();
123
+ database.exec("PRAGMA busy_timeout = 5000");
124
+ database.exec("CREATE TABLE IF NOT EXISTS mutex (id INTEGER PRIMARY KEY)");
125
+ database.exec("BEGIN IMMEDIATE");
126
+ const result = action();
127
+ database.exec("COMMIT");
128
+ return result;
123
129
  } finally {
124
130
  database.close();
125
131
  }
@@ -159,16 +165,16 @@ function identityEnvironment(windows: boolean) {
159
165
  : { PATH: "/usr/bin:/bin", LC_ALL: "C" };
160
166
  }
161
167
 
162
- function processStartTime(result: ReturnType<typeof Bun.spawnSync>): string {
163
- return result.stdout?.toString().trim() ?? "";
168
+ function processStartTime(result: ReturnType<typeof spawnSync>): string {
169
+ return result.stdout.toString().trim();
164
170
  }
165
171
 
166
172
  export function processIdentity(pid: number): ProcessIdentity | null {
167
173
  const windows = process.platform === "win32";
168
174
  const argv = identityCommand(pid, windows);
169
- let result: ReturnType<typeof Bun.spawnSync>;
175
+ let result: ReturnType<typeof spawnSync>;
170
176
  try {
171
- result = Bun.spawnSync(argv, {
177
+ result = spawnSync(argv, {
172
178
  env: identityEnvironment(windows),
173
179
  stdout: "pipe",
174
180
  stderr: "ignore",
@@ -0,0 +1,21 @@
1
+ import { resolve, join } from "node:path";
2
+
3
+ export const sourceRuntime = import.meta.filename.endsWith(".ts");
4
+ export const runnerRoot = resolve(
5
+ import.meta.dirname,
6
+ sourceRuntime ? ".." : "../..",
7
+ );
8
+
9
+ export function examplePath(...parts: string[]): string {
10
+ const path = join(
11
+ runnerRoot,
12
+ ...(sourceRuntime ? [] : ["dist"]),
13
+ "examples",
14
+ ...parts,
15
+ );
16
+ return runtimeModule(path);
17
+ }
18
+
19
+ export function runtimeModule(path: string): string {
20
+ return sourceRuntime ? path : path.replace(/\.ts$/, ".js");
21
+ }