Skip to content

Commit 17f13a4

Browse files
author
Sean Roberts
committed
fix: reuse common workspace
1 parent 12bc4c2 commit 17f13a4

4 files changed

Lines changed: 20 additions & 10 deletions

File tree

src/runner/runner.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ async function executeJob(
344344
rubric: scenario.rubric,
345345
agentConfig,
346346
output,
347+
workingDirectory: workspace,
347348
},
348349
cleanup,
349350
};

src/scoring/judge.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,23 @@ export interface JudgeCallOptions {
1313

1414
/**
1515
* Call an LLM judge using the same adapter as the test run.
16-
* Creates an isolated temp workspace, runs the adapter with a synthetic scenario,
17-
* and returns the result text.
16+
*
17+
* Uses the agent's original workspace when available so the judge can
18+
* independently verify the agent's actual work (files created, endpoints
19+
* deployed, etc.). Falls back to a disposable temp directory only when
20+
* no workspace is set (e.g. programmatic API usage without the runner).
1821
*/
1922
export async function callJudge(
2023
runResult: RunResult,
2124
prompt: string,
2225
options: JudgeCallOptions,
2326
): Promise<string> {
2427
const adapter = getAdapter(runResult.agentConfig.adapter);
28+
const originalWorkspace = runResult.workingDirectory;
29+
30+
const workspace = originalWorkspace ?? fs.mkdtempSync(path.join(os.tmpdir(), `axis-${options.scenarioKey}-`));
31+
const shouldCleanup = !originalWorkspace;
2532

26-
const workspace = fs.mkdtempSync(path.join(os.tmpdir(), `axis-${options.scenarioKey}-`));
2733
try {
2834
const output = await adapter.run({
2935
prompt,
@@ -38,10 +44,12 @@ export async function callJudge(
3844
});
3945
return output.result ?? "";
4046
} finally {
41-
try {
42-
fs.rmSync(workspace, { recursive: true, force: true });
43-
} catch {
44-
/* ignore */
47+
if (shouldCleanup) {
48+
try {
49+
fs.rmSync(workspace, { recursive: true, force: true });
50+
} catch {
51+
/* ignore */
52+
}
4553
}
4654
}
4755
}

src/scoring/prompt-templates.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ const GOAL_STRING_RUBRIC_TEMPLATE: PromptTemplate = {
183183
stage: "goal_achievement",
184184
template: `You are an expert evaluator for an AI agent testing framework called AXIS.
185185
186-
An AI agent was given a task. You must evaluate how well it performed by reviewing its transcript AND by independently verifying the results yourself.
186+
An AI agent was given a task. You must evaluate how well it performed based on the evidence in its transcript.
187187
188188
SCENARIO: {{scenarioName}}
189189
@@ -209,8 +209,7 @@ RUBRIC:
209209
210210
INSTRUCTIONS:
211211
1. Review the transcript to understand what the agent did.
212-
2. Where possible, independently verify the results — visit URLs, check endpoints, confirm that the claimed outcomes actually exist. Do not trust the transcript alone.
213-
3. Score based on what you can verify, not just what the agent claims.
212+
2. Where possible, independently verify the results — check the filesystem for created/modified files, visit URLs, confirm that the claimed outcomes actually exist. Do not trust the transcript alone.
214213
215214
When done, respond with ONLY valid JSON on its own line:
216215
{"score": <0-10>, "rationale": "<1-2 sentence explanation>"}

src/types/output.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export interface BaseRunResult {
2020
rubric: string | RubricCriterion[];
2121
agentConfig: AgentConfig;
2222
output: AgentOutput;
23+
/** Path to the agent's workspace directory (available during scoring, before cleanup). */
24+
workingDirectory?: string;
2325
}
2426

2527
export interface RunResult extends BaseRunResult {}

0 commit comments

Comments
 (0)