@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,403 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
|
|
3
|
+
type RunOption = {
|
|
4
|
+
type: "string" | "boolean";
|
|
5
|
+
kind: "string" | "boolean" | "number" | "path" | "path-list";
|
|
6
|
+
multiple?: boolean;
|
|
7
|
+
cliOnly?: boolean;
|
|
8
|
+
private?: boolean;
|
|
9
|
+
extension?: boolean;
|
|
10
|
+
route?: "codex" | "claude";
|
|
11
|
+
section:
|
|
12
|
+
| "required"
|
|
13
|
+
| "common"
|
|
14
|
+
| "native"
|
|
15
|
+
| "extension"
|
|
16
|
+
| "grading"
|
|
17
|
+
| "provenance"
|
|
18
|
+
| "deprecated";
|
|
19
|
+
help: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Parsing, saved-setting semantics, protection and help share one inventory. */
|
|
23
|
+
export const RUN_OPTIONS = {
|
|
24
|
+
json: {
|
|
25
|
+
type: "boolean",
|
|
26
|
+
kind: "boolean",
|
|
27
|
+
cliOnly: true,
|
|
28
|
+
section: "common",
|
|
29
|
+
help: "One versioned JSON result on stdout (default: false); human diagnostics go to stderr.",
|
|
30
|
+
},
|
|
31
|
+
"run-manifest-file": {
|
|
32
|
+
type: "string",
|
|
33
|
+
kind: "path",
|
|
34
|
+
cliOnly: true,
|
|
35
|
+
private: true,
|
|
36
|
+
section: "common",
|
|
37
|
+
help: "<path> Saved sevro.run.v1 settings; explicit flags override them.",
|
|
38
|
+
},
|
|
39
|
+
"retain-host-diagnostics": {
|
|
40
|
+
type: "boolean",
|
|
41
|
+
kind: "boolean",
|
|
42
|
+
section: "common",
|
|
43
|
+
help: "Retain private native diagnostics (default: false).",
|
|
44
|
+
},
|
|
45
|
+
dry: {
|
|
46
|
+
type: "boolean",
|
|
47
|
+
kind: "boolean",
|
|
48
|
+
section: "common",
|
|
49
|
+
help: "Prepare only (default: false).",
|
|
50
|
+
},
|
|
51
|
+
"case-file": {
|
|
52
|
+
type: "string",
|
|
53
|
+
kind: "path",
|
|
54
|
+
private: true,
|
|
55
|
+
section: "required",
|
|
56
|
+
help: "<path> Select exactly one of --case-file or --extension-command-file.",
|
|
57
|
+
},
|
|
58
|
+
"case-id": {
|
|
59
|
+
type: "string",
|
|
60
|
+
kind: "string",
|
|
61
|
+
extension: true,
|
|
62
|
+
section: "extension",
|
|
63
|
+
help: "<id> Required with --extension-command-file.",
|
|
64
|
+
},
|
|
65
|
+
"extension-command-file": {
|
|
66
|
+
type: "string",
|
|
67
|
+
kind: "path",
|
|
68
|
+
extension: true,
|
|
69
|
+
private: true,
|
|
70
|
+
section: "required",
|
|
71
|
+
help: "<path> Select one extension case instead of --case-file.",
|
|
72
|
+
},
|
|
73
|
+
"extension-source-file": {
|
|
74
|
+
type: "string",
|
|
75
|
+
kind: "path-list",
|
|
76
|
+
multiple: true,
|
|
77
|
+
extension: true,
|
|
78
|
+
private: true,
|
|
79
|
+
section: "extension",
|
|
80
|
+
help: "<path> Required source closure; repeatable.",
|
|
81
|
+
},
|
|
82
|
+
"extension-configuration-file": {
|
|
83
|
+
type: "string",
|
|
84
|
+
kind: "path",
|
|
85
|
+
extension: true,
|
|
86
|
+
private: true,
|
|
87
|
+
section: "extension",
|
|
88
|
+
help: "<path> Private JSON object; supply with --extension-redacted-configuration-file.",
|
|
89
|
+
},
|
|
90
|
+
"extension-redacted-configuration-file": {
|
|
91
|
+
type: "string",
|
|
92
|
+
kind: "path",
|
|
93
|
+
extension: true,
|
|
94
|
+
private: true,
|
|
95
|
+
section: "extension",
|
|
96
|
+
help: "<path> Redacted retained configuration; supply with --extension-configuration-file.",
|
|
97
|
+
},
|
|
98
|
+
"task-verdict-policy": {
|
|
99
|
+
type: "string",
|
|
100
|
+
kind: "string",
|
|
101
|
+
extension: true,
|
|
102
|
+
section: "extension",
|
|
103
|
+
help: "<id> Select an advertised namespaced extension policy.",
|
|
104
|
+
},
|
|
105
|
+
"replace-builtin-grader": {
|
|
106
|
+
type: "string",
|
|
107
|
+
kind: "string",
|
|
108
|
+
multiple: true,
|
|
109
|
+
extension: true,
|
|
110
|
+
section: "extension",
|
|
111
|
+
help: "<id> Explicit replacement; repeatable.",
|
|
112
|
+
},
|
|
113
|
+
"case-source-root": {
|
|
114
|
+
type: "string",
|
|
115
|
+
kind: "path",
|
|
116
|
+
private: true,
|
|
117
|
+
section: "extension",
|
|
118
|
+
help: "<path> Supply with --case-source-map-file for mapped sources.",
|
|
119
|
+
},
|
|
120
|
+
"case-source-map-file": {
|
|
121
|
+
type: "string",
|
|
122
|
+
kind: "path",
|
|
123
|
+
private: true,
|
|
124
|
+
section: "extension",
|
|
125
|
+
help: "<path> Supply with --case-source-root for mapped sources.",
|
|
126
|
+
},
|
|
127
|
+
"adapter-module": {
|
|
128
|
+
type: "string",
|
|
129
|
+
kind: "path",
|
|
130
|
+
section: "required",
|
|
131
|
+
help: "<path> Select exactly one of --adapter-module or --host <codex|claude>.",
|
|
132
|
+
},
|
|
133
|
+
"semantic-adapter-module": {
|
|
134
|
+
type: "string",
|
|
135
|
+
kind: "path",
|
|
136
|
+
private: true,
|
|
137
|
+
section: "grading",
|
|
138
|
+
help: "<path> Select this or --semantic-host codex.",
|
|
139
|
+
},
|
|
140
|
+
"semantic-host": {
|
|
141
|
+
type: "string",
|
|
142
|
+
kind: "string",
|
|
143
|
+
section: "grading",
|
|
144
|
+
help: "<codex> Native semantic route; none selected by default.",
|
|
145
|
+
},
|
|
146
|
+
"semantic-model": {
|
|
147
|
+
type: "string",
|
|
148
|
+
kind: "string",
|
|
149
|
+
section: "grading",
|
|
150
|
+
help: "<name> Required for native semantic route.",
|
|
151
|
+
},
|
|
152
|
+
"semantic-effort": {
|
|
153
|
+
type: "string",
|
|
154
|
+
kind: "string",
|
|
155
|
+
section: "grading",
|
|
156
|
+
help: "<level> Required for native semantic route.",
|
|
157
|
+
},
|
|
158
|
+
"advisory-adapter-module": {
|
|
159
|
+
type: "string",
|
|
160
|
+
kind: "path",
|
|
161
|
+
private: true,
|
|
162
|
+
section: "grading",
|
|
163
|
+
help: "<path> Select this or --advisory-host codex.",
|
|
164
|
+
},
|
|
165
|
+
"advisory-host": {
|
|
166
|
+
type: "string",
|
|
167
|
+
kind: "string",
|
|
168
|
+
section: "grading",
|
|
169
|
+
help: "<codex> Native advisory route; none selected by default.",
|
|
170
|
+
},
|
|
171
|
+
"advisory-model": {
|
|
172
|
+
type: "string",
|
|
173
|
+
kind: "string",
|
|
174
|
+
section: "grading",
|
|
175
|
+
help: "<name> Required for native advisory route.",
|
|
176
|
+
},
|
|
177
|
+
"advisory-effort": {
|
|
178
|
+
type: "string",
|
|
179
|
+
kind: "string",
|
|
180
|
+
section: "grading",
|
|
181
|
+
help: "<level> Required for native advisory route.",
|
|
182
|
+
},
|
|
183
|
+
"advisory-exclude": {
|
|
184
|
+
type: "string",
|
|
185
|
+
kind: "string",
|
|
186
|
+
multiple: true,
|
|
187
|
+
section: "grading",
|
|
188
|
+
help: "<relative-path> Exclude an evaluator path; repeatable.",
|
|
189
|
+
},
|
|
190
|
+
host: {
|
|
191
|
+
type: "string",
|
|
192
|
+
kind: "string",
|
|
193
|
+
section: "required",
|
|
194
|
+
help: "<codex|claude> Bundled candidate route instead of --adapter-module.",
|
|
195
|
+
},
|
|
196
|
+
"codex-bin": {
|
|
197
|
+
type: "string",
|
|
198
|
+
kind: "path",
|
|
199
|
+
route: "codex",
|
|
200
|
+
section: "native",
|
|
201
|
+
help: "<path> (default: codex on PATH) Explicit binary override.",
|
|
202
|
+
},
|
|
203
|
+
"codex-entrypoint": {
|
|
204
|
+
type: "string",
|
|
205
|
+
kind: "string",
|
|
206
|
+
section: "native",
|
|
207
|
+
help: "<exec|app-server> Candidate transport (default: exec).",
|
|
208
|
+
},
|
|
209
|
+
"codex-timeout-ms": {
|
|
210
|
+
type: "string",
|
|
211
|
+
kind: "number",
|
|
212
|
+
route: "codex",
|
|
213
|
+
section: "native",
|
|
214
|
+
help: "<integer> 1..1800000 milliseconds (default: 600000).",
|
|
215
|
+
},
|
|
216
|
+
"codex-auth-file": {
|
|
217
|
+
type: "string",
|
|
218
|
+
kind: "path",
|
|
219
|
+
private: true,
|
|
220
|
+
route: "codex",
|
|
221
|
+
section: "native",
|
|
222
|
+
help: "<path> Required for every Codex route.",
|
|
223
|
+
},
|
|
224
|
+
"claude-bin": {
|
|
225
|
+
type: "string",
|
|
226
|
+
kind: "path",
|
|
227
|
+
route: "claude",
|
|
228
|
+
section: "native",
|
|
229
|
+
help: "<path> (default: claude on PATH) Explicit binary override.",
|
|
230
|
+
},
|
|
231
|
+
"claude-credential-file": {
|
|
232
|
+
type: "string",
|
|
233
|
+
kind: "path",
|
|
234
|
+
private: true,
|
|
235
|
+
route: "claude",
|
|
236
|
+
section: "native",
|
|
237
|
+
help: "<path> Optional credential override; otherwise use native auth.",
|
|
238
|
+
},
|
|
239
|
+
"claude-uv-cache-dir": {
|
|
240
|
+
type: "string",
|
|
241
|
+
kind: "path",
|
|
242
|
+
route: "claude",
|
|
243
|
+
section: "deprecated",
|
|
244
|
+
help: "<path> Migrate to sevro.json; cannot be combined with a runtime policy.",
|
|
245
|
+
},
|
|
246
|
+
"claude-project-settings": {
|
|
247
|
+
type: "boolean",
|
|
248
|
+
kind: "boolean",
|
|
249
|
+
route: "claude",
|
|
250
|
+
section: "native",
|
|
251
|
+
help: "Allow fixture project settings (default: false).",
|
|
252
|
+
},
|
|
253
|
+
"toolchain-bin-dir": {
|
|
254
|
+
type: "string",
|
|
255
|
+
kind: "path",
|
|
256
|
+
section: "deprecated",
|
|
257
|
+
help: "<path> Migrate to sevro.json; cannot be combined with a runtime policy.",
|
|
258
|
+
},
|
|
259
|
+
model: {
|
|
260
|
+
type: "string",
|
|
261
|
+
kind: "string",
|
|
262
|
+
section: "native",
|
|
263
|
+
help: "<name> Required for a bundled candidate host.",
|
|
264
|
+
},
|
|
265
|
+
effort: {
|
|
266
|
+
type: "string",
|
|
267
|
+
kind: "string",
|
|
268
|
+
section: "native",
|
|
269
|
+
help: "<level> Required for a bundled candidate host.",
|
|
270
|
+
},
|
|
271
|
+
"shell-isolation": {
|
|
272
|
+
type: "boolean",
|
|
273
|
+
kind: "boolean",
|
|
274
|
+
section: "common",
|
|
275
|
+
help: "Isolate shell checks (default: false).",
|
|
276
|
+
},
|
|
277
|
+
"protected-root": {
|
|
278
|
+
type: "string",
|
|
279
|
+
kind: "path-list",
|
|
280
|
+
multiple: true,
|
|
281
|
+
section: "common",
|
|
282
|
+
help: "<path> Extra protected source/private root; repeatable.",
|
|
283
|
+
},
|
|
284
|
+
"project-root": {
|
|
285
|
+
type: "string",
|
|
286
|
+
kind: "path",
|
|
287
|
+
section: "common",
|
|
288
|
+
help: "<path> (default: current directory) Project identity; does not copy its files into the fixture.",
|
|
289
|
+
},
|
|
290
|
+
"config-root": {
|
|
291
|
+
type: "string",
|
|
292
|
+
kind: "path",
|
|
293
|
+
section: "common",
|
|
294
|
+
help: "<path> (default: --project-root) Native concurrency configuration.",
|
|
295
|
+
},
|
|
296
|
+
"runtime-config-file": {
|
|
297
|
+
type: "string",
|
|
298
|
+
kind: "path",
|
|
299
|
+
private: true,
|
|
300
|
+
section: "common",
|
|
301
|
+
help: "<path> Runtime policy; otherwise discover project sevro.json.",
|
|
302
|
+
},
|
|
303
|
+
"results-root": {
|
|
304
|
+
type: "string",
|
|
305
|
+
kind: "path",
|
|
306
|
+
section: "common",
|
|
307
|
+
help: "<path> (default: <project-root>/.sevro/results) Retained evidence.",
|
|
308
|
+
},
|
|
309
|
+
"run-state-root": {
|
|
310
|
+
type: "string",
|
|
311
|
+
kind: "path",
|
|
312
|
+
section: "common",
|
|
313
|
+
help: "<path> (default: --results-root) Active records/checkpoints.",
|
|
314
|
+
},
|
|
315
|
+
"runner-build-digest": {
|
|
316
|
+
type: "string",
|
|
317
|
+
kind: "string",
|
|
318
|
+
section: "provenance",
|
|
319
|
+
help: "<sha256> 64 lowercase hex characters; normally derived automatically.",
|
|
320
|
+
},
|
|
321
|
+
"runner-checkout-root": {
|
|
322
|
+
type: "string",
|
|
323
|
+
kind: "path",
|
|
324
|
+
section: "provenance",
|
|
325
|
+
help: "<path> Record the running checkout's revision/dirty digest.",
|
|
326
|
+
},
|
|
327
|
+
"project-digest": {
|
|
328
|
+
type: "string",
|
|
329
|
+
kind: "string",
|
|
330
|
+
section: "provenance",
|
|
331
|
+
help: "<sha256> 64 lowercase hex characters; normally derived automatically.",
|
|
332
|
+
},
|
|
333
|
+
condition: {
|
|
334
|
+
type: "string",
|
|
335
|
+
kind: "string",
|
|
336
|
+
section: "common",
|
|
337
|
+
help: "<passive|enforced> (default: passive) Bundled hosts use passive.",
|
|
338
|
+
},
|
|
339
|
+
trials: {
|
|
340
|
+
type: "string",
|
|
341
|
+
kind: "number",
|
|
342
|
+
section: "common",
|
|
343
|
+
help: "<integer> (default: 1) Positive number of trials.",
|
|
344
|
+
},
|
|
345
|
+
jobs: {
|
|
346
|
+
type: "string",
|
|
347
|
+
kind: "number",
|
|
348
|
+
section: "common",
|
|
349
|
+
help: "<integer> (default: 3) Maximum parallel trials, positive integer.",
|
|
350
|
+
},
|
|
351
|
+
threshold: {
|
|
352
|
+
type: "string",
|
|
353
|
+
kind: "number",
|
|
354
|
+
section: "common",
|
|
355
|
+
help: "<number> (default: 1) All assessed trials must pass; range (0, 1].",
|
|
356
|
+
},
|
|
357
|
+
} as const satisfies Record<string, RunOption>;
|
|
358
|
+
|
|
359
|
+
export type RunOptionName = keyof typeof RUN_OPTIONS;
|
|
360
|
+
|
|
361
|
+
type MatchingOptions<K extends keyof RunOption, V> = {
|
|
362
|
+
[N in RunOptionName]: (typeof RUN_OPTIONS)[N] extends Record<K, V>
|
|
363
|
+
? N
|
|
364
|
+
: never;
|
|
365
|
+
}[RunOptionName];
|
|
366
|
+
|
|
367
|
+
export function optionsWith<
|
|
368
|
+
K extends keyof RunOption,
|
|
369
|
+
const V extends RunOption[K],
|
|
370
|
+
>(key: K, value: V): MatchingOptions<K, V>[] {
|
|
371
|
+
return (Object.keys(RUN_OPTIONS) as RunOptionName[]).filter(
|
|
372
|
+
(name) => (RUN_OPTIONS[name] as RunOption)[key] === value,
|
|
373
|
+
) as MatchingOptions<K, V>[];
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export const PATH_OPTIONS = optionsWith("kind", "path");
|
|
377
|
+
export const PATH_LIST_OPTIONS = optionsWith("kind", "path-list");
|
|
378
|
+
export const NUMBER_OPTIONS = new Set<string>(optionsWith("kind", "number"));
|
|
379
|
+
export const LIST_OPTIONS = new Set<string>(optionsWith("multiple", true));
|
|
380
|
+
export const CLI_ONLY = new Set<string>(optionsWith("cliOnly", true));
|
|
381
|
+
export const EXTENSION_OPTIONS = optionsWith("extension", true);
|
|
382
|
+
|
|
383
|
+
export function runArguments(argv: string[]) {
|
|
384
|
+
return parseArgs({
|
|
385
|
+
args: argv,
|
|
386
|
+
allowPositionals: true,
|
|
387
|
+
allowNegative: true,
|
|
388
|
+
strict: true,
|
|
389
|
+
options: RUN_OPTIONS,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export type RunValues = ReturnType<typeof runArguments>["values"];
|
|
394
|
+
|
|
395
|
+
/** Preserve the last explicit output selection even when parsing fails. */
|
|
396
|
+
export function jsonOutputRequested(argv: string[]): boolean {
|
|
397
|
+
let json = false;
|
|
398
|
+
for (const argument of argv) {
|
|
399
|
+
if (argument === "--json") json = true;
|
|
400
|
+
if (argument === "--no-json") json = false;
|
|
401
|
+
}
|
|
402
|
+
return json;
|
|
403
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { EXTENSION_OPTIONS, optionsWith, type RunValues } from "./run-options";
|
|
2
|
+
|
|
3
|
+
type Key = keyof RunValues;
|
|
4
|
+
|
|
5
|
+
function removeSaved(saved: RunValues, keys: readonly Key[]): void {
|
|
6
|
+
for (const key of keys) Reflect.deleteProperty(saved, key);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const CANDIDATE_OPTIONS = [
|
|
10
|
+
"host",
|
|
11
|
+
"model",
|
|
12
|
+
"effort",
|
|
13
|
+
"codex-entrypoint",
|
|
14
|
+
] as const;
|
|
15
|
+
|
|
16
|
+
function overrideCandidate(saved: RunValues, explicit: RunValues): void {
|
|
17
|
+
if (explicit["adapter-module"] !== undefined)
|
|
18
|
+
removeSaved(saved, CANDIDATE_OPTIONS);
|
|
19
|
+
if (explicit.host === undefined) return;
|
|
20
|
+
delete saved["adapter-module"];
|
|
21
|
+
if (saved.host !== explicit.host)
|
|
22
|
+
removeSaved(saved, ["model", "effort", "codex-entrypoint"]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function overrideSecondary(
|
|
26
|
+
saved: RunValues,
|
|
27
|
+
explicit: RunValues,
|
|
28
|
+
role: "semantic" | "advisory",
|
|
29
|
+
): void {
|
|
30
|
+
if (explicit[`${role}-host`] !== undefined)
|
|
31
|
+
Reflect.deleteProperty(saved, `${role}-adapter-module`);
|
|
32
|
+
if (explicit[`${role}-adapter-module`] !== undefined)
|
|
33
|
+
removeSaved(saved, [`${role}-host`, `${role}-model`, `${role}-effort`]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function removeUnusedNativeOptions(saved: RunValues, merged: RunValues): void {
|
|
37
|
+
if (
|
|
38
|
+
![merged.host, merged["semantic-host"], merged["advisory-host"]].includes(
|
|
39
|
+
"codex",
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
removeSaved(saved, optionsWith("route", "codex"));
|
|
43
|
+
if (merged.host !== "claude")
|
|
44
|
+
removeSaved(saved, optionsWith("route", "claude"));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function overrideRunSelections(
|
|
48
|
+
saved: RunValues,
|
|
49
|
+
explicit: RunValues,
|
|
50
|
+
): void {
|
|
51
|
+
if (explicit["case-file"] !== undefined)
|
|
52
|
+
removeSaved(saved, EXTENSION_OPTIONS);
|
|
53
|
+
if (explicit["extension-command-file"] !== undefined)
|
|
54
|
+
delete saved["case-file"];
|
|
55
|
+
overrideCandidate(saved, explicit);
|
|
56
|
+
overrideSecondary(saved, explicit, "semantic");
|
|
57
|
+
overrideSecondary(saved, explicit, "advisory");
|
|
58
|
+
if (
|
|
59
|
+
[
|
|
60
|
+
"host",
|
|
61
|
+
"adapter-module",
|
|
62
|
+
"semantic-host",
|
|
63
|
+
"semantic-adapter-module",
|
|
64
|
+
"advisory-host",
|
|
65
|
+
"advisory-adapter-module",
|
|
66
|
+
].some((key) => explicit[key as Key] !== undefined)
|
|
67
|
+
)
|
|
68
|
+
removeUnusedNativeOptions(saved, { ...saved, ...explicit });
|
|
69
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import type { HostAdapter } from "../engine";
|
|
3
|
+
import type { PreparedInvocation } from "./preparation";
|
|
4
|
+
import { nativeRoutes } from "./invocation";
|
|
5
|
+
|
|
6
|
+
type NativeRoute = { binary: string; timeoutMs?: number } | undefined;
|
|
7
|
+
|
|
8
|
+
function nativeSettings(native: NativeRoute) {
|
|
9
|
+
if (!native) return { executable: null, timeoutMs: null };
|
|
10
|
+
return { executable: native.binary, timeoutMs: native.timeoutMs ?? 600_000 };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function routeSettings(host: HostAdapter | undefined, native: NativeRoute) {
|
|
14
|
+
if (!host) return null;
|
|
15
|
+
return {
|
|
16
|
+
host: host.id,
|
|
17
|
+
model: host.model,
|
|
18
|
+
effort: host.effort,
|
|
19
|
+
...nativeSettings(native),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** A whitelist of resolved operator settings; never copy credentials or runtime environment. */
|
|
24
|
+
export function effectiveSettings(prepared: PreparedInvocation) {
|
|
25
|
+
const { invocation, host, semanticHost, advisoryHost } = prepared;
|
|
26
|
+
return {
|
|
27
|
+
format: "sevro.resolved-run-settings.v1",
|
|
28
|
+
...sourceSettings(prepared),
|
|
29
|
+
...extensionSettings(invocation.extension),
|
|
30
|
+
...adapterSettings(invocation),
|
|
31
|
+
...legacyRuntimeSettings(invocation),
|
|
32
|
+
protectedRoots: invocation.protectedRoots,
|
|
33
|
+
condition: invocation.condition,
|
|
34
|
+
trials: invocation.trialCount,
|
|
35
|
+
threshold: invocation.passThreshold,
|
|
36
|
+
jobs: invocation.jobs,
|
|
37
|
+
dry: invocation.dry,
|
|
38
|
+
projectRoot: invocation.projectRoot,
|
|
39
|
+
configRoot: invocation.configRoot,
|
|
40
|
+
resultsRoot: invocation.resultsRoot,
|
|
41
|
+
runStateRoot: invocation.runStateRoot,
|
|
42
|
+
runtimeConfigFile: selectedRuntimeFile(prepared),
|
|
43
|
+
candidate: routeSettings(host, invocation.codex ?? invocation.claude),
|
|
44
|
+
semantic: routeSettings(semanticHost, invocation.semanticCodex),
|
|
45
|
+
advisory: routeSettings(advisoryHost, invocation.advisoryCodex),
|
|
46
|
+
codexEntrypoint: selectedEntrypoint(invocation),
|
|
47
|
+
agentConcurrencyLimit: prepared.agentConcurrencyLimit,
|
|
48
|
+
shellIsolation: Boolean(invocation.shellIsolation),
|
|
49
|
+
retainHostDiagnostics: retainedDiagnostics(invocation),
|
|
50
|
+
claudeProjectSettings: projectSettings(invocation),
|
|
51
|
+
shellCheckDefaults: { expectedExitCode: 0, timeoutMs: 30_000 },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function selectedCaseId(prepared: PreparedInvocation): string | null {
|
|
56
|
+
if (prepared.caseData) return prepared.caseData.id;
|
|
57
|
+
return prepared.invocation.extension?.caseId ?? null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function sourceSettings(prepared: PreparedInvocation) {
|
|
61
|
+
const { invocation } = prepared;
|
|
62
|
+
return {
|
|
63
|
+
runManifestFile: invocation.runManifestFile ?? null,
|
|
64
|
+
caseFile: invocation.caseFile ?? null,
|
|
65
|
+
caseId: selectedCaseId(prepared),
|
|
66
|
+
caseSourceMapping: Boolean(invocation.caseSourceRoot),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function extensionSettings(
|
|
71
|
+
extension: PreparedInvocation["invocation"]["extension"],
|
|
72
|
+
) {
|
|
73
|
+
if (!extension)
|
|
74
|
+
return {
|
|
75
|
+
extensionCommandFile: null,
|
|
76
|
+
extensionSourceFileCount: 0,
|
|
77
|
+
taskVerdictPolicy: null,
|
|
78
|
+
replaceBuiltinGraders: [],
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
extensionCommandFile: extension.commandFile,
|
|
82
|
+
extensionSourceFileCount: extension.sourceFiles.length,
|
|
83
|
+
taskVerdictPolicy: extension.taskVerdictPolicy ?? null,
|
|
84
|
+
replaceBuiltinGraders: extension.replaceBuiltinGraders,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function adapterSettings(invocation: PreparedInvocation["invocation"]) {
|
|
89
|
+
return {
|
|
90
|
+
adapterModule: invocation.adapterModule ?? null,
|
|
91
|
+
semanticAdapterModule: invocation.semanticAdapterModule ?? null,
|
|
92
|
+
advisoryAdapterModule: invocation.advisoryAdapterModule ?? null,
|
|
93
|
+
advisoryExcludedPaths: invocation.advisoryExcludedPaths,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function selectedEntrypoint(invocation: PreparedInvocation["invocation"]) {
|
|
98
|
+
return invocation.codex ? (invocation.codex.entrypoint ?? "exec") : null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function projectSettings(
|
|
102
|
+
invocation: PreparedInvocation["invocation"],
|
|
103
|
+
): boolean {
|
|
104
|
+
return invocation.claude?.projectSettings ?? false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function legacyRuntimeSettings(invocation: PreparedInvocation["invocation"]) {
|
|
108
|
+
return {
|
|
109
|
+
toolchainBinDir: selectedToolchain(invocation),
|
|
110
|
+
claudeUvCacheDir: invocation.claude?.uvCacheDir ?? null,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function selectedToolchain(invocation: PreparedInvocation["invocation"]) {
|
|
115
|
+
return (
|
|
116
|
+
(invocation.shellIsolation ?? invocation.claude)?.toolchainBinDir ?? null
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function retainedDiagnostics(
|
|
121
|
+
invocation: PreparedInvocation["invocation"],
|
|
122
|
+
): boolean {
|
|
123
|
+
return nativeRoutes(invocation).some((host) => host.retainHostDiagnostics);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Assessment-affecting CLI settings absent from the engine's other identity inputs. */
|
|
127
|
+
export function assessmentSettings(prepared: PreparedInvocation) {
|
|
128
|
+
const { invocation } = prepared;
|
|
129
|
+
return {
|
|
130
|
+
shellIsolation: Boolean(invocation.shellIsolation),
|
|
131
|
+
protectedRoots: invocation.protectedRoots,
|
|
132
|
+
...legacyRuntimeSettings(invocation),
|
|
133
|
+
candidateTimeoutMs: nativeSettings(invocation.codex ?? invocation.claude)
|
|
134
|
+
.timeoutMs,
|
|
135
|
+
semanticTimeoutMs: nativeSettings(invocation.semanticCodex).timeoutMs,
|
|
136
|
+
advisoryTimeoutMs: nativeSettings(invocation.advisoryCodex).timeoutMs,
|
|
137
|
+
claudeProjectSettings: invocation.claude?.projectSettings ?? false,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function selectedRuntimeFile(prepared: PreparedInvocation): string | null {
|
|
142
|
+
return (
|
|
143
|
+
prepared.invocation.runtimeConfigFile ??
|
|
144
|
+
(prepared.runtimePolicy
|
|
145
|
+
? join(prepared.invocation.projectRoot, "sevro.json")
|
|
146
|
+
: null)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function displayEffectiveSettings(prepared: PreparedInvocation): void {
|
|
151
|
+
process.stderr.write(
|
|
152
|
+
`sevro: effective settings ${JSON.stringify(effectiveSettings(prepared))}\n`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { CliResultData, ReportData } from "../schema-types";
|
|
2
|
+
|
|
3
|
+
function line(value: string): string {
|
|
4
|
+
return value.replaceAll(/\p{Cc}/gu, " ").slice(0, 4096);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function metric(value: number | null): string {
|
|
8
|
+
return value === null ? "unknown" : String(value);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function displayTrialSummary(result: CliResultData): void {
|
|
12
|
+
for (const selected of result.cases)
|
|
13
|
+
for (const trial of selected.trials) {
|
|
14
|
+
process.stdout.write(
|
|
15
|
+
`trial case=${line(selected.caseId)} trial=${trial.trial} execution=${trial.execution.status} grading=${trial.grading.status} task=${trial.task.verdict}\n`,
|
|
16
|
+
);
|
|
17
|
+
displayFailedChecks(trial.checks);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function displayFailedChecks(
|
|
22
|
+
checks: CliResultData["cases"][number]["trials"][number]["checks"],
|
|
23
|
+
): void {
|
|
24
|
+
for (const check of checks)
|
|
25
|
+
if (check.status !== "passed")
|
|
26
|
+
process.stdout.write(
|
|
27
|
+
` check=${line(check.id)} status=${check.status} reason=${line(check.detail ?? "unknown")}\n`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function displayMeasurements(report: ReportData): void {
|
|
32
|
+
for (const row of report.rows) {
|
|
33
|
+
const duration =
|
|
34
|
+
row.candidateDurationMs === null
|
|
35
|
+
? "unknown"
|
|
36
|
+
: `${row.candidateDurationMs.toFixed(2)}ms`;
|
|
37
|
+
const cost =
|
|
38
|
+
row.costUsd === null ? "unknown" : `$${row.costUsd.toFixed(4)}`;
|
|
39
|
+
process.stdout.write(
|
|
40
|
+
`case=${line(row.caseId)} candidate duration=${duration} candidate tokens=${metric(row.inputTokens)}/${metric(row.outputTokens)} cost=${cost}\n`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|