meter: the call leaves no transcript (finding meter-transcripts-need-no-keeping)

--no-session-persistence on the meter's call only: it keeps no handle and
resumes nothing, and every other call is resumed by its session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-11-03 12:45:21 +01:00
commit 877f7a92cd
3 changed files with 17 additions and 5 deletions

View file

@ -177,7 +177,7 @@ impl ClaudeCodeBackend {
request.input = vec![InputItem::UserText {
text: "ok?".to_string(),
}];
match self.run(&request, METER_CALLER).1 {
match self.run(&request, METER_CALLER, true).1 {
TransportOutcome::Completed { usage, .. } => Ok(usage),
TransportOutcome::Failed { kind, .. } => Err(format!("{kind:?}")),
}
@ -189,10 +189,13 @@ impl ClaudeCodeBackend {
binary_matches_pin(&self.config)
}
/// `ephemeral` leaves no transcript behind: the meter keeps no handle and
/// resumes nothing, every other call is resumed by its session.
fn run(
&self,
request: &ProviderRequest,
caller: &str,
ephemeral: bool,
) -> (Vec<TransportEvent>, TransportOutcome) {
let Some(secret) = usable_secret(self.handle_secret.as_ref()) else {
return failed(
@ -236,7 +239,7 @@ impl ClaudeCodeBackend {
"claude-code: the system prompt could not be staged",
));
};
let argv = argv(&self.config, request, &plan, prompt.path());
let argv = argv(&self.config, request, &plan, prompt.path(), ephemeral);
let env = child_env(&self.config, request);
let deadline = Instant::now() + self.config.limits.deadline;
@ -350,7 +353,7 @@ impl ProviderBackend for ClaudeCodeBackend {
}
fn execute(&self, call: &ProviderCall) -> TransportResult {
let (events, outcome) = self.run(call.request(), call.caller_runtime_id());
let (events, outcome) = self.run(call.request(), call.caller_runtime_id(), false);
call.transported(events, outcome)
}

View file

@ -2773,6 +2773,10 @@ fn the_meter_call_reads_the_week_from_a_real_captured_event() {
let after = |flag: &str| argv[argv.iter().position(|a| a == flag).unwrap() + 1].clone();
assert_eq!(after("--model"), METER_MODEL);
assert_eq!(after("--tools"), "", "the call can use no tool");
assert!(
argv.iter().any(|a| a == "--no-session-persistence"),
"the meter's transcript is nobody's to keep: {argv:?}"
);
assert_eq!(rig.spawns(), 1, "one child, never run again");
}

View file

@ -107,13 +107,15 @@ fn effort(effort: ReasoningEffort) -> &'static str {
/// rather than an argument because one argument is capped near 128 KiB
/// (E2BIG) and instructions are not, the child has
/// no tools, no MCP servers, no settings, no slash commands and nobody to ask
/// for permission, and a resume always forks. A request's output schema goes
/// to the CLI as `--json-schema`; without one the flag is absent.
/// for permission, and a resume always forks. An ephemeral call (the
/// meter's) keeps no session on disk. A request's output schema goes to the
/// CLI as `--json-schema`; without one the flag is absent.
pub(crate) fn argv(
config: &ClaudeCodeConfig,
request: &ProviderRequest,
plan: &Plan,
system_prompt_file: &Path,
ephemeral: bool,
) -> Vec<String> {
let mut argv: Vec<String> = [
config.claude_binary.to_string_lossy().as_ref(),
@ -139,6 +141,9 @@ pub(crate) fn argv(
.into_iter()
.map(str::to_string)
.collect();
if ephemeral {
argv.push("--no-session-persistence".to_string());
}
if let Some(level) = request.reasoning_effort {
argv.extend(["--effort".to_string(), effort(level).to_string()]);
}