Skip to content

fix(guardrails): stop primary agent deny overriding config merge allow - #293

Merged
terisuke merged 1 commit into
devfrom
fix-merge-perm-leak
Aug 4, 2026
Merged

fix(guardrails): stop primary agent deny overriding config merge allow#293
terisuke merged 1 commit into
devfrom
fix-merge-perm-leak

Conversation

@terisuke

@terisuke terisuke commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Fixes #292.

The default primary agent (implement) declared "gh pr merge *": "deny" in its frontmatter. agent.ts builds a user-defined agent's permission as merge(merge(defaults, userConfig), agentDefinition), and Permission.evaluate is last-wins (findLast). So the agent definition is applied AFTER the user config and overrides it. For the default primary agent (the main session agent), the deny therefore overrode the explicit "gh pr merge *": "allow" in opencode.json — silently blocking the main session from merging despite the config granting it (pattern I over-restriction).

This is the root cause of the 2026-08-04 incident where 4 CI-green PRs were blocked for hours after the entrypoint was re-pinned to a profile whose implement.md carried the deny.

Why the existing symmetry test missed it

implementBashRuleset() evaluated implement.md's bash block in isolation, never the merged effective ruleset that agent.ts actually produces. The bug only appears in the merge.

Change

  • packages/guardrails/profile/agents/implement.md: removed the single conflicting "gh pr merge *": "deny" (the only primary-agent deny that contradicts a config allow). Added a maintainer comment explaining why a deny must not be re-added here. All other denies (rm -rf, force-push, reset --hard, …) remain — they are consistent with the config.
  • packages/guardrails/profile/agents/planner.md: unchanged. planner is a read-only primary agent; its gh pr merge* deny is intentional and not the bug.

Tests (falsifiable, real-file)

New anti-pattern I — primary-agent permission leak (issue #292) block in anti-pattern-guards.test.ts reads the real agent files (not a hand-mirrored fixture) so drift cannot hide the regression again:

  • ✅ implement effective permission allows gh pr merge … per config
  • falsify: layering a deny on the config allow → deny (proves the test mechanism detects the regression; flipping implement.md back resurfaces it)
  • negative: destructive ops the config also denies (rm -rf, git push --force, git reset --hard) remain denied
  • ✅ specialized primary (planner) may still self-restrict

Proof

  • RED before fix: expect(...).toBe("allow")Received: "deny"
  • GREEN after fix: 23/23 pass in anti-pattern-guards.test.ts
  • tsgo --noEmit clean
  • local:deploy green (binary 0.0.0-fix-merge-perm-leak-*, entrypoint repinned); local:check permission/guardrail/team smokes all pass

Scope notes / follow-ups (tracked, not fixed inline)

  • git merge * on implement.md is a milder case of the same pattern (config=ask, agent=deny). Not reported, left out of this PR for focus.
  • Core agent.ts:293 merge-order asymmetry (user-defined agents override config; native agents do not) is an upstream concern, intentionally not patched here per the profile's "prefer profile over core runtime" rule.
  • local:check has 2 pre-existing failures unrelated to this change: OpenRouter catalog freshness (qwen/qwen3.8-max not yet whitelisted) and the entrypoint_guardrails_smoke (manual opencode debug info is clean).

Closes #292

#292)

The default primary agent (implement) declared "gh pr merge *": "deny" in its
frontmatter. agent.ts merges a user-defined agent's permission AFTER the user
config and Permission.evaluate is last-wins, so the deny overrode the explicit
"gh pr merge *": "allow" in opencode.json — silently blocking the main session
from merging despite the config granting it (pattern I over-restriction).

Remove the only primary-agent deny that contradicts a config allow. Specialized
primary agents (planner) keep their intentional read-only denies. Add real-file
regression tests (the prior mirror fixture missed this because it evaluated
implement.md in isolation, not the merged effective ruleset): the effective
permission now allows gh pr merge, the falsifiable deny case still blocks,
destructive denies (rm -rf / force-push / reset --hard) still hold, and planner
may still self-restrict.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

The following comment was made by an LLM, it may be inaccurate:

@terisuke
terisuke merged commit 7676bbf into dev Aug 4, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant