@bjoernrochel/sevro 1.0.0 → 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 (403) hide show
  1. package/CONTRIBUTING.md +34 -4
  2. package/README.md +7 -6
  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/architecture.md +5 -2
  349. package/docs/creating-cases.md +2 -3
  350. package/docs/development-cli.md +12 -7
  351. package/docs/documentation-quality.md +4 -3
  352. package/docs/evaluation-workflow.md +8 -8
  353. package/docs/getting-started.md +7 -6
  354. package/docs/guide-evaluation.md +1 -1
  355. package/docs/identity-v1.md +4 -1
  356. package/docs/installing.md +31 -13
  357. package/docs/licensing.md +2 -2
  358. package/docs/native-hosts.md +1 -1
  359. package/docs/recipes.md +41 -40
  360. package/docs/releases.md +20 -4
  361. package/docs/run-settings-v1.md +3 -3
  362. package/docs/specs/repository-guide.md +1 -1
  363. package/docs/troubleshooting.md +1 -1
  364. package/docs/typescript-quality.md +18 -1
  365. package/examples/recipes/executable.ts +19 -0
  366. package/examples/recipes/extension-artifacts.ts +1 -1
  367. package/examples/recipes/extension.ts +2 -1
  368. package/examples/recipes/modules.ts +9 -0
  369. package/examples/recipes/run-inputs.ts +14 -19
  370. package/examples/recipes/run-options.ts +9 -8
  371. package/examples/recipes/run.ts +21 -7
  372. package/examples/templates/repository-skill/extension-data.ts +1 -1
  373. package/examples/templates/repository-skill/extension.ts +2 -1
  374. package/package.json +14 -6
  375. package/src/cli/demo.ts +3 -2
  376. package/src/cli/help.ts +4 -3
  377. package/src/cli/init-settings.ts +5 -4
  378. package/src/cli/init.ts +9 -8
  379. package/src/cli/invocation.ts +2 -1
  380. package/src/cli/preparation.ts +2 -2
  381. package/src/cli.ts +1 -1
  382. package/src/executable.ts +19 -0
  383. package/src/extension-client.ts +6 -12
  384. package/src/fixtures/setup.ts +3 -2
  385. package/src/git.ts +2 -1
  386. package/src/graders/git-head.ts +3 -2
  387. package/src/graders/shell.ts +4 -3
  388. package/src/hosts/claude-keychain.ts +3 -2
  389. package/src/hosts/claude-login-refresh.ts +3 -2
  390. package/src/hosts/claude-refresh-lock.ts +2 -1
  391. package/src/hosts/isolation-roots.ts +3 -2
  392. package/src/hosts/process-lifecycle.ts +4 -6
  393. package/src/hosts/protected-worktrees.ts +2 -1
  394. package/src/hosts/skill-hook-handler.ts +1 -1
  395. package/src/hosts/skill-hooks.ts +10 -2
  396. package/src/provenance.ts +7 -6
  397. package/src/results-lock.ts +4 -4
  398. package/src/run-owner.ts +15 -9
  399. package/src/runner-paths.ts +21 -0
  400. package/src/runtime/hook-processes.ts +2 -1
  401. package/src/runtime/hooks.ts +9 -7
  402. package/src/runtime-process.ts +194 -0
  403. package/src/sqlite-lock.ts +25 -0
package/CONTRIBUTING.md CHANGED
@@ -29,7 +29,10 @@ by applicable law.
29
29
  Use Bun 1.3.13, Git, Node 24, npm, and ripgrep (`rg`). Full suite isolation uses `sandbox-exec`
30
30
  on macOS or `bubblewrap` and `socat` on Ubuntu. The macOS synthetic libc regression
31
31
  fixtures compile with `/usr/bin/cc`, supplied by Apple's Command Line Tools.
32
- Windows acceptance is unverified.
32
+ Windows acceptance is unverified. Bun remains the development runtime; installed
33
+ users may use Node without Bun. `bun run build` generates ignored `dist/`
34
+ JavaScript and source maps. `npm pack` builds automatically through `prepack`;
35
+ when packing with `--ignore-scripts`, build explicitly first.
33
36
  From a fresh checkout:
34
37
 
35
38
  ```sh
@@ -42,11 +45,38 @@ Its complete recipe checks also require UV, Python 3, mise, and an existing
42
45
  `mise install node@24.13.0` installation; see [recipe prerequisites](docs/recipes.md).
43
46
  CI explicitly provisions these tools. Missing prerequisites fail with a named
44
47
  setup instruction rather than skipping a recipe.
45
- To run recipe commands from this source checkout, set
46
- `export SEVRO_RECIPES="$PWD/examples/recipes"` from the repository root, then
47
- follow the [recipe commands](docs/recipes.md#prepare-a-recipe-project).
48
+ To run the documented JavaScript recipes from this source checkout, build first:
49
+
50
+ ```sh
51
+ bun run build
52
+ export SEVRO_RECIPES="$PWD/dist/examples/recipes"
53
+ ```
54
+
55
+ Then follow the [recipe commands](docs/recipes.md#prepare-a-recipe-project).
48
56
  Native model trials need their own [credentials and prerequisites](docs/native-hosts.md).
49
57
 
58
+ ## Install a development archive
59
+
60
+ To try source changes in an installed package, prepare an archive from the
61
+ repository root with Bun:
62
+
63
+ ```sh
64
+ bun install --frozen-lockfile
65
+ bun run build
66
+ npm pack --ignore-scripts
67
+ ```
68
+
69
+ The last command prints the archive filename. Transfer that file to the consumer
70
+ project and install it with Node and npm; Bun is not required there:
71
+
72
+ ```sh
73
+ npm install --save-exact /absolute/path/to/candidate.tgz
74
+ ```
75
+
76
+ Continue with the [installed-package tutorial](docs/getting-started.md#from-an-installed-package).
77
+ This creates a development package; maintainers follow the separate
78
+ [release workflow](docs/releases.md) for publication.
79
+
50
80
  ## Quality contract and checks
51
81
 
52
82
  [The TypeScript quality contract](docs/typescript-quality.md) defines the checked
package/README.md CHANGED
@@ -19,11 +19,12 @@ Sevro is under active development. The npm package is `@bjoernrochel/sevro`;
19
19
  its command is `sevro`. The [current release](docs/installing.md#current-release) includes runtime
20
20
  configuration, native goals, selected plugin hooks, and the current licensing terms.
21
21
  Earlier `rc.1` and `rc.2` packages retain their original BSL grants.
22
- See [installation and release differences](docs/installing.md).
22
+ See [installation](docs/installing.md).
23
23
 
24
- Use Bun 1.3.13. The development checkout runs native isolation on macOS with
25
- `sandbox-exec` and on Ubuntu with `bubblewrap` and `socat`.
26
- Contributor package/release checks also need Node 24 and npm.
24
+ Run the installed package with Node.js 24.13.0 or newer, or Bun 1.3.13.
25
+ Bun is not required for Node users. Native isolation uses macOS `sandbox-exec`
26
+ or Ubuntu `bubblewrap` and `socat`. Contributors keep Bun 1.3.13 for development,
27
+ builds and tests, plus Node 24.13.0 and npm for package acceptance.
27
28
  Windows support is unverified. The basic example uses an injected
28
29
  deterministic adapter and needs no native model credentials.
29
30
 
@@ -32,7 +33,7 @@ deterministic adapter and needs no native model credentials.
32
33
  ```sh
33
34
  mkdir sevro-demo
34
35
  cd sevro-demo
35
- bun init -y
36
+ npm init -y
36
37
  ```
37
38
 
38
39
  Install the [current release](docs/installing.md#current-release) in that directory.
@@ -54,7 +55,7 @@ Machine-readable contracts live in [schemas/](schemas/).
54
55
 
55
56
  ## Ask the repository guide
56
57
 
57
- Open this checkout in a fresh Codex or Claude Code session and ask
58
+ Open the Sevro repository in a fresh Codex or Claude Code session and ask
58
59
  “What is Sevro, and how do I run my first evaluation?” Explicit invocation is
59
60
  `$sevro-guide` in Codex or `/sevro-guide` in Claude Code.
60
61
  The guide reads sources, cites its answers, and handles follow-ups. It explains
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": "basic-graded",
3
+ "prompt": "Return ready.",
4
+ "fixture": { "files": { "README.md": "fixture\n" } },
5
+ "checks": [
6
+ {
7
+ "id": "ready",
8
+ "grader": "sevro.regex",
9
+ "configuration": { "pattern": "^ready$" }
10
+ }
11
+ ],
12
+ "requiredEvidence": []
13
+ }
@@ -0,0 +1,9 @@
1
+ export default {
2
+ id: "sevro.host.example",
3
+ model: "deterministic-example",
4
+ effort: "none",
5
+ run() {
6
+ return Promise.resolve({ finalMessage: "ready", complete: true });
7
+ },
8
+ };
9
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["host.ts"],"names":[],"mappings":"AAAA,eAAe;IACb,EAAE,EAAE,oBAAoB;IACxB,KAAK,EAAE,uBAAuB;IAC9B,MAAM,EAAE,MAAM;IACd,GAAG;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;CACF,CAAC","sourcesContent":["export default {\n id: \"sevro.host.example\",\n model: \"deterministic-example\",\n effort: \"none\",\n run() {\n return Promise.resolve({ finalMessage: \"ready\", complete: true });\n },\n};\n"]}
@@ -0,0 +1,7 @@
1
+ {
2
+ "id": "basic-prompt-only",
3
+ "prompt": "Return ready.",
4
+ "fixture": { "files": { "README.md": "fixture\n" } },
5
+ "checks": [],
6
+ "requiredEvidence": []
7
+ }
@@ -0,0 +1,23 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ /** Trusted, deterministic participant for exercising the recipe's real graders. */
4
+ const host = {
5
+ id: "recipes.deterministic",
6
+ model: "fixture-editor",
7
+ effort: "none",
8
+ async run({ workspace }) {
9
+ const task = await readFile(join(workspace, "README.md"), "utf8");
10
+ const failing = process.env.SEVRO_RECIPE_FAIL === "1";
11
+ if (task.includes("Fix add")) {
12
+ await writeFile(join(workspace, "math.cjs"), `exports.add = (a, b) => a ${failing ? "-" : "+"} b;\n`);
13
+ }
14
+ return {
15
+ finalMessage: failing
16
+ ? "Start with npm start on port 9000."
17
+ : "Run bun run dev on port 3000.",
18
+ complete: true,
19
+ };
20
+ },
21
+ };
22
+ export default host;
23
+ //# sourceMappingURL=candidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate.js","sourceRoot":"","sources":["candidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,yBAAyB;AACvD,OAAO,EAAE,IAAI,EAAE,kBAAkB;AAEjC,mFAAmF;AACnF,MAAM,IAAI,GAAG;IACX,EAAE,EAAE,uBAAuB;IAC3B,KAAK,EAAE,gBAAgB;IACvB,MAAM,EAAE,MAAM;IACd,KAAK,CAAC,GAAG,CAAC,EAAE,SAAS,EAAyB;QAC5C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,CAAC;QACtD,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,MAAM,SAAS,CACb,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAC3B,6BAA6B,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CACxD,CAAC;QACJ,CAAC;QACD,OAAO;YACL,YAAY,EAAE,OAAO;gBACnB,CAAC,CAAC,oCAAoC;gBACtC,CAAC,CAAC,+BAA+B;YACnC,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;CACF,CAAC;AACF,eAAe,IAAI,CAAC","sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\n/** Trusted, deterministic participant for exercising the recipe's real graders. */\nconst host = {\n id: \"recipes.deterministic\",\n model: \"fixture-editor\",\n effort: \"none\",\n async run({ workspace }: { workspace: string }) {\n const task = await readFile(join(workspace, \"README.md\"), \"utf8\");\n const failing = process.env.SEVRO_RECIPE_FAIL === \"1\";\n if (task.includes(\"Fix add\")) {\n await writeFile(\n join(workspace, \"math.cjs\"),\n `exports.add = (a, b) => a ${failing ? \"-\" : \"+\"} b;\\n`,\n );\n }\n return {\n finalMessage: failing\n ? \"Start with npm start on port 9000.\"\n : \"Run bun run dev on port 3000.\",\n complete: true,\n };\n },\n};\nexport default host;\n"]}
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "recipe-coding-change",
3
+ "prompt": "Fix add in math.cjs so it adds its two numeric arguments. Do not modify README.md. Explain how to start the application.",
4
+ "fixture": {
5
+ "files": {
6
+ "README.md": "Fix add in math.cjs. Start the application with bun run dev on port 3000.\n",
7
+ "math.cjs": "exports.add = (a, b) => a - b;\n"
8
+ }
9
+ },
10
+ "checks": [
11
+ {
12
+ "id": "addition",
13
+ "grader": "sevro.shell",
14
+ "configuration": {
15
+ "run": "{{evaluator-test}}",
16
+ "expectExact": "coding checks passed"
17
+ }
18
+ }
19
+ ],
20
+ "requiredEvidence": []
21
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "recipe-host-tools",
3
+ "prompt": "Read app.env with rg, then explain the application's start command and port.",
4
+ "fixture": {
5
+ "files": {
6
+ "README.md": "Start with bun run dev on port 3000.\n",
7
+ "app.env": "port=3000\n"
8
+ }
9
+ },
10
+ "checks": [
11
+ {
12
+ "id": "rg-access",
13
+ "grader": "sevro.shell",
14
+ "configuration": {
15
+ "run": "rg '^port=3000$' app.env",
16
+ "expectExact": "port=3000"
17
+ }
18
+ }
19
+ ],
20
+ "requiredEvidence": []
21
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "recipe-mise",
3
+ "prompt": "Use node from PATH to read app.json, then explain the application's start command and port. The operator has resolved mise's existing node@24.13.0 installation; do not download anything.",
4
+ "fixture": {
5
+ "files": {
6
+ "README.md": "Start with bun run dev on port 3000.\n",
7
+ "app.json": "{\"port\":3000}\n"
8
+ }
9
+ },
10
+ "checks": [
11
+ {
12
+ "id": "mise-node-access",
13
+ "grader": "sevro.shell",
14
+ "configuration": {
15
+ "run": "node -e 'if (process.version !== \"v24.13.0\") process.exit(1); const a = require(\"./app.json\"); if (a.port !== 3000) process.exit(1); console.log(a.port)'",
16
+ "expectExact": "3000"
17
+ }
18
+ }
19
+ ],
20
+ "requiredEvidence": []
21
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "recipe-node",
3
+ "prompt": "Read app.json with Node and explain the application's start command and port.",
4
+ "fixture": {
5
+ "files": {
6
+ "README.md": "Start with bun run dev on port 3000.\n",
7
+ "app.json": "{\"port\":3000}\n"
8
+ }
9
+ },
10
+ "checks": [
11
+ {
12
+ "id": "node-access",
13
+ "grader": "sevro.shell",
14
+ "configuration": {
15
+ "run": "node -e 'const a = require(\"./app.json\"); if (a.port !== 3000) process.exit(1); console.log(a.port)'",
16
+ "expectExact": "3000"
17
+ }
18
+ }
19
+ ],
20
+ "requiredEvidence": []
21
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "recipe-python-uv",
3
+ "prompt": "Use uv run --offline --no-project --python \"$RECIPE_PYTHON\" python to read app.json, then explain the application's start command and port.",
4
+ "fixture": {
5
+ "files": {
6
+ "README.md": "Start with bun run dev on port 3000.\n",
7
+ "app.json": "{\"port\":3000}\n"
8
+ }
9
+ },
10
+ "checks": [
11
+ {
12
+ "id": "uv-python-access",
13
+ "grader": "sevro.shell",
14
+ "configuration": {
15
+ "run": "uv run --offline --no-project --python \"$RECIPE_PYTHON\" python -c 'import json; p=json.load(open(\"app.json\"))[\"port\"]; assert p == 3000; print(p)'",
16
+ "expectExact": "3000"
17
+ }
18
+ }
19
+ ],
20
+ "requiredEvidence": []
21
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "id": "recipe-semantic",
3
+ "prompt": "Read README.md and explain how to start the application, including its port.",
4
+ "fixture": {
5
+ "files": { "README.md": "Start with bun run dev on port 3000.\n" }
6
+ },
7
+ "checks": [
8
+ {
9
+ "id": "startup-meaning",
10
+ "grader": "sevro.semantic",
11
+ "configuration": {
12
+ "proposition": "The response tells the reader to run bun run dev and says that the application listens on port 3000."
13
+ }
14
+ }
15
+ ],
16
+ "requiredEvidence": []
17
+ }
@@ -0,0 +1,16 @@
1
+ import assert from "node:assert/strict";
2
+ import { join } from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ function isAddition(value) {
5
+ return (typeof value === "object" &&
6
+ value !== null &&
7
+ "add" in value &&
8
+ typeof value.add === "function");
9
+ }
10
+ const candidate = await import(pathToFileURL(join(process.cwd(), "math.cjs")).href);
11
+ assert.ok(isAddition(candidate), "Candidate must export add");
12
+ assert.equal(candidate.add(2, 3), 5);
13
+ assert.equal(candidate.add(-2, 3), 1);
14
+ assert.equal(candidate.add(0, 0), 0);
15
+ console.log("coding checks passed");
16
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["check.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,2BAA2B;AACxC,OAAO,EAAE,IAAI,EAAE,kBAAkB;AACjC,OAAO,EAAE,aAAa,EAAE,iBAAiB;AAKzC,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,KAAK,IAAI,KAAK;QACd,OAAO,KAAK,CAAC,GAAG,KAAK,UAAU,CAChC,CAAC;AACJ,CAAC;AACD,MAAM,SAAS,GAAY,MAAM,MAAM,CACrC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CACpD,CAAC;AACF,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,2BAA2B,CAAC,CAAC;AAC9D,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACtC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\ninterface Addition {\n add: (left: number, right: number) => number;\n}\nfunction isAddition(value: unknown): value is Addition {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"add\" in value &&\n typeof value.add === \"function\"\n );\n}\nconst candidate: unknown = await import(\n pathToFileURL(join(process.cwd(), \"math.cjs\")).href\n);\nassert.ok(isAddition(candidate), \"Candidate must export add\");\nassert.equal(candidate.add(2, 3), 5);\nassert.equal(candidate.add(-2, 3), 1);\nassert.equal(candidate.add(0, 0), 0);\nconsole.log(\"coding checks passed\");\n"]}
@@ -0,0 +1,20 @@
1
+ import { accessSync, constants, statSync } from "node:fs";
2
+ import { delimiter, resolve } from "node:path";
3
+ export function which(name, path) {
4
+ for (const directory of executablePath(path).split(delimiter)) {
5
+ const candidate = resolve(directory, name);
6
+ try {
7
+ accessSync(candidate, constants.X_OK);
8
+ if (statSync(candidate).isFile())
9
+ return candidate;
10
+ }
11
+ catch {
12
+ /* Continue searching the declared executable path. */
13
+ }
14
+ }
15
+ return null;
16
+ }
17
+ function executablePath(path) {
18
+ return path ?? process.env.PATH ?? "";
19
+ }
20
+ //# sourceMappingURL=executable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executable.js","sourceRoot":"","sources":["executable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB;AAC1D,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB;AAE/C,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,IAAa;IAC/C,KAAK,MAAM,SAAS,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE;gBAAE,OAAO,SAAS,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,sDAAsD;QACxD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,IAAwB;IAC9C,OAAO,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;AACxC,CAAC","sourcesContent":["import { accessSync, constants, statSync } from \"node:fs\";\nimport { delimiter, resolve } from \"node:path\";\n\nexport function which(name: string, path?: string): string | null {\n for (const directory of executablePath(path).split(delimiter)) {\n const candidate = resolve(directory, name);\n try {\n accessSync(candidate, constants.X_OK);\n if (statSync(candidate).isFile()) return candidate;\n } catch {\n /* Continue searching the declared executable path. */\n }\n }\n return null;\n}\n\nfunction executablePath(path: string | undefined): string {\n return path ?? process.env.PATH ?? \"\";\n}\n"]}
@@ -0,0 +1,56 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ export function artifact(relativePath, content) {
5
+ return {
6
+ id: `recipes.${createHash("sha256").update(relativePath).digest("hex").slice(0, 16)}`,
7
+ relativePath,
8
+ sha256: createHash("sha256").update(content).digest("hex"),
9
+ contentBase64: Buffer.from(content).toString("base64"),
10
+ gitExclude: true,
11
+ };
12
+ }
13
+ export async function repositoryArtifacts(host) {
14
+ const directory = host === "claude" ? ".claude" : ".agents";
15
+ const relative = `${directory}/skills/startup-guide/SKILL.md`;
16
+ const body = await readFile(join(import.meta.dirname, "repository-skill", relative), "utf8");
17
+ return [artifact(relative, body)];
18
+ }
19
+ export function pluginArtifacts() {
20
+ const files = {
21
+ "marketplace/.claude-plugin/marketplace.json": JSON.stringify({
22
+ name: "recipes",
23
+ owner: { name: "Sevro examples" },
24
+ plugins: [
25
+ { name: "startup", source: "./plugin", description: "Startup recipe" },
26
+ ],
27
+ }),
28
+ "marketplace/plugin/.claude-plugin/plugin.json": JSON.stringify({
29
+ name: "startup",
30
+ version: "1.0.0",
31
+ }),
32
+ "marketplace/plugin/.codex-plugin/plugin.json": JSON.stringify({
33
+ name: "startup",
34
+ version: "1.0.0",
35
+ skills: "./skills/",
36
+ }),
37
+ "marketplace/plugin/skills/startup-guide/SKILL.md": "---\nname: startup-guide\ndescription: Explain application startup.\n---\nRead README.md. Explain its command and port.\n",
38
+ "marketplace/plugin/hooks/hooks.json": JSON.stringify({
39
+ hooks: {
40
+ SessionStart: [
41
+ {
42
+ hooks: [
43
+ {
44
+ type: "command",
45
+ command: '/bin/sh "${CLAUDE_PLUGIN_ROOT}/hooks/start.sh"',
46
+ },
47
+ ],
48
+ },
49
+ ],
50
+ },
51
+ }),
52
+ "marketplace/plugin/hooks/start.sh": "#!/bin/sh\nprintf 'hook ran\\n' > \"$PWD/hook-ran.txt\"\n",
53
+ };
54
+ return Object.entries(files).map(([path, content]) => artifact(path, content));
55
+ }
56
+ //# sourceMappingURL=extension-artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-artifacts.js","sourceRoot":"","sources":["extension-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,oBAAoB;AACzC,OAAO,EAAE,QAAQ,EAAE,yBAAyB;AAC5C,OAAO,EAAE,IAAI,EAAE,kBAAkB;AAEjC,MAAM,UAAU,QAAQ,CAAC,YAAoB,EAAE,OAAe;IAC5D,OAAO;QACL,EAAE,EAAE,WAAW,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;QACrF,YAAY;QACZ,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAC1D,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACtD,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAY;IACpD,MAAM,SAAS,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,MAAM,QAAQ,GAAG,GAAG,SAAS,gCAAgC,CAAC;IAC9D,MAAM,IAAI,GAAG,MAAM,QAAQ,CACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,CAAC,EACvD,MAAM,CACP,CAAC;IACF,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,KAAK,GAAG;QACZ,6CAA6C,EAAE,IAAI,CAAC,SAAS,CAAC;YAC5D,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;YACjC,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE;aACvE;SACF,CAAC;QACF,+CAA+C,EAAE,IAAI,CAAC,SAAS,CAAC;YAC9D,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,OAAO;SACjB,CAAC;QACF,8CAA8C,EAAE,IAAI,CAAC,SAAS,CAAC;YAC7D,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,WAAW;SACpB,CAAC;QACF,kDAAkD,EAChD,2HAA2H;QAC7H,qCAAqC,EAAE,IAAI,CAAC,SAAS,CAAC;YACpD,KAAK,EAAE;gBACL,YAAY,EAAE;oBACZ;wBACE,KAAK,EAAE;4BACL;gCACE,IAAI,EAAE,SAAS;gCACf,OAAO,EAAE,gDAAgD;6BAC1D;yBACF;qBACF;iBACF;aACF;SACF,CAAC;QACF,mCAAmC,EACjC,2DAA2D;KAC9D,CAAC;IACF,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CACnD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CACxB,CAAC;AACJ,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport function artifact(relativePath: string, content: string) {\n return {\n id: `recipes.${createHash(\"sha256\").update(relativePath).digest(\"hex\").slice(0, 16)}`,\n relativePath,\n sha256: createHash(\"sha256\").update(content).digest(\"hex\"),\n contentBase64: Buffer.from(content).toString(\"base64\"),\n gitExclude: true,\n };\n}\n\nexport async function repositoryArtifacts(host: string) {\n const directory = host === \"claude\" ? \".claude\" : \".agents\";\n const relative = `${directory}/skills/startup-guide/SKILL.md`;\n const body = await readFile(\n join(import.meta.dirname, \"repository-skill\", relative),\n \"utf8\",\n );\n return [artifact(relative, body)];\n}\n\nexport function pluginArtifacts() {\n const files = {\n \"marketplace/.claude-plugin/marketplace.json\": JSON.stringify({\n name: \"recipes\",\n owner: { name: \"Sevro examples\" },\n plugins: [\n { name: \"startup\", source: \"./plugin\", description: \"Startup recipe\" },\n ],\n }),\n \"marketplace/plugin/.claude-plugin/plugin.json\": JSON.stringify({\n name: \"startup\",\n version: \"1.0.0\",\n }),\n \"marketplace/plugin/.codex-plugin/plugin.json\": JSON.stringify({\n name: \"startup\",\n version: \"1.0.0\",\n skills: \"./skills/\",\n }),\n \"marketplace/plugin/skills/startup-guide/SKILL.md\":\n \"---\\nname: startup-guide\\ndescription: Explain application startup.\\n---\\nRead README.md. Explain its command and port.\\n\",\n \"marketplace/plugin/hooks/hooks.json\": JSON.stringify({\n hooks: {\n SessionStart: [\n {\n hooks: [\n {\n type: \"command\",\n command: '/bin/sh \"${CLAUDE_PLUGIN_ROOT}/hooks/start.sh\"',\n },\n ],\n },\n ],\n },\n }),\n \"marketplace/plugin/hooks/start.sh\":\n \"#!/bin/sh\\nprintf 'hook ran\\\\n' > \\\"$PWD/hook-ran.txt\\\"\\n\",\n };\n return Object.entries(files).map(([path, content]) =>\n artifact(path, content),\n );\n}\n"]}
@@ -0,0 +1,167 @@
1
+ import { artifact, pluginArtifacts, repositoryArtifacts, } from "./extension-artifacts.js";
2
+ export function record(value) {
3
+ if (value === null || typeof value !== "object" || Array.isArray(value))
4
+ throw new Error("Expected a JSON object");
5
+ return value;
6
+ }
7
+ export function describe(mode, host) {
8
+ const capabilities = {
9
+ lifecycle: [],
10
+ "repository-skill": [`sevro.${host}.repository-invocation`],
11
+ plugins: host === "codex"
12
+ ? ["sevro.codex.plugin-marketplace", "sevro.codex.explicit-invocation"]
13
+ : ["sevro.claude.plugin-dirs", "sevro.claude.explicit-invocation"],
14
+ };
15
+ const requiredCapabilities = capabilities[mode];
16
+ if (!requiredCapabilities)
17
+ throw new Error("Unknown extension recipe");
18
+ return {
19
+ extension: { id: "recipes.startup", version: "1.0.0" },
20
+ protocols: ["sevro.extension.v1"],
21
+ requiredCapabilities,
22
+ optionalCapabilities: [],
23
+ graders: ["recipes.startup"],
24
+ taskVerdictPolicies: [],
25
+ };
26
+ }
27
+ function requiredInvocation(mode, host) {
28
+ if (mode !== "repository-skill")
29
+ return [];
30
+ return [
31
+ host === "codex"
32
+ ? "sevro.codex.explicit-invocation"
33
+ : "sevro.claude.repository-invocation",
34
+ ];
35
+ }
36
+ export function resolveCase(mode, host, fail) {
37
+ const invocation = mode === "lifecycle" ? "" : "{{sevro.skill_invocation}} ";
38
+ const prompt = fail
39
+ ? "Deliberate negative control: return only wrong."
40
+ : "Read README.md. Explain the application's start command and port. Do not change files.";
41
+ const requiredEvidence = requiredInvocation(mode, host);
42
+ return {
43
+ cases: [
44
+ {
45
+ id: "recipe-extension",
46
+ prompt: invocation + prompt,
47
+ fixture: {
48
+ kind: "generated",
49
+ commits: [
50
+ {
51
+ message: "chore: initialize sample",
52
+ files: { "README.md": "Run bun run dev on port 3000.\n" },
53
+ },
54
+ ],
55
+ },
56
+ checks: [
57
+ {
58
+ id: "startup-command",
59
+ grader: "sevro.regex",
60
+ configuration: { pattern: "bun run dev" },
61
+ },
62
+ {
63
+ id: "prepared-input",
64
+ grader: "sevro.shell",
65
+ configuration: {
66
+ run: "test \"$(cat startup.txt)\" = 'prepared startup data'",
67
+ },
68
+ },
69
+ ...(mode === "plugins"
70
+ ? [
71
+ {
72
+ id: "plugin-hook",
73
+ grader: "sevro.shell",
74
+ configuration: {
75
+ run: "cat hook-ran.txt",
76
+ expectExact: "hook ran",
77
+ },
78
+ },
79
+ ]
80
+ : []),
81
+ {
82
+ id: "recipes.startup.answer",
83
+ grader: "recipes.startup",
84
+ configuration: {},
85
+ },
86
+ ],
87
+ requiredEvidence,
88
+ extensionData: { "recipes.startup": { mode, host } },
89
+ },
90
+ ],
91
+ };
92
+ }
93
+ export async function prepare(mode, host) {
94
+ const base = {
95
+ artifacts: [artifact("startup.txt", "prepared startup data\n")],
96
+ requestedInstrumentation: [],
97
+ extensionData: { "recipes.startup": { mode, host } },
98
+ };
99
+ switch (mode) {
100
+ case "repository-skill":
101
+ return {
102
+ ...base,
103
+ artifacts: [...base.artifacts, ...(await repositoryArtifacts(host))],
104
+ ...(host === "codex"
105
+ ? { codexRepositorySkillInvocation: { skillName: "startup-guide" } }
106
+ : {
107
+ claudeRepositorySkillInvocation: { skillName: "startup-guide" },
108
+ }),
109
+ };
110
+ case "plugins":
111
+ return {
112
+ ...base,
113
+ artifacts: [...base.artifacts, ...pluginArtifacts()],
114
+ ...(host === "codex"
115
+ ? {
116
+ codexMarketplace: {
117
+ artifactRoot: "marketplace",
118
+ marketplaceName: "recipes",
119
+ pluginNames: ["startup"],
120
+ },
121
+ codexSkillInvocation: {
122
+ pluginName: "startup",
123
+ skillName: "startup-guide",
124
+ },
125
+ }
126
+ : {
127
+ claudePluginDirs: { artifactRoots: ["marketplace/plugin"] },
128
+ claudeSkillInvocation: {
129
+ pluginName: "startup",
130
+ skillName: "startup-guide",
131
+ },
132
+ }),
133
+ };
134
+ default:
135
+ return base;
136
+ }
137
+ }
138
+ function answerStatus(observation) {
139
+ if (observation.completeness !== "complete")
140
+ return "unavailable";
141
+ const text = record(observation.data).text;
142
+ return typeof text === "string" && /\b3000\b/.test(text)
143
+ ? "passed"
144
+ : "failed";
145
+ }
146
+ export function evaluate(params) {
147
+ if (!Array.isArray(params.observations))
148
+ throw new Error("Missing observations");
149
+ const observations = params.observations;
150
+ const observation = observations
151
+ .map(record)
152
+ .find((item) => item.id === "sevro.observation.final-message");
153
+ if (!observation)
154
+ throw new Error("Missing final-message observation");
155
+ const status = answerStatus(observation);
156
+ return {
157
+ checks: [
158
+ {
159
+ id: "recipes.startup.answer",
160
+ status,
161
+ evidenceRefs: ["sevro.observation.final-message"],
162
+ },
163
+ ],
164
+ metrics: [],
165
+ };
166
+ }
167
+ //# sourceMappingURL=extension-methods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-methods.js","sourceRoot":"","sources":["extension-methods.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n artifact,\n pluginArtifacts,\n repositoryArtifacts,\n} from \"./extension-artifacts\";\n\nexport function record(value: unknown): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value))\n throw new Error(\"Expected a JSON object\");\n return value as Record<string, unknown>;\n}\n\nexport function describe(mode: string, host: string) {\n const capabilities: Record<string, string[]> = {\n lifecycle: [],\n \"repository-skill\": [`sevro.${host}.repository-invocation`],\n plugins:\n host === \"codex\"\n ? [\"sevro.codex.plugin-marketplace\", \"sevro.codex.explicit-invocation\"]\n : [\"sevro.claude.plugin-dirs\", \"sevro.claude.explicit-invocation\"],\n };\n const requiredCapabilities = capabilities[mode];\n if (!requiredCapabilities) throw new Error(\"Unknown extension recipe\");\n return {\n extension: { id: \"recipes.startup\", version: \"1.0.0\" },\n protocols: [\"sevro.extension.v1\"],\n requiredCapabilities,\n optionalCapabilities: [],\n graders: [\"recipes.startup\"],\n taskVerdictPolicies: [],\n };\n}\n\nfunction requiredInvocation(mode: string, host: string): string[] {\n if (mode !== \"repository-skill\") return [];\n return [\n host === \"codex\"\n ? \"sevro.codex.explicit-invocation\"\n : \"sevro.claude.repository-invocation\",\n ];\n}\n\nexport function resolveCase(mode: string, host: string, fail: boolean) {\n const invocation = mode === \"lifecycle\" ? \"\" : \"{{sevro.skill_invocation}} \";\n const prompt = fail\n ? \"Deliberate negative control: return only wrong.\"\n : \"Read README.md. Explain the application's start command and port. Do not change files.\";\n const requiredEvidence = requiredInvocation(mode, host);\n return {\n cases: [\n {\n id: \"recipe-extension\",\n prompt: invocation + prompt,\n fixture: {\n kind: \"generated\",\n commits: [\n {\n message: \"chore: initialize sample\",\n files: { \"README.md\": \"Run bun run dev on port 3000.\\n\" },\n },\n ],\n },\n checks: [\n {\n id: \"startup-command\",\n grader: \"sevro.regex\",\n configuration: { pattern: \"bun run dev\" },\n },\n {\n id: \"prepared-input\",\n grader: \"sevro.shell\",\n configuration: {\n run: \"test \\\"$(cat startup.txt)\\\" = 'prepared startup data'\",\n },\n },\n ...(mode === \"plugins\"\n ? [\n {\n id: \"plugin-hook\",\n grader: \"sevro.shell\",\n configuration: {\n run: \"cat hook-ran.txt\",\n expectExact: \"hook ran\",\n },\n },\n ]\n : []),\n {\n id: \"recipes.startup.answer\",\n grader: \"recipes.startup\",\n configuration: {},\n },\n ],\n requiredEvidence,\n extensionData: { \"recipes.startup\": { mode, host } },\n },\n ],\n };\n}\n\nexport async function prepare(mode: string, host: string) {\n const base = {\n artifacts: [artifact(\"startup.txt\", \"prepared startup data\\n\")],\n requestedInstrumentation: [],\n extensionData: { \"recipes.startup\": { mode, host } },\n };\n switch (mode) {\n case \"repository-skill\":\n return {\n ...base,\n artifacts: [...base.artifacts, ...(await repositoryArtifacts(host))],\n ...(host === \"codex\"\n ? { codexRepositorySkillInvocation: { skillName: \"startup-guide\" } }\n : {\n claudeRepositorySkillInvocation: { skillName: \"startup-guide\" },\n }),\n };\n case \"plugins\":\n return {\n ...base,\n artifacts: [...base.artifacts, ...pluginArtifacts()],\n ...(host === \"codex\"\n ? {\n codexMarketplace: {\n artifactRoot: \"marketplace\",\n marketplaceName: \"recipes\",\n pluginNames: [\"startup\"],\n },\n codexSkillInvocation: {\n pluginName: \"startup\",\n skillName: \"startup-guide\",\n },\n }\n : {\n claudePluginDirs: { artifactRoots: [\"marketplace/plugin\"] },\n claudeSkillInvocation: {\n pluginName: \"startup\",\n skillName: \"startup-guide\",\n },\n }),\n };\n default:\n return base;\n }\n}\n\nfunction answerStatus(observation: Record<string, unknown>) {\n if (observation.completeness !== \"complete\") return \"unavailable\";\n const text = record(observation.data).text;\n return typeof text === \"string\" && /\\b3000\\b/.test(text)\n ? \"passed\"\n : \"failed\";\n}\n\nexport function evaluate(params: Record<string, unknown>) {\n if (!Array.isArray(params.observations))\n throw new Error(\"Missing observations\");\n const observations: unknown[] = params.observations;\n const observation = observations\n .map(record)\n .find((item) => item.id === \"sevro.observation.final-message\");\n if (!observation) throw new Error(\"Missing final-message observation\");\n const status = answerStatus(observation);\n return {\n checks: [\n {\n id: \"recipes.startup.answer\",\n status,\n evidenceRefs: [\"sevro.observation.final-message\"],\n },\n ],\n metrics: [],\n };\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { describe, evaluate, prepare, record, resolveCase, } from "./extension-methods.js";
3
+ const mode = process.argv[2] ?? "lifecycle";
4
+ const host = process.argv[3] ?? "deterministic";
5
+ const fail = process.argv[4] === "fail";
6
+ const request = record(JSON.parse(readFileSync(0, "utf8")));
7
+ async function result() {
8
+ switch (request.method) {
9
+ case "describe":
10
+ return describe(mode, host);
11
+ case "resolve":
12
+ return resolveCase(mode, host, fail);
13
+ case "prepare":
14
+ return await prepare(mode, host);
15
+ case "evaluate":
16
+ return evaluate(record(request.params));
17
+ default:
18
+ throw new Error("Unsupported extension method");
19
+ }
20
+ }
21
+ // One request per process; stdout contains only the matching protocol response.
22
+ process.stdout.write(JSON.stringify({
23
+ protocol: request.protocol,
24
+ id: request.id,
25
+ method: request.method,
26
+ result: await result(),
27
+ }));
28
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB;AACvC,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,MAAM,EACN,WAAW,GACZ,+BAA4B;AAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC;AAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC;AAChD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;AACxC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAY,CAAC,CAAC;AAEvE,KAAK,UAAU,MAAM;IACnB,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,UAAU;YACb,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9B,KAAK,SAAS;YACZ,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACvC,KAAK,SAAS;YACZ,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnC,KAAK,UAAU;YACb,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1C;YACE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC,QAAQ;IAC1B,EAAE,EAAE,OAAO,CAAC,EAAE;IACd,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,MAAM,EAAE,MAAM,MAAM,EAAE;CACvB,CAAC,CACH,CAAC","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport {\n describe,\n evaluate,\n prepare,\n record,\n resolveCase,\n} from \"./extension-methods\";\n\nconst mode = process.argv[2] ?? \"lifecycle\";\nconst host = process.argv[3] ?? \"deterministic\";\nconst fail = process.argv[4] === \"fail\";\nconst request = record(JSON.parse(readFileSync(0, \"utf8\")) as unknown);\n\nasync function result() {\n switch (request.method) {\n case \"describe\":\n return describe(mode, host);\n case \"resolve\":\n return resolveCase(mode, host, fail);\n case \"prepare\":\n return await prepare(mode, host);\n case \"evaluate\":\n return evaluate(record(request.params));\n default:\n throw new Error(\"Unsupported extension method\");\n }\n}\n\n// One request per process; stdout contains only the matching protocol response.\nprocess.stdout.write(\n JSON.stringify({\n protocol: request.protocol,\n id: request.id,\n method: request.method,\n result: await result(),\n }),\n);\n"]}
@@ -0,0 +1,9 @@
1
+ import { join } from "node:path";
2
+ /** Locate source modules for Bun development or compiled modules for consumers. */
3
+ export function recipeFile(...parts) {
4
+ const path = join(import.meta.dirname, ...parts);
5
+ return import.meta.filename.endsWith(".ts")
6
+ ? path
7
+ : path.replace(/\.ts$/, ".js");
8
+ }
9
+ //# sourceMappingURL=modules.js.map