Skip to content

bug: agent-level permission deny rules leak into the main agent context (pattern I over-restriction) #292

Description

@terisuke

Summary

Agent definition files (, , etc.) declare "gh pr merge *": "deny" to prevent subagents from merging PRs. This is correct: only the ship agent and the main session should merge. But these deny rules leak into the MAIN agent's effective permission set, overriding the profile-level "gh pr merge *": "allow" in opencode.json.

Incident (2026-08-04, Grift repo)

The main agent successfully merged PRs (anomalyco#1763-anomalyco#1775) on 2026-08-03 using gh pr merge. On 2026-08-04, after the entrypoint was re-pinned to the test-reliability-guards worktree (PR #291), gh pr merge started being blocked by a second permission layer that includes "gh pr merge *": "deny" sourced from agent definition files.

The profile's opencode.json has:

"gh pr merge *": "allow"   ← main agent permission

But the agent files (e.g. agents/implement.md) have:

"gh pr merge *": "deny"    ← subagent-only restriction

The deny is being applied to the main agent, making the effective permission deny.

Root Cause

OpenCode merges ALL agent-level permission rules into a second layer that is applied on top of the main agent's permissions. Deny rules in any agent definition effectively restrict the main agent, because the intersection (most restrictive) wins.

This means: adding a new agent with "X": "deny" silently restricts the main agent's ability to do X, even if the profile explicitly allows it.

Expected Behavior

Agent-level permission rules should apply only when that specific agent is spawned as a subagent. The main agent should use only:

  1. The profile-level opencode.json permissions
  2. The managed opencode.json permissions

Agent definition permissions should be a subset applied at spawn time, not a global intersection.

Actual Behavior

All agent-level deny rules from all defined agents are accumulated into a second permission layer, applied to every session including the main agent. This is functionally equivalent to "any agent can veto any permission for everyone".

Impact

  • The main agent cannot perform gh pr merge despite the profile explicitly allowing it
  • Workaround: restart the session or have a human merge from the terminal
  • No visible warning or override mechanism (the deny is silent and unexplained)
  • This affected 4 ready-to-merge PRs that were blocked for hours

Reproduction

  1. Pin entrypoint to any worktree whose profile defines agents with "gh pr merge *": "deny"
  2. From the main agent, attempt gh pr merge <PR> --merge
  3. Observe: blocked by the deny rule, despite opencode.json having "allow"
  4. The error shows two permission layers: first has allow, second has deny

Proposed Fix

  1. Agent permissions should be isolated: when spawning a subagent, merge the agent's permissions ON TOP of the profile permissions for that subagent's session only. Do not accumulate them globally.
  2. Main agent should not inherit agent-level deny rules: the main session's permission source is the profile + managed opencode.json, not agent definitions.
  3. Warning when deny overrides allow: if a deny rule overrides an explicit allow, emit a warning so the user knows the source.

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions