Skip to content

keeper: finish-flow-guard — refuse an inferred pr flow in an unattended run - #7

Open
bjones84arrow wants to merge 1 commit into
alienfast:mainfrom
bjones84arrow:proposal/ja-keeper-backlog
Open

keeper: finish-flow-guard — refuse an inferred pr flow in an unattended run#7
bjones84arrow wants to merge 1 commit into
alienfast:mainfrom
bjones84arrow:proposal/ja-keeper-backlog

Conversation

@bjones84arrow

Copy link
Copy Markdown

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.sh

A 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:

issue date shape
JA-390 2026-08-19 /full auto wt pr from a bare /loop /auto
JA-367 2026-08-20 dispatched auto JA-367 merge, then ran detection with pr
JA-415 2026-08-20 /auto ja-415Skill(full, "auto wt pr JA-415")

Cost. 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.

Why a hook and not more prose. Prose already lost here once: jarvis CLAUDE.md 448ad05 stated the rule and JA-415 drifted hours later — 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. 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 auto token is in the dispatch chain, so a hand-typed /finish pr, a bare /finish that means pr by a project's own convention, and /loop /auto pr all 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 ~/.claude main was never reset after PR #6 was adopted, leaving 21 local commits (19 non-merge). Adjudicated:

  • 16 superseded by upstream rewrites. Every JA number on the local side appears upstream — 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 two fix(scripts) commits match c8e46d9 (PR keeper: drain the queue — 21 issues, 24 config improvements #6 item 25) and 175035d (PR keeper: drain the queue — 21 issues, 24 config improvements #6 item 24). da1f606 matches 028ab3a's ride-alongs.
  • 2 already upstream verbatimgit cherry reports them patch-identical.
  • 1 machine-locallocal: settings (model, key ordering). Only its finish-flow-guard hook registration is carried here.
  • 1 withdrawn on reviewb7218d5, which un-blocked bare git switch <branch>, reversing 22c30bf. Its stated premise ("switch refuses when the move would overwrite local changes") does not hold: git switch refuses only when the move would overwrite differing files, and silently carries cleanly-applying uncommitted work onto the target branch — exactly the hazard 22c30bf guards. 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/main with a rescue branch left behind.

…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.
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.

1 participant