@bjoernrochel/sevro 0.1.0-rc.8 → 1.0.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 (228) hide show
  1. package/CONTRIBUTING.md +22 -6
  2. package/README.md +5 -1
  3. package/docs/README.md +19 -15
  4. package/docs/architecture.md +138 -17
  5. package/docs/assets/README.md +5 -4
  6. package/docs/builtin-graders-v1.md +9 -2
  7. package/docs/codex-host.md +155 -57
  8. package/docs/contracts.md +2 -1
  9. package/docs/creating-cases.md +9 -2
  10. package/docs/development-cli.md +187 -19
  11. package/docs/documentation-quality.md +12 -2
  12. package/docs/evaluation-workflow.md +110 -0
  13. package/docs/extension-protocol-v1.md +26 -3
  14. package/docs/getting-started.md +23 -2
  15. package/docs/guide-evaluation.md +33 -1
  16. package/docs/identity-v1.md +25 -2
  17. package/docs/installing.md +11 -11
  18. package/docs/native-controls.md +76 -5
  19. package/docs/native-hosts.md +196 -7
  20. package/docs/reading-results.md +102 -0
  21. package/docs/recipes.md +489 -0
  22. package/docs/releases.md +31 -12
  23. package/docs/report-v1.md +29 -1
  24. package/docs/results-v1.md +122 -4
  25. package/docs/run-settings-v1.md +147 -0
  26. package/docs/runtime-v1.md +255 -22
  27. package/docs/troubleshooting.md +12 -12
  28. package/docs/typescript-quality.md +89 -26
  29. package/examples/recipes/candidate.ts +26 -0
  30. package/examples/recipes/cases/coding-change.json +21 -0
  31. package/examples/recipes/cases/host-tools.json +21 -0
  32. package/examples/recipes/cases/mise.json +21 -0
  33. package/examples/recipes/cases/node.json +21 -0
  34. package/examples/recipes/cases/python-uv.json +21 -0
  35. package/examples/recipes/cases/semantic.json +17 -0
  36. package/examples/recipes/coding-change/check.ts +23 -0
  37. package/examples/recipes/extension-artifacts.ts +65 -0
  38. package/examples/recipes/extension-methods.ts +174 -0
  39. package/examples/recipes/extension.ts +37 -0
  40. package/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
  41. package/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
  42. package/examples/recipes/repository-skill/README.md +3 -0
  43. package/examples/recipes/run-inputs.ts +188 -0
  44. package/examples/recipes/run-options.ts +131 -0
  45. package/examples/recipes/run.ts +63 -0
  46. package/examples/recipes/runtime/empty.json +1 -0
  47. package/examples/recipes/runtime/goals.json +1 -0
  48. package/examples/recipes/runtime/mise.json +6 -0
  49. package/examples/recipes/runtime/path.json +1 -0
  50. package/examples/recipes/runtime/plugins.json +4 -0
  51. package/examples/recipes/runtime/python-uv.json +10 -0
  52. package/examples/recipes/semantic-judge.ts +29 -0
  53. package/examples/templates/coding/adapter.ts +17 -0
  54. package/examples/templates/coding/case.json +15 -0
  55. package/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
  56. package/examples/templates/repository-skill/extension-data.ts +64 -0
  57. package/examples/templates/repository-skill/extension.ts +31 -0
  58. package/examples/templates/response/adapter.ts +12 -0
  59. package/examples/templates/response/case.json +13 -0
  60. package/package.json +11 -5
  61. package/schemas/report-v1.schema.json +9 -0
  62. package/schemas/run-evidence-v1.schema.json +2 -1
  63. package/schemas/runtime-v1.schema.json +43 -7
  64. package/src/advisory.ts +2 -2
  65. package/src/candidate-artifacts.ts +42 -11
  66. package/src/candidate-codex-state.ts +185 -0
  67. package/src/case-validation.ts +73 -50
  68. package/src/cli/cancellation.ts +20 -0
  69. package/src/cli/command.ts +87 -0
  70. package/src/cli/completion.ts +15 -0
  71. package/src/cli/demo.ts +60 -0
  72. package/src/cli/evaluation.ts +55 -0
  73. package/src/cli/extension.ts +79 -0
  74. package/src/cli/help.ts +198 -0
  75. package/src/cli/hosts.ts +55 -0
  76. package/src/cli/init-settings.ts +30 -0
  77. package/src/cli/init.ts +111 -0
  78. package/src/{cli-invocation.ts → cli/invocation.ts} +214 -218
  79. package/src/cli/loading.ts +151 -0
  80. package/src/cli/preparation.ts +154 -0
  81. package/src/cli/presentation.ts +93 -0
  82. package/src/cli/progress.ts +6 -0
  83. package/src/cli/run-manifest.ts +128 -0
  84. package/src/cli/run-options.ts +403 -0
  85. package/src/cli/run-overrides.ts +69 -0
  86. package/src/cli/settings.ts +154 -0
  87. package/src/cli/summary.ts +43 -0
  88. package/src/cli.ts +13 -591
  89. package/src/contract-types.ts +94 -0
  90. package/src/engine.ts +9 -5
  91. package/src/evaluation/advisory.ts +150 -0
  92. package/src/{evaluation-check-plan.ts → evaluation/check-plan.ts} +103 -67
  93. package/src/evaluation/collection.ts +88 -0
  94. package/src/evaluation/context.ts +10 -0
  95. package/src/{evaluation-grading-host.ts → evaluation/grading-host.ts} +5 -5
  96. package/src/evaluation/grading.ts +235 -0
  97. package/src/{evaluation-invocation-plan.ts → evaluation/invocation-plan.ts} +147 -58
  98. package/src/{evaluation-plan.ts → evaluation/plan.ts} +208 -141
  99. package/src/evaluation/progress.ts +19 -0
  100. package/src/evaluation/resources.ts +241 -0
  101. package/src/evaluation/run.ts +206 -0
  102. package/src/{evaluation-semantic.ts → evaluation/semantic.ts} +77 -87
  103. package/src/evaluation/trial.ts +800 -0
  104. package/src/{evaluation-types.ts → evaluation/types.ts} +79 -29
  105. package/src/evidence/host-results.ts +85 -0
  106. package/src/evidence/retained-artifacts.ts +18 -0
  107. package/src/evidence/trial-writer.ts +203 -0
  108. package/src/evidence/usage.ts +17 -0
  109. package/src/extension-client.ts +34 -96
  110. package/src/extension-session.ts +24 -48
  111. package/src/{advisory-fixture.ts → fixtures/advisory.ts} +12 -72
  112. package/src/{fixture-bin.ts → fixtures/bin.ts} +1 -1
  113. package/src/{fixture-cleanup.ts → fixtures/cleanup.ts} +13 -7
  114. package/src/fixtures/create.ts +183 -0
  115. package/src/{generated-fixture.ts → fixtures/generated.ts} +10 -53
  116. package/src/{git-hooks.ts → fixtures/git-hooks.ts} +1 -1
  117. package/src/{preparation.ts → fixtures/preparation.ts} +6 -16
  118. package/src/{repository-fixture.ts → fixtures/repository.ts} +30 -64
  119. package/src/{fixture-setup.ts → fixtures/setup.ts} +33 -51
  120. package/src/{fixture-tools.ts → fixtures/tools.ts} +1 -1
  121. package/src/{workspace-state.ts → fixtures/workspace-state.ts} +5 -5
  122. package/src/generated/cli-result.d.cts +2 -1
  123. package/src/generated/extension.d.cts +2 -1
  124. package/src/generated/report.cjs +1 -1
  125. package/src/generated/report.d.cts +2 -1
  126. package/src/generated/run-evidence.cjs +1 -1
  127. package/src/generated/run-evidence.d.cts +2 -1
  128. package/src/generated/runtime.cjs +1 -1
  129. package/src/generated/runtime.d.cts +2 -1
  130. package/src/git.ts +93 -0
  131. package/src/graders/git-head.ts +29 -84
  132. package/src/graders/shell.ts +50 -68
  133. package/src/host-diagnostic-redaction.ts +52 -0
  134. package/src/host-diagnostics.ts +331 -0
  135. package/src/hosts/claude-continuation.ts +57 -40
  136. package/src/hosts/claude-credential.ts +160 -63
  137. package/src/hosts/claude-events.ts +34 -18
  138. package/src/hosts/claude-keychain.ts +78 -21
  139. package/src/hosts/claude-login-recovery.ts +85 -0
  140. package/src/hosts/claude-login-refresh.ts +178 -0
  141. package/src/hosts/claude-login-store.ts +162 -0
  142. package/src/hosts/claude-login.ts +107 -0
  143. package/src/hosts/claude-native-goal.ts +15 -12
  144. package/src/hosts/claude-process.ts +10 -50
  145. package/src/hosts/claude-refresh-lock.ts +81 -0
  146. package/src/hosts/claude-repository-invocation.ts +9 -34
  147. package/src/hosts/claude-settings.ts +46 -9
  148. package/src/hosts/claude-skill-activations.ts +169 -0
  149. package/src/hosts/claude-state.ts +28 -15
  150. package/src/hosts/claude-tool-calls.ts +13 -10
  151. package/src/hosts/claude.ts +121 -81
  152. package/src/hosts/codex-app-server.ts +78 -52
  153. package/src/hosts/codex-configuration.ts +5 -10
  154. package/src/hosts/codex-exec-controls.ts +516 -0
  155. package/src/hosts/codex-marketplace.ts +12 -10
  156. package/src/hosts/codex-native-calls.ts +15 -122
  157. package/src/hosts/codex-process.ts +10 -183
  158. package/src/hosts/codex-profile.ts +36 -21
  159. package/src/hosts/codex-session-files.ts +1 -9
  160. package/src/hosts/codex-state.ts +134 -18
  161. package/src/hosts/codex.ts +210 -183
  162. package/src/hosts/isolation-common.ts +8 -11
  163. package/src/hosts/isolation-roots.ts +2 -2
  164. package/src/hosts/linux-sandbox.ts +15 -2
  165. package/src/hosts/mac-sandbox.ts +87 -18
  166. package/src/hosts/native-controls.ts +72 -22
  167. package/src/hosts/native-request.ts +55 -0
  168. package/src/hosts/process-lifecycle.ts +216 -48
  169. package/src/hosts/protected-worktrees.ts +1 -1
  170. package/src/hosts/skill-hook-catalog.ts +131 -0
  171. package/src/hosts/skill-hook-handler.ts +374 -0
  172. package/src/hosts/skill-hooks.ts +577 -0
  173. package/src/instrumentation.ts +7 -8
  174. package/src/native-transcript-state.ts +22 -3
  175. package/src/native-transcript-view.ts +52 -13
  176. package/src/native-transcripts.ts +26 -11
  177. package/src/paths.ts +22 -0
  178. package/src/process-lifecycle.ts +150 -0
  179. package/src/provenance.ts +27 -7
  180. package/src/prune.ts +300 -0
  181. package/src/report.ts +63 -36
  182. package/src/resolved-case.ts +1 -1
  183. package/src/results-lock.ts +42 -0
  184. package/src/results.ts +14 -18
  185. package/src/{runtime-config.ts → runtime/config.ts} +160 -46
  186. package/src/{runtime-discovery-apple.ts → runtime/discovery-apple.ts} +3 -3
  187. package/src/{runtime-discovery-providers.ts → runtime/discovery-providers.ts} +3 -9
  188. package/src/{runtime-discovery.ts → runtime/discovery.ts} +4 -4
  189. package/src/{runtime-hook-processes.ts → runtime/hook-processes.ts} +1 -1
  190. package/src/{runtime-hooks.ts → runtime/hooks.ts} +32 -22
  191. package/src/{runtime-paths.ts → runtime/paths.ts} +5 -19
  192. package/src/{runtime-query.ts → runtime/query.ts} +5 -5
  193. package/src/{runtime-seeds.ts → runtime/seeds.ts} +3 -3
  194. package/src/runtime/shared-cache.ts +130 -0
  195. package/src/{runtime-state.ts → runtime/state.ts} +28 -11
  196. package/src/schema-types.ts +73 -161
  197. package/src/shell.ts +4 -0
  198. package/src/transcript-retention.ts +146 -0
  199. package/src/value-guards.ts +22 -0
  200. package/docs/assets/sevro-logo.png +0 -0
  201. package/docs/assets/sevro-symbol.svg +0 -1
  202. package/docs/assets/sevro-wordmark.svg +0 -1
  203. package/docs/cache-ownership-validation.md +0 -49
  204. package/docs/claude-continuation-validation.md +0 -47
  205. package/docs/concurrency-validation.md +0 -86
  206. package/docs/configuration-root-validation.md +0 -70
  207. package/docs/engine-slice.md +0 -114
  208. package/docs/evidence/runtime-startup-30/README.md +0 -185
  209. package/docs/evidence/runtime-startup-30/after.json +0 -319
  210. package/docs/evidence/runtime-startup-30/baseline-timeout.jsonl +0 -2
  211. package/docs/evidence/runtime-startup-30/before.json +0 -403
  212. package/docs/evidence/runtime-startup-30/consumer-smoke.json +0 -63
  213. package/docs/evidence/runtime-startup-30/full-policy-diagnostic.jsonl +0 -3
  214. package/docs/evidence/runtime-startup-30/minimal-policy-diagnostic.jsonl +0 -3
  215. package/docs/evidence/runtime-startup-30/plugin-template-assessment.json +0 -20
  216. package/docs/evidence/runtime-startup-30/seedless-timeout.jsonl +0 -2
  217. package/docs/evidence.md +0 -17
  218. package/docs/fixture-cleanup-validation.md +0 -73
  219. package/docs/guide-verification.json +0 -239
  220. package/src/evaluation-context.ts +0 -259
  221. package/src/evaluation-fixture.ts +0 -302
  222. package/src/evaluation-run.ts +0 -200
  223. package/src/evaluation-trial.ts +0 -1016
  224. package/src/hosts/claude-nested-skills.ts +0 -272
  225. package/src/hosts/codex-command-output.ts +0 -510
  226. package/src/hosts/codex-executor-command.ts +0 -291
  227. package/src/hosts/codex-skill-reads.ts +0 -783
  228. /package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +0 -0
@@ -0,0 +1,131 @@
1
+ import { delimiter, isAbsolute, join } from "node:path";
2
+ import { homedir } from "node:os";
3
+
4
+ export const recipeNames = [
5
+ "coding-change",
6
+ "host-tools",
7
+ "node",
8
+ "python-uv",
9
+ "mise",
10
+ "semantic",
11
+ "lifecycle",
12
+ "repository-skill",
13
+ "plugins",
14
+ ];
15
+
16
+ function validateSelection(
17
+ recipe: string,
18
+ route: string,
19
+ flags: string[],
20
+ ): void {
21
+ if (!recipeNames.includes(recipe))
22
+ throw new Error(`Choose a recipe: ${recipeNames.join(", ")}`);
23
+ if (!["deterministic", "codex", "claude"].includes(route))
24
+ throw new Error("Choose deterministic, codex, or claude");
25
+ if (flags.some((flag) => !["--dry", "--fail", "--goals-only"].includes(flag)))
26
+ throw new Error("Supported flags: --dry --fail --goals-only");
27
+ }
28
+
29
+ function validateNativeRecipe(recipe: string, route: string): void {
30
+ if (
31
+ ["repository-skill", "plugins"].includes(recipe) &&
32
+ route === "deterministic"
33
+ )
34
+ throw new Error(
35
+ "Skill and plugin recipes require codex or claude (add --dry to prepare without model calls)",
36
+ );
37
+ }
38
+
39
+ export function selectedOptions() {
40
+ const [recipe = "", route = "deterministic", ...flags] =
41
+ process.argv.slice(2);
42
+ validateSelection(recipe, route, flags);
43
+ validateNativeRecipe(recipe, route);
44
+ validateGoalsStep(flags);
45
+ return {
46
+ recipe,
47
+ route,
48
+ dry: flags.includes("--dry"),
49
+ fail: flags.includes("--fail"),
50
+ goalsOnly: flags.includes("--goals-only"),
51
+ };
52
+ }
53
+ export type RecipeOptions = ReturnType<typeof selectedOptions>;
54
+
55
+ function validateGoalsStep(flags: string[]): void {
56
+ if (flags.includes("--goals-only") && !flags.includes("--dry"))
57
+ throw new Error(
58
+ "--goals-only is a dry preparation step; omit it for the complete hook recipe",
59
+ );
60
+ }
61
+
62
+ export function requireTool(name: string): string {
63
+ const path = Bun.which(name);
64
+ if (!path)
65
+ throw new Error(
66
+ `Recipe prerequisite missing: install ${name} and put it on PATH`,
67
+ );
68
+ return path;
69
+ }
70
+
71
+ export function runtimeFile(options: RecipeOptions): string {
72
+ const files: Record<string, string> = {
73
+ "coding-change": "path",
74
+ "host-tools": "path",
75
+ node: "path",
76
+ "python-uv": "python-uv",
77
+ mise: "mise",
78
+ plugins: options.goalsOnly ? "goals" : "plugins",
79
+ };
80
+ return join(
81
+ import.meta.dir,
82
+ "runtime",
83
+ `${files[options.recipe] ?? "empty"}.json`,
84
+ );
85
+ }
86
+
87
+ function languagePrerequisites(recipe: string): void {
88
+ if (recipe === "python-uv")
89
+ process.env.RECIPE_PYTHON ??= requireTool("python3");
90
+ if (recipe === "mise") selectMiseNode();
91
+ if (recipe === "host-tools") requireStandaloneRipgrep();
92
+ }
93
+
94
+ function requireStandaloneRipgrep(): void {
95
+ const roots = [
96
+ process.env.CODEX_HOME ?? join(homedir(), ".codex"),
97
+ process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), ".claude"),
98
+ ];
99
+ const paths = (process.env.PATH ?? "")
100
+ .split(delimiter)
101
+ .filter((entry) => !roots.some((root) => entry.startsWith(root)));
102
+ if (!Bun.which("rg", { PATH: paths.join(delimiter) }))
103
+ throw new Error(
104
+ "Install standalone ripgrep outside Codex/Claude credential directories, then put it on PATH (for example brew install ripgrep or apt-get install ripgrep)",
105
+ );
106
+ }
107
+
108
+ function selectMiseNode(): void {
109
+ const result = Bun.spawnSync([requireTool("mise"), "where", "node@24.13.0"], {
110
+ stdout: "pipe",
111
+ stderr: "pipe",
112
+ });
113
+ const installation = result.stdout.toString().trim();
114
+ if (result.exitCode !== 0 || !isAbsolute(installation))
115
+ throw new Error(
116
+ "Install the recipe's Node with mise install node@24.13.0 before running it",
117
+ );
118
+ process.env.PATH = `${join(installation, "bin")}${delimiter}${process.env.PATH ?? "/usr/bin:/bin"}`;
119
+ }
120
+
121
+ export function runtimePrerequisites(recipe: string): void {
122
+ const tools: Record<string, string[]> = {
123
+ "coding-change": ["node"],
124
+ "host-tools": ["rg"],
125
+ node: ["node"],
126
+ "python-uv": ["uv", "python3"],
127
+ mise: ["mise"],
128
+ };
129
+ for (const tool of tools[recipe] ?? []) requireTool(tool);
130
+ languagePrerequisites(recipe);
131
+ }
@@ -0,0 +1,63 @@
1
+ import { mkdir, realpath, writeFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { hostArguments, recipeInputs, semanticArguments } from "./run-inputs";
4
+ import {
5
+ runtimeFile,
6
+ runtimePrerequisites,
7
+ selectedOptions,
8
+ } from "./run-options";
9
+
10
+ const options = selectedOptions();
11
+ runtimePrerequisites(options.recipe);
12
+ const mode = options.dry ? "dry" : options.fail ? "fail" : "pass";
13
+ const state = resolve(
14
+ ".sevro-recipes",
15
+ options.recipe,
16
+ options.route,
17
+ options.goalsOnly ? "goals" : mode,
18
+ );
19
+ await mkdir(join(state, "project"), { recursive: true });
20
+ await mkdir(join(state, "config"), { recursive: true });
21
+ const root = await realpath(state);
22
+ const cli =
23
+ process.env.SEVRO_RECIPE_CLI ?? resolve(import.meta.dir, "../../src/cli.ts");
24
+ const args = [
25
+ process.execPath,
26
+ cli,
27
+ "run",
28
+ "--json",
29
+ "--project-root",
30
+ join(root, "project"),
31
+ "--config-root",
32
+ join(root, "config"),
33
+ "--results-root",
34
+ join(root, "results"),
35
+ "--runtime-config-file",
36
+ runtimeFile(options),
37
+ "--condition",
38
+ "passive",
39
+ "--trials",
40
+ "1",
41
+ "--threshold",
42
+ "1",
43
+ "--shell-isolation",
44
+ "--protected-root",
45
+ import.meta.dir,
46
+ ...(await recipeInputs(options, root)),
47
+ ...(await hostArguments(options, root)),
48
+ ...(await semanticArguments(options, root)),
49
+ ...(options.dry ? ["--dry"] : []),
50
+ ];
51
+ const child = Bun.spawn(args, {
52
+ env: { ...process.env, SEVRO_RECIPE_FAIL: options.fail ? "1" : "0" },
53
+ stdout: "pipe",
54
+ stderr: "inherit",
55
+ });
56
+ const [output, code] = await Promise.all([
57
+ new Response(child.stdout).text(),
58
+ child.exited,
59
+ ]);
60
+ await writeFile(join(root, "result.json"), output);
61
+ process.stderr.write(`Recipe result: ${join(root, "result.json")}\n`);
62
+ process.stdout.write(output);
63
+ process.exit(code);
@@ -0,0 +1 @@
1
+ { "format": "sevro.runtime.v1" }
@@ -0,0 +1 @@
1
+ { "format": "sevro.runtime.v1", "hooks": { "nativeGoal": true } }
@@ -0,0 +1,6 @@
1
+ {
2
+ "format": "sevro.runtime.v1",
3
+ "environment": {
4
+ "inherit": ["PATH"]
5
+ }
6
+ }
@@ -0,0 +1 @@
1
+ { "format": "sevro.runtime.v1", "environment": { "inherit": ["PATH"] } }
@@ -0,0 +1,4 @@
1
+ {
2
+ "format": "sevro.runtime.v1",
3
+ "hooks": { "nativeGoal": true, "plugins": ["startup"] }
4
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "format": "sevro.runtime.v1",
3
+ "environment": {
4
+ "inherit": ["PATH", "RECIPE_PYTHON"],
5
+ "set": {
6
+ "UV_CACHE_DIR": "{{sevro.runtime}}/uv-cache",
7
+ "UV_PYTHON_DOWNLOADS": "never"
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,29 @@
1
+ /** Protocol control only: use a real judge for qualitative model assessment. */
2
+ const judge = {
3
+ id: "recipes.protocol-judge",
4
+ model: "exact-fixture-oracle",
5
+ effort: "none",
6
+ run({ prompt }: { prompt: string }) {
7
+ const match =
8
+ /<candidate-response-json>\s*([\s\S]*?)\s*<\/candidate-response-json>/.exec(
9
+ prompt,
10
+ );
11
+ if (!match?.[1]) throw new Error("Missing semantic candidate response");
12
+ const candidate: unknown = JSON.parse(match[1]);
13
+ const passed = candidate === "Run bun run dev on port 3000.";
14
+ return Promise.resolve({
15
+ complete: true,
16
+ finalMessage: JSON.stringify({
17
+ checks: [
18
+ {
19
+ id: "startup-meaning",
20
+ verdict: passed ? "pass" : "fail",
21
+ reason:
22
+ "Exact deterministic fixture oracle; no model judgment was made.",
23
+ },
24
+ ],
25
+ }),
26
+ });
27
+ },
28
+ };
29
+ export default judge;
@@ -0,0 +1,17 @@
1
+ import { writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+
4
+ /** Deterministic file editor; it exercises the evaluator, not model coding ability. */
5
+ export default {
6
+ id: "template.coding",
7
+ model: "deterministic-editor",
8
+ effort: "none",
9
+ async run({ workspace }: { workspace: string }) {
10
+ if (process.env.SEVRO_TEMPLATE_FAIL !== "1")
11
+ await writeFile(
12
+ join(workspace, "add.sh"),
13
+ 'add() { echo "$(( $1 + $2 ))"; }\n',
14
+ );
15
+ return { finalMessage: "Completed the coding task.", complete: true };
16
+ },
17
+ };
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "coding-addition",
3
+ "prompt": "Fix add.sh so add computes integer addition. Preserve the add shell function interface.",
4
+ "fixture": { "files": { "add.sh": "add() { echo \"$(( $1 - $2 ))\"; }\n" } },
5
+ "checks": [
6
+ {
7
+ "id": "addition",
8
+ "grader": "sevro.shell",
9
+ "configuration": {
10
+ "run": ". ./add.sh; test \"$(add 2 3)\" = 5 && test \"$(add -2 -3)\" = -5 && test \"$(add 0 0)\" = 0"
11
+ }
12
+ }
13
+ ],
14
+ "requiredEvidence": []
15
+ }
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: startup-guide
3
+ description: Explain the sample application's start command and port.
4
+ ---
5
+
6
+ Read README.md. State the exact start command and port. Do not change files.
@@ -0,0 +1,64 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+
5
+ export const description = {
6
+ extension: { id: "template.startup", version: "1.0.0" },
7
+ protocols: ["sevro.extension.v1"],
8
+ requiredCapabilities: ["sevro.codex.repository-invocation"],
9
+ optionalCapabilities: [],
10
+ graders: [],
11
+ taskVerdictPolicies: [],
12
+ };
13
+
14
+ export const resolved = {
15
+ cases: [
16
+ {
17
+ id: "repository-skill",
18
+ prompt:
19
+ "{{sevro.skill_invocation}} Explain the application's start command and port. Do not change files.",
20
+ fixture: {
21
+ kind: "generated",
22
+ commits: [
23
+ {
24
+ message: "Initialize application",
25
+ files: { "README.md": "Run bun run dev on port 3000.\n" },
26
+ },
27
+ ],
28
+ },
29
+ checks: [
30
+ {
31
+ id: "start-command",
32
+ grader: "sevro.regex",
33
+ configuration: { pattern: "bun run dev" },
34
+ },
35
+ {
36
+ id: "port",
37
+ grader: "sevro.regex",
38
+ configuration: { pattern: "\\b3000\\b" },
39
+ },
40
+ ],
41
+ requiredEvidence: ["sevro.codex.explicit-invocation"],
42
+ extensionData: {},
43
+ },
44
+ ],
45
+ };
46
+
47
+ export async function prepare() {
48
+ const relativePath = ".agents/skills/startup-guide/SKILL.md";
49
+ const body = await readFile(join(import.meta.dir, relativePath));
50
+ return {
51
+ artifacts: [
52
+ {
53
+ id: "template.startup-skill",
54
+ relativePath,
55
+ sha256: createHash("sha256").update(body).digest("hex"),
56
+ contentBase64: body.toString("base64"),
57
+ gitExclude: true,
58
+ },
59
+ ],
60
+ requestedInstrumentation: [],
61
+ extensionData: {},
62
+ codexRepositorySkillInvocation: { skillName: "startup-guide" },
63
+ };
64
+ }
@@ -0,0 +1,31 @@
1
+ import { description, prepare, resolved } from "./extension-data";
2
+
3
+ function record(value: unknown): Record<string, unknown> {
4
+ if (!value || typeof value !== "object" || Array.isArray(value))
5
+ throw new Error("Expected a protocol request object");
6
+ return value as Record<string, unknown>;
7
+ }
8
+
9
+ const request = record(JSON.parse(await Bun.stdin.text()) as unknown);
10
+ async function result() {
11
+ switch (request.method) {
12
+ case "describe":
13
+ return description;
14
+ case "resolve":
15
+ return resolved;
16
+ case "prepare":
17
+ return await prepare();
18
+ case "evaluate":
19
+ return { checks: [], metrics: [] };
20
+ default:
21
+ throw new Error("Unsupported extension method");
22
+ }
23
+ }
24
+ process.stdout.write(
25
+ JSON.stringify({
26
+ protocol: request.protocol,
27
+ id: request.id,
28
+ method: request.method,
29
+ result: await result(),
30
+ }),
31
+ );
@@ -0,0 +1,12 @@
1
+ /** Deterministic starter; replace with an explicit native route to evaluate a model. */
2
+ export default {
3
+ id: "template.response",
4
+ model: "deterministic-example",
5
+ effort: "none",
6
+ run() {
7
+ return Promise.resolve({
8
+ finalMessage: process.env.SEVRO_TEMPLATE_FAIL === "1" ? "wrong" : "ready",
9
+ complete: true,
10
+ });
11
+ },
12
+ };
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": "response-check",
3
+ "prompt": "Return exactly ready.",
4
+ "fixture": { "files": { "README.md": "Response-check fixture.\n" } },
5
+ "checks": [
6
+ {
7
+ "id": "ready",
8
+ "grader": "sevro.regex",
9
+ "configuration": { "pattern": "^ready$" }
10
+ }
11
+ ],
12
+ "requiredEvidence": []
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bjoernrochel/sevro",
3
- "version": "0.1.0-rc.8",
3
+ "version": "1.0.0",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "A standalone evaluation runner for agentic coding capabilities",
6
6
  "type": "module",
@@ -19,7 +19,14 @@
19
19
  "README.md",
20
20
  "CONTRIBUTING.md",
21
21
  "LICENSE",
22
- "docs/",
22
+ "docs/*.md",
23
+ "!docs/*-validation.md",
24
+ "!docs/engine-slice.md",
25
+ "!docs/evidence.md",
26
+ "!docs/usability-study.md",
27
+ "docs/assets/README.md",
28
+ "docs/licenses/",
29
+ "docs/specs/",
23
30
  "examples/",
24
31
  "schemas/",
25
32
  "src/"
@@ -44,7 +51,7 @@
44
51
  "eval:guide": "bun scripts/eval-guide.ts",
45
52
  "release:prepare": "bun scripts/prepare-release.ts",
46
53
  "typecheck": "tsc --noEmit",
47
- "format:check": "prettier --check README.md CONTRIBUTING.md AGENTS.md CLAUDE.md 'docs/**/*.md' '.agents/**/*.md' '.agents/**/*.json' '.claude/**/*.md' 'scripts/**/*.md' examples/**/*.json examples/**/*.ts schemas/*.json src/**/*.ts scripts/**/*.ts scripts/**/*.cjs tests/**/*.ts eslint.config.mjs package.json tsconfig.json typescript-sources.json .github/workflows/*.yml"
54
+ "format:check": "prettier --check README.md CONTRIBUTING.md AGENTS.md CLAUDE.md 'docs/**/*.md' '.agents/**/*.md' '.agents/**/*.json' '.claude/**/*.md' 'scripts/**/*.md' 'scripts/**/*.json' 'examples/**/*.json' 'examples/**/*.ts' 'schemas/*.json' 'src/**/*.ts' 'scripts/**/*.ts' 'scripts/**/*.cjs' 'tests/**/*.ts' eslint.config.mjs package.json tsconfig.json '.github/workflows/*.yml'"
48
55
  },
49
56
  "dependencies": {
50
57
  "ajv": "8.20.0",
@@ -68,10 +75,9 @@
68
75
  "istanbul-lib-coverage": "3.2.2",
69
76
  "istanbul-lib-instrument": "6.0.3",
70
77
  "istanbul-lib-report": "3.0.1",
71
- "istanbul-lib-source-maps": "5.0.6",
72
78
  "istanbul-reports": "3.2.0",
73
79
  "markdown-it": "14.2.0",
74
- "prettier": "^3.9.9",
80
+ "prettier": "3.9.9",
75
81
  "shell-quote": "1.12.0",
76
82
  "typescript-eslint": "8.71.1"
77
83
  }
@@ -110,6 +110,15 @@
110
110
  "domainOutcomes"
111
111
  ],
112
112
  "properties": {
113
+ "nativeTranscripts": {
114
+ "type": "object",
115
+ "required": ["retained", "pruned"],
116
+ "properties": {
117
+ "retained": { "type": "integer", "minimum": 0 },
118
+ "pruned": { "type": "integer", "minimum": 0 }
119
+ },
120
+ "additionalProperties": false
121
+ },
113
122
  "resultFile": { "$ref": "#/$defs/path" },
114
123
  "evidencePath": { "type": ["string", "null"] },
115
124
  "runId": { "type": ["string", "null"] },
@@ -80,7 +80,8 @@
80
80
  "required": ["digest", "redacted"],
81
81
  "properties": {
82
82
  "digest": { "$ref": "#/$defs/digest" },
83
- "redacted": { "type": "object" }
83
+ "redacted": { "type": "object" },
84
+ "resolved": { "type": "object" }
84
85
  },
85
86
  "additionalProperties": false
86
87
  },
@@ -5,7 +5,23 @@
5
5
  "type": "object",
6
6
  "additionalProperties": false,
7
7
  "required": ["format"],
8
+ "$defs": {
9
+ "runtimeRole": {
10
+ "$comment": "Generated from RUNTIME_ROLES by bun run schemas:generate.",
11
+ "enum": ["candidate", "checks", "hooks", "semantic", "advisory"]
12
+ }
13
+ },
8
14
  "properties": {
15
+ "codexState": {
16
+ "type": "boolean"
17
+ },
18
+ "network": {
19
+ "type": "object",
20
+ "additionalProperties": false,
21
+ "properties": {
22
+ "localHttp": { "type": "boolean" }
23
+ }
24
+ },
9
25
  "nativeTranscripts": {
10
26
  "type": "boolean"
11
27
  },
@@ -52,6 +68,32 @@
52
68
  }
53
69
  }
54
70
  },
71
+ "sharedCacheDirectories": {
72
+ "type": "array",
73
+ "maxItems": 16,
74
+ "items": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "required": ["source", "target", "roles"],
78
+ "properties": {
79
+ "source": { "type": "string", "minLength": 1, "maxLength": 4096 },
80
+ "target": {
81
+ "type": "string",
82
+ "pattern": "^[a-z][a-z0-9-]{0,63}$",
83
+ "not": { "enum": ["home", "tmp"] }
84
+ },
85
+ "roles": {
86
+ "type": "array",
87
+ "minItems": 1,
88
+ "maxItems": 5,
89
+ "uniqueItems": true,
90
+ "items": {
91
+ "$ref": "#/$defs/runtimeRole"
92
+ }
93
+ }
94
+ }
95
+ }
96
+ },
55
97
  "seedDirectories": {
56
98
  "type": "array",
57
99
  "maxItems": 16,
@@ -78,13 +120,7 @@
78
120
  "maxItems": 5,
79
121
  "uniqueItems": true,
80
122
  "items": {
81
- "enum": [
82
- "candidate",
83
- "checks",
84
- "hooks",
85
- "semantic",
86
- "advisory"
87
- ]
123
+ "$ref": "#/$defs/runtimeRole"
88
124
  }
89
125
  }
90
126
  }
package/src/advisory.ts CHANGED
@@ -7,14 +7,14 @@ const DIMENSIONS = [
7
7
  "scopeDiscipline",
8
8
  ] as const;
9
9
 
10
- export interface AdvisoryAssessment {
10
+ export type AdvisoryAssessment = {
11
11
  verdict: "pass" | "fail";
12
12
  overallScore: number;
13
13
  dimensions: Record<(typeof DIMENSIONS)[number], number>;
14
14
  strengths: string[];
15
15
  weaknesses: string[];
16
16
  summary: string;
17
- }
17
+ };
18
18
 
19
19
  function object(value: unknown): Record<string, unknown> {
20
20
  if (!value || typeof value !== "object" || Array.isArray(value))