feat(gitflow): manual-push mode honoured by the lib, quiet unpushed-guard

`gitflow.autopush false` (human-set git config) now means "nothing is
pushed" end to end, not only in the post-commit/post-merge hooks:

- lib/gitflow.sh: `_gitflow_push_off` is the single reader of
  GITFLOW_NO_PUSH / gitflow.autopush for the lib's push sites; `start`
  and `finish` stop pushing in manual mode. `gitflow_delete` checks out
  the base that contains the branch and drops a lagging upstream before
  `git branch -d` (LRN-161: `-d` judges against the upstream when set).
  Skipped remote deletes say `left in place`; `_gitflow_sync_base`
  replaces the silent `pull --ff-only || true` and warns when a base is
  behind origin and cannot fast-forward.
- hooks/unpushed-guard.sh: manual mode is silent at Stop and gives one
  `ℹ manual push mode:` line at SessionStart counting every local
  branch; an unparseable value is named and treated as auto.
- CLAUDE.global.md: manual-push mode doctrine, "ahead = defect" scoped
  to auto mode.
- Tests: gitflow-test T18m block (T18m0, T18i-T18o, 7 cases),
  unpushed-guard T10-T16.

Follow-ups (TODO.md): run B push-guard hook + settings deny widening +
banner; run C skills that push on their own (/close STEP 5C, …).
Do not enable manual mode on the work machine before B and C land.
This commit is contained in:
bchanot
2026-10-06 17:49:20 +02:00
parent fa67664bac
commit 2fc88304ac
5 changed files with 172 additions and 11 deletions
+38
View File
@@ -38,4 +38,42 @@ check T8-dirty-start-reported "$(has "$(fire SessionStart "$PWD")" "uncommitted"
out=$(jq -n --arg d "$PWD" '{hook_event_name:"SessionStart", cwd:$d}' | bash "$H" 2>/dev/null)
check T9-start-adds-context "$(printf '%s' "$out" | jq -r '.hookSpecificOutput.hookEventName')" SessionStart
# ── manual-push mode (gitflow.autopush=false) ──
git checkout -q -- a
git config gitflow.autopush false
check T10-manual-clean-start "$(fire SessionStart "$PWD")" silent
check T10-manual-clean-stop "$(fire Stop "$PWD")" silent
echo m>m; git add m; git commit -q -m m
git branch side HEAD; git checkout -q side; echo s>s; git add s; git commit -q -m s
git checkout -q -
check T11-manual-stop-silent "$(fire Stop "$PWD")" silent
out=$(fire SessionStart "$PWD")
check T11-manual-info "$(has "$out" "manual push mode")" yes
check T11-manual-count "$(has "$out" "2 commit(s)")" yes
check T11-manual-lists-branch "$(has "$out" "side")" yes
check T11-manual-no-warning "$(has "$out" "unpushed work")" no
git checkout -q -b fresh
check T12-fresh-branch-repo-wide "$(has "$(fire SessionStart "$PWD")" "2 commit(s)")" yes
git checkout -q -
git push -q origin HEAD side 2>/dev/null; echo d>>a
out=$(fire SessionStart "$PWD")
check T13-dirty-info "$(has "$out" "manual push mode")" yes
check T13-dirty-uncommitted "$(has "$out" "uncommitted")" yes
check T13-dirty-no-commit-clause "$(has "$out" "commit(s) not on origin")" no
check T13-dirty-stop-silent "$(fire Stop "$PWD")" silent
git checkout -q -- a
git config gitflow.autopush flase
echo i>i; git add i; git commit -q -m i
out=$(fire SessionStart "$PWD")
check T14-invalid-named "$(has "$out" "not a boolean")" yes
check T14-invalid-treated-auto "$(has "$out" "unpushed work")" yes
check T14-invalid-stop-auto "$(has "$(fire Stop "$PWD")" "1 commit(s)")" yes
git config --unset gitflow.autopush
check T15-unset-auto-intact "$(has "$(fire Stop "$PWD")" "1 commit(s)")" yes
git config gitflow.autopush false; git remote remove origin
out=$(fire SessionStart "$PWD")
check T16-no-origin-manual "$(has "$out" "manual push mode")" yes
check T16-no-origin-clause "$(has "$out" "no 'origin' remote")" yes
check T16-no-origin-stop-silent "$(fire Stop "$PWD")" silent
printf 'PASS=%s FAIL=%s\n' "$pass" "$fail"; [ "$fail" -eq 0 ]