Skip to content

docs: document BLOCKED_BY_PERMISSION for merge-skill callers - #230

Merged
schmug merged 1 commit into
mainfrom
claude/issue-228-blocked-by-permission
Sep 14, 2026
Merged

schmug merged 1 commit into
mainfrom
claude/issue-228-blocked-by-permission

Conversation

@schmug

@schmug schmug commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • A Workflow(...) call to merge-pr-with-gate, stacked-merge-walk, or factory-land can be denied by Claude Code's auto-mode permission classifier before the script body ever runs — so no workflow's status/outcome schema can represent the denial, and this repo cannot make the tool call itself reach the script. The fix has to live in the skill prose that instructs the invoking agent, not in workflow-script logic.
  • skills/merge-pr-with-gate/SKILL.md, skills/stacked-merge-walk/SKILL.md, and skills/factory-land/SKILL.md each document a BLOCKED_BY_PERMISSION reporting convention: recognize a classifier denial (observed denial text [Git Destructive] / Blocked by classifier), report it distinctly from a gate verdict (STAGED/ESCALATED/MERGED/LANDED), and never fall back to an unmediated gh pr merge to route around it.
  • skills/critic-gated-build/SKILL.md gets the same handling for its own landing step, which merges via a direct gh pr merge rather than a nested Workflow() call, so the guidance there is phrased generically (either mechanism) rather than citing the Workflow-call denial text specifically.
  • README.md "Residual risk (out of scope here)" gets one paragraph cross-referencing this — the classifier is upstream product behavior this repo doesn't control, same framing already used there for the Workflow runtime itself.

Closes #228

Test plan

  • npm test — 1230 passing, 0 failing (31 suites; docs-only change, so this confirms plugin-integrity.test.mjs's README/SKILL.md invariants — 1:1 workflow↔skill mapping, wrapper shape, no pinned test total — still hold and nothing else regressed).

Choices made

  • Where the fix lives. The issue's Reproduction shows the classifier denying Workflow(...) calls outright, before the script's AsyncFunction body executes — confirmed by re-reading merge-pr-with-gate.js/stacked-merge-walk.js's own status enums (STAGED/ESCALATED/MERGED/LANDED/FAILED), none of which the script can ever populate for a call it never received. So BLOCKED_BY_PERMISSION is documented as a reporting convention for the calling agent (in the four SKILL.md files the issue itself pointed at), not as a new value in any workflow's output schema — there's no schema to add it to.
  • critic-gated-build phrased generically, not with the specific denial-text substrings. Its landing step (Phase 1: "CI green → squash merge") is a direct gh pr merge, not a nested call to merge-pr-with-gate/stacked-merge-walk — so the two denial strings observed in Auto-mode classifier blocks every merge path, including the unattended-safe one #228 (which were specifically about Workflow(...) tool-call denials) may not be what a Bash-tool gh pr merge denial looks like. Rather than assert a pattern I have no evidence for, that skill's guidance covers "a merge/landing action denied by the permission system" generically, covering both mechanisms.
  • Auto-merge left on — this diff touches only README.md and four SKILL.md files: no plugin.json, no .claude-plugin/, and no workflow injection-hardening code (no .claude/workflows/*.js files changed at all), so it's within the repo's stated auto-merge policy for ordinary changes that pass npm test.

Deferred

  • Acceptance criteria 1 and 5 — the controlled measurement of the classifier's actual discriminator (varying approval/execute/scriptPath/args.repo one at a time, including a claude -p non-interactive run) — could not be performed by this automated session: it requires live experimentation across permission configurations in the environment that produced the original observation (Claude Code desktop, permissions.defaultMode: "auto"), which this session has no means to fork or vary, and Auto-mode classifier blocks every merge path, including the unattended-safe one #228's own constraints forbid editing ~/.claude/settings.json as part of the fix. Filed as follow-up issue Measure the auto-mode classifier's actual discriminator for merge-skill Workflow calls #229, which will also correct the denial-text substrings and the "approval is the discriminator" assumption documented here if the actual measurement contradicts them.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UptYu2GqTnLk5eYHVD9Njv


Generated by Claude Code

A Workflow(...) call to merge-pr-with-gate/stacked-merge-walk/factory-land
can be denied by Claude Code's auto-mode permission classifier before the
script body ever runs, so no workflow status/outcome schema can represent
it. Document a BLOCKED_BY_PERMISSION reporting convention in each affected
skill (plus critic-gated-build, whose landing step is a direct `gh pr
merge`) so a caller can recognize and report a permission denial distinctly
from a gate verdict, instead of treating it as an ordinary tool failure or
reaching for an unmediated gh pr merge fallback.

The controlled measurement of the classifier's actual discriminator
(acceptance criteria 1 and 5) needs live experimentation across permission
configs in the environment that produced the original observation, which
this session cannot perform — filed as a follow-up issue.

Closes #228

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UptYu2GqTnLk5eYHVD9Njv
@schmug
schmug enabled auto-merge (squash) September 14, 2026 12:01
@schmug
schmug merged commit d738e7f into main Sep 14, 2026
5 of 6 checks passed
@schmug
schmug deleted the claude/issue-228-blocked-by-permission branch September 14, 2026 12:02

schmug commented Sep 14, 2026

Copy link
Copy Markdown
Owner Author

Failing check: github-advanced-security (GitHub's Copilot-based ghas-code-scanning-agentic autofind check on this PR's head, fef0b31).

Not this PR's failure. The job log shows it never reached this diff's content — it fails during session setup with SessionModelError: Execution failed: CAPIError: 400 The requested model is not supported (claude-opus-5[ReasoningEffort=medium] rejected by GitHub's own Copilot backend before any file is analyzed). This PR changes 5 Markdown files only (README.md + 4 SKILL.md wrappers) — nothing in the diff can trigger a model-routing error in GitHub's scanning backend. No fix exists in this repo to port; the failure is entirely inside GitHub's Copilot code-scanning service.

I attempted the one permitted re-run (rerun_failed_jobs on the run) to rule out a transient backend hiccup, but the API refused it: 403 This workflow run cannot be retried — this run type isn't retriable through the API available to me. Per this repo's constraints, CI/CD config and branch protection are off-limits from a code PR, so I'm not otherwise touching anything here. Leaving the PR watched; auto-merge is enabled and will proceed once the required test (Node 20)/test (Node 22) checks are green (already passing) and this check is not blocking, or GitHub's own retry of the underlying service clears it.


Generated by Claude Code

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.

Auto-mode classifier blocks every merge path, including the unattended-safe one

2 participants