@bjoernrochel/sevro 0.1.0-rc.7 → 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 +17 -3
- package/docs/codex-host.md +155 -49
- 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 +141 -4
- package/docs/run-settings-v1.md +147 -0
- package/docs/runtime-v1.md +307 -18
- 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 +63 -7
- package/src/advisory.ts +2 -2
- package/src/candidate-artifacts.ts +206 -0
- 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 +13 -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} +133 -115
- package/src/evaluation/trial.ts +800 -0
- package/src/evaluation/types.ts +207 -0
- 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} +15 -76
- 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/fixtures/workspace-state.ts +212 -0
- 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 +57 -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 +91 -14
- package/src/hosts/claude-skill-activations.ts +169 -0
- package/src/hosts/claude-state.ts +46 -16
- package/src/hosts/claude-tool-calls.ts +13 -10
- package/src/hosts/claude.ts +122 -73
- 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 -54
- package/src/hosts/codex-profile.ts +50 -21
- package/src/hosts/codex-session-files.ts +1 -9
- package/src/hosts/codex-state.ts +141 -19
- package/src/hosts/codex.ts +221 -179
- package/src/hosts/isolation-common.ts +15 -11
- package/src/hosts/isolation-roots.ts +13 -20
- package/src/hosts/linux-sandbox.ts +27 -3
- package/src/hosts/mac-sandbox.ts +111 -18
- package/src/hosts/native-controls.ts +72 -22
- package/src/hosts/native-request.ts +55 -0
- package/src/hosts/process-lifecycle.ts +221 -45
- 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 +34 -15
- 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/run-owner.ts +4 -4
- package/src/{runtime-config.ts → runtime/config.ts} +182 -44
- 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} +33 -22
- package/src/{runtime-paths.ts → runtime/paths.ts} +6 -18
- 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 -70
- package/docs/guide-verification.json +0 -239
- package/src/evaluation-context.ts +0 -257
- package/src/evaluation-fixture.ts +0 -313
- package/src/evaluation-run.ts +0 -198
- package/src/evaluation-trial.ts +0 -946
- package/src/evaluation-types.ts +0 -149
- 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 -609
- /package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +0 -0
package/src/hosts/codex-state.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
import { runtimeSeedSources } from "../runtime
|
|
1
|
+
import { runtimeLocalHttpEnabled, runtimeSeedSources } from "../runtime/config";
|
|
2
|
+
import { shellQuote } from "../shell";
|
|
3
|
+
import {
|
|
4
|
+
candidateArtifactEnvironment,
|
|
5
|
+
candidateArtifactReadRoots,
|
|
6
|
+
} from "../candidate-artifacts";
|
|
7
|
+
import {
|
|
8
|
+
codexStateEnabled,
|
|
9
|
+
retainCandidateCodexState,
|
|
10
|
+
} from "../candidate-codex-state";
|
|
2
11
|
import { randomUUID } from "node:crypto";
|
|
3
12
|
import { existsSync } from "node:fs";
|
|
13
|
+
import { isMissingFile } from "../fixtures/tools";
|
|
4
14
|
import {
|
|
5
15
|
cp,
|
|
16
|
+
lstat,
|
|
6
17
|
mkdir,
|
|
7
18
|
readFile,
|
|
8
19
|
realpath,
|
|
@@ -17,12 +28,17 @@ import {
|
|
|
17
28
|
candidateTranscriptEnvironment,
|
|
18
29
|
candidateTranscriptRoots,
|
|
19
30
|
} from "../native-transcripts";
|
|
20
|
-
import { prepareHookMounts } from "../runtime
|
|
31
|
+
import { prepareHookMounts } from "../runtime/hooks";
|
|
32
|
+
import { requireNativeHookRoots } from "../native-transcript-state";
|
|
21
33
|
import {
|
|
22
34
|
requireRuntimeReadRoots,
|
|
23
35
|
runtimeExecutableProtection,
|
|
24
|
-
} from "../runtime
|
|
25
|
-
import { prepareRuntimeState } from "../runtime
|
|
36
|
+
} from "../runtime/paths";
|
|
37
|
+
import { prepareRuntimeState } from "../runtime/state";
|
|
38
|
+
import {
|
|
39
|
+
sharedCacheDenyRoots,
|
|
40
|
+
sharedCacheRoots,
|
|
41
|
+
} from "../runtime/shared-cache";
|
|
26
42
|
import { codexPermissionProfile } from "./codex-profile";
|
|
27
43
|
import { evaluationProtectedRoots } from "./isolation-roots";
|
|
28
44
|
type Request = Parameters<HostAdapter["run"]>[0];
|
|
@@ -40,6 +56,7 @@ export interface CodexHostOptions {
|
|
|
40
56
|
agentConcurrencyLimit?: number | null;
|
|
41
57
|
timeoutMs?: number;
|
|
42
58
|
entrypoint?: "exec" | "app-server";
|
|
59
|
+
retainHostDiagnostics?: boolean;
|
|
43
60
|
/** Integration-test seam; production uses the same CLI for execution and preflight. */
|
|
44
61
|
sandboxBinary?: string;
|
|
45
62
|
}
|
|
@@ -60,23 +77,22 @@ async function copyAuth(source: string, target: string): Promise<void> {
|
|
|
60
77
|
await writeFile(target, bytes, { flag: "wx", mode: 0o600 });
|
|
61
78
|
}
|
|
62
79
|
|
|
63
|
-
function shellQuote(value: string): string {
|
|
64
|
-
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
80
|
export async function codexHookMounts(
|
|
68
81
|
request: Request,
|
|
69
82
|
state: CodexState,
|
|
70
83
|
installedPluginRoots: string[],
|
|
71
84
|
) {
|
|
72
|
-
if (!request.runtimePolicy) return undefined;
|
|
73
85
|
const hooks = await prepareHookMounts({
|
|
74
86
|
workspace: request.workspace,
|
|
75
|
-
stateRoot:
|
|
87
|
+
stateRoot: state.stateRoot,
|
|
76
88
|
privateRoot: state.codexHome,
|
|
77
89
|
pluginRoots: installedPluginRoots,
|
|
78
90
|
protectedRoots: state.protectedRoots,
|
|
79
|
-
policy: request.runtimePolicy
|
|
91
|
+
policy: request.runtimePolicy ?? {
|
|
92
|
+
format: "sevro.runtime.v1",
|
|
93
|
+
environment: {},
|
|
94
|
+
readOnlyRoots: [],
|
|
95
|
+
},
|
|
80
96
|
});
|
|
81
97
|
for (const [index, root] of installedPluginRoots.entries()) {
|
|
82
98
|
const curated = hooks.directories[index];
|
|
@@ -84,9 +100,28 @@ export async function codexHookMounts(
|
|
|
84
100
|
await rm(root, { recursive: true });
|
|
85
101
|
await cp(curated, root, { recursive: true });
|
|
86
102
|
}
|
|
103
|
+
await grantCodexHookReads(state, hooks.directories);
|
|
87
104
|
return hooks;
|
|
88
105
|
}
|
|
89
106
|
|
|
107
|
+
/** Hooks advertise paths relative to these curated copies, not the install cache. */
|
|
108
|
+
async function grantCodexHookReads(
|
|
109
|
+
state: CodexState,
|
|
110
|
+
roots: string[],
|
|
111
|
+
): Promise<void> {
|
|
112
|
+
if (roots.length === 0) return;
|
|
113
|
+
await requireNativeHookRoots(roots, state.codexHome);
|
|
114
|
+
const path = join(state.codexHome, "config.toml");
|
|
115
|
+
const config = await readFile(path, "utf8");
|
|
116
|
+
const header = `[permissions.${state.profileId}.filesystem]\n`;
|
|
117
|
+
const grants = roots
|
|
118
|
+
.map((root) => `${JSON.stringify(root)} = "read"\n`)
|
|
119
|
+
.join("");
|
|
120
|
+
await writeFile(path, config.replace(header, header + grants), {
|
|
121
|
+
mode: 0o600,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
90
125
|
async function privateCodexDirectories(stateRoot: string) {
|
|
91
126
|
const codexHome = join(stateRoot, "codex-home"),
|
|
92
127
|
parentHome = join(stateRoot, "home"),
|
|
@@ -141,9 +176,14 @@ async function writeCodexProfile(
|
|
|
141
176
|
protectedRoots: string[],
|
|
142
177
|
limit: number | null,
|
|
143
178
|
commandEnvironment = request.runtimePolicy?.environment,
|
|
144
|
-
runtimeWriteRoot
|
|
179
|
+
runtimeWriteRoot: string | undefined,
|
|
180
|
+
writableCacheRoots: string[],
|
|
145
181
|
): Promise<void> {
|
|
146
182
|
const profile = codexPermissionProfile({
|
|
183
|
+
localHttp: runtimeLocalHttpEnabled(
|
|
184
|
+
request.runtimePolicy,
|
|
185
|
+
request.runtimeRole ?? "candidate",
|
|
186
|
+
),
|
|
147
187
|
commandEnvironment: codexProfileEnvironment(
|
|
148
188
|
request,
|
|
149
189
|
paths,
|
|
@@ -152,6 +192,10 @@ async function writeCodexProfile(
|
|
|
152
192
|
runtimeWriteRoot,
|
|
153
193
|
runtimeReadRoots: request.runtimePolicy?.readOnlyRoots,
|
|
154
194
|
nativeReadRoots: codexNativeReadRoots(request, paths.codexHome),
|
|
195
|
+
nativeWriteRoots: [
|
|
196
|
+
...codexStateWriteRoots(request, paths),
|
|
197
|
+
...writableCacheRoots,
|
|
198
|
+
],
|
|
155
199
|
id: profileId,
|
|
156
200
|
workspace: request.workspace,
|
|
157
201
|
commandHome: paths.commandHome,
|
|
@@ -162,11 +206,17 @@ async function writeCodexProfile(
|
|
|
162
206
|
});
|
|
163
207
|
await writeFile(
|
|
164
208
|
join(paths.codexHome, "config.toml"),
|
|
165
|
-
profile +
|
|
209
|
+
profile +
|
|
210
|
+
concurrencyConfiguration(limit) +
|
|
211
|
+
fixtureTrustConfiguration(request),
|
|
166
212
|
{ flag: "wx", mode: 0o600 },
|
|
167
213
|
);
|
|
168
214
|
}
|
|
169
215
|
|
|
216
|
+
function fixtureTrustConfiguration(request: Request): string {
|
|
217
|
+
return `\n[projects.${JSON.stringify(request.workspace)}]\ntrust_level = "untrusted"\n`;
|
|
218
|
+
}
|
|
219
|
+
|
|
170
220
|
function codexProfileEnvironment(
|
|
171
221
|
request: Request,
|
|
172
222
|
paths: Awaited<ReturnType<typeof privateCodexDirectories>>,
|
|
@@ -176,6 +226,12 @@ function codexProfileEnvironment(
|
|
|
176
226
|
...codexCommandEnvironment(request, environment),
|
|
177
227
|
...codexTranscriptEnvironment(request, paths.codexHome),
|
|
178
228
|
...candidateTranscriptEnvironment(request.candidateTranscriptRoot),
|
|
229
|
+
...candidateArtifactEnvironment(request.candidateArtifactRoots),
|
|
230
|
+
...(request.runtimePolicy?.codexState === true
|
|
231
|
+
? {
|
|
232
|
+
SEVRO_CODEX_AGENT_SKILLS: join(paths.parentHome, ".agents", "skills"),
|
|
233
|
+
}
|
|
234
|
+
: {}),
|
|
179
235
|
};
|
|
180
236
|
}
|
|
181
237
|
|
|
@@ -183,16 +239,26 @@ function codexTranscriptEnvironment(
|
|
|
183
239
|
request: Request,
|
|
184
240
|
home: string,
|
|
185
241
|
): Record<string, string> {
|
|
186
|
-
return
|
|
187
|
-
? { CODEX_HOME: home
|
|
188
|
-
|
|
242
|
+
return {
|
|
243
|
+
...(request.runtimePolicy?.codexState === true ? { CODEX_HOME: home } : {}),
|
|
244
|
+
...(request.runtimePolicy?.nativeTranscripts === true
|
|
245
|
+
? {
|
|
246
|
+
CODEX_HOME: home,
|
|
247
|
+
SEVRO_NATIVE_TRANSCRIPT_ROOT: join(home, "sessions"),
|
|
248
|
+
}
|
|
249
|
+
: {}),
|
|
250
|
+
};
|
|
189
251
|
}
|
|
190
252
|
|
|
191
253
|
function codexNativeReadRoots(request: Request, home: string) {
|
|
192
254
|
return [
|
|
193
255
|
...linuxArg0ReadRoots(home),
|
|
256
|
+
...(request.runtimePolicy?.codexState === true
|
|
257
|
+
? [join(home, "config.toml"), join(home, "skills", ".system")]
|
|
258
|
+
: []),
|
|
194
259
|
...codexTranscriptRoots(request, home),
|
|
195
260
|
...candidateTranscriptRoots(request.candidateTranscriptRoot),
|
|
261
|
+
...candidateArtifactReadRoots(request.candidateArtifactRoots),
|
|
196
262
|
];
|
|
197
263
|
}
|
|
198
264
|
|
|
@@ -293,7 +359,7 @@ async function codexRuntime(
|
|
|
293
359
|
request.workspace,
|
|
294
360
|
request.runtimePolicy,
|
|
295
361
|
request.runtimeRole ?? "candidate",
|
|
296
|
-
join(stateRoot, "runtime"),
|
|
362
|
+
request.candidateRuntimeRoot ?? join(stateRoot, "runtime"),
|
|
297
363
|
);
|
|
298
364
|
paths.commandHome = runtime.home;
|
|
299
365
|
paths.commandTemp = runtime.temp;
|
|
@@ -315,7 +381,11 @@ function applyCodexRuntime(
|
|
|
315
381
|
function codexRuntimeProfile(
|
|
316
382
|
runtime: Awaited<ReturnType<typeof codexRuntime>>,
|
|
317
383
|
) {
|
|
318
|
-
return {
|
|
384
|
+
return {
|
|
385
|
+
environment: runtime?.environment,
|
|
386
|
+
root: runtime?.root,
|
|
387
|
+
writableCacheRoots: runtime?.writableCacheRoots ?? [],
|
|
388
|
+
};
|
|
319
389
|
}
|
|
320
390
|
|
|
321
391
|
export async function prepareCodexState(
|
|
@@ -325,6 +395,7 @@ export async function prepareCodexState(
|
|
|
325
395
|
request: Request,
|
|
326
396
|
helperRoot?: string,
|
|
327
397
|
) {
|
|
398
|
+
await requireIsolatedGitMetadata(request.workspace);
|
|
328
399
|
const paths = await privateCodexDirectories(stateRoot);
|
|
329
400
|
const runtime = await codexRuntime(request, paths, stateRoot);
|
|
330
401
|
await copyAuth(options.authFile, join(paths.codexHome, "auth.json"));
|
|
@@ -350,6 +421,14 @@ export async function prepareCodexState(
|
|
|
350
421
|
);
|
|
351
422
|
if (helperRoot) readRoots.push(helperRoot);
|
|
352
423
|
requireCodexRuntimeReadRoots(request, protectedRoots);
|
|
424
|
+
await sharedCacheRoots(
|
|
425
|
+
request.runtimePolicy,
|
|
426
|
+
request.runtimeRole,
|
|
427
|
+
protectedRoots,
|
|
428
|
+
);
|
|
429
|
+
protectedRoots.push(
|
|
430
|
+
...sharedCacheDenyRoots(request.runtimePolicy, request.runtimeRole),
|
|
431
|
+
);
|
|
353
432
|
requireUnprotectedExecutables(
|
|
354
433
|
readRoots,
|
|
355
434
|
runtimeExecutableProtection(
|
|
@@ -369,11 +448,54 @@ export async function prepareCodexState(
|
|
|
369
448
|
limit,
|
|
370
449
|
runtimeProfile.environment,
|
|
371
450
|
runtimeProfile.root,
|
|
451
|
+
runtimeProfile.writableCacheRoots,
|
|
372
452
|
);
|
|
373
453
|
const shellRoot = await fixtureShellRoot(request, paths.parentHome);
|
|
374
454
|
const env = codexEnvironment(paths, request, shellRoot);
|
|
375
455
|
applyCodexRuntime(runtime, env, paths);
|
|
376
|
-
|
|
456
|
+
await prepareCodexStateEvidence(request, stateRoot, paths);
|
|
457
|
+
return { ...paths, stateRoot, sandboxBinary, profileId, env, protectedRoots };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function codexStateWriteRoots(
|
|
461
|
+
request: Request,
|
|
462
|
+
paths: Awaited<ReturnType<typeof privateCodexDirectories>>,
|
|
463
|
+
): string[] {
|
|
464
|
+
return codexStateEnabled(request.runtimePolicy)
|
|
465
|
+
? [
|
|
466
|
+
join(paths.codexHome, "skills"),
|
|
467
|
+
join(paths.parentHome, ".agents", "skills"),
|
|
468
|
+
join(paths.commandHome, ".agents", "skills"),
|
|
469
|
+
join(paths.commandHome, ".codex", "skills"),
|
|
470
|
+
]
|
|
471
|
+
: [];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async function prepareCodexStateEvidence(
|
|
475
|
+
request: Request,
|
|
476
|
+
stateRoot: string,
|
|
477
|
+
paths: Awaited<ReturnType<typeof privateCodexDirectories>>,
|
|
478
|
+
): Promise<void> {
|
|
479
|
+
if (!codexStateEnabled(request.runtimePolicy)) return;
|
|
480
|
+
const skillRoots = codexStateWriteRoots(request, paths);
|
|
481
|
+
await Promise.all(
|
|
482
|
+
skillRoots.map((root) => mkdir(root, { recursive: true, mode: 0o700 })),
|
|
483
|
+
);
|
|
484
|
+
await mkdir(join(paths.codexHome, "skills", ".system"), { mode: 0o700 });
|
|
485
|
+
await retainCandidateCodexState(
|
|
486
|
+
request.candidateRuntimeRoot,
|
|
487
|
+
stateRoot,
|
|
488
|
+
paths,
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
async function requireIsolatedGitMetadata(workspace: string): Promise<void> {
|
|
493
|
+
try {
|
|
494
|
+
if (!(await lstat(join(workspace, ".git"))).isDirectory())
|
|
495
|
+
throw new Error("Codex Git metadata must be an isolated directory");
|
|
496
|
+
} catch (cause) {
|
|
497
|
+
if (!isMissingFile(cause)) throw cause;
|
|
498
|
+
}
|
|
377
499
|
}
|
|
378
500
|
|
|
379
501
|
function requireCodexRuntimeReadRoots(
|