docs: document BLOCKED_BY_PERMISSION for merge-skill callers - #230
Conversation
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
|
Failing check: Not this PR's failure. The job log shows it never reached this diff's content — it fails during session setup with I attempted the one permitted re-run ( Generated by Claude Code |
Summary
Workflow(...)call tomerge-pr-with-gate,stacked-merge-walk, orfactory-landcan be denied by Claude Code's auto-mode permission classifier before the script body ever runs — so no workflow'sstatus/outcomeschema 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, andskills/factory-land/SKILL.mdeach document aBLOCKED_BY_PERMISSIONreporting 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 unmediatedgh pr mergeto route around it.skills/critic-gated-build/SKILL.mdgets the same handling for its own landing step, which merges via a directgh pr mergerather than a nestedWorkflow()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 confirmsplugin-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
Workflow(...)calls outright, before the script'sAsyncFunctionbody executes — confirmed by re-readingmerge-pr-with-gate.js/stacked-merge-walk.js's ownstatusenums (STAGED/ESCALATED/MERGED/LANDED/FAILED), none of which the script can ever populate for a call it never received. SoBLOCKED_BY_PERMISSIONis documented as a reporting convention for the calling agent (in the fourSKILL.mdfiles 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-buildphrased generically, not with the specific denial-text substrings. Its landing step (Phase 1: "CI green → squash merge") is a directgh pr merge, not a nested call tomerge-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 aboutWorkflow(...)tool-call denials) may not be what a Bash-toolgh pr mergedenial 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.README.mdand fourSKILL.mdfiles: noplugin.json, no.claude-plugin/, and no workflow injection-hardening code (no.claude/workflows/*.jsfiles changed at all), so it's within the repo's stated auto-merge policy for ordinary changes that passnpm test.Deferred
claude -pnon-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.jsonas 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