@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.
- package/CONTRIBUTING.md +22 -6
- package/README.md +5 -1
- package/docs/README.md +19 -15
- package/docs/architecture.md +138 -17
- package/docs/assets/README.md +5 -4
- package/docs/builtin-graders-v1.md +9 -2
- package/docs/codex-host.md +155 -57
- package/docs/contracts.md +2 -1
- package/docs/creating-cases.md +9 -2
- package/docs/development-cli.md +187 -19
- package/docs/documentation-quality.md +12 -2
- package/docs/evaluation-workflow.md +110 -0
- package/docs/extension-protocol-v1.md +26 -3
- package/docs/getting-started.md +23 -2
- package/docs/guide-evaluation.md +33 -1
- package/docs/identity-v1.md +25 -2
- package/docs/installing.md +11 -11
- package/docs/native-controls.md +76 -5
- package/docs/native-hosts.md +196 -7
- package/docs/reading-results.md +102 -0
- package/docs/recipes.md +489 -0
- package/docs/releases.md +31 -12
- package/docs/report-v1.md +29 -1
- package/docs/results-v1.md +122 -4
- package/docs/run-settings-v1.md +147 -0
- package/docs/runtime-v1.md +255 -22
- package/docs/troubleshooting.md +12 -12
- package/docs/typescript-quality.md +89 -26
- package/examples/recipes/candidate.ts +26 -0
- package/examples/recipes/cases/coding-change.json +21 -0
- package/examples/recipes/cases/host-tools.json +21 -0
- package/examples/recipes/cases/mise.json +21 -0
- package/examples/recipes/cases/node.json +21 -0
- package/examples/recipes/cases/python-uv.json +21 -0
- package/examples/recipes/cases/semantic.json +17 -0
- package/examples/recipes/coding-change/check.ts +23 -0
- package/examples/recipes/extension-artifacts.ts +65 -0
- package/examples/recipes/extension-methods.ts +174 -0
- package/examples/recipes/extension.ts +37 -0
- package/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
- package/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
- package/examples/recipes/repository-skill/README.md +3 -0
- package/examples/recipes/run-inputs.ts +188 -0
- package/examples/recipes/run-options.ts +131 -0
- package/examples/recipes/run.ts +63 -0
- package/examples/recipes/runtime/empty.json +1 -0
- package/examples/recipes/runtime/goals.json +1 -0
- package/examples/recipes/runtime/mise.json +6 -0
- package/examples/recipes/runtime/path.json +1 -0
- package/examples/recipes/runtime/plugins.json +4 -0
- package/examples/recipes/runtime/python-uv.json +10 -0
- package/examples/recipes/semantic-judge.ts +29 -0
- package/examples/templates/coding/adapter.ts +17 -0
- package/examples/templates/coding/case.json +15 -0
- package/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
- package/examples/templates/repository-skill/extension-data.ts +64 -0
- package/examples/templates/repository-skill/extension.ts +31 -0
- package/examples/templates/response/adapter.ts +12 -0
- package/examples/templates/response/case.json +13 -0
- package/package.json +11 -5
- package/schemas/report-v1.schema.json +9 -0
- package/schemas/run-evidence-v1.schema.json +2 -1
- package/schemas/runtime-v1.schema.json +43 -7
- package/src/advisory.ts +2 -2
- package/src/candidate-artifacts.ts +42 -11
- package/src/candidate-codex-state.ts +185 -0
- package/src/case-validation.ts +73 -50
- package/src/cli/cancellation.ts +20 -0
- package/src/cli/command.ts +87 -0
- package/src/cli/completion.ts +15 -0
- package/src/cli/demo.ts +60 -0
- package/src/cli/evaluation.ts +55 -0
- package/src/cli/extension.ts +79 -0
- package/src/cli/help.ts +198 -0
- package/src/cli/hosts.ts +55 -0
- package/src/cli/init-settings.ts +30 -0
- package/src/cli/init.ts +111 -0
- package/src/{cli-invocation.ts → cli/invocation.ts} +214 -218
- package/src/cli/loading.ts +151 -0
- package/src/cli/preparation.ts +154 -0
- package/src/cli/presentation.ts +93 -0
- package/src/cli/progress.ts +6 -0
- package/src/cli/run-manifest.ts +128 -0
- package/src/cli/run-options.ts +403 -0
- package/src/cli/run-overrides.ts +69 -0
- package/src/cli/settings.ts +154 -0
- package/src/cli/summary.ts +43 -0
- package/src/cli.ts +13 -591
- package/src/contract-types.ts +94 -0
- package/src/engine.ts +9 -5
- package/src/evaluation/advisory.ts +150 -0
- package/src/{evaluation-check-plan.ts → evaluation/check-plan.ts} +103 -67
- package/src/evaluation/collection.ts +88 -0
- package/src/evaluation/context.ts +10 -0
- package/src/{evaluation-grading-host.ts → evaluation/grading-host.ts} +5 -5
- package/src/evaluation/grading.ts +235 -0
- package/src/{evaluation-invocation-plan.ts → evaluation/invocation-plan.ts} +147 -58
- package/src/{evaluation-plan.ts → evaluation/plan.ts} +208 -141
- package/src/evaluation/progress.ts +19 -0
- package/src/evaluation/resources.ts +241 -0
- package/src/evaluation/run.ts +206 -0
- package/src/{evaluation-semantic.ts → evaluation/semantic.ts} +77 -87
- package/src/evaluation/trial.ts +800 -0
- package/src/{evaluation-types.ts → evaluation/types.ts} +79 -29
- package/src/evidence/host-results.ts +85 -0
- package/src/evidence/retained-artifacts.ts +18 -0
- package/src/evidence/trial-writer.ts +203 -0
- package/src/evidence/usage.ts +17 -0
- package/src/extension-client.ts +34 -96
- package/src/extension-session.ts +24 -48
- package/src/{advisory-fixture.ts → fixtures/advisory.ts} +12 -72
- package/src/{fixture-bin.ts → fixtures/bin.ts} +1 -1
- package/src/{fixture-cleanup.ts → fixtures/cleanup.ts} +13 -7
- package/src/fixtures/create.ts +183 -0
- package/src/{generated-fixture.ts → fixtures/generated.ts} +10 -53
- package/src/{git-hooks.ts → fixtures/git-hooks.ts} +1 -1
- package/src/{preparation.ts → fixtures/preparation.ts} +6 -16
- package/src/{repository-fixture.ts → fixtures/repository.ts} +30 -64
- package/src/{fixture-setup.ts → fixtures/setup.ts} +33 -51
- package/src/{fixture-tools.ts → fixtures/tools.ts} +1 -1
- package/src/{workspace-state.ts → fixtures/workspace-state.ts} +5 -5
- package/src/generated/cli-result.d.cts +2 -1
- package/src/generated/extension.d.cts +2 -1
- package/src/generated/report.cjs +1 -1
- package/src/generated/report.d.cts +2 -1
- package/src/generated/run-evidence.cjs +1 -1
- package/src/generated/run-evidence.d.cts +2 -1
- package/src/generated/runtime.cjs +1 -1
- package/src/generated/runtime.d.cts +2 -1
- package/src/git.ts +93 -0
- package/src/graders/git-head.ts +29 -84
- package/src/graders/shell.ts +50 -68
- package/src/host-diagnostic-redaction.ts +52 -0
- package/src/host-diagnostics.ts +331 -0
- package/src/hosts/claude-continuation.ts +57 -40
- package/src/hosts/claude-credential.ts +160 -63
- package/src/hosts/claude-events.ts +34 -18
- package/src/hosts/claude-keychain.ts +78 -21
- package/src/hosts/claude-login-recovery.ts +85 -0
- package/src/hosts/claude-login-refresh.ts +178 -0
- package/src/hosts/claude-login-store.ts +162 -0
- package/src/hosts/claude-login.ts +107 -0
- package/src/hosts/claude-native-goal.ts +15 -12
- package/src/hosts/claude-process.ts +10 -50
- package/src/hosts/claude-refresh-lock.ts +81 -0
- package/src/hosts/claude-repository-invocation.ts +9 -34
- package/src/hosts/claude-settings.ts +46 -9
- package/src/hosts/claude-skill-activations.ts +169 -0
- package/src/hosts/claude-state.ts +28 -15
- package/src/hosts/claude-tool-calls.ts +13 -10
- package/src/hosts/claude.ts +121 -81
- package/src/hosts/codex-app-server.ts +78 -52
- package/src/hosts/codex-configuration.ts +5 -10
- package/src/hosts/codex-exec-controls.ts +516 -0
- package/src/hosts/codex-marketplace.ts +12 -10
- package/src/hosts/codex-native-calls.ts +15 -122
- package/src/hosts/codex-process.ts +10 -183
- package/src/hosts/codex-profile.ts +36 -21
- package/src/hosts/codex-session-files.ts +1 -9
- package/src/hosts/codex-state.ts +134 -18
- package/src/hosts/codex.ts +210 -183
- package/src/hosts/isolation-common.ts +8 -11
- package/src/hosts/isolation-roots.ts +2 -2
- package/src/hosts/linux-sandbox.ts +15 -2
- package/src/hosts/mac-sandbox.ts +87 -18
- package/src/hosts/native-controls.ts +72 -22
- package/src/hosts/native-request.ts +55 -0
- package/src/hosts/process-lifecycle.ts +216 -48
- package/src/hosts/protected-worktrees.ts +1 -1
- package/src/hosts/skill-hook-catalog.ts +131 -0
- package/src/hosts/skill-hook-handler.ts +374 -0
- package/src/hosts/skill-hooks.ts +577 -0
- package/src/instrumentation.ts +7 -8
- package/src/native-transcript-state.ts +22 -3
- package/src/native-transcript-view.ts +52 -13
- package/src/native-transcripts.ts +26 -11
- package/src/paths.ts +22 -0
- package/src/process-lifecycle.ts +150 -0
- package/src/provenance.ts +27 -7
- package/src/prune.ts +300 -0
- package/src/report.ts +63 -36
- package/src/resolved-case.ts +1 -1
- package/src/results-lock.ts +42 -0
- package/src/results.ts +14 -18
- package/src/{runtime-config.ts → runtime/config.ts} +160 -46
- package/src/{runtime-discovery-apple.ts → runtime/discovery-apple.ts} +3 -3
- package/src/{runtime-discovery-providers.ts → runtime/discovery-providers.ts} +3 -9
- package/src/{runtime-discovery.ts → runtime/discovery.ts} +4 -4
- package/src/{runtime-hook-processes.ts → runtime/hook-processes.ts} +1 -1
- package/src/{runtime-hooks.ts → runtime/hooks.ts} +32 -22
- package/src/{runtime-paths.ts → runtime/paths.ts} +5 -19
- package/src/{runtime-query.ts → runtime/query.ts} +5 -5
- package/src/{runtime-seeds.ts → runtime/seeds.ts} +3 -3
- package/src/runtime/shared-cache.ts +130 -0
- package/src/{runtime-state.ts → runtime/state.ts} +28 -11
- package/src/schema-types.ts +73 -161
- package/src/shell.ts +4 -0
- package/src/transcript-retention.ts +146 -0
- package/src/value-guards.ts +22 -0
- package/docs/assets/sevro-logo.png +0 -0
- package/docs/assets/sevro-symbol.svg +0 -1
- package/docs/assets/sevro-wordmark.svg +0 -1
- package/docs/cache-ownership-validation.md +0 -49
- package/docs/claude-continuation-validation.md +0 -47
- package/docs/concurrency-validation.md +0 -86
- package/docs/configuration-root-validation.md +0 -70
- package/docs/engine-slice.md +0 -114
- package/docs/evidence/runtime-startup-30/README.md +0 -185
- package/docs/evidence/runtime-startup-30/after.json +0 -319
- package/docs/evidence/runtime-startup-30/baseline-timeout.jsonl +0 -2
- package/docs/evidence/runtime-startup-30/before.json +0 -403
- package/docs/evidence/runtime-startup-30/consumer-smoke.json +0 -63
- package/docs/evidence/runtime-startup-30/full-policy-diagnostic.jsonl +0 -3
- package/docs/evidence/runtime-startup-30/minimal-policy-diagnostic.jsonl +0 -3
- package/docs/evidence/runtime-startup-30/plugin-template-assessment.json +0 -20
- package/docs/evidence/runtime-startup-30/seedless-timeout.jsonl +0 -2
- package/docs/evidence.md +0 -17
- package/docs/fixture-cleanup-validation.md +0 -73
- package/docs/guide-verification.json +0 -239
- package/src/evaluation-context.ts +0 -259
- package/src/evaluation-fixture.ts +0 -302
- package/src/evaluation-run.ts +0 -200
- package/src/evaluation-trial.ts +0 -1016
- package/src/hosts/claude-nested-skills.ts +0 -272
- package/src/hosts/codex-command-output.ts +0 -510
- package/src/hosts/codex-executor-command.ts +0 -291
- package/src/hosts/codex-skill-reads.ts +0 -783
- /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 @@
|
|
|
1
|
+
{ "format": "sevro.runtime.v1", "environment": { "inherit": ["PATH"] } }
|
|
@@ -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,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": "
|
|
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
|
|
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": "
|
|
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"] },
|
|
@@ -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
|
-
"
|
|
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
|
|
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))
|