Repository navigation
v0.9.8: make one-shot approval outcomes durable and fail-closed #5360
Description
Why
Mining deepseek-ai/deepseek-harness 0.1.0-rc.5 at 47f943859bef60e4160492346772ded9b24f765a found one approval pattern worth adopting without importing its Cordis/plugin architecture: every approval request has one closed outcome, the ask/decision pair is written to the session log, and only an explicit one-shot allow grants execution. Missing, cancelled, throwing, or malformed answerers become a fail-closed outcome.
Codewhale already fails closed at the live channel boundary in crates/tui/src/core/engine/approval.rs, but approval evidence is split between transient engine events and the optional CODEWHALE_TOOL_AUDIT_LOG projection in core/engine/tool_execution.rs. A resumed session cannot reconstruct the exact ask/outcome pair from its own durable record.
Small design
Keep the existing engine and tool-call path. Do not add a plugin bus or generic policy framework.
- Define one closed internal approval outcome covering: approved once, denied, cancelled, unavailable, and retry once with the approved sandbox policy.
- Correlate each outcome to the exact tool call/approval attempt. Reuse the tool-call id if it is already unique enough; add a separate approval id only if a test proves it is needed.
- Persist an
askedreceipt before waiting and one terminaldecidedreceipt before execution proceeds or the denied result is returned. - Treat channel closure, cancellation, malformed/stale decisions, and persistence failure as non-grants. Only
approved onceor the exact approved retry policy may cross the gate. - Keep the external JSONL audit as an optional projection, never the authority.
- Keep approval receipts out of the model transcript; the existing tool result remains the model-visible outcome.
Acceptance
- A keyless engine test covers approved, denied, cancelled, unavailable/channel-closed, and retry-with-policy outcomes.
- Replay/resume reconstructs every completed ask/decision pair and detects an unmatched ask after interruption.
- No path executes a tool when the terminal approval receipt cannot be committed.
- Existing Ask / Auto-Review / Full Access / Never behavior and sandbox precedence do not change.
- Focused tests plus
cargo fmt --all -- --checkpass.
Source comparison
- Harness:
packages/interaction/user-approval/src/index.ts,docs/subsystems/approval.md - Codewhale:
crates/tui/src/core/engine/approval.rs,crates/tui/src/core/engine/turn_loop.rs,crates/tui/src/core/engine/tool_execution.rs
No-Issue: research-derived v0.9.8 hardening task.
Activity
Hmbown commentedon Aug 17, 2026
Rolled to v0.9.10: the v0.9.9 release branch merged to main tonight (#5476) without this landing; nothing here is closed or dropped.
docs(release): open the 0.9.10 contributor ledger
docs(release): open the 0.9.10 contributor ledger