Auto-mode classifier blocks gh pr merge inconsistently, including harmless --help

Status Open
Maintainer reply None cached
Activity 0 comments · opened Sep 3, 2026

Description

While running the ship-issue skill (which drives a GitHub issue through implement → PR → merge → deploy end-to-end) in Auto mode, the auto-mode permission classifier blocked gh pr merge — and, once blocked, continued blocking further attempts to even inspect the command, including a plain gh pr merge --help call with no side effects at all.

Steps to reproduce

  1. In an "Auto mode active" session (bias toward proceeding without stopping for clarifying questions), inside a git worktree checkout, open and get a PR to all-green required checks.
  2. Run gh pr merge <PR#> --squash --delete-branch.
  3. Observe the tool call is denied by the classifier:

> Permission for this action was denied by the Claude Code auto mode classifier. Reason: Blocked by classifier. ...

  1. After asking the user for confirmation and getting an explicit "retry" instruction, run the same command again. This time it fails for an unrelated, legitimate reason (a git worktree conflict — fatal: 'main' is already used by worktree at '<primary checkout path>'), not a permission denial. So the classifier isn't consistently blocking it either.
  2. Try an alternate route to accomplish the same explicitly-user-approved merge without the local worktree conflict: gh api repos/<owner>/<repo>/pulls/<PR#>/merge -X PUT -f merge_method=squash -f sha=<headRefOid>. This is blocked by the classifier again.
  3. Try a fully read-only, no-side-effect sanity check: gh pr merge --help. This is also blocked by the classifier, with the same generic "Blocked by classifier" message.

Expected behavior

  • gh pr merge on a PR with all required checks green and no pending reviews is a normal, expected action for an end-to-end "ship this issue" workflow that the user has explicitly asked to run — it shouldn't be denied outright without at least a specific, actionable reason (e.g. "this looks like a force-merge" or "branch protection would be bypassed") rather than a generic "Blocked by classifier."
  • A read-only --help invocation of a CLI subcommand should never be blocked by an action-safety classifier — it has no side effects to guard against.
  • The classifier's behavior should be consistent for the identical command run twice in a row (denied, then not denied but failing on an unrelated git error) — if the first denial was a hard "no" for this action/session, subsequent identical attempts should behave the same, not silently pass through to a different failure mode.

Actual behavior

  • gh pr merge was denied with no specific reason beyond "Blocked by classifier."
  • A retried, identical gh pr merge invocation was not re-blocked — it proceeded to actually attempt the merge and failed on a real git error instead, suggesting the block wasn't durable/consistent.
  • A different but equivalent merge path (gh api .../merge -X PUT) was blocked again.
  • A harmless gh pr merge --help was also blocked, which shouldn't trigger an action-safety classifier at all since it performs no action.

Impact

This broke an otherwise fully green, user-approved automated ship workflow at the very last step (merging a PR with all required checks passing), with no actionable path forward other than asking the user to do it manually — even after the user had already granted explicit approval to retry.

Environment

  • Claude Code running via the Claude desktop app (Code tab), Auto mode.
  • Running inside a git worktree (a secondary checkout, e.g. under .claude/worktrees/<name>), which is what triggered the unrelated fatal: 'main' is already used by worktree failure on the merge itself (a separate, real issue from the classifier one, but worth noting since it may be a scenario the classifier hasn't been tuned against, e.g. mistaking a worktree-related git failure for something riskier).
  • gh CLI authenticated, PR had all required checks (backend-test, frontend-test, validate) green and zero pending reviews at the time of the merge attempt.

View original on GitHub ↗