Skip to content

fix(server): full-access OpenCode threads no longer ask for approvals - #9282

Open
shivamhwp wants to merge 4 commits into
pingdotgg:mainfrom
shivamhwp:t3code/check-opencode-full-access-approvals
Open

fix(server): full-access OpenCode threads no longer ask for approvals#9282
shivamhwp wants to merge 4 commits into
pingdotgg:mainfrom
shivamhwp:t3code/check-opencode-full-access-approvals

Conversation

@shivamhwp

@shivamhwp shivamhwp commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

A user reported that OpenCode threads set to full access still pop approval dialogs. I reproduced it live against OpenCode 1.18.26 with a ChatGPT subscription. Ordinary tool calls are fine, but two paths in OpenCode ignore the session-level allow we send:

  • Doom loop. When the model repeats the same tool call three times, OpenCode evaluates the ask against the agent ruleset only, so our wildcard allow is never consulted. This showed up in the UI as an "unknown" approval.
  • Subagents. Child sessions spawned by the task tool keep only deny and external-directory rules from the parent, so a subagent reading *.env or hitting any agent default prompts. Since fix(opencode): handle child approvals, stops, and model catalogs #8480 routes child asks to the thread, this also shows a dialog.

Both are upstream OpenCode behavior, and full access means the user already said yes. The adapter now answers "always" to any permission ask that arrives while the session is in full access, and swallows the matching replied event so nothing reaches the UI. If the reply call fails, it falls back to showing the approval as before. Other modes are untouched.

Tests cover the doom-loop ask on the parent session, a child-session ask, and the failed-reply fallback.

Work done by Claude Fable 5.1 via Claude Code.

🤖 Generated with Claude Code


Note

Medium Risk
Changes permission handling for full-access OpenCode sessions only, but auto-approving without user confirmation increases blast radius if mis-gated; approval-required and other modes are unchanged.

Overview
Fixes full-access OpenCode threads still showing approval dialogs when upstream ignores the session wildcard (doom-loop detection and child/subagent sessions).

In OpenCodeAdapter, permission.asked while runtimeMode === "full-access" now calls permission.reply with always before emitting UI events. Matching permission.replied events are suppressed via autoRepliedRequestIds so request.opened / request.resolved never reach the client. Request ids are marked resolved before the async reply to avoid races with retries and duplicate dialogs.

If the auto-reply fails, behavior falls back to surfacing the approval (single attempt, no retry loop), with extra guards when a terminal reply already landed during the in-flight SDK call.

Tests add a mock permissionReplyImplementation hook and cover parent doom-loop asks, child-session asks, and failed-reply fallback.

Reviewed by Cursor Bugbot for commit 5226415. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix full-access OpenCodeAdapter threads to skip approval prompts

Adds integration tests that verify full-access OpenCode sessions auto-reply to permission requests with always instead of surfacing user approval events. Covers parent-session doom-loop asks, child-session asks, and the fallback path where a failed auto-reply emits a request.opened event. Updates OpenCodeRuntimeTestDouble.permission.reply to support an injectable async hook so tests can simulate both success and failure of the auto-reply.

Macroscope summarized 291c0dd.

OpenCode ignores the session ruleset for doom-loop checks and drops the
parent's wildcard allow when it spawns subagent sessions, so full-access
threads still surfaced approval dialogs for those asks. Auto-reply
"always" to any permission ask while the session is in full access and
swallow the matching replied event, falling back to the dialog if the
reply call fails.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Sep 2, 2026
Comment thread apps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeapp Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused OpenCode bug fix that makes already-selected full-access sessions consistently auto-answer permission prompts while preserving approval-required behavior, with targeted coverage for parent, child, and failure paths. A Medium race finding remains separately recorded regarding stale approvals after terminal replies.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

A retry or recovery fiber could re-enter the pending-request path, or the
matching permission.replied could land, while the auto-reply SDK call was
still in flight. That raced to emit a duplicate request.opened or a stray
request.resolved. Record the resolved and auto-replied ids synchronously
before awaiting, and roll them back if the reply fails.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Sep 2, 2026
// The reply failed, so fall back to surfacing the approval. Undo
// the bookkeeping so the terminal event and any retry treat it as
// a normal pending request.
context.resolvedRequestIds.delete(request.id);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium Layers/OpenCodeAdapter.ts:1645

A failed in-flight auto-reply can emit request.opened after a matching permission.replied was already processed, leaving the UI with an approval for a request that is terminal and cannot be answered. The terminal handler records the request in emittedTerminalRequestIds, but the failure path at this point unconditionally removes the bookkeeping and falls through to emit the stale request; return early when that terminal marker is present.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/Layers/OpenCodeAdapter.ts around line 1645:

A failed in-flight auto-reply can emit `request.opened` after a matching `permission.replied` was already processed, leaving the UI with an approval for a request that is terminal and cannot be answered. The terminal handler records the request in `emittedTerminalRequestIds`, but the failure path at this point unconditionally removes the bookkeeping and falls through to emit the stale request; return early when that terminal marker is present.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 291c0dd. Configure here.

Comment thread apps/server/src/provider/Layers/OpenCodeAdapter.ts
shivamhwp and others added 2 commits September 2, 2026 23:25
… resolved

If the auto-reply SDK call fails locally but OpenCode still resolved the
permission, the terminal permission.replied lands and is swallowed while the
reply is in flight, consuming the terminal slot. The failure path then rolled
back and opened a dialog that could never resolve. Guard the fallback: if the
terminal event already landed, keep the request resolved and do not reopen it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Guard against a regression where the fallback retries the reply instead of
surfacing the dialog.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant