@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
@@ -0,0 +1,82 @@
1
+ import { setTimeout as sleep } from "node:timers/promises";
2
+ import { mkdir, rmdir, stat, utimes } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+
5
+ /**
6
+ * Claude Code serializes OAuth refresh through this directory lock in the
7
+ * configuration directory. These values match its lockfile settings, observed
8
+ * in Claude Code 2.1.284 and 2.1.309: stale after 60s, refreshed every 5s.
9
+ */
10
+ const LOCK_NAME = ".oauth_refresh.lock";
11
+ const STALE_MS = 60_000;
12
+ const UPDATE_MS = 5_000;
13
+ const RETRY_MS = 250;
14
+ const DEFAULT_WAIT_MS = 120_000;
15
+
16
+ /** Run an action while holding the refresh lock Claude Code also honors. */
17
+ export async function withClaudeRefreshLock<T>(
18
+ root: string,
19
+ action: () => Promise<T>,
20
+ { waitMs = DEFAULT_WAIT_MS, updateMs = UPDATE_MS } = {},
21
+ ): Promise<T> {
22
+ await mkdir(root, { recursive: true, mode: 0o700 });
23
+ const lock = join(root, LOCK_NAME);
24
+ await acquireLock(lock, Date.now() + waitMs);
25
+ const heartbeat = setInterval(() => {
26
+ void touchLock(lock);
27
+ }, updateMs);
28
+ try {
29
+ return await action();
30
+ } finally {
31
+ clearInterval(heartbeat);
32
+ await releaseLock(lock);
33
+ }
34
+ }
35
+
36
+ async function acquireLock(lock: string, deadline: number): Promise<void> {
37
+ while (!(await createLock(lock))) {
38
+ if (Date.now() >= deadline)
39
+ throw new Error(
40
+ "Timed out waiting for another process to refresh the Claude login",
41
+ );
42
+ await sleep(RETRY_MS);
43
+ }
44
+ }
45
+
46
+ async function createLock(lock: string): Promise<boolean> {
47
+ try {
48
+ await mkdir(lock);
49
+ return true;
50
+ } catch (cause) {
51
+ if ((cause as NodeJS.ErrnoException).code !== "EEXIST")
52
+ throw new Error("Claude refresh lock is unavailable", { cause });
53
+ }
54
+ await removeStaleLock(lock);
55
+ return false;
56
+ }
57
+
58
+ /** An abandoned holder stops touching the lock; reclaim it as Claude does. */
59
+ async function removeStaleLock(lock: string): Promise<void> {
60
+ try {
61
+ if (Date.now() - (await stat(lock)).mtimeMs > STALE_MS) await rmdir(lock);
62
+ } catch {
63
+ // Another contender released or reclaimed it first.
64
+ }
65
+ }
66
+
67
+ async function touchLock(lock: string): Promise<void> {
68
+ const now = new Date();
69
+ try {
70
+ await utimes(lock, now, now);
71
+ } catch {
72
+ // Release or reclamation races are resolved by the post-lock re-read.
73
+ }
74
+ }
75
+
76
+ async function releaseLock(lock: string): Promise<void> {
77
+ try {
78
+ await rmdir(lock);
79
+ } catch {
80
+ // Already removed; the heartbeat keeps a live holder from being reclaimed.
81
+ }
82
+ }
@@ -4,6 +4,7 @@ import { join } from "node:path";
4
4
  import type { HostAdapter } from "../engine";
5
5
  import { isRecord } from "../value-guards";
6
6
  import type { ClaudeToolCallsObservation } from "./claude-tool-calls";
7
+ import { parseClaudeEvents, type ClaudeEvents } from "./claude-events";
7
8
 
8
9
  type Entry = Record<string, unknown>;
9
10
  export interface ClaudeRepositoryInvocation {
@@ -13,15 +14,12 @@ export interface ClaudeRepositoryInvocation {
13
14
  prompt: string;
14
15
  }
15
16
 
16
- function entries(text: string): Entry[] {
17
- return text
18
- .split(/\r?\n/)
19
- .filter((line) => line.trim())
20
- .map((line) => {
21
- const value: unknown = JSON.parse(line);
22
- if (!isRecord(value)) throw new Error("invalid Claude session entry");
23
- return value;
24
- });
17
+ function entries(text: string | ClaudeEvents): Entry[] {
18
+ return parseClaudeEvents(text).lines.map((line) => {
19
+ if (!line.parsed) throw line.error;
20
+ if (!isRecord(line.value)) throw new Error("invalid Claude session entry");
21
+ return line.value;
22
+ });
25
23
  }
26
24
 
27
25
  function content(entry: Entry): string {
@@ -250,7 +248,7 @@ function bodyCorrelated(
250
248
  /** Read only the completed bound native session; retain no arguments or body. */
251
249
  export async function claudeRepositoryInvocationObservation(input: {
252
250
  invocation: ClaudeRepositoryInvocation;
253
- stream: string;
251
+ stream: string | ClaudeEvents;
254
252
  configRoot: string;
255
253
  workspace: string;
256
254
  tools: ClaudeToolCallsObservation;
@@ -264,14 +262,6 @@ export async function claudeRepositoryInvocationObservation(input: {
264
262
  } catch {
265
263
  /* Unavailable or malformed native evidence stays partial. */
266
264
  }
267
- const observed = input.tools.data.calls
268
- .filter((call) => call.name === "Skill")
269
- .map((call) => call.skill);
270
- const observedSkills = repositoryObservedSkills(
271
- receipt,
272
- input.invocation.skillName,
273
- observed,
274
- );
275
265
  return {
276
266
  id: "sevro.claude.repository-invocation" as const,
277
267
  completeness:
@@ -282,26 +272,11 @@ export async function claudeRepositoryInvocationObservation(input: {
282
272
  method: "native_repository_command",
283
273
  ...receipt,
284
274
  skill: input.invocation.skillName,
285
- primarySkill: observedSkills[0] ?? null,
286
- observedSkills,
287
275
  },
288
276
  };
289
277
  }
290
278
 
291
- function repositoryObservedSkills(
292
- receipt: Receipt,
293
- skillName: string,
294
- observed: string[],
295
- ): string[] {
296
- return [
297
- ...new Set([
298
- ...(receipt.accepted === true ? [skillName] : []),
299
- ...observed,
300
- ]),
301
- ];
302
- }
303
-
304
- function repositorySessionId(stream: string): string | null {
279
+ function repositorySessionId(stream: string | ClaudeEvents): string | null {
305
280
  const sessions = [
306
281
  ...new Set(
307
282
  entries(stream)
@@ -1,17 +1,18 @@
1
1
  import { isAbsolute } from "node:path";
2
2
  import { CLAUDE_AUTH_VARIABLES } from "./claude-credential";
3
- import type { RuntimePolicy } from "../runtime-config";
4
- import { runtimeHooksEnabled } from "../runtime-hooks";
5
- import { requireRuntimeReadRoots, isRuntimeHomeRoot } from "../runtime-paths";
3
+ import type { RuntimePolicy } from "../runtime/config";
4
+ import { runtimeHooksEnabled } from "../runtime/hooks";
5
+ import { requireRuntimeReadRoots, isRuntimeHomeRoot } from "../runtime/paths";
6
6
  import { nativeStatePath } from "../native-transcript-state";
7
7
  import {
8
8
  workspaceStatePath,
9
9
  workspaceBoundaryException,
10
- } from "../workspace-state";
10
+ } from "../fixtures/workspace-state";
11
11
 
12
12
  interface WritableRuntime {
13
13
  root: string;
14
14
  workspace: string;
15
+ cacheRoots?: string[];
15
16
  }
16
17
 
17
18
  function absoluteRule(root: string, tool: "Read" | "Edit"): string {
@@ -53,6 +54,10 @@ export function claudeHostSettings(
53
54
  throw new Error("Claude private state paths are invalid");
54
55
  const readRoots = runtimeReadRoots(runtimePolicy);
55
56
  requireRuntimeReadRoots(readRoots, [privateRoot, ...protectedRoots]);
57
+ requireRuntimeReadRoots(runtimeCacheRoots(runtime), [
58
+ privateRoot,
59
+ ...protectedRoots,
60
+ ]);
56
61
  return {
57
62
  disableAllHooks: !runtimeHooksEnabled(runtimePolicy),
58
63
  sandbox: {
@@ -95,6 +100,7 @@ function claudeFilesystemPolicy(
95
100
  workspace: string | undefined,
96
101
  ) {
97
102
  const runtimeWriteRoot = runtime?.root;
103
+ const writableRoots = runtimeWriteRoots(runtime);
98
104
  return {
99
105
  denyRead: [privateRoot, ...protectedRoots],
100
106
  allowRead: [
@@ -102,13 +108,18 @@ function claudeFilesystemPolicy(
102
108
  ...readRoots,
103
109
  ...transcriptReadRoots,
104
110
  ...pluginRoots,
105
- ...optionalRuntimeRoot(runtimeWriteRoot),
111
+ ...writableRoots,
106
112
  ],
107
- ...(runtimeWriteRoot ? { allowWrite: [runtimeWriteRoot] } : {}),
113
+ ...(writableRoots.length ? { allowWrite: writableRoots } : {}),
108
114
  denyWrite: [
109
115
  privateRoot,
110
116
  ...pluginRoots,
111
- ...writableProtectedRoots(protectedRoots, runtimeWriteRoot, workspace),
117
+ ...writableProtectedRoots(
118
+ protectedRoots,
119
+ runtimeWriteRoot,
120
+ workspace,
121
+ runtimeCacheRoots(runtime),
122
+ ),
112
123
  ...readRoots,
113
124
  ...transcriptReadRoots,
114
125
  ],
@@ -139,7 +150,7 @@ function claudePermissions(
139
150
  ? roots.filter((root) => !isRuntimeHomeRoot(root))
140
151
  : roots;
141
152
  const toolRoots = [...runtimeReadRoots(policy), ...transcriptReadRoots];
142
- const writableRoots = optionalRuntimeRoot(runtimeWriteRoot);
153
+ const writableRoots = runtimeWriteRoots(runtime);
143
154
  return {
144
155
  allow: claudeToolAllowRules(policy, runtime, managedWorkspace),
145
156
  ...(policy || managedWorkspace
@@ -153,7 +164,12 @@ function claudePermissions(
153
164
  }
154
165
  : {}),
155
166
  deny: [
156
- ...writableProtectedRoots(roots, runtimeWriteRoot).flatMap((root) =>
167
+ ...writableProtectedRoots(
168
+ roots,
169
+ runtimeWriteRoot,
170
+ workspace,
171
+ runtimeCacheRoots(runtime),
172
+ ).flatMap((root) =>
157
173
  protectedToolRules(
158
174
  root,
159
175
  readRoots.includes(root) &&
@@ -189,6 +205,7 @@ function claudeToolAllowRules(
189
205
  "Agent",
190
206
  absoluteRule(runtime.workspace, "Edit"),
191
207
  absoluteRule(runtime.root, "Edit"),
208
+ ...(runtime.cacheRoots ?? []).map((root) => absoluteRule(root, "Edit")),
192
209
  ];
193
210
  }
194
211
 
@@ -197,15 +214,35 @@ function writableProtectedRoots(
197
214
  roots: string[],
198
215
  runtimeWriteRoot: string | undefined,
199
216
  workspace?: string,
217
+ cacheRoots: string[] = [],
200
218
  ): string[] {
201
219
  const namespace = nativeStatePath();
202
220
  return roots.filter(
203
221
  (root) =>
204
222
  !workspaceBoundaryException(root, workspace).length &&
223
+ !sharedHomeGrant(root, cacheRoots) &&
205
224
  keepNativeWriteDeny(root, namespace, runtimeWriteRoot),
206
225
  );
207
226
  }
208
227
 
228
+ function sharedHomeGrant(root: string, cacheRoots: string[]): boolean {
229
+ return (
230
+ isRuntimeHomeRoot(root) &&
231
+ cacheRoots.some((cache) => cache.startsWith(`${root}/`))
232
+ );
233
+ }
234
+
235
+ function runtimeCacheRoots(runtime: WritableRuntime | undefined): string[] {
236
+ return runtime?.cacheRoots ?? [];
237
+ }
238
+
239
+ function runtimeWriteRoots(runtime: WritableRuntime | undefined): string[] {
240
+ return [
241
+ ...optionalRuntimeRoot(runtime?.root),
242
+ ...(runtime?.cacheRoots ?? []),
243
+ ];
244
+ }
245
+
209
246
  function keepNativeWriteDeny(
210
247
  root: string,
211
248
  namespace: string,
@@ -0,0 +1,169 @@
1
+ import { isRecord } from "../value-guards";
2
+ import {
3
+ summarizeClaudeEvents,
4
+ parseClaudeEvents,
5
+ type ClaudeEvents,
6
+ type ClaudeEventLine,
7
+ } from "./claude-events";
8
+
9
+ const MAX_CALLS = 128;
10
+ type Entry = Record<string, unknown>;
11
+ interface SkillCall {
12
+ sessionId: string;
13
+ parentToolUseId: string | null;
14
+ toolUseId: string;
15
+ invocation: string;
16
+ status: "unknown" | "succeeded" | "failed";
17
+ }
18
+ interface State {
19
+ calls: Map<string, SkillCall>;
20
+ partial: boolean;
21
+ truncated: boolean;
22
+ }
23
+
24
+ function label(value: unknown): string | null {
25
+ return typeof value === "string" && /^[A-Za-z0-9_.:-]{1,256}$/.test(value)
26
+ ? value
27
+ : null;
28
+ }
29
+
30
+ function blocks(event: Entry): unknown[] {
31
+ const content: unknown = isRecord(event.message)
32
+ ? event.message.content
33
+ : null;
34
+ return Array.isArray(content) ? content : [];
35
+ }
36
+
37
+ function key(event: Entry, id: string): string {
38
+ return JSON.stringify([
39
+ event.session_id ?? event.sessionId,
40
+ event.parent_tool_use_id ?? null,
41
+ id,
42
+ ]);
43
+ }
44
+
45
+ function call(event: Entry, block: Entry, state: State) {
46
+ const id = label(block.id);
47
+ const sessionId = label(event.session_id ?? event.sessionId);
48
+ const invocation = skillInput(block.input);
49
+ if (!id || !sessionId || !invocation) {
50
+ state.partial = true;
51
+ return;
52
+ }
53
+ addCall(
54
+ key(event, id),
55
+ {
56
+ sessionId,
57
+ parentToolUseId: label(event.parent_tool_use_id),
58
+ toolUseId: id,
59
+ invocation,
60
+ status: "unknown",
61
+ },
62
+ state,
63
+ );
64
+ }
65
+
66
+ function skillInput(input: unknown): string | null {
67
+ return isRecord(input) ? label(input.skill) : null;
68
+ }
69
+
70
+ function addCall(id: string, value: SkillCall, state: State) {
71
+ const previous = state.calls.get(id);
72
+ if (previous) {
73
+ state.partial ||= previous.invocation !== value.invocation;
74
+ return;
75
+ }
76
+ if (state.calls.size >= MAX_CALLS) {
77
+ state.truncated = true;
78
+ return;
79
+ }
80
+ state.calls.set(id, value);
81
+ }
82
+
83
+ function result(event: Entry, block: Entry, state: State) {
84
+ const id = label(block.tool_use_id);
85
+ if (!id) return;
86
+ const pending = state.calls.get(key(event, id));
87
+ if (!pending) return;
88
+ const status = resultStatus(block.is_error);
89
+ if (!status) {
90
+ state.partial = true;
91
+ return;
92
+ }
93
+ state.partial ||= conflictingResult(pending.status, status);
94
+ pending.status = status;
95
+ }
96
+
97
+ function resultStatus(value: unknown): "failed" | "succeeded" | null {
98
+ if (value !== undefined && typeof value !== "boolean") return null;
99
+ return value === true ? "failed" : "succeeded";
100
+ }
101
+
102
+ function conflictingResult(
103
+ previous: SkillCall["status"],
104
+ next: SkillCall["status"],
105
+ ): boolean {
106
+ return previous !== "unknown" && previous !== next;
107
+ }
108
+
109
+ function visit(line: ClaudeEventLine, state: State) {
110
+ if (!line.parsed || !isRecord(line.value)) {
111
+ state.partial = true;
112
+ return;
113
+ }
114
+ for (const block of blocks(line.value)) visitBlock(line.value, block, state);
115
+ }
116
+
117
+ function visitBlock(event: Entry, block: unknown, state: State) {
118
+ if (!isRecord(block)) return;
119
+ switch (event.type) {
120
+ case "assistant":
121
+ if (isSkillCall(block)) call(event, block, state);
122
+ break;
123
+ case "user":
124
+ if (block.type === "tool_result") result(event, block, state);
125
+ }
126
+ }
127
+
128
+ function isSkillCall(block: Entry): boolean {
129
+ return block.type === "tool_use" && block.name === "Skill";
130
+ }
131
+
132
+ function completeCollection(completed: boolean, state: State): boolean {
133
+ return (
134
+ completed &&
135
+ !state.partial &&
136
+ !state.truncated &&
137
+ [...state.calls.values()].every((item) => item.status !== "unknown")
138
+ );
139
+ }
140
+
141
+ /** Observe the native Skill seam and distinguish successful results from attempts. */
142
+ export function claudeSkillActivationsObservation(
143
+ stream: string | ClaudeEvents,
144
+ code: number,
145
+ ) {
146
+ const events = parseClaudeEvents(stream);
147
+ const summary = summarizeClaudeEvents(events, code);
148
+ const state: State = { calls: new Map(), partial: false, truncated: false };
149
+ for (const line of events.lines) visit(line, state);
150
+ const calls = [...state.calls.values()];
151
+ const complete = completeCollection(summary.complete, state);
152
+ return {
153
+ id: "sevro.host.skill-activations",
154
+ completeness: complete ? ("complete" as const) : ("partial" as const),
155
+ data: {
156
+ method: "skill_tool_result",
157
+ visibility: "skill_tool",
158
+ observedSkills: [
159
+ ...new Set(
160
+ calls
161
+ .filter((item) => item.status === "succeeded")
162
+ .map((item) => item.invocation),
163
+ ),
164
+ ],
165
+ calls,
166
+ truncated: state.truncated,
167
+ },
168
+ };
169
+ }
@@ -1,4 +1,6 @@
1
- import { runtimeSeedSources } from "../runtime-config";
1
+ import { runtimeSeedSources } from "../runtime/config";
2
+ import { minimalRoots } from "../paths";
3
+ import { shellQuote } from "../shell";
2
4
  import {
3
5
  candidateArtifactEnvironment,
4
6
  candidateArtifactReadRoots,
@@ -17,17 +19,21 @@ import { nativeStateParent } from "../native-transcript-state";
17
19
  import {
18
20
  workspaceBoundaryException,
19
21
  workspaceStatePath,
20
- } from "../workspace-state";
22
+ } from "../fixtures/workspace-state";
21
23
  import {
22
24
  candidateTranscriptEnvironment,
23
25
  candidateTranscriptRoots,
24
26
  } from "../native-transcripts";
25
- import { prepareHookMounts, runtimeHooksEnabled } from "../runtime-hooks";
27
+ import { prepareHookMounts, runtimeHooksEnabled } from "../runtime/hooks";
26
28
  import {
27
29
  insideRuntimeRoot as inside,
28
30
  runtimeExecutableProtection,
29
- } from "../runtime-paths";
30
- import { prepareRuntimeState } from "../runtime-state";
31
+ } from "../runtime/paths";
32
+ import { prepareRuntimeState } from "../runtime/state";
33
+ import {
34
+ sharedCacheDenyRoots,
35
+ sharedCacheRoots,
36
+ } from "../runtime/shared-cache";
31
37
  import { stageClaudeAuthentication } from "./claude-credential";
32
38
  import { claudeHostSettings } from "./claude-settings";
33
39
  import { evaluationProtectedRoots } from "./isolation-roots";
@@ -44,12 +50,7 @@ export interface ClaudeHostOptions {
44
50
  toolchainBinDir?: string;
45
51
  projectSettings?: boolean;
46
52
  timeoutMs?: number;
47
- }
48
-
49
- function minimalRoots(roots: string[]): string[] {
50
- return roots.filter(
51
- (root) => !roots.some((other) => other !== root && inside(other, root)),
52
- );
53
+ retainHostDiagnostics?: boolean;
53
54
  }
54
55
 
55
56
  function claudeSeedSources(request: Request): string[] {
@@ -59,6 +60,7 @@ function claudeSeedSources(request: Request): string[] {
59
60
  async function createClaudePrivateState(
60
61
  stateRoot: string,
61
62
  options: ClaudeHostOptions,
63
+ loginLifetimeMs: number,
62
64
  ) {
63
65
  await mkdir(join(stateRoot, "private"), { mode: 0o700 });
64
66
  const privateRoot = await realpath(join(stateRoot, "private"));
@@ -68,6 +70,7 @@ async function createClaudePrivateState(
68
70
  const authentication = await stageClaudeAuthentication(
69
71
  join(privateRoot, "config"),
70
72
  options.credentialFile,
73
+ { binary: options.binary, lifetimeMs: loginLifetimeMs },
71
74
  );
72
75
  return {
73
76
  privateRoot,
@@ -189,14 +192,16 @@ function claudeRuntimeEnvironment(
189
192
  : {};
190
193
  }
191
194
 
195
+ /** `lifetimeMs` is the access-token lifetime the complete execution needs. */
192
196
  export async function prepareClaudeState(
193
197
  stateRoot: string,
194
198
  options: ClaudeHostOptions,
195
199
  request: Request,
196
200
  pluginDirs: string[],
201
+ lifetimeMs: number,
197
202
  ) {
198
203
  await requireClaudeRuntimeNamespace(request, stateRoot);
199
- const state = await createClaudePrivateState(stateRoot, options);
204
+ const state = await createClaudePrivateState(stateRoot, options, lifetimeMs);
200
205
  const transcripts = await claudeTranscriptAccess(
201
206
  stateRoot,
202
207
  state.credential,
@@ -221,6 +226,11 @@ export async function prepareClaudeState(
221
226
  runtime,
222
227
  stateRoot,
223
228
  );
229
+ const cacheRoots = await sharedCacheRoots(
230
+ request.runtimePolicy,
231
+ request.runtimeRole,
232
+ roots,
233
+ );
224
234
  await writeFile(
225
235
  settingsPath,
226
236
  JSON.stringify(
@@ -228,7 +238,10 @@ export async function prepareClaudeState(
228
238
  state.privateRoot,
229
239
  state.credential,
230
240
  [...pluginDirs, ...effectivePlugins],
231
- roots,
241
+ [
242
+ ...roots,
243
+ ...sharedCacheDenyRoots(request.runtimePolicy, request.runtimeRole),
244
+ ],
232
245
  transcripts.policy,
233
246
  [
234
247
  ...transcripts.readRoots,
@@ -236,7 +249,7 @@ export async function prepareClaudeState(
236
249
  ...candidateArtifactReadRoots(request.candidateArtifactRoots),
237
250
  ],
238
251
  runtimeWriteRoot
239
- ? { root: runtimeWriteRoot, workspace: request.workspace }
252
+ ? { root: runtimeWriteRoot, workspace: request.workspace, cacheRoots }
240
253
  : undefined,
241
254
  request.workspace,
242
255
  ),
@@ -308,7 +321,7 @@ async function claudeTranscriptAccess(
308
321
  await mkdir(projects, { recursive: true, mode: 0o700 });
309
322
  await symlink(projects, join(dirname(credential), "projects"));
310
323
  const startup = join(view, "shell-env");
311
- const script = `export CLAUDE_CONFIG_DIR='${view.replaceAll("'", `'"'"'`)}'\n`;
324
+ const script = `export CLAUDE_CONFIG_DIR=${shellQuote(view)}\n`;
312
325
  await writeFile(startup, script, { flag: "wx", mode: 0o600 });
313
326
  await writeFile(join(view, ".zshenv"), script, { flag: "wx", mode: 0o600 });
314
327
  return {
@@ -1,6 +1,11 @@
1
1
  import { sha256 } from "../identity";
2
2
  import { isRecord } from "../value-guards";
3
- import { summarizeClaudeEvents } from "./claude-events";
3
+ import {
4
+ summarizeClaudeEvents,
5
+ parseClaudeEvents,
6
+ type ClaudeEvents,
7
+ type ClaudeEventLine,
8
+ } from "./claude-events";
4
9
 
5
10
  const MAX_RETAINED_CALLS = 128;
6
11
  type Entry = Record<string, unknown>;
@@ -51,18 +56,18 @@ type Actor = { actor: "parent" | "nested"; parentToolUseId: string | null };
51
56
 
52
57
  /** Retain ordered host call metadata, never tool prompts or results. */
53
58
  export function claudeToolCallsObservation(
54
- stream: string,
59
+ stream: string | ClaudeEvents,
55
60
  exitCode: number,
56
61
  ): ClaudeToolCallsObservation {
57
- const summary = summarizeClaudeEvents(stream, exitCode);
62
+ const events = parseClaudeEvents(stream);
63
+ const summary = summarizeClaudeEvents(events, exitCode);
58
64
  const state: CallState = {
59
65
  calls: [],
60
66
  malformed: false,
61
67
  truncated: false,
62
68
  ordinal: 0,
63
69
  };
64
- for (const line of stream.split("\n")) {
65
- if (!line.trim()) continue;
70
+ for (const line of events.lines) {
66
71
  collectEvent(line, state);
67
72
  if (state.truncated) break;
68
73
  }
@@ -86,14 +91,12 @@ function callCompleteness(
86
91
  : "partial";
87
92
  }
88
93
 
89
- function collectEvent(line: string, state: CallState): void {
90
- let event: unknown;
91
- try {
92
- event = JSON.parse(line);
93
- } catch {
94
+ function collectEvent(line: ClaudeEventLine, state: CallState): void {
95
+ if (!line.parsed) {
94
96
  state.malformed = true;
95
97
  return;
96
98
  }
99
+ const event = line.value;
97
100
  if (!isRecord(event) || event.type !== "assistant") return;
98
101
  collectAssistant(event, state);
99
102
  }