@bjoernrochel/sevro 0.1.0-rc.16 → 0.1.0-rc.18
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/docs/development-cli.md +1 -1
- package/docs/identity-v1.md +4 -1
- package/docs/installing.md +2 -2
- package/docs/native-controls.md +47 -12
- package/docs/native-hosts.md +1 -1
- package/docs/recipes.md +7 -3
- package/docs/results-v1.md +5 -0
- package/docs/runtime-v1.md +60 -13
- package/package.json +1 -1
- package/schemas/runtime-v1.schema.json +32 -0
- package/src/evaluation/trial.ts +12 -1
- package/src/fixtures/cleanup.ts +13 -7
- package/src/generated/runtime.cjs +1 -1
- package/src/graders/shell.ts +14 -4
- package/src/hosts/claude-settings.ts +42 -5
- package/src/hosts/claude-state.ts +14 -2
- package/src/hosts/codex-exec-controls.ts +195 -55
- package/src/hosts/codex-state.ts +24 -3
- package/src/hosts/isolation-common.ts +2 -0
- package/src/hosts/linux-sandbox.ts +13 -0
- package/src/hosts/mac-sandbox.ts +23 -3
- package/src/hosts/native-controls.ts +24 -2
- package/src/runtime/config.ts +58 -10
- package/src/runtime/hooks.ts +19 -6
- package/src/runtime/shared-cache.ts +143 -0
- package/src/runtime/state.ts +25 -3
package/docs/development-cli.md
CHANGED
|
@@ -280,7 +280,7 @@ It runs candidate tools under Claude Code's native sandbox with private,
|
|
|
280
280
|
source, and result paths denied. The route disables hooks by default and does not expose
|
|
281
281
|
the Write tool. It currently supports passive candidate turns only. Use
|
|
282
282
|
`--protected-root` to exclude additional private paths from the candidate's
|
|
283
|
-
filesystem access. Configure shared host tools, private caches, goals, and selected
|
|
283
|
+
filesystem access. Configure shared host tools, private or reusable caches, goals, and selected
|
|
284
284
|
plugin hooks with [`sevro.json` or `--runtime-config-file`](runtime-v1.md).
|
|
285
285
|
The same policy reaches isolated checks and native grading hosts.
|
|
286
286
|
|
package/docs/identity-v1.md
CHANGED
|
@@ -87,7 +87,10 @@ contents and temporary native state paths do not enter identity.
|
|
|
87
87
|
Selected [runtime configuration](runtime-v1.md) is retained under
|
|
88
88
|
`configuration.redacted.runtimePolicy` and enters `configurationDigest`.
|
|
89
89
|
It includes declared non-secret environment values, canonical read roots,
|
|
90
|
-
private seed digests and optional role selections,
|
|
90
|
+
private seed digests and optional role selections, shared-cache sources/slots/roles,
|
|
91
|
+
and hook authority. Mutable shared-cache contents are excluded; equal identities
|
|
92
|
+
do not establish equal cache contents or trial independence in shared mode.
|
|
93
|
+
Per-role output paths are resolved
|
|
91
94
|
only during execution; runtime placeholders remain symbolic in identity.
|
|
92
95
|
Runtime roots also retain lexical aliases, metadata discovery sources,
|
|
93
96
|
and skipped optional directories. Moving or
|
package/docs/installing.md
CHANGED
|
@@ -23,10 +23,10 @@ Local installation records the selected version in the project lockfile.
|
|
|
23
23
|
|
|
24
24
|
## Current release
|
|
25
25
|
|
|
26
|
-
The current release is `0.1.0-rc.
|
|
26
|
+
The current release is `0.1.0-rc.18`. Install this exact version:
|
|
27
27
|
|
|
28
28
|
```sh
|
|
29
|
-
bun add --exact @bjoernrochel/sevro@0.1.0-rc.
|
|
29
|
+
bun add --exact @bjoernrochel/sevro@0.1.0-rc.18
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
<!-- sevro-current-release:end -->
|
package/docs/native-controls.md
CHANGED
|
@@ -5,7 +5,8 @@ retain an observation with that ID. It exposes host facts for extension policy:
|
|
|
5
5
|
|
|
6
6
|
- `method: native_control_calls`;
|
|
7
7
|
- ordered `calls` containing only `ordinal`, `namespace`, and `name`;
|
|
8
|
-
- `acceptedAgentCount`, a verified Codex acceptance count
|
|
8
|
+
- `acceptedAgentCount`, a verified direct native Codex acceptance count when
|
|
9
|
+
overall coverage is complete, otherwise `null` (also `null` on Claude);
|
|
9
10
|
- `submittedExecCalls`, the Codex submitted-code count or `null` on Claude; and
|
|
10
11
|
- `truncated`, which is `false` for a complete record and may be unknown (`null`)
|
|
11
12
|
for an incomplete Codex record.
|
|
@@ -16,6 +17,18 @@ invocation attempt, not success. Extensions decide which calls are prohibited.
|
|
|
16
17
|
An unknown acceptance count cannot establish agent acceptance.
|
|
17
18
|
|
|
18
19
|
Codex projects labels and counts from its bound native-session observation.
|
|
20
|
+
It additionally retains `directAcceptedAgentCount`, the number of positively
|
|
21
|
+
correlated direct native spawn acceptances in that source, independently of exec
|
|
22
|
+
inspection. This is an observed count, not a total across unknown launch paths.
|
|
23
|
+
`coverage.nativeCalls` records native-session completeness;
|
|
24
|
+
`coverage.execInspection` records whether all submitted exec sources were
|
|
25
|
+
understood and matched to the direct submission inventory;
|
|
26
|
+
`coverage.acceptedAgents: direct_native_calls` names the scope of both acceptance
|
|
27
|
+
counts. Accepted launches through exec are not included in these direct counts.
|
|
28
|
+
When native capture is incomplete, even a zero observed count cannot establish
|
|
29
|
+
absence. Native labels remain usable as positive attempt evidence regardless
|
|
30
|
+
of an unrelated exec inspection gap. A rejected attempt is never an acceptance.
|
|
31
|
+
|
|
19
32
|
When submitted code is present, both observations also retain `execCalls`:
|
|
20
33
|
one receipt per native `exec` submission, with its native `ordinal`, inspection
|
|
21
34
|
`completeness`, and ordered `calls` containing `index`, `namespace`, and `name`.
|
|
@@ -27,25 +40,46 @@ programs without executing them. It accepts literal tool calls, constant result
|
|
|
27
40
|
bindings, template interpolation and `+` composition of inspected expressions,
|
|
28
41
|
direct `text`/`store` output, and literal `Promise.all`/`allSettled` batches.
|
|
29
42
|
Batch results may use flat constant array bindings or result-only
|
|
30
|
-
`forEach(text)` or `for ... of` output
|
|
43
|
+
`forEach(text)` or `for ... of` output, including blocks and conditional
|
|
44
|
+
result-field selection. `JSON.stringify`, `String`, object spread/shorthand,
|
|
45
|
+
and nested result fields are supported. Numeric output loops must use the
|
|
46
|
+
bounded shape `for (let i = 0; i < results.length; i++)`, indexing the known
|
|
47
|
+
batch with that loop variable. Output loops and conditional expressions cannot
|
|
48
|
+
invoke tools. Destructuring defaults, rest elements,
|
|
31
49
|
holes, nested bindings, duplicate names, and shadowed globals remain unsupported.
|
|
32
|
-
|
|
33
|
-
unique, later native completion for the same call ID with an intact successful
|
|
34
|
-
script envelope. Tool argument strings, comments and printed tool-looking text
|
|
50
|
+
Tool argument strings, comments and printed tool-looking text
|
|
35
51
|
do not become call labels. A rejected tool request returned by a completed
|
|
36
52
|
script still appears in its submitted-call inventory. This inventory proves
|
|
37
53
|
submission of those requests, not successful effects or acceptance; the existing
|
|
38
54
|
acceptance count describes independently correlated direct native spawns.
|
|
39
55
|
|
|
40
56
|
Dynamic lookup, aliases, shadowed globals, callbacks that invoke tools,
|
|
41
|
-
conditional
|
|
42
|
-
|
|
57
|
+
conditional tool execution, and nested executors keep source inspection partial.
|
|
58
|
+
Each receipt's `inspectionReason` is `null` on success, or `unsupported_source`,
|
|
59
|
+
`malformed_source`, `source_limit`, or `foreign_namespace`. Unsupported syntax
|
|
60
|
+
and expression/call-budget exhaustion use `unsupported_source`.
|
|
61
|
+
Source is bounded at
|
|
43
62
|
64 KiB, traversed expressions at 2,048, and calls at 128 per submission; tool
|
|
44
63
|
labels are bounded at 64 characters. Private source and output bytes are discarded.
|
|
45
64
|
The portable observation becomes partial if any submission is uninspected or
|
|
46
|
-
receipt counts/ordinals disagree with the native list.
|
|
47
|
-
`null
|
|
48
|
-
|
|
65
|
+
receipt counts/ordinals disagree with the native list. `acceptedAgentCount`
|
|
66
|
+
remains `null` in that case, while native coverage, direct acceptance facts and
|
|
67
|
+
the native `submittedExecCalls` count remain independently available.
|
|
68
|
+
`submittedExecCalls` and `truncated` depend on native capture, not exec output.
|
|
69
|
+
|
|
70
|
+
Receipt `completeness` describes source inspection, independently of execution
|
|
71
|
+
or displayed output. `execution` is `completed`, `failed`, or `incomplete`;
|
|
72
|
+
`output` is `complete`, `truncated`, or `unavailable`. Output evidence requires
|
|
73
|
+
a unique later output bound to the same native call ID, with recognized text
|
|
74
|
+
blocks. `complete` describes the displayed receipt, not the whole program's
|
|
75
|
+
execution. Execution status additionally requires a successful or failed script
|
|
76
|
+
header. Missing, ambiguous or
|
|
77
|
+
malformed output yields `incomplete`/`unavailable`; a yielded or unrecognized
|
|
78
|
+
header stays `incomplete`. Displayed truncation does not change source coverage.
|
|
79
|
+
A fully inspected source with no launch call proves that absence even if its
|
|
80
|
+
shell output was truncated or the exec cell failed. Source inspection cannot
|
|
81
|
+
prove execution or success. Missing fields in historical receipts are unknown;
|
|
82
|
+
historical artifacts retain their original results and meanings.
|
|
49
83
|
|
|
50
84
|
Claude records every tool-use label from the bounded stream, with namespace
|
|
51
85
|
`claude`, without filtering to Skill or Agent. It requires a completed successful
|
|
@@ -55,11 +89,12 @@ Tool-looking text in arguments or output does not become a native call.
|
|
|
55
89
|
|
|
56
90
|
Consumers must verify the source, completeness, shape, ordering, and counts
|
|
57
91
|
before using an empty call list to establish absence. Missing or partial
|
|
58
|
-
|
|
92
|
+
source coverage cannot establish a negative assertion. For Codex, consumers must
|
|
59
93
|
inspect every `execCalls` receipt in addition to the direct `calls` list,
|
|
60
94
|
validate receipt ordinals against the direct `exec` submissions, and require
|
|
61
95
|
all receipts to be complete with counts matching `submittedExecCalls`.
|
|
62
|
-
They
|
|
96
|
+
They can use positively observed native attempt labels before requiring complete
|
|
97
|
+
coverage for an absence pass. They must examine submitted labels for prohibited controls even when
|
|
63
98
|
`acceptedAgentCount` is zero. Older consumers that require
|
|
64
99
|
`submittedExecCalls === 0` remain conservative but cannot use this new evidence
|
|
65
100
|
until they adopt receipt validation.
|
package/docs/native-hosts.md
CHANGED
|
@@ -44,7 +44,7 @@ Repository skill mounts under `.claude/skills` require explicit
|
|
|
44
44
|
`--claude-project-settings`; otherwise repository dispatch is refused before
|
|
45
45
|
launch. The bundled route disables hooks by default and omits candidate Write
|
|
46
46
|
access. [Runtime configuration](runtime-v1.md) enables native goals and selected
|
|
47
|
-
plugin hooks and reuses declared host tools with private caches. These changes
|
|
47
|
+
plugin hooks and reuses declared host tools with private or explicitly shared caches. These changes
|
|
48
48
|
require `rc.3` or later. The CLI reference covers credential scrubbing
|
|
49
49
|
and follow-ups.
|
|
50
50
|
|
package/docs/recipes.md
CHANGED
|
@@ -209,9 +209,13 @@ The negative fixture changes the port to `9000`; Python raises an assertion:
|
|
|
209
209
|
bun "$SEVRO_RECIPES/run.ts" python-uv deterministic --fail
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
-
For real dependencies, prepare a public cache
|
|
213
|
-
|
|
214
|
-
offline install command.
|
|
212
|
+
For real dependencies, prepare a public cache once outside the evaluated project
|
|
213
|
+
and declare a [shared cache](runtime-v1.md#reuse-a-shared-dependency-cache), then
|
|
214
|
+
use your locked offline install command. Select only the roles using UV; add
|
|
215
|
+
`checks` only when the grader needs it. The same directory can serve candidates,
|
|
216
|
+
hooks, and UV-based graders across trials and runs without copying the cache.
|
|
217
|
+
Use [private seeds](runtime-v1.md#private-writable-state) when isolated dependency
|
|
218
|
+
bytes matter more than disk reuse. This dependency-free recipe needs no cache seed.
|
|
215
219
|
|
|
216
220
|
### An existing mise installation
|
|
217
221
|
|
package/docs/results-v1.md
CHANGED
|
@@ -147,6 +147,11 @@ remain available through grading and are removed afterward, including failed
|
|
|
147
147
|
and cancelled trials. Failed-fixture retention does not preserve them.
|
|
148
148
|
Read access does not automatically retain artifact bytes in run evidence.
|
|
149
149
|
|
|
150
|
+
Checker private home, temporary storage, and copied dependency slots are removed
|
|
151
|
+
after grading on success, failure, and cancellation. Retained failed fixtures and
|
|
152
|
+
saved evidence do not retain checker runtime copies. Explicitly declared shared
|
|
153
|
+
caches survive this cleanup and remain under operator control.
|
|
154
|
+
|
|
150
155
|
A host adapter can return `executionFailed: true` with bounded artifacts from
|
|
151
156
|
a failed process. The engine retains those artifacts, skips all grading, and
|
|
152
157
|
reports `failed` / `not_requested` / `not_assessed` with exit code `2`. A final
|
package/docs/runtime-v1.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Runtime configuration v1
|
|
2
2
|
|
|
3
|
-
Configure access to existing host tools, private
|
|
3
|
+
Configure access to existing host tools, private state, reusable caches, native goals,
|
|
4
4
|
and selected plugin hooks in `<project-root>/sevro.json`.
|
|
5
5
|
|
|
6
6
|
`--runtime-config-file /absolute/path/runtime.json` selects a replacement file.
|
|
@@ -36,7 +36,13 @@ capabilities:
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"runtime": {
|
|
39
|
-
"
|
|
39
|
+
"sharedCacheDirectories": [
|
|
40
|
+
{
|
|
41
|
+
"source": "../public-uv-cache",
|
|
42
|
+
"target": "uv-cache",
|
|
43
|
+
"roles": ["candidate", "hooks"]
|
|
44
|
+
}
|
|
45
|
+
]
|
|
40
46
|
},
|
|
41
47
|
"hooks": {
|
|
42
48
|
"nativeGoal": true,
|
|
@@ -45,7 +51,7 @@ capabilities:
|
|
|
45
51
|
}
|
|
46
52
|
```
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
Prepare the example's `public-uv-cache` directory outside the project, or
|
|
49
55
|
omit `runtime` when no prepared cache is needed. Selected plugin names must be
|
|
50
56
|
present in the case's prepared mounts; remove names that the case does not mount.
|
|
51
57
|
`DARROW_CACHE_DIR` is an ordinary explicit variable in this example, not a
|
|
@@ -235,10 +241,12 @@ digits, and hyphens. `home` and `tmp` are reserved. Targets must be unique.
|
|
|
235
241
|
An optional nonempty `roles` array selects any of `candidate`, `checks`, `hooks`,
|
|
236
242
|
`semantic`, and `advisory`. For example, `"roles": ["candidate", "checks", "hooks"]`
|
|
237
243
|
keeps dependency slots out of semantic and advisory runtimes. Without `roles`,
|
|
238
|
-
|
|
244
|
+
candidate, hook, artifact semantic, and advisory roles receive private copies.
|
|
245
|
+
Shell checks require explicit `"checks"` selection; a non-UV grader receives no
|
|
246
|
+
implicit UV/Python cache. Existing configurations whose shell checks need seeded
|
|
247
|
+
dependencies must add `"checks"` to `roles`. Response-only
|
|
239
248
|
semantic grading omits implicit seeds; include `"semantic"` explicitly in `roles`
|
|
240
|
-
when that route needs dependencies.
|
|
241
|
-
shell checks keep their declared tools and default seed selection.
|
|
249
|
+
when that route needs dependencies. Declared host tools remain available to shell checks.
|
|
242
250
|
|
|
243
251
|
Each source tree is bounded to 16,384 entries and 512 MiB. Escaping symlinks,
|
|
244
252
|
directory cycles, dangling links, and special files are refused. File content
|
|
@@ -254,6 +262,41 @@ retaining large policies can retain up to the configured per-seed byte bounds.
|
|
|
254
262
|
Source caches are never a writable runtime. Use prepared public caches rather
|
|
255
263
|
than credential-bearing homes or evaluator directories.
|
|
256
264
|
|
|
265
|
+
### Reuse a shared dependency cache
|
|
266
|
+
|
|
267
|
+
`runtime.sharedCacheDirectories` opts into persistent writable caches without
|
|
268
|
+
copying or hashing their contents for each trial. Each entry requires `source`,
|
|
269
|
+
`target`, and a nonempty `roles` array drawn from the same five roles above.
|
|
270
|
+
The source must already be an owned, readable, writable directory. Relative paths
|
|
271
|
+
resolve beside the runtime file. Sevro resolves declaration symlinks to their
|
|
272
|
+
canonical source and revalidates that directory before execution.
|
|
273
|
+
Targets use the seed slot rules and must be unique across seeds and shared caches.
|
|
274
|
+
Sources cannot overlap each other, private seed sources, declared read-only
|
|
275
|
+
inputs, evaluated project/source trees, results, credentials, or native private state.
|
|
276
|
+
|
|
277
|
+
Select only roles that actually use UV, for example `"roles": ["candidate", "hooks"]`.
|
|
278
|
+
If a grader also uses UV, add `"checks"` to that same entry; both roles use the
|
|
279
|
+
same cache. Each selected private slot aliases the original directory, with a
|
|
280
|
+
narrow sandbox write grant. Other roles receive no slot or source grant.
|
|
281
|
+
Shared content survives successful, failed, and cancelled trials and later runs.
|
|
282
|
+
Sevro removes only disposable role state, never the declared shared source.
|
|
283
|
+
|
|
284
|
+
Prepare UV packages once outside evaluation, point `UV_CACHE_DIR` at
|
|
285
|
+
`{{sevro.runtime}}/uv-cache`, and reuse the existing Python installation through
|
|
286
|
+
declared read-only tool roots. Set `UV_PYTHON_DOWNLOADS=never` to require that
|
|
287
|
+
installation. Sevro keeps `UV_OFFLINE=1`; a missing dependency fails rather than
|
|
288
|
+
downloading during a trial. Project virtual environments and temporary files
|
|
289
|
+
remain disposable; UV's install/link mode can still allocate files in a virtual
|
|
290
|
+
environment. The shared option removes the full cache copy per trial.
|
|
291
|
+
|
|
292
|
+
Shared caches are mutable across trials, roles, and runs. Use them only for public
|
|
293
|
+
dependencies and accept that a participant can change them for later participants.
|
|
294
|
+
Use isolated seeds when dependency independence is required. Configuration identity
|
|
295
|
+
binds the source, slot, and roles, but excludes mutable cache contents; equal
|
|
296
|
+
identities therefore do not prove identical shared-cache bytes. Sevro does not
|
|
297
|
+
age-delete shared caches. Manage their size between evaluations with the cache
|
|
298
|
+
tool, such as `uv cache prune --cache-dir /absolute/public-uv-cache`.
|
|
299
|
+
|
|
257
300
|
`{{sevro.runtime}}` in an environment value resolves to that role's writable
|
|
258
301
|
root. Codex commands receive a `TMPPREFIX` inside their private `TMPDIR`,
|
|
259
302
|
so zsh here-documents use their existing private temporary storage while shared
|
|
@@ -266,13 +309,15 @@ use. Its temporary directory stays disposable.
|
|
|
266
309
|
Candidate, hook, checker, semantic, and advisory
|
|
267
310
|
state are separate. With a runtime policy, native candidate, semantic, and
|
|
268
311
|
advisory roots live in a unique runner-owned host directory outside the Git
|
|
269
|
-
fixture. The root contains `home`, `tmp`, and
|
|
312
|
+
fixture. The root contains `home`, `tmp`, private seed slots and selected shared-cache links; plugins can
|
|
270
313
|
use paths such as `~/.darrow/reviews` without creating repository-local review
|
|
271
314
|
state. Command runtime directories are separate from host authentication,
|
|
272
|
-
configuration, and live transcript sources. Checker and hook
|
|
273
|
-
outside candidate-controlled workspace state. Private roots survive native
|
|
315
|
+
configuration, and live transcript sources. Checker and hook private state also lives
|
|
316
|
+
outside candidate-controlled workspace state. Shared sources remain at their declared locations. Private roots survive native
|
|
274
317
|
continuation turns and children, then are removed with their owning trial or
|
|
275
|
-
host state after owned hooks terminate.
|
|
318
|
+
host state after owned hooks terminate. Checker home, temporary storage, and copied
|
|
319
|
+
seeds are removed after grading even when the fixture is retained after failure
|
|
320
|
+
or cancellation. Results and evidence are preserved. Opted-in candidate artifact runtimes
|
|
276
321
|
remain alive through grading as described below. Runs with neither fixture setup
|
|
277
322
|
nor a selected runtime policy
|
|
278
323
|
retain their previous writable-state locations.
|
|
@@ -525,7 +570,7 @@ run evidence. Extensions and external benchmarks consume the
|
|
|
525
570
|
## Evidence and compatibility
|
|
526
571
|
|
|
527
572
|
`configuration.redacted.runtimePolicy` retains the selected environment,
|
|
528
|
-
canonical read roots, seed digests, and hook declaration. The engine snapshots
|
|
573
|
+
canonical read roots, seed digests, shared-cache declarations, and hook declaration. The engine snapshots
|
|
529
574
|
this input once; it participates in `configurationDigest` and evaluation
|
|
530
575
|
identity. Symbolic runtime placeholders remain symbolic in identity, while
|
|
531
576
|
execution uses per-role paths. This binds declared setup and seed contents;
|
|
@@ -539,7 +584,8 @@ file contents do not. The same discovery and skip evidence reaches
|
|
|
539
584
|
`sevro.host.runtime` observations.
|
|
540
585
|
|
|
541
586
|
Bundled hosts supply `sevro.host.runtime` with the applied policy digest, role,
|
|
542
|
-
environment names, read roots,
|
|
587
|
+
environment names, read roots, seed slots, and selected shared-cache declarations.
|
|
588
|
+
Shared entries contain no content digest. `sevro.host.hooks` records source
|
|
543
589
|
and effective plugin digests plus observed executions and their exit codes.
|
|
544
590
|
An empty execution list does not prove hook activation. Partial lifecycle
|
|
545
591
|
evidence remains partial. Cases can require these observations; missing required
|
|
@@ -549,7 +595,8 @@ task verdict.
|
|
|
549
595
|
`--toolchain-bin-dir` and `--claude-uv-cache-dir` are deprecated. They keep their
|
|
550
596
|
previous behavior with a warning when no runtime file is selected. Combining
|
|
551
597
|
them with a runtime file fails before execution. Migrate to `environment`,
|
|
552
|
-
`filesystem`, and private seed slots
|
|
598
|
+
`filesystem`, and either private seed slots or shared-cache declarations; removal
|
|
599
|
+
is no earlier than `0.2.0`. The deprecated UV option continues to copy privately.
|
|
553
600
|
See the [CLI reference](development-cli.md), [native hosts](native-hosts.md),
|
|
554
601
|
and [identity contract](identity-v1.md).
|
|
555
602
|
|
package/package.json
CHANGED
|
@@ -62,6 +62,38 @@
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
|
+
"sharedCacheDirectories": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"maxItems": 16,
|
|
68
|
+
"items": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"additionalProperties": false,
|
|
71
|
+
"required": ["source", "target", "roles"],
|
|
72
|
+
"properties": {
|
|
73
|
+
"source": { "type": "string", "minLength": 1, "maxLength": 4096 },
|
|
74
|
+
"target": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"pattern": "^[a-z][a-z0-9-]{0,63}$",
|
|
77
|
+
"not": { "enum": ["home", "tmp"] }
|
|
78
|
+
},
|
|
79
|
+
"roles": {
|
|
80
|
+
"type": "array",
|
|
81
|
+
"minItems": 1,
|
|
82
|
+
"maxItems": 5,
|
|
83
|
+
"uniqueItems": true,
|
|
84
|
+
"items": {
|
|
85
|
+
"enum": [
|
|
86
|
+
"candidate",
|
|
87
|
+
"checks",
|
|
88
|
+
"hooks",
|
|
89
|
+
"semantic",
|
|
90
|
+
"advisory"
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
65
97
|
"seedDirectories": {
|
|
66
98
|
"type": "array",
|
|
67
99
|
"maxItems": 16,
|
package/src/evaluation/trial.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { rm } from "node:fs/promises";
|
|
2
|
+
import { hashJson } from "../identity";
|
|
2
3
|
import {
|
|
3
4
|
allocateCandidateRuntime,
|
|
4
5
|
candidateArtifactRoots,
|
|
@@ -38,7 +39,10 @@ import type {
|
|
|
38
39
|
ObservationCompleteness,
|
|
39
40
|
TaskVerdict,
|
|
40
41
|
} from "../contract-types";
|
|
41
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
clearFixtureContents,
|
|
44
|
+
removeDisposableDirectory,
|
|
45
|
+
} from "../fixtures/cleanup";
|
|
42
46
|
import { retainWorkspace } from "../fixtures/workspace-state";
|
|
43
47
|
import { gitHeadRevision } from "../graders/git-head";
|
|
44
48
|
import {
|
|
@@ -789,6 +793,13 @@ class EvaluationTrial {
|
|
|
789
793
|
evaluationProgress(this.options, stage, status, this.trial);
|
|
790
794
|
}
|
|
791
795
|
private async cleanup(): Promise<void> {
|
|
796
|
+
await removeDisposableDirectory(
|
|
797
|
+
join(
|
|
798
|
+
this.context.resources.stateDir,
|
|
799
|
+
"shell-sandbox/runtime",
|
|
800
|
+
hashJson(this.fixture.workspace),
|
|
801
|
+
),
|
|
802
|
+
);
|
|
792
803
|
if (this.state.candidateTranscriptRoot)
|
|
793
804
|
await rm(this.state.candidateTranscriptRoot, {
|
|
794
805
|
recursive: true,
|
package/src/fixtures/cleanup.ts
CHANGED
|
@@ -15,6 +15,18 @@ async function restoreDirectoryAccess(path: string): Promise<void> {
|
|
|
15
15
|
await restoreDirectoryAccess(join(path, child.name));
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/** Remove owned disposable state without following cache or fixture symlinks. */
|
|
19
|
+
export async function removeDisposableDirectory(path: string): Promise<void> {
|
|
20
|
+
try {
|
|
21
|
+
await rm(path, { recursive: true, force: true });
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if ((error as NodeJS.ErrnoException).code === "ENOTDIR") return;
|
|
24
|
+
if (!permissionFailure(error)) throw error;
|
|
25
|
+
await restoreDirectoryAccess(path);
|
|
26
|
+
await rm(path, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
/** Clear a completed fixture while preserving its reserved root for active peers. */
|
|
19
31
|
export async function clearFixtureContents(workspace: string): Promise<void> {
|
|
20
32
|
const root = await lstat(workspace);
|
|
@@ -26,13 +38,7 @@ export async function clearFixtureContents(workspace: string): Promise<void> {
|
|
|
26
38
|
await Promise.all(
|
|
27
39
|
names.map(async (name) => {
|
|
28
40
|
const path = join(workspace, name);
|
|
29
|
-
|
|
30
|
-
await rm(path, { recursive: true, force: true });
|
|
31
|
-
} catch (error) {
|
|
32
|
-
if (!permissionFailure(error)) throw error;
|
|
33
|
-
await restoreDirectoryAccess(path);
|
|
34
|
-
await rm(path, { recursive: true, force: true });
|
|
35
|
-
}
|
|
41
|
+
await removeDisposableDirectory(path);
|
|
36
42
|
}),
|
|
37
43
|
);
|
|
38
44
|
}
|