Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions bench/cdeb/evaluator/freeze-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* the OID rather than trusting the claim (ingest.ts).
*/

import { spawnSync } from "node:child_process";
import { writeFileSync } from "node:fs";
import { join } from "node:path";

Expand All @@ -36,6 +37,42 @@ export interface FrozenFinalTree {
readonly staged_file_count: number;
}

/** The extra §11.1 provenance CDEB-07 stores in `final-tree.json`. */
export interface FrozenTreeProvenance {
readonly base_tree_oid: string;
readonly canonical_diff_sha256: string;
readonly workspace_status_digest: string;
}

const FROZEN_GIT_ENV: Readonly<Record<string, string>> = {
GIT_CONFIG_GLOBAL: "/dev/null",
GIT_CONFIG_SYSTEM: "/dev/null",
GIT_TERMINAL_PROMPT: "0",
GIT_ADVICE: "0",
GIT_OPTIONAL_LOCKS: "0",
};

const FROZEN_GIT_FLAGS = [
"-c", "core.fsmonitor=false",
"-c", "core.autocrlf=false",
"-c", "core.symlinks=true",
"-c", "core.ignorecase=false",
"-c", "core.fileMode=true",
] as const;

const gitOrThrow = (workdir: string, env: Record<string, string>, args: readonly string[]): Buffer => {
const result = spawnSync("git", [...args], {
cwd: workdir,
env: { PATH: process.env.PATH ?? "/usr/bin:/bin", ...env },
encoding: "buffer",
maxBuffer: 64 * 1024 * 1024,
});
if (result.status !== 0) {
throw new Error(`final tree provenance: git ${args.join(" ")} failed (${String(result.status)}): ${Buffer.from(result.stderr ?? Buffer.alloc(0)).toString("utf8").trim()}`);
}
return Buffer.from(result.stdout ?? Buffer.alloc(0));
};

/**
* Freezes the agent's final working tree. `scratchDir` must be a fresh
* directory the caller owns; nothing here writes inside `workdir`.
Expand All @@ -55,6 +92,53 @@ export const freezeFinalTree = (workdir: string, scratchDir: string): FrozenFina
};
};

/**
* Captures the base→final binary diff and porcelain status from the actual
* materialized repository. It stages through a temporary index and asserts
* that its tree is the OID the hermetic freezer already produced; otherwise a
* "diff of the tree" would be a second, drifting implementation of §11.1.
*
* This is intentionally separate from `freezeFinalTree`: evaluator controls
* also freeze plain fixture directories with no Git history, while a measured
* CDEB workspace is always a materialized repository and therefore has a base.
*/
export const frozenTreeProvenance = (
workdir: string,
scratchDir: string,
frozen: FrozenFinalTree,
): FrozenTreeProvenance => {
const indexPath = join(scratchDir, "cdeb-final-index");
const env: Record<string, string> = {
...FROZEN_GIT_ENV,
GIT_INDEX_FILE: indexPath,
TMPDIR: scratchDir,
};
const base_tree_oid = gitOrThrow(workdir, env, ["rev-parse", "HEAD^{tree}"]).toString("utf8").trim();
gitOrThrow(workdir, env, [...FROZEN_GIT_FLAGS, "read-tree", "HEAD"]);
gitOrThrow(workdir, env, [...FROZEN_GIT_FLAGS, "add", "-A", "--", "."]);
const staged = gitOrThrow(workdir, env, [...FROZEN_GIT_FLAGS, "write-tree"]).toString("utf8").trim();
if (staged !== frozen.final_tree_oid) {
throw new Error(
`final tree provenance: temporary-index OID ${staged} differs from hermetic freezer OID ${frozen.final_tree_oid}`,
);
}
const canonicalDiff = gitOrThrow(
workdir,
env,
[...FROZEN_GIT_FLAGS, "diff", "--cached", "--binary", "--full-index", "--no-ext-diff", "--no-renames", "HEAD"],
);
const workspaceStatus = gitOrThrow(
workdir,
env,
["status", "--porcelain=v1", "-z", "--untracked-files=all"],
);
return {
base_tree_oid,
canonical_diff_sha256: sha256Hex(canonicalDiff),
workspace_status_digest: sha256Hex(workspaceStatus),
};
};

/** Writes the §19.1 artifacts (`final-tree.tar.zst`) under a run directory. */
export const writeFrozenArtifacts = (runDir: string, frozen: FrozenFinalTree): string => {
const archivePath = join(runDir, "final-tree.tar.zst");
Expand Down
Loading
Loading