Skip to content

feat(permissions): approval notes and session-scoped user rules for the AI auto-approve judge #2228

Description

@YodonTan

Goal

Let users attach approval notes in the AI auto-approve permission mode and turn those notes (plus always-approvals and rejections) into session-scoped rules that the AI judge reuses across dialog turns, so unattended work no longer re-asks for the same class of operation while staying fail-closed on dangerous requests.

Background

BitFun's permission surface has four modes: Ask, Auto approve, Full access, and AI auto approve. In AI auto-approve mode a fast model judges every tool call that would normally require confirmation: safe and routine requests auto-approve, critical-risk requests (e.g. rm -rf /) are rejected outright, and everything else escalates to the user.

The current flow has two gaps that make long unattended ("async office") sessions awkward:

  1. Approvals cannot carry a note. When the user approves an escalated request they cannot attach guidance such as "approve all log-viewing commands". The approval is a bare yes/no; the agent only learns that one specific call was OK, not the user's intent for similar future calls.

  2. User intent does not survive across turns. An approval or note made in one dialog turn is invisible to the judge in later turns and in subagents, so the same class of operation keeps escalating and the user re-approves the same kind of request repeatedly.

Goal

  1. Approval notes: let the user attach an optional note when approving (once, always, or batch) a permission request. The note is recorded in the permission audit and surfaced to the agent in the tool result (User approved this tool call with feedback: ...), so the current turn benefits immediately.

  2. Session-scoped user rules for the judge: persist user intent as rules rebuilt once per dialog turn from the session's permission audit:

    • Always approvals,
    • approvals with a note,
    • rejections with a note (so the agent stops retrying what the user refused).
      Rules are newest-first, capped at 50, rendered between the stable session context and the growing tool history so the judge prefix stays byte-stable and KV-cache friendly inside a turn.
  3. Subagent inheritance: subagent tool calls inherit the parent session's rules through delegation.parent_session_id, so delegated work follows the same user intent.

  4. In-turn notes on tool history: notes attached in the current turn are marked on tool-history entries ((user note: "...")) so the judge can honor the user's stated intent for directly matching calls before the next turn formalizes them into rules.

  5. Safety stays fail-closed:

    • Inherently read-only tools (Read/Search on non-sensitive resources) keep the deterministic fast path and never wait on the model.
    • Rules are guidance, not blank checks: only directly matching operations count, and dangerous operations (destructive, secret-exposing, system-wide) are never approved by a rule.
    • A fixed preamble in the rules section states this to the model.

Expected behavior

  • User approves an escalated request with note "approve all log-viewing commands": the same turn's similar calls are allowed via the tool-history marker, and from the next turn on the rule is visible to the judge, so similar log commands auto-approve without asking again.
  • Subagent tool calls see the parent session's rules and behave accordingly.
  • rm -rf / is still rejected outright even if a rule text mentions similar-looking commands.

Acceptance criteria

  • Wire-compatible DTO extension: PermissionReply::Once / Always carry optional feedback; the old wire shape ({"reply":"once"}) still deserializes.
  • Audit records contain the approval note with source: user.
  • Tool result surfaces the note to the agent.
  • Rules are rebuilt per dialog turn from user-source replies only, newest-first, capped at 50, with the fail-closed preamble; session-scoped (not shared across sessions), project grants listed separately as authorization facts.
  • Subagent judge inputs include the parent session's rules.
  • Read-only fast path and hard rejections are unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions