Originally created by: yablokolabs
When a model emits an approval-gated call together with other calls, Atomic correctly isolates the first gated call, but it discards every sibling payload and asks the model to regenerate them on the next step. This preserves the approval boundary but costs an avoidable inference and loses the exact original arguments.
This is the residual form of finding §5 from Yabloko Labs' evaluation. Current v0.1.73 improved the old repair path by mechanically trimming the batch, but the dropped-call behavior remains explicit.
tryTrimApprovalGated keeps only the first approval-gated call and records every other call as dropped:
step-executor.ts (github.com)The next-step notice tells the model to emit those calls again:
step-executor.ts (github.com)Observed pattern:
[approval-gated write, read-back verification]
→ execute write alone
→ drop read payload
→ spend another model step reconstructing the read
Treat approval-gated calls as ordered barriers rather than selecting one call and dropping the rest.
The retained-barrier path is eligible only when the original batch size is at most maxParallelToolCalls and every call can be preflighted. Every oversized batch containing an approval-gated or other non-pure_read call must go through fail-closed repair. Deterministic cap splitting is reserved for the all-pure_read case tracked in [#111].
For an eligible batch:
reply and finish should not be automatically replayed through this mechanism. A batch containing terminal calls, invalid arguments, unknown tools, an oversized original payload, or another non-preflightable shape should remain on the existing fail-closed repair path.
maxParallelToolCalls.reply and finish are excluded from automatic retained-call replay.[approval_gated, pure_read, ...] batch triggers parse_retry; no original call is dispatched before a valid repaired response.