feat: persist the tool transcript on every result record

Records stored only a run's token/turn totals, so an arm's turn cost —
the dominant driver of cache-read tokens — could not be diagnosed from
the store. Retain the ordered transcript of tool invocations (the exact
shell commands, MCP calls, and built-in tools the run made) on every
scored record, absent only for a hung run that produced no transcript.

The canonical TranscriptEntry shape lives on the record (result.ts); the
isolation audit's ToolUse now aliases it so the persisted and audited
shapes cannot drift.
This commit is contained in:
2026-07-17 14:43:43 -04:00
parent 05b72f6987
commit 14d494afa2
4 changed files with 40 additions and 8 deletions

View File

@@ -12,17 +12,17 @@
// runner (runner.ts) drives the run and feeds the transcript here.
import type { ArmDefinition } from "./arm.js";
import type { TranscriptEntry } from "./result.js";
/**
* One tool invocation recorded in the agent's transcript, reduced to what the
* isolation audit needs. `shell` is a proposed shell command; `mcp` is a call to
* an attached MCP server's tool; `other` is a built-in, non-Gitea-reaching tool
* (file read/edit and the like) that carries no isolation risk.
* (file read/edit and the like) that carries no isolation risk. This is the same
* shape the record persists ({@link TranscriptEntry}); the audit and the record
* share one type so they cannot drift.
*/
export type ToolUse =
| { kind: "shell"; command: string }
| { kind: "mcp"; server: string; tool: string }
| { kind: "other"; name: string };
export type ToolUse = TranscriptEntry;
/**
* The audit's verdict. On a leak it carries a human-readable reason per foreign