Skip to content

feat(permissions): add permission denial tracking with escalating con…#2831

Open
chinesepowered wants to merge 1 commit intoQwenLM:mainfrom
chinesepowered:permission-loop
Open

feat(permissions): add permission denial tracking with escalating con…#2831
chinesepowered wants to merge 1 commit intoQwenLM:mainfrom
chinesepowered:permission-loop

Conversation

@chinesepowered
Copy link
Copy Markdown
Contributor

@chinesepowered chinesepowered commented Apr 2, 2026

Add permission denial tracking with escalating context to prevent the model from endlessly retrying denied tool calls.

TLDR

Adds a PermissionDenialTracker that monitors per-tool permission denials across a session. When the model repeatedly attempts a denied tool, the error message escalates with contextual guidance: after 2 denials it suggests trying a different approach, and after 4 denials it strongly instructs the model to stop retrying and ask the user for help.

Screenshots / Video Demo

N/A — no user-facing UI change. The behavior manifests as augmented error messages in the model's tool response when denials repeat.

Example progression:

  • 1st denial: Qwen Code requires permission to use "run_shell_command", but that permission was declined.
  • 2nd denial: Same message + [This tool has been denied 2 times this session. Consider trying a different approach instead of retrying.]
  • 4th denial: Same message + [This tool has been denied 4 times this session. STOP retrying this tool. Ask the user for guidance or use a different approach entirely.]

Dive Deeper

  • New PermissionDenialTracker class in packages/core/src/services/permissionDenialTracker.ts
    • Tracks per-tool denial counts at both session and turn granularity
    • recordDenial(toolName, message) increments count and returns augmented message if threshold crossed
    • resetTurn() resets per-turn counters while preserving session totals
    • getSummary() returns all denial counts for downstream consumers
  • Integrated at all 7 EXECUTION_DENIED error paths in coreToolScheduler.ts:
    • isToolEnabled() check (PM disabled tool)
    • Legacy getPermissionsDeny() fallback
    • PM finalPermission === 'deny' (security/rule violation)
    • Non-interactive mode auto-deny
    • PermissionRequest hook denial
    • PreToolUse hook block
    • PostToolUse hook stop

Modified files:

  • packages/core/src/services/permissionDenialTracker.ts — New tracker service
  • packages/core/src/core/coreToolScheduler.ts — Import tracker, instantiate as field, wrap all EXECUTION_DENIED paths

Reviewer Test Plan

  1. Configure a deny rule for a tool (e.g., run_shell_command) and ask the model to use it repeatedly
  2. Verify first denial shows the standard message
  3. Verify second denial appends "Consider trying a different approach" guidance
  4. Verify fourth denial appends "STOP retrying" guidance
  5. Run existing scheduler tests: npx vitest run src/core/coreToolScheduler.test.ts (all 53 pass)

Testing Matrix

macOS Windows Linux
npm run ? pass ?
npx ? ? ?
Docker ? ? ?
Podman ? - -
Seatbelt ? - -

Linked issues / bugs

Fixes #2819

…text

Track per-tool permission denials across a session. When the model
repeatedly attempts a denied tool, the error message escalates with
guidance to try a different approach (after 2 denials) or stop
retrying entirely (after 4 denials). Prevents frustrating dead-end
loops where the model keeps retrying the same denied action.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Permission Denial Tracking with Contextual Fallback

1 participant