keeper: finish-flow-guard — refuse an inferred pr flow in an unattended run - #7
Open
bjones84arrow wants to merge 1 commit into
Open
keeper: finish-flow-guard — refuse an inferred pr flow in an unattended run#7bjones84arrow wants to merge 1 commit into
pr flow in an unattended run#7bjones84arrow wants to merge 1 commit into
Conversation
…nded run
PreToolUse(Bash) hook that refuses `finish-detect-mode.sh pr` in an unattended
run whose originating invocation never carried a `pr` token.
Evidence — three sessions added `pr` on their own judgment, each citing the same
false reasoning ("every recent issue shipped via PR", which is a product of the
INTERACTIVE convention, so the run reads its own prior output back as proof):
JA-390 2026-08-19 /full auto wt pr from a bare /loop /auto
JA-367 2026-08-20 dispatched `auto JA-367 merge`, ran detection with `pr`
JA-415 2026-08-20 /auto ja-415 -> Skill(full, "auto wt pr JA-415")
Cost is not cosmetic: in pr mode the source branch does not advance until the PR
merges, so the next issue forks without its predecessor's code; `In Review` is a
started-type state, so `blocks` edges never release and dependents stay invisible
to /next and /auto; and SHIPPED-PR leaves the worktree behind.
Prose already lost here once — jarvis CLAUDE.md 448ad05 stated the rule and
JA-415 drifted hours later, because a worktree session reads a CLAUDE.md snapshot
predating the fix, keys a separate memory namespace, and carries its own PR
precedent through compaction. Per fleet-retro doctrine a rule that already
existed and lost gets a mechanical guard, not more prose — precedents:
linear-create-state-guard.sh, no-blind-sleep.sh, auto-heartbeat.sh,
full-continue.sh.
Interactive flows are deliberately untouched: the guard fires only when an `auto`
token is in the dispatch chain, so a hand-typed `/finish pr`, a bare `/finish`
meaning pr by a project convention, and `/loop /auto pr` all pass.
Complements the prose landed upstream as cd7252c (PR alienfast#6 item 26) rather than
replacing it. hooks/finish-flow-guard.test.sh: 19/19 pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
One item. The rest of this machine's local backlog was adjudicated as already-adopted and is being dropped — see Withdrawn below, which is the more useful half of this PR for you.
Included —
finish-flow-guard.shA
PreToolUse(Bash)hook that refusesfinish-detect-mode.sh prin an unattended run whose originating invocation never carried aprtoken.Evidence. Three sessions added
pron their own judgment, each citing the same false reasoning — "every recent issue shipped via PR" — which is a product of the interactive convention, so the run reads its own prior output back as proof:/full auto wt prfrom a bare/loop /autoauto JA-367 merge, then ran detection withpr/auto ja-415→Skill(full, "auto wt pr JA-415")Cost. In
prmode the source branch does not advance until the PR merges, so the next issue forks without its predecessor's code;In Reviewis astarted-type state, soblocksedges never release and dependents stay invisible to/nextand/auto; andSHIPPED-PRleaves the worktree behind.Why a hook and not more prose. Prose already lost here once: jarvis
CLAUDE.md448ad05stated the rule and JA-415 drifted hours later — a worktree session reads aCLAUDE.mdsnapshot predating the fix, keys a separate memory namespace, and carries its own PR precedent through compaction. Per fleet-retro doctrine a rule that already existed and lost gets a mechanical guard. Precedents:linear-create-state-guard.sh,no-blind-sleep.sh,auto-heartbeat.sh,full-continue.sh.This complements
cd7252c(PR #6 item 26) rather than replacing it — that landed the prose; this enforces it.Scope. Interactive flows are deliberately untouched. The guard fires only when an
autotoken is in the dispatch chain, so a hand-typed/finish pr, a bare/finishthat means pr by a project's own convention, and/loop /auto prall pass.Gate.
hooks/finish-flow-guard.test.sh— 19/19 pass, covering both deny cases and 19 allow cases including three fail-open paths.Withdrawn — already adopted upstream
This machine's
~/.claudemain was never reset after PR #6 was adopted, leaving 21 local commits (19 non-merge). Adjudicated:JA-283 297 314 319 323 334 336 339 342 345 347 348 353 355 356 364 366 373 401 422 428— several under slash shorthand (JA-319/345/353,JA-334/347/366). The twofix(scripts)commits matchc8e46d9(PR keeper: drain the queue — 21 issues, 24 config improvements #6 item 25) and175035d(PR keeper: drain the queue — 21 issues, 24 config improvements #6 item 24).da1f606matches028ab3a's ride-alongs.git cherryreports them patch-identical.local: settings(model, key ordering). Only itsfinish-flow-guardhook registration is carried here.b7218d5, which un-blocked baregit switch <branch>, reversing22c30bf. Its stated premise ("switch refuses when the move would overwrite local changes") does not hold:git switchrefuses only when the move would overwrite differing files, and silently carries cleanly-applying uncommitted work onto the target branch — exactly the hazard22c30bfguards. The deny is also not absolute; it permits proceeding with explicit approval. Upstream's block is correct and stays.Local main is being reset to a pure clone of
origin/mainwith a rescue branch left behind.