Filing a bug against a third-party project was refused outright because the command
carried no --label. The label it wanted belongs to this repo's vocabulary, and
the enforcer had no way to know it was pointing at someone else's. The milestone enforcer, in the
same breath, suggested assigning the foreign issue to one of our sprints.
$ gh issue create --repo herdrdev/herdr --title "..." --body-file ... BLOCKED: Missing --label flag. Add a label to categorize this issue: --label bug / enhancement / chore / docs [gh-milestone-enforcer] No --milestone set. Consider assigning to a milestone.
Both are pure flag parsers with no network and no file I/O, which is what keeps them inside the
50ms PreToolUse budget. That same property means they cannot check whether the target repo has a
bug label at all. Enforcing anyway ranges from noise (our sprint milestones) to
hard breakage: gh exits non-zero when a label does not exist
there, so "helpfully" appending one would turn a nit into a failed command.
A missing label is auto-correctable. A PreToolUse deny is not a nudge, it aborts
before execution and costs the whole turn. CC 2.1.25 updatedInput exists precisely so a
hook can fix the command instead of rejecting it.
| command | label hook | milestone hook |
|---|---|---|
gh issue create --title "Fix crash" | rewrite: append --label bug | advisory |
... --title "Update README typos" | rewrite: --label docs | advisory |
... --title "Weekly dep sweep" | rewrite: --label chore | advisory |
... --repo other/repo ... | skip entirely | skip entirely |
GH_REPO=other/repo gh issue create | skip entirely | skip entirely |
cat > f <<EOF ... EOF && gh issue create | advisory only | advisory |
Inference is title-driven and ordered,
so docs outranks bug and "fix typo in README" lands as docs
rather than a bug report. Unmatched titles get chore, the one label every governed repo
in this estate defines.
Appending --label to A && B && C cannot target the right
segment without a real shell parser, and denying a compound discards the segments that already
matter, which is the original #3283 report. So compounds keep the advisory and nothing is rewritten.
The result sets updatedInput and additionalContext but deliberately no
permissionDecision. Returning 'allow' would skip the permission prompt as a
side effect of a labelling nit, which is a strictly worse trade than the deny it replaced. A test
pins permissionDecision as undefined.
gh-label + gh-milestone + sync-bash-dispatcher 86 passed, 0 failed
full hook unit suite 7559 passed, 2 skipped, 6 failed <- all in context-gate, pre-existing
reproduced identically at origin/main in a 2nd worktree, filed as #3391
tsc --noEmit clean
One thing checked before building the auto-correct, because the milestone this lands
in exists to stop exactly this: sync-bash-dispatcher genuinely propagates a single
hook's updatedInput (collected at :197, merged at :112-135). Had it dropped the field
the way it once dropped ask-tier decisions, the rewrite would have been another no-op that reads as a
working feature, which is the #3386 shape this repo is currently paying down.