fix(approval): check is_approved in execute_code guard (#39275)

check_execute_code_guard() never called is_approved() before entering the
approval flow, and never persisted session/permanent approvals from the
gateway response. This meant 'Approve session' and 'Always' buttons had
no effect — every execute_code call re-prompted the user.

- Add is_approved() check after get_current_session_key(), matching
  check_all_command_guards()
- Persist session ('approve_session') and permanent ('approve_permanent')
  approvals based on the gateway choice, same as terminal command guard
- Add 3 regression tests for session persistence, permanent persistence,
  and short-circuit on pre-existing approval
This commit is contained in:
kyssta-exe
2026-06-05 00:07:43 +00:00
committed by Teknium
parent facd011b63
commit 25742372eb
2 changed files with 62 additions and 3 deletions

View File

@ -1584,6 +1584,12 @@ def check_execute_code_guard(code: str, env_type: str) -> dict:
# paths don't pay to copy a potentially-large script into this string.
command = f"execute_code <<'PY'\n{code}\nPY"
# Check session/permanent approval — same gate as check_all_command_guards.
# Without this, "Approve session" / "Always" choices are stored but never
# consulted, so every execute_code call re-prompts the user (#39275).
if is_approved(session_key, pattern_key):
return {"approved": True, "message": None}
# Smart mode: ask the aux LLM about the whole script. An APPROVE here only
# suppresses the redundant whole-script prompt; the per-call terminal()
# guards (restored by context propagation) still run independently.
@ -1674,9 +1680,15 @@ def check_execute_code_guard(code: str, env_type: str) -> dict:
"user_consent": False,
}
# Approved — one-shot only. Deliberately NO approve_session/approve_permanent:
# each execute_code script is distinct arbitrary code, so approval never
# persists to future scripts.
# Approved — persist based on scope (same logic as check_all_command_guards).
if choice == "session":
approve_session(session_key, pattern_key)
elif choice == "always":
approve_session(session_key, pattern_key)
approve_permanent(pattern_key)
save_permanent_allowlist(_permanent_approved)
# choice == "once": no persistence — approval lasts this single call only.
return {"approved": True, "message": None,
"user_approved": True, "description": description}