@bjoernrochel/sevro 1.0.0 → 1.1.1

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 (405) 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 +158 -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/claude-settings.ts +3 -1
  392. package/src/hosts/claude.ts +1 -1
  393. package/src/hosts/isolation-roots.ts +3 -2
  394. package/src/hosts/process-lifecycle.ts +4 -6
  395. package/src/hosts/protected-worktrees.ts +2 -1
  396. package/src/hosts/skill-hook-handler.ts +1 -1
  397. package/src/hosts/skill-hooks.ts +10 -2
  398. package/src/provenance.ts +7 -6
  399. package/src/results-lock.ts +4 -4
  400. package/src/run-owner.ts +15 -9
  401. package/src/runner-paths.ts +21 -0
  402. package/src/runtime/hook-processes.ts +2 -1
  403. package/src/runtime/hooks.ts +9 -7
  404. package/src/runtime-process.ts +194 -0
  405. package/src/sqlite-lock.ts +25 -0
@@ -0,0 +1,2 @@
1
+ // Generated by bun run schemas:generate; do not edit.
2
+ "use strict";module.exports = validate104;module.exports.default = validate104;const schema164 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"urn:sevro:schema:runtime:v1","title":"Sevro runtime policy v1","type":"object","additionalProperties":false,"required":["format"],"$defs":{"runtimeRole":{"$comment":"Generated from RUNTIME_ROLES by bun run schemas:generate.","enum":["candidate","checks","hooks","semantic","advisory"]}},"properties":{"codexState":{"type":"boolean"},"network":{"type":"object","additionalProperties":false,"properties":{"localHttp":{"type":"boolean"}}},"nativeTranscripts":{"type":"boolean"},"hooks":{"type":"object","additionalProperties":false,"properties":{"nativeGoal":{"type":"boolean"},"plugins":{"type":"array","maxItems":64,"uniqueItems":true,"items":{"type":"string","pattern":"^[a-z][a-z0-9-]*$","maxLength":128}}}},"runtime":{"type":"object","additionalProperties":false,"properties":{"artifactDirectories":{"type":"array","maxItems":16,"items":{"type":"object","additionalProperties":false,"required":["name","path"],"properties":{"name":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"path":{"type":"string","minLength":1,"maxLength":4096}}}},"sharedCacheDirectories":{"type":"array","maxItems":16,"items":{"type":"object","additionalProperties":false,"required":["source","target","roles"],"properties":{"source":{"type":"string","minLength":1,"maxLength":4096},"target":{"type":"string","pattern":"^[a-z][a-z0-9-]{0,63}$","not":{"enum":["home","tmp"]}},"roles":{"type":"array","minItems":1,"maxItems":5,"uniqueItems":true,"items":{"$ref":"#/$defs/runtimeRole"}}}}},"seedDirectories":{"type":"array","maxItems":16,"items":{"type":"object","additionalProperties":false,"required":["source","target"],"properties":{"source":{"type":"string","minLength":1,"maxLength":4096},"target":{"type":"string","pattern":"^[a-z][a-z0-9-]{0,63}$","not":{"enum":["home","tmp"]}},"roles":{"type":"array","minItems":1,"maxItems":5,"uniqueItems":true,"items":{"$ref":"#/$defs/runtimeRole"}}}}}}},"format":{"const":"sevro.runtime.v1"},"filesystem":{"type":"object","additionalProperties":false,"properties":{"optionalReadOnlyRoots":{"type":"array","maxItems":64,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":4096}},"readOnlyRoots":{"type":"array","maxItems":64,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":4096}}}},"environment":{"type":"object","additionalProperties":false,"properties":{"inherit":{"type":"array","maxItems":64,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]{0,127}$"}},"set":{"type":"object","maxProperties":64,"propertyNames":{"pattern":"^[A-Za-z_][A-Za-z0-9_]{0,127}$"},"additionalProperties":{"type":"string","maxLength":8192}}}}}};const schema165 = {"$comment":"Generated from RUNTIME_ROLES by bun run schemas:generate.","enum":["candidate","checks","hooks","semantic","advisory"]};const func2 = require("ajv/dist/runtime/ucs2length").default;const func0 = require("ajv/dist/runtime/equal").default;const pattern55 = new RegExp("^[a-z][a-z0-9-]*$", "u");const pattern56 = new RegExp("^[a-z][a-z0-9_]{0,63}$", "u");const pattern57 = new RegExp("^[a-z][a-z0-9-]{0,63}$", "u");const pattern59 = new RegExp("^[A-Za-z_][A-Za-z0-9_]{0,127}$", "u");function validate104(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="urn:sevro:schema:runtime:v1" */;let vErrors = null;let errors = 0;const evaluated0 = validate104.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(errors === 0){if(data && typeof data == "object" && !Array.isArray(data)){let missing0;if((data.format === undefined) && (missing0 = "format")){validate104.errors = [{instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: missing0},message:"must have required property '"+missing0+"'"}];return false;}else {const _errs1 = errors;for(const key0 in data){if(!((((((((key0 === "codexState") || (key0 === "network")) || (key0 === "nativeTranscripts")) || (key0 === "hooks")) || (key0 === "runtime")) || (key0 === "format")) || (key0 === "filesystem")) || (key0 === "environment"))){validate104.errors = [{instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}];return false;break;}}if(_errs1 === errors){if(data.codexState !== undefined){const _errs2 = errors;if(typeof data.codexState !== "boolean"){validate104.errors = [{instancePath:instancePath+"/codexState",schemaPath:"#/properties/codexState/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}var valid0 = _errs2 === errors;}else {var valid0 = true;}if(valid0){if(data.network !== undefined){let data1 = data.network;const _errs4 = errors;if(errors === _errs4){if(data1 && typeof data1 == "object" && !Array.isArray(data1)){const _errs6 = errors;for(const key1 in data1){if(!(key1 === "localHttp")){validate104.errors = [{instancePath:instancePath+"/network",schemaPath:"#/properties/network/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}];return false;break;}}if(_errs6 === errors){if(data1.localHttp !== undefined){if(typeof data1.localHttp !== "boolean"){validate104.errors = [{instancePath:instancePath+"/network/localHttp",schemaPath:"#/properties/network/properties/localHttp/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}}}}else {validate104.errors = [{instancePath:instancePath+"/network",schemaPath:"#/properties/network/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs4 === errors;}else {var valid0 = true;}if(valid0){if(data.nativeTranscripts !== undefined){const _errs9 = errors;if(typeof data.nativeTranscripts !== "boolean"){validate104.errors = [{instancePath:instancePath+"/nativeTranscripts",schemaPath:"#/properties/nativeTranscripts/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}var valid0 = _errs9 === errors;}else {var valid0 = true;}if(valid0){if(data.hooks !== undefined){let data4 = data.hooks;const _errs11 = errors;if(errors === _errs11){if(data4 && typeof data4 == "object" && !Array.isArray(data4)){const _errs13 = errors;for(const key2 in data4){if(!((key2 === "nativeGoal") || (key2 === "plugins"))){validate104.errors = [{instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}];return false;break;}}if(_errs13 === errors){if(data4.nativeGoal !== undefined){const _errs14 = errors;if(typeof data4.nativeGoal !== "boolean"){validate104.errors = [{instancePath:instancePath+"/hooks/nativeGoal",schemaPath:"#/properties/hooks/properties/nativeGoal/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}];return false;}var valid2 = _errs14 === errors;}else {var valid2 = true;}if(valid2){if(data4.plugins !== undefined){let data6 = data4.plugins;const _errs16 = errors;if(errors === _errs16){if(Array.isArray(data6)){if(data6.length > 64){validate104.errors = [{instancePath:instancePath+"/hooks/plugins",schemaPath:"#/properties/hooks/properties/plugins/maxItems",keyword:"maxItems",params:{limit: 64},message:"must NOT have more than 64 items"}];return false;}else {var valid3 = true;const len0 = data6.length;for(let i0=0; i0<len0; i0++){let data7 = data6[i0];const _errs18 = errors;if(errors === _errs18){if(typeof data7 === "string"){if(func2(data7) > 128){validate104.errors = [{instancePath:instancePath+"/hooks/plugins/" + i0,schemaPath:"#/properties/hooks/properties/plugins/items/maxLength",keyword:"maxLength",params:{limit: 128},message:"must NOT have more than 128 characters"}];return false;}else {if(!pattern55.test(data7)){validate104.errors = [{instancePath:instancePath+"/hooks/plugins/" + i0,schemaPath:"#/properties/hooks/properties/plugins/items/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9-]*$"},message:"must match pattern \""+"^[a-z][a-z0-9-]*$"+"\""}];return false;}}}else {validate104.errors = [{instancePath:instancePath+"/hooks/plugins/" + i0,schemaPath:"#/properties/hooks/properties/plugins/items/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid3 = _errs18 === errors;if(!valid3){break;}}if(valid3){let i1 = data6.length;let j0;if(i1 > 1){const indices0 = {};for(;i1--;){let item0 = data6[i1];if(typeof item0 !== "string"){continue;}if(typeof indices0[item0] == "number"){j0 = indices0[item0];validate104.errors = [{instancePath:instancePath+"/hooks/plugins",schemaPath:"#/properties/hooks/properties/plugins/uniqueItems",keyword:"uniqueItems",params:{i: i1, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i1+" are identical)"}];return false;break;}indices0[item0] = i1;}}}}}else {validate104.errors = [{instancePath:instancePath+"/hooks/plugins",schemaPath:"#/properties/hooks/properties/plugins/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid2 = _errs16 === errors;}else {var valid2 = true;}}}}else {validate104.errors = [{instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs11 === errors;}else {var valid0 = true;}if(valid0){if(data.runtime !== undefined){let data8 = data.runtime;const _errs20 = errors;if(errors === _errs20){if(data8 && typeof data8 == "object" && !Array.isArray(data8)){const _errs22 = errors;for(const key3 in data8){if(!(((key3 === "artifactDirectories") || (key3 === "sharedCacheDirectories")) || (key3 === "seedDirectories"))){validate104.errors = [{instancePath:instancePath+"/runtime",schemaPath:"#/properties/runtime/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}];return false;break;}}if(_errs22 === errors){if(data8.artifactDirectories !== undefined){let data9 = data8.artifactDirectories;const _errs23 = errors;if(errors === _errs23){if(Array.isArray(data9)){if(data9.length > 16){validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories",schemaPath:"#/properties/runtime/properties/artifactDirectories/maxItems",keyword:"maxItems",params:{limit: 16},message:"must NOT have more than 16 items"}];return false;}else {var valid6 = true;const len1 = data9.length;for(let i2=0; i2<len1; i2++){let data10 = data9[i2];const _errs25 = errors;if(errors === _errs25){if(data10 && typeof data10 == "object" && !Array.isArray(data10)){let missing1;if(((data10.name === undefined) && (missing1 = "name")) || ((data10.path === undefined) && (missing1 = "path"))){validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2,schemaPath:"#/properties/runtime/properties/artifactDirectories/items/required",keyword:"required",params:{missingProperty: missing1},message:"must have required property '"+missing1+"'"}];return false;}else {const _errs27 = errors;for(const key4 in data10){if(!((key4 === "name") || (key4 === "path"))){validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2,schemaPath:"#/properties/runtime/properties/artifactDirectories/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}];return false;break;}}if(_errs27 === errors){if(data10.name !== undefined){let data11 = data10.name;const _errs28 = errors;if(errors === _errs28){if(typeof data11 === "string"){if(!pattern56.test(data11)){validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2+"/name",schemaPath:"#/properties/runtime/properties/artifactDirectories/items/properties/name/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9_]{0,63}$"},message:"must match pattern \""+"^[a-z][a-z0-9_]{0,63}$"+"\""}];return false;}}else {validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2+"/name",schemaPath:"#/properties/runtime/properties/artifactDirectories/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid7 = _errs28 === errors;}else {var valid7 = true;}if(valid7){if(data10.path !== undefined){let data12 = data10.path;const _errs30 = errors;if(errors === _errs30){if(typeof data12 === "string"){if(func2(data12) > 4096){validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2+"/path",schemaPath:"#/properties/runtime/properties/artifactDirectories/items/properties/path/maxLength",keyword:"maxLength",params:{limit: 4096},message:"must NOT have more than 4096 characters"}];return false;}else {if(func2(data12) < 1){validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2+"/path",schemaPath:"#/properties/runtime/properties/artifactDirectories/items/properties/path/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"}];return false;}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2+"/path",schemaPath:"#/properties/runtime/properties/artifactDirectories/items/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid7 = _errs30 === errors;}else {var valid7 = true;}}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories/" + i2,schemaPath:"#/properties/runtime/properties/artifactDirectories/items/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid6 = _errs25 === errors;if(!valid6){break;}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/artifactDirectories",schemaPath:"#/properties/runtime/properties/artifactDirectories/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid5 = _errs23 === errors;}else {var valid5 = true;}if(valid5){if(data8.sharedCacheDirectories !== undefined){let data13 = data8.sharedCacheDirectories;const _errs32 = errors;if(errors === _errs32){if(Array.isArray(data13)){if(data13.length > 16){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/maxItems",keyword:"maxItems",params:{limit: 16},message:"must NOT have more than 16 items"}];return false;}else {var valid8 = true;const len2 = data13.length;for(let i3=0; i3<len2; i3++){let data14 = data13[i3];const _errs34 = errors;if(errors === _errs34){if(data14 && typeof data14 == "object" && !Array.isArray(data14)){let missing2;if((((data14.source === undefined) && (missing2 = "source")) || ((data14.target === undefined) && (missing2 = "target"))) || ((data14.roles === undefined) && (missing2 = "roles"))){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3,schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/required",keyword:"required",params:{missingProperty: missing2},message:"must have required property '"+missing2+"'"}];return false;}else {const _errs36 = errors;for(const key5 in data14){if(!(((key5 === "source") || (key5 === "target")) || (key5 === "roles"))){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3,schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}];return false;break;}}if(_errs36 === errors){if(data14.source !== undefined){let data15 = data14.source;const _errs37 = errors;if(errors === _errs37){if(typeof data15 === "string"){if(func2(data15) > 4096){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/source",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/source/maxLength",keyword:"maxLength",params:{limit: 4096},message:"must NOT have more than 4096 characters"}];return false;}else {if(func2(data15) < 1){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/source",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/source/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"}];return false;}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/source",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid9 = _errs37 === errors;}else {var valid9 = true;}if(valid9){if(data14.target !== undefined){let data16 = data14.target;const _errs39 = errors;const _errs41 = errors;const _errs42 = errors;if(!((data16 === "home") || (data16 === "tmp"))){const err0 = {};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}var valid10 = _errs42 === errors;if(valid10){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/target",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/target/not",keyword:"not",params:{},message:"must NOT be valid"}];return false;}else {errors = _errs41;if(vErrors !== null){if(_errs41){vErrors.length = _errs41;}else {vErrors = null;}}}if(errors === _errs39){if(typeof data16 === "string"){if(!pattern57.test(data16)){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/target",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/target/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9-]{0,63}$"},message:"must match pattern \""+"^[a-z][a-z0-9-]{0,63}$"+"\""}];return false;}}else {validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/target",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid9 = _errs39 === errors;}else {var valid9 = true;}if(valid9){if(data14.roles !== undefined){let data17 = data14.roles;const _errs43 = errors;if(errors === _errs43){if(Array.isArray(data17)){if(data17.length > 5){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/roles",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/roles/maxItems",keyword:"maxItems",params:{limit: 5},message:"must NOT have more than 5 items"}];return false;}else {if(data17.length < 1){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/roles",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/roles/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"}];return false;}else {var valid11 = true;const len3 = data17.length;for(let i4=0; i4<len3; i4++){let data18 = data17[i4];const _errs45 = errors;if(!(((((data18 === "candidate") || (data18 === "checks")) || (data18 === "hooks")) || (data18 === "semantic")) || (data18 === "advisory"))){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/roles/" + i4,schemaPath:"#/$defs/runtimeRole/enum",keyword:"enum",params:{allowedValues: schema165.enum},message:"must be equal to one of the allowed values"}];return false;}var valid11 = _errs45 === errors;if(!valid11){break;}}if(valid11){let i5 = data17.length;let j1;if(i5 > 1){outer0:for(;i5--;){for(j1 = i5; j1--;){if(func0(data17[i5], data17[j1])){validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/roles",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/roles/uniqueItems",keyword:"uniqueItems",params:{i: i5, j: j1},message:"must NOT have duplicate items (items ## "+j1+" and "+i5+" are identical)"}];return false;break outer0;}}}}}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3+"/roles",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/properties/roles/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid9 = _errs43 === errors;}else {var valid9 = true;}}}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories/" + i3,schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/items/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid8 = _errs34 === errors;if(!valid8){break;}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/sharedCacheDirectories",schemaPath:"#/properties/runtime/properties/sharedCacheDirectories/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid5 = _errs32 === errors;}else {var valid5 = true;}if(valid5){if(data8.seedDirectories !== undefined){let data19 = data8.seedDirectories;const _errs48 = errors;if(errors === _errs48){if(Array.isArray(data19)){if(data19.length > 16){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories",schemaPath:"#/properties/runtime/properties/seedDirectories/maxItems",keyword:"maxItems",params:{limit: 16},message:"must NOT have more than 16 items"}];return false;}else {var valid14 = true;const len4 = data19.length;for(let i6=0; i6<len4; i6++){let data20 = data19[i6];const _errs50 = errors;if(errors === _errs50){if(data20 && typeof data20 == "object" && !Array.isArray(data20)){let missing3;if(((data20.source === undefined) && (missing3 = "source")) || ((data20.target === undefined) && (missing3 = "target"))){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6,schemaPath:"#/properties/runtime/properties/seedDirectories/items/required",keyword:"required",params:{missingProperty: missing3},message:"must have required property '"+missing3+"'"}];return false;}else {const _errs52 = errors;for(const key6 in data20){if(!(((key6 === "source") || (key6 === "target")) || (key6 === "roles"))){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6,schemaPath:"#/properties/runtime/properties/seedDirectories/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}];return false;break;}}if(_errs52 === errors){if(data20.source !== undefined){let data21 = data20.source;const _errs53 = errors;if(errors === _errs53){if(typeof data21 === "string"){if(func2(data21) > 4096){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/source",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/source/maxLength",keyword:"maxLength",params:{limit: 4096},message:"must NOT have more than 4096 characters"}];return false;}else {if(func2(data21) < 1){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/source",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/source/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"}];return false;}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/source",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid15 = _errs53 === errors;}else {var valid15 = true;}if(valid15){if(data20.target !== undefined){let data22 = data20.target;const _errs55 = errors;const _errs57 = errors;const _errs58 = errors;if(!((data22 === "home") || (data22 === "tmp"))){const err1 = {};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}var valid16 = _errs58 === errors;if(valid16){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/target",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/target/not",keyword:"not",params:{},message:"must NOT be valid"}];return false;}else {errors = _errs57;if(vErrors !== null){if(_errs57){vErrors.length = _errs57;}else {vErrors = null;}}}if(errors === _errs55){if(typeof data22 === "string"){if(!pattern57.test(data22)){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/target",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/target/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9-]{0,63}$"},message:"must match pattern \""+"^[a-z][a-z0-9-]{0,63}$"+"\""}];return false;}}else {validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/target",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid15 = _errs55 === errors;}else {var valid15 = true;}if(valid15){if(data20.roles !== undefined){let data23 = data20.roles;const _errs59 = errors;if(errors === _errs59){if(Array.isArray(data23)){if(data23.length > 5){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/roles",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/roles/maxItems",keyword:"maxItems",params:{limit: 5},message:"must NOT have more than 5 items"}];return false;}else {if(data23.length < 1){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/roles",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/roles/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"}];return false;}else {var valid17 = true;const len5 = data23.length;for(let i7=0; i7<len5; i7++){let data24 = data23[i7];const _errs61 = errors;if(!(((((data24 === "candidate") || (data24 === "checks")) || (data24 === "hooks")) || (data24 === "semantic")) || (data24 === "advisory"))){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/roles/" + i7,schemaPath:"#/$defs/runtimeRole/enum",keyword:"enum",params:{allowedValues: schema165.enum},message:"must be equal to one of the allowed values"}];return false;}var valid17 = _errs61 === errors;if(!valid17){break;}}if(valid17){let i8 = data23.length;let j2;if(i8 > 1){outer1:for(;i8--;){for(j2 = i8; j2--;){if(func0(data23[i8], data23[j2])){validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/roles",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/roles/uniqueItems",keyword:"uniqueItems",params:{i: i8, j: j2},message:"must NOT have duplicate items (items ## "+j2+" and "+i8+" are identical)"}];return false;break outer1;}}}}}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6+"/roles",schemaPath:"#/properties/runtime/properties/seedDirectories/items/properties/roles/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid15 = _errs59 === errors;}else {var valid15 = true;}}}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories/" + i6,schemaPath:"#/properties/runtime/properties/seedDirectories/items/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid14 = _errs50 === errors;if(!valid14){break;}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime/seedDirectories",schemaPath:"#/properties/runtime/properties/seedDirectories/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid5 = _errs48 === errors;}else {var valid5 = true;}}}}}else {validate104.errors = [{instancePath:instancePath+"/runtime",schemaPath:"#/properties/runtime/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs20 === errors;}else {var valid0 = true;}if(valid0){if(data.format !== undefined){const _errs64 = errors;if("sevro.runtime.v1" !== data.format){validate104.errors = [{instancePath:instancePath+"/format",schemaPath:"#/properties/format/const",keyword:"const",params:{allowedValue: "sevro.runtime.v1"},message:"must be equal to constant"}];return false;}var valid0 = _errs64 === errors;}else {var valid0 = true;}if(valid0){if(data.filesystem !== undefined){let data26 = data.filesystem;const _errs65 = errors;if(errors === _errs65){if(data26 && typeof data26 == "object" && !Array.isArray(data26)){const _errs67 = errors;for(const key7 in data26){if(!((key7 === "optionalReadOnlyRoots") || (key7 === "readOnlyRoots"))){validate104.errors = [{instancePath:instancePath+"/filesystem",schemaPath:"#/properties/filesystem/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}];return false;break;}}if(_errs67 === errors){if(data26.optionalReadOnlyRoots !== undefined){let data27 = data26.optionalReadOnlyRoots;const _errs68 = errors;if(errors === _errs68){if(Array.isArray(data27)){if(data27.length > 64){validate104.errors = [{instancePath:instancePath+"/filesystem/optionalReadOnlyRoots",schemaPath:"#/properties/filesystem/properties/optionalReadOnlyRoots/maxItems",keyword:"maxItems",params:{limit: 64},message:"must NOT have more than 64 items"}];return false;}else {var valid21 = true;const len6 = data27.length;for(let i9=0; i9<len6; i9++){let data28 = data27[i9];const _errs70 = errors;if(errors === _errs70){if(typeof data28 === "string"){if(func2(data28) > 4096){validate104.errors = [{instancePath:instancePath+"/filesystem/optionalReadOnlyRoots/" + i9,schemaPath:"#/properties/filesystem/properties/optionalReadOnlyRoots/items/maxLength",keyword:"maxLength",params:{limit: 4096},message:"must NOT have more than 4096 characters"}];return false;}else {if(func2(data28) < 1){validate104.errors = [{instancePath:instancePath+"/filesystem/optionalReadOnlyRoots/" + i9,schemaPath:"#/properties/filesystem/properties/optionalReadOnlyRoots/items/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"}];return false;}}}else {validate104.errors = [{instancePath:instancePath+"/filesystem/optionalReadOnlyRoots/" + i9,schemaPath:"#/properties/filesystem/properties/optionalReadOnlyRoots/items/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid21 = _errs70 === errors;if(!valid21){break;}}if(valid21){let i10 = data27.length;let j3;if(i10 > 1){const indices1 = {};for(;i10--;){let item1 = data27[i10];if(typeof item1 !== "string"){continue;}if(typeof indices1[item1] == "number"){j3 = indices1[item1];validate104.errors = [{instancePath:instancePath+"/filesystem/optionalReadOnlyRoots",schemaPath:"#/properties/filesystem/properties/optionalReadOnlyRoots/uniqueItems",keyword:"uniqueItems",params:{i: i10, j: j3},message:"must NOT have duplicate items (items ## "+j3+" and "+i10+" are identical)"}];return false;break;}indices1[item1] = i10;}}}}}else {validate104.errors = [{instancePath:instancePath+"/filesystem/optionalReadOnlyRoots",schemaPath:"#/properties/filesystem/properties/optionalReadOnlyRoots/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid20 = _errs68 === errors;}else {var valid20 = true;}if(valid20){if(data26.readOnlyRoots !== undefined){let data29 = data26.readOnlyRoots;const _errs72 = errors;if(errors === _errs72){if(Array.isArray(data29)){if(data29.length > 64){validate104.errors = [{instancePath:instancePath+"/filesystem/readOnlyRoots",schemaPath:"#/properties/filesystem/properties/readOnlyRoots/maxItems",keyword:"maxItems",params:{limit: 64},message:"must NOT have more than 64 items"}];return false;}else {var valid23 = true;const len7 = data29.length;for(let i11=0; i11<len7; i11++){let data30 = data29[i11];const _errs74 = errors;if(errors === _errs74){if(typeof data30 === "string"){if(func2(data30) > 4096){validate104.errors = [{instancePath:instancePath+"/filesystem/readOnlyRoots/" + i11,schemaPath:"#/properties/filesystem/properties/readOnlyRoots/items/maxLength",keyword:"maxLength",params:{limit: 4096},message:"must NOT have more than 4096 characters"}];return false;}else {if(func2(data30) < 1){validate104.errors = [{instancePath:instancePath+"/filesystem/readOnlyRoots/" + i11,schemaPath:"#/properties/filesystem/properties/readOnlyRoots/items/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"}];return false;}}}else {validate104.errors = [{instancePath:instancePath+"/filesystem/readOnlyRoots/" + i11,schemaPath:"#/properties/filesystem/properties/readOnlyRoots/items/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid23 = _errs74 === errors;if(!valid23){break;}}if(valid23){let i12 = data29.length;let j4;if(i12 > 1){const indices2 = {};for(;i12--;){let item2 = data29[i12];if(typeof item2 !== "string"){continue;}if(typeof indices2[item2] == "number"){j4 = indices2[item2];validate104.errors = [{instancePath:instancePath+"/filesystem/readOnlyRoots",schemaPath:"#/properties/filesystem/properties/readOnlyRoots/uniqueItems",keyword:"uniqueItems",params:{i: i12, j: j4},message:"must NOT have duplicate items (items ## "+j4+" and "+i12+" are identical)"}];return false;break;}indices2[item2] = i12;}}}}}else {validate104.errors = [{instancePath:instancePath+"/filesystem/readOnlyRoots",schemaPath:"#/properties/filesystem/properties/readOnlyRoots/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid20 = _errs72 === errors;}else {var valid20 = true;}}}}else {validate104.errors = [{instancePath:instancePath+"/filesystem",schemaPath:"#/properties/filesystem/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs65 === errors;}else {var valid0 = true;}if(valid0){if(data.environment !== undefined){let data31 = data.environment;const _errs76 = errors;if(errors === _errs76){if(data31 && typeof data31 == "object" && !Array.isArray(data31)){const _errs78 = errors;for(const key8 in data31){if(!((key8 === "inherit") || (key8 === "set"))){validate104.errors = [{instancePath:instancePath+"/environment",schemaPath:"#/properties/environment/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}];return false;break;}}if(_errs78 === errors){if(data31.inherit !== undefined){let data32 = data31.inherit;const _errs79 = errors;if(errors === _errs79){if(Array.isArray(data32)){if(data32.length > 64){validate104.errors = [{instancePath:instancePath+"/environment/inherit",schemaPath:"#/properties/environment/properties/inherit/maxItems",keyword:"maxItems",params:{limit: 64},message:"must NOT have more than 64 items"}];return false;}else {var valid26 = true;const len8 = data32.length;for(let i13=0; i13<len8; i13++){let data33 = data32[i13];const _errs81 = errors;if(errors === _errs81){if(typeof data33 === "string"){if(!pattern59.test(data33)){validate104.errors = [{instancePath:instancePath+"/environment/inherit/" + i13,schemaPath:"#/properties/environment/properties/inherit/items/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z_][A-Za-z0-9_]{0,127}$"},message:"must match pattern \""+"^[A-Za-z_][A-Za-z0-9_]{0,127}$"+"\""}];return false;}}else {validate104.errors = [{instancePath:instancePath+"/environment/inherit/" + i13,schemaPath:"#/properties/environment/properties/inherit/items/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid26 = _errs81 === errors;if(!valid26){break;}}if(valid26){let i14 = data32.length;let j5;if(i14 > 1){const indices3 = {};for(;i14--;){let item3 = data32[i14];if(typeof item3 !== "string"){continue;}if(typeof indices3[item3] == "number"){j5 = indices3[item3];validate104.errors = [{instancePath:instancePath+"/environment/inherit",schemaPath:"#/properties/environment/properties/inherit/uniqueItems",keyword:"uniqueItems",params:{i: i14, j: j5},message:"must NOT have duplicate items (items ## "+j5+" and "+i14+" are identical)"}];return false;break;}indices3[item3] = i14;}}}}}else {validate104.errors = [{instancePath:instancePath+"/environment/inherit",schemaPath:"#/properties/environment/properties/inherit/type",keyword:"type",params:{type: "array"},message:"must be array"}];return false;}}var valid25 = _errs79 === errors;}else {var valid25 = true;}if(valid25){if(data31.set !== undefined){let data34 = data31.set;const _errs83 = errors;if(errors === _errs83){if(data34 && typeof data34 == "object" && !Array.isArray(data34)){if(Object.keys(data34).length > 64){validate104.errors = [{instancePath:instancePath+"/environment/set",schemaPath:"#/properties/environment/properties/set/maxProperties",keyword:"maxProperties",params:{limit: 64},message:"must NOT have more than 64 properties"}];return false;}else {for(const key9 in data34){const _errs85 = errors;if(typeof key9 === "string"){if(!pattern59.test(key9)){const err2 = {instancePath:instancePath+"/environment/set",schemaPath:"#/properties/environment/properties/set/propertyNames/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z_][A-Za-z0-9_]{0,127}$"},message:"must match pattern \""+"^[A-Za-z_][A-Za-z0-9_]{0,127}$"+"\"",propertyName:key9};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}}var valid28 = _errs85 === errors;if(!valid28){const err3 = {instancePath:instancePath+"/environment/set",schemaPath:"#/properties/environment/properties/set/propertyNames",keyword:"propertyNames",params:{propertyName: key9},message:"property name must be valid"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;validate104.errors = vErrors;return false;break;}}if(valid28){for(const key10 in data34){let data35 = data34[key10];const _errs87 = errors;if(errors === _errs87){if(typeof data35 === "string"){if(func2(data35) > 8192){validate104.errors = [{instancePath:instancePath+"/environment/set/" + key10.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/environment/properties/set/additionalProperties/maxLength",keyword:"maxLength",params:{limit: 8192},message:"must NOT have more than 8192 characters"}];return false;}}else {validate104.errors = [{instancePath:instancePath+"/environment/set/" + key10.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/environment/properties/set/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}var valid29 = _errs87 === errors;if(!valid29){break;}}}}}else {validate104.errors = [{instancePath:instancePath+"/environment/set",schemaPath:"#/properties/environment/properties/set/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid25 = _errs83 === errors;}else {var valid25 = true;}}}}else {validate104.errors = [{instancePath:instancePath+"/environment",schemaPath:"#/properties/environment/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}var valid0 = _errs76 === errors;}else {var valid0 = true;}}}}}}}}}}}else {validate104.errors = [{instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}];return false;}}validate104.errors = vErrors;return errors === 0;}validate104.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};
@@ -0,0 +1,72 @@
1
+ import { spawn } from "./runtime-process.js";
2
+ import { captureBoundedBytes, terminateOwnedProcessGroup, } from "./process-lifecycle.js";
3
+ function nullDevice() {
4
+ return process.platform === "win32" ? "NUL" : "/dev/null";
5
+ }
6
+ /** Do not inherit repository selectors, credentials, injection flags or config. */
7
+ export function gitEnvironment(identity) {
8
+ return {
9
+ PATH: process.env.PATH ?? "/usr/bin:/bin",
10
+ ...(process.env.SystemRoot ? { SystemRoot: process.env.SystemRoot } : {}),
11
+ GIT_CONFIG_NOSYSTEM: "1",
12
+ GIT_CONFIG_GLOBAL: nullDevice(),
13
+ GIT_NO_REPLACE_OBJECTS: "1",
14
+ GIT_TERMINAL_PROMPT: "0",
15
+ ...gitIdentity(identity),
16
+ };
17
+ }
18
+ function gitIdentity(identity) {
19
+ if (!identity)
20
+ return {};
21
+ const name = identity === "fixture" ? "Sevro Fixture" : "Sevro Advisory";
22
+ const email = `${identity}@sevro.invalid`;
23
+ return {
24
+ GIT_AUTHOR_NAME: name,
25
+ GIT_AUTHOR_EMAIL: email,
26
+ GIT_COMMITTER_NAME: name,
27
+ GIT_COMMITTER_EMAIL: email,
28
+ GIT_AUTHOR_DATE: "2000-01-01T00:00:00+00:00",
29
+ GIT_COMMITTER_DATE: "2000-01-01T00:00:00+00:00",
30
+ };
31
+ }
32
+ /** Shared by fixture execution and the independently deadline-bound HEAD grader. */
33
+ export function gitArguments(args) {
34
+ return ["git", "-c", `core.hooksPath=${nullDevice()}`, ...args];
35
+ }
36
+ async function gitOutput(stream, options) {
37
+ const { bytes } = await captureBoundedBytes(stream, {
38
+ limit: options.maxOutputBytes,
39
+ overflow: "reject",
40
+ exceeded: () => new Error(`${options.label} Git output is too large`),
41
+ });
42
+ if (options.validateUtf8)
43
+ new TextDecoder("utf-8", { fatal: true }).decode(bytes);
44
+ return Buffer.from(bytes);
45
+ }
46
+ /** Capture both bounded streams; binary patches remain bytes through stdin. */
47
+ export async function runGit(options) {
48
+ const proc = spawn(gitArguments(options.args), {
49
+ cwd: options.cwd,
50
+ stdin: options.input ?? "ignore",
51
+ stdout: "pipe",
52
+ stderr: "pipe",
53
+ detached: process.platform !== "win32",
54
+ env: gitEnvironment(options.identity),
55
+ });
56
+ try {
57
+ const [stdout, , code] = await Promise.all([
58
+ gitOutput(proc.stdout, options),
59
+ gitOutput(proc.stderr, options),
60
+ proc.exited,
61
+ ]);
62
+ if (code !== 0)
63
+ throw new Error(`${options.label} Git operation failed`);
64
+ return stdout;
65
+ }
66
+ catch (error) {
67
+ terminateOwnedProcessGroup(proc);
68
+ await proc.exited;
69
+ throw error;
70
+ }
71
+ }
72
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["git.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"./runtime-process\";\nimport {\n captureBoundedBytes,\n terminateOwnedProcessGroup,\n} from \"./process-lifecycle\";\n\ntype GitIdentity = \"fixture\" | \"advisory\";\n\nfunction nullDevice(): string {\n return process.platform === \"win32\" ? \"NUL\" : \"/dev/null\";\n}\n\n/** Do not inherit repository selectors, credentials, injection flags or config. */\nexport function gitEnvironment(identity?: GitIdentity): Record<string, string> {\n return {\n PATH: process.env.PATH ?? \"/usr/bin:/bin\",\n ...(process.env.SystemRoot ? { SystemRoot: process.env.SystemRoot } : {}),\n GIT_CONFIG_NOSYSTEM: \"1\",\n GIT_CONFIG_GLOBAL: nullDevice(),\n GIT_NO_REPLACE_OBJECTS: \"1\",\n GIT_TERMINAL_PROMPT: \"0\",\n ...gitIdentity(identity),\n };\n}\n\nfunction gitIdentity(\n identity: GitIdentity | undefined,\n): Record<string, string> {\n if (!identity) return {};\n const name = identity === \"fixture\" ? \"Sevro Fixture\" : \"Sevro Advisory\";\n const email = `${identity}@sevro.invalid`;\n return {\n GIT_AUTHOR_NAME: name,\n GIT_AUTHOR_EMAIL: email,\n GIT_COMMITTER_NAME: name,\n GIT_COMMITTER_EMAIL: email,\n GIT_AUTHOR_DATE: \"2000-01-01T00:00:00+00:00\",\n GIT_COMMITTER_DATE: \"2000-01-01T00:00:00+00:00\",\n };\n}\n\n/** Shared by fixture execution and the independently deadline-bound HEAD grader. */\nexport function gitArguments(args: string[]): string[] {\n return [\"git\", \"-c\", `core.hooksPath=${nullDevice()}`, ...args];\n}\n\ninterface GitOptions {\n cwd: string;\n args: string[];\n identity: GitIdentity;\n label: string;\n maxOutputBytes: number;\n input?: Uint8Array;\n validateUtf8?: boolean;\n}\n\nasync function gitOutput(\n stream: ReadableStream<Uint8Array>,\n options: GitOptions,\n): Promise<Buffer> {\n const { bytes } = await captureBoundedBytes(stream, {\n limit: options.maxOutputBytes,\n overflow: \"reject\",\n exceeded: () => new Error(`${options.label} Git output is too large`),\n });\n if (options.validateUtf8)\n new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n return Buffer.from(bytes);\n}\n\n/** Capture both bounded streams; binary patches remain bytes through stdin. */\nexport async function runGit(options: GitOptions): Promise<Buffer> {\n const proc = spawn(gitArguments(options.args), {\n cwd: options.cwd,\n stdin: options.input ?? \"ignore\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n detached: process.platform !== \"win32\",\n env: gitEnvironment(options.identity),\n });\n try {\n const [stdout, , code] = await Promise.all([\n gitOutput(proc.stdout, options),\n gitOutput(proc.stderr, options),\n proc.exited,\n ]);\n if (code !== 0) throw new Error(`${options.label} Git operation failed`);\n return stdout;\n } catch (error) {\n terminateOwnedProcessGroup(proc);\n await proc.exited;\n throw error;\n }\n}\n"]}
@@ -0,0 +1,68 @@
1
+ import { lstat, readFile, readdir, realpath } from "node:fs/promises";
2
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep, } from "node:path";
3
+ const MAX_ARTIFACT_BYTES = 64 * 1024;
4
+ export function validateArtifactPath(path) {
5
+ if (typeof path !== "string" || !validArtifactPath(path))
6
+ throw new Error("semantic artifact path must be relative with at most one basename *");
7
+ }
8
+ function validArtifactPath(path) {
9
+ return (safeRelativePath(path) &&
10
+ !dirname(path).includes("*") &&
11
+ /^[^*]*\*?[^*]*$/.test(basename(path)));
12
+ }
13
+ function safeRelativePath(path) {
14
+ return (Boolean(path.trim()) &&
15
+ !path.includes("\\") &&
16
+ !isAbsolute(path) &&
17
+ !path.split("/").some((part) => part === ".." || part === ".git"));
18
+ }
19
+ function within(root, path) {
20
+ return path === root || path.startsWith(root + sep);
21
+ }
22
+ async function artifactDirectory(root, pattern) {
23
+ const dir = resolve(root, dirname(pattern));
24
+ if (!within(root, dir))
25
+ throw new Error("semantic artifact directory escapes the fixture");
26
+ const directory = await realpath(dir);
27
+ if (!within(root, directory))
28
+ throw new Error("semantic artifact directory escapes the fixture");
29
+ if (relative(root, directory).split(sep).includes(".git"))
30
+ throw new Error("semantic artifact directory resolves to Git metadata");
31
+ return directory;
32
+ }
33
+ async function artifactMatches(directory, name) {
34
+ if (!name.includes("*"))
35
+ return [name];
36
+ const [prefix = "", suffix = ""] = name.split("*");
37
+ return (await readdir(directory)).filter((entry) => entry.startsWith(prefix) && entry.endsWith(suffix));
38
+ }
39
+ function selectedArtifact(directory, matches) {
40
+ const [name] = matches;
41
+ if (matches.length !== 1 || name === undefined)
42
+ throw new Error(`semantic artifact pattern matched ${matches.length} files`);
43
+ return join(directory, name);
44
+ }
45
+ async function resolveArtifact(root, path) {
46
+ const stat = await lstat(path);
47
+ if (!stat.isFile() || stat.size > MAX_ARTIFACT_BYTES)
48
+ throw new Error("semantic artifact must be a regular file of at most 64 KiB");
49
+ const resolved = await realpath(path);
50
+ if (!within(root, resolved))
51
+ throw new Error("semantic artifact escapes the fixture");
52
+ if (relative(root, resolved).split(sep).includes(".git"))
53
+ throw new Error("semantic artifact resolves to Git metadata");
54
+ return resolved;
55
+ }
56
+ export async function readSemanticArtifact(repoDir, pattern) {
57
+ validateArtifactPath(pattern);
58
+ const root = await realpath(repoDir);
59
+ const directory = await artifactDirectory(root, pattern);
60
+ const matches = await artifactMatches(directory, basename(pattern));
61
+ const path = selectedArtifact(directory, matches);
62
+ const resolved = await resolveArtifact(root, path);
63
+ return {
64
+ path: relative(root, resolved),
65
+ content: await readFile(resolved, "utf8"),
66
+ };
67
+ }
68
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.js","sourceRoot":"","sources":["artifact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,yBAAyB;AACtE,OAAO,EACL,QAAQ,EACR,OAAO,EACP,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,GAAG,GACJ,kBAAkB;AACnB,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,CAAC;AAErC,MAAM,UAAU,oBAAoB,CAAC,IAAa;IAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;AACN,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,CACL,gBAAgB,CAAC,IAAI,CAAC;QACtB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC5B,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CACvC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,CACL,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACpB,CAAC,UAAU,CAAC,IAAI,CAAC;QACjB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,MAAM,CAAC,CAClE,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,IAAY,EAAE,IAAY;IACxC,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AACtD,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,IAAY,EACZ,OAAe;IAEf,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,IAAI,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,SAAiB,EACjB,IAAY;IAEZ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CACtC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC9D,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAiB,EAAE,OAAiB;IAC5D,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;IACvB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,SAAS;QAC5C,MAAM,IAAI,KAAK,CACb,qCAAqC,OAAO,CAAC,MAAM,QAAQ,CAC5D,CAAC;IACJ,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY;IACvD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG,kBAAkB;QAClD,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;IACJ,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,IAAI,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,OAAe;IAEf,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC9B,OAAO,EAAE,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1C,CAAC;AACJ,CAAC","sourcesContent":["import { lstat, readFile, readdir, realpath } from \"node:fs/promises\";\nimport {\n basename,\n dirname,\n isAbsolute,\n join,\n relative,\n resolve,\n sep,\n} from \"node:path\";\nconst MAX_ARTIFACT_BYTES = 64 * 1024;\n\nexport function validateArtifactPath(path: unknown): asserts path is string {\n if (typeof path !== \"string\" || !validArtifactPath(path))\n throw new Error(\n \"semantic artifact path must be relative with at most one basename *\",\n );\n}\n\nfunction validArtifactPath(path: string): boolean {\n return (\n safeRelativePath(path) &&\n !dirname(path).includes(\"*\") &&\n /^[^*]*\\*?[^*]*$/.test(basename(path))\n );\n}\n\nfunction safeRelativePath(path: string): boolean {\n return (\n Boolean(path.trim()) &&\n !path.includes(\"\\\\\") &&\n !isAbsolute(path) &&\n !path.split(\"/\").some((part) => part === \"..\" || part === \".git\")\n );\n}\n\nfunction within(root: string, path: string): boolean {\n return path === root || path.startsWith(root + sep);\n}\n\nasync function artifactDirectory(\n root: string,\n pattern: string,\n): Promise<string> {\n const dir = resolve(root, dirname(pattern));\n if (!within(root, dir))\n throw new Error(\"semantic artifact directory escapes the fixture\");\n const directory = await realpath(dir);\n if (!within(root, directory))\n throw new Error(\"semantic artifact directory escapes the fixture\");\n if (relative(root, directory).split(sep).includes(\".git\"))\n throw new Error(\"semantic artifact directory resolves to Git metadata\");\n return directory;\n}\n\nasync function artifactMatches(\n directory: string,\n name: string,\n): Promise<string[]> {\n if (!name.includes(\"*\")) return [name];\n const [prefix = \"\", suffix = \"\"] = name.split(\"*\");\n return (await readdir(directory)).filter(\n (entry) => entry.startsWith(prefix) && entry.endsWith(suffix),\n );\n}\n\nfunction selectedArtifact(directory: string, matches: string[]): string {\n const [name] = matches;\n if (matches.length !== 1 || name === undefined)\n throw new Error(\n `semantic artifact pattern matched ${matches.length} files`,\n );\n return join(directory, name);\n}\n\nasync function resolveArtifact(root: string, path: string): Promise<string> {\n const stat = await lstat(path);\n if (!stat.isFile() || stat.size > MAX_ARTIFACT_BYTES)\n throw new Error(\n \"semantic artifact must be a regular file of at most 64 KiB\",\n );\n const resolved = await realpath(path);\n if (!within(root, resolved))\n throw new Error(\"semantic artifact escapes the fixture\");\n if (relative(root, resolved).split(sep).includes(\".git\"))\n throw new Error(\"semantic artifact resolves to Git metadata\");\n return resolved;\n}\n\nexport async function readSemanticArtifact(\n repoDir: string,\n pattern: string,\n): Promise<{ path: string; content: string }> {\n validateArtifactPath(pattern);\n const root = await realpath(repoDir);\n const directory = await artifactDirectory(root, pattern);\n const matches = await artifactMatches(directory, basename(pattern));\n const path = selectedArtifact(directory, matches);\n const resolved = await resolveArtifact(root, path);\n return {\n path: relative(root, resolved),\n content: await readFile(resolved, \"utf8\"),\n };\n}\n"]}
@@ -0,0 +1,112 @@
1
+ import { spawn } from "../runtime-process.js";
2
+ import { isRecord } from "../value-guards.js";
3
+ import { lstat } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { gitArguments, gitEnvironment } from "../git.js";
6
+ import { captureBoundedText, ProcessDeadline, terminateOwnedProcessGroup, } from "../process-lifecycle.js";
7
+ const MAX_OUTPUT_BYTES = 128;
8
+ const TIMEOUT_MS = 10_000;
9
+ const REVISION = /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/;
10
+ export function prepareGitHeadChecks(declarations) {
11
+ return declarations.map(({ id, configuration }) => {
12
+ if (!id || !validGitHeadConfiguration(configuration))
13
+ throw new Error("invalid Git HEAD check declaration");
14
+ return { id, kind: configuration.kind };
15
+ });
16
+ }
17
+ function validGitHeadKind(value) {
18
+ return (value === "changed" || value === "unchanged" || value === "base-ancestor");
19
+ }
20
+ function validGitHeadConfiguration(value) {
21
+ return (isRecord(value) &&
22
+ !Object.keys(value).some((key) => key !== "kind") &&
23
+ validGitHeadKind(value.kind));
24
+ }
25
+ async function validateGitMetadata(workspace) {
26
+ const directory = await lstat(join(workspace, ".git"));
27
+ if (!directory.isDirectory() || directory.isSymbolicLink())
28
+ throw new Error("Git fixture metadata is not a directory");
29
+ }
30
+ class GitHeadExecution {
31
+ proc;
32
+ deadline;
33
+ constructor(proc, signal) {
34
+ this.proc = proc;
35
+ this.deadline = new ProcessDeadline({
36
+ timeoutMs: TIMEOUT_MS,
37
+ signal,
38
+ interruption: (reason) => new Error(reason === "timeout"
39
+ ? "Git HEAD check timed out"
40
+ : "Git HEAD check cancelled"),
41
+ });
42
+ }
43
+ complete() {
44
+ return Promise.all([
45
+ captureBoundedText(this.proc.stdout, {
46
+ limit: MAX_OUTPUT_BYTES,
47
+ overflow: "reject",
48
+ exceeded: () => new Error("Git HEAD output is oversized"),
49
+ }),
50
+ this.proc.exited,
51
+ ]).then(([output, code]) => ({ output: output.trim(), code }));
52
+ }
53
+ async run() {
54
+ try {
55
+ return await this.deadline.wait(this.complete());
56
+ }
57
+ catch (error) {
58
+ terminateOwnedProcessGroup(this.proc);
59
+ await this.proc.exited;
60
+ throw error;
61
+ }
62
+ finally {
63
+ this.deadline.dispose();
64
+ }
65
+ }
66
+ }
67
+ async function git(workspace, args, signal) {
68
+ if (signal?.aborted)
69
+ throw new Error("Git HEAD check cancelled");
70
+ await validateGitMetadata(workspace);
71
+ const proc = spawn(gitArguments(args), {
72
+ cwd: workspace,
73
+ stdin: "ignore",
74
+ stdout: "pipe",
75
+ stderr: "ignore",
76
+ detached: process.platform !== "win32",
77
+ env: gitEnvironment(),
78
+ });
79
+ return new GitHeadExecution(proc, signal).run();
80
+ }
81
+ export async function gitHeadRevision(workspace, signal) {
82
+ const result = await git(workspace, ["rev-parse", "--verify", "HEAD^{commit}"], signal);
83
+ if (result.code !== 0 || !REVISION.test(result.output))
84
+ throw new Error("Git HEAD revision is unavailable");
85
+ return result.output;
86
+ }
87
+ export async function gitHeadState(workspace, baseRevision, signal) {
88
+ if (!REVISION.test(baseRevision))
89
+ throw new Error("invalid base revision");
90
+ const currentRevision = await gitHeadRevision(workspace, signal);
91
+ const ancestry = await git(workspace, ["merge-base", "--is-ancestor", baseRevision, currentRevision], signal);
92
+ if (ancestry.code !== 0 && ancestry.code !== 1)
93
+ throw new Error("Git HEAD ancestry is unavailable");
94
+ return { currentRevision, baseAncestor: ancestry.code === 0 };
95
+ }
96
+ export function assessGitHeadCheck(check, baseRevision, state) {
97
+ if (check.kind === "unchanged")
98
+ return {
99
+ passed: state.currentRevision === baseRevision,
100
+ detail: "candidate created or switched to a different commit",
101
+ };
102
+ if (check.kind === "changed")
103
+ return {
104
+ passed: state.currentRevision !== baseRevision,
105
+ detail: "candidate did not create the expected commit",
106
+ };
107
+ return {
108
+ passed: state.baseAncestor,
109
+ detail: "candidate replaced or diverged from the fixture history",
110
+ };
111
+ }
112
+ //# sourceMappingURL=git-head.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-head.js","sourceRoot":"","sources":["git-head.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type Subprocess } from \"../runtime-process\";\nimport { isRecord } from \"../value-guards\";\nimport { lstat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { gitArguments, gitEnvironment } from \"../git\";\nimport {\n captureBoundedText,\n ProcessDeadline,\n terminateOwnedProcessGroup,\n} from \"../process-lifecycle\";\n\nconst MAX_OUTPUT_BYTES = 128;\nconst TIMEOUT_MS = 10_000;\nconst REVISION = /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/;\n\nexport interface GitHeadCheckDeclaration {\n id: string;\n grader: \"sevro.git-head\";\n configuration: Record<string, unknown>;\n}\n\nexport interface PreparedGitHeadCheck {\n id: string;\n kind: \"changed\" | \"unchanged\" | \"base-ancestor\";\n}\n\nexport function prepareGitHeadChecks(\n declarations: GitHeadCheckDeclaration[],\n): PreparedGitHeadCheck[] {\n return declarations.map(({ id, configuration }) => {\n if (!id || !validGitHeadConfiguration(configuration))\n throw new Error(\"invalid Git HEAD check declaration\");\n return { id, kind: configuration.kind };\n });\n}\n\nfunction validGitHeadKind(\n value: unknown,\n): value is PreparedGitHeadCheck[\"kind\"] {\n return (\n value === \"changed\" || value === \"unchanged\" || value === \"base-ancestor\"\n );\n}\n\nfunction validGitHeadConfiguration(\n value: unknown,\n): value is { kind: PreparedGitHeadCheck[\"kind\"] } {\n return (\n isRecord(value) &&\n !Object.keys(value).some((key) => key !== \"kind\") &&\n validGitHeadKind(value.kind)\n );\n}\n\nasync function validateGitMetadata(workspace: string): Promise<void> {\n const directory = await lstat(join(workspace, \".git\"));\n if (!directory.isDirectory() || directory.isSymbolicLink())\n throw new Error(\"Git fixture metadata is not a directory\");\n}\n\nclass GitHeadExecution {\n private readonly deadline: ProcessDeadline;\n constructor(\n private readonly proc: Subprocess,\n signal: AbortSignal | undefined,\n ) {\n this.deadline = new ProcessDeadline({\n timeoutMs: TIMEOUT_MS,\n signal,\n interruption: (reason) =>\n new Error(\n reason === \"timeout\"\n ? \"Git HEAD check timed out\"\n : \"Git HEAD check cancelled\",\n ),\n });\n }\n\n private complete() {\n return Promise.all([\n captureBoundedText(this.proc.stdout, {\n limit: MAX_OUTPUT_BYTES,\n overflow: \"reject\",\n exceeded: () => new Error(\"Git HEAD output is oversized\"),\n }),\n this.proc.exited,\n ]).then(([output, code]) => ({ output: output.trim(), code }));\n }\n\n async run(): Promise<{ output: string; code: number }> {\n try {\n return await this.deadline.wait(this.complete());\n } catch (error) {\n terminateOwnedProcessGroup(this.proc);\n await this.proc.exited;\n throw error;\n } finally {\n this.deadline.dispose();\n }\n }\n}\n\nasync function git(\n workspace: string,\n args: string[],\n signal?: AbortSignal,\n): Promise<{ code: number; output: string }> {\n if (signal?.aborted) throw new Error(\"Git HEAD check cancelled\");\n await validateGitMetadata(workspace);\n const proc = spawn(gitArguments(args), {\n cwd: workspace,\n stdin: \"ignore\",\n stdout: \"pipe\",\n stderr: \"ignore\",\n detached: process.platform !== \"win32\",\n env: gitEnvironment(),\n });\n return new GitHeadExecution(proc, signal).run();\n}\n\nexport async function gitHeadRevision(\n workspace: string,\n signal?: AbortSignal,\n): Promise<string> {\n const result = await git(\n workspace,\n [\"rev-parse\", \"--verify\", \"HEAD^{commit}\"],\n signal,\n );\n if (result.code !== 0 || !REVISION.test(result.output))\n throw new Error(\"Git HEAD revision is unavailable\");\n return result.output;\n}\n\nexport async function gitHeadState(\n workspace: string,\n baseRevision: string,\n signal?: AbortSignal,\n): Promise<{ currentRevision: string; baseAncestor: boolean }> {\n if (!REVISION.test(baseRevision)) throw new Error(\"invalid base revision\");\n const currentRevision = await gitHeadRevision(workspace, signal);\n const ancestry = await git(\n workspace,\n [\"merge-base\", \"--is-ancestor\", baseRevision, currentRevision],\n signal,\n );\n if (ancestry.code !== 0 && ancestry.code !== 1)\n throw new Error(\"Git HEAD ancestry is unavailable\");\n return { currentRevision, baseAncestor: ancestry.code === 0 };\n}\n\nexport function assessGitHeadCheck(\n check: PreparedGitHeadCheck,\n baseRevision: string,\n state: { currentRevision: string; baseAncestor: boolean },\n): { passed: boolean; detail: string } {\n if (check.kind === \"unchanged\")\n return {\n passed: state.currentRevision === baseRevision,\n detail: \"candidate created or switched to a different commit\",\n };\n if (check.kind === \"changed\")\n return {\n passed: state.currentRevision !== baseRevision,\n detail: \"candidate did not create the expected commit\",\n };\n return {\n passed: state.baseAncestor,\n detail: \"candidate replaced or diverged from the fixture history\",\n };\n}\n"]}