Real Git-invoked Pre-push Hook Integration Tests

Claude Code·Soph·2mo ago·50hr 20min·8 Checkpoints·18 file changes·+417/-78·653.5K tokens

A session-scoped Stop hook is now active with condition: "Can you take a look at the repo and the existing e2e tests targeting individual agents. What we are missing is tests that handle upstream git resolution properly and cover various talking to git remotes. Can you gather data, also look at earlier PRs / bugfixes and develop a test plan so we have proper coverage for git operations for both storage backends". Briefly acknowledge the goal, then immediately start (or continue) working toward it — treat the condition itself as your directive and do not pause to ask the user what to do. The hook will block stopping until the condition holds. It auto-clears once the condition is met — do not tell the user to run /goal clear after success; that's only for clearing a goal early.

2mo ago

A session-scoped Stop hook is now active with condition: "Can you take a look at the repo and the existing e2e tests targeting individual agents. What we are missing is tests that handle upstream git resolution properly and cover various talking to git remotes. Can you gather data, also look at earlier PRs / bugfixes and develop a test plan so we have proper coverage for git operations for both storage backends". Briefly acknowledge the goal, then immediately start (or continue) working toward it — treat the condition itself as your directive and do not pause to ask the user what to do. The hook will block stopping until the condition holds. It auto-clears once the condition is met — do not tell the user to run /goal clear after success; that's only for clearing a goal early.

2mo ago·2m

All three research agents are running in the background; the synthesis task is queued behind them. I'll pick up as each report lands and then write the test plan.

2mo ago·18.5s

Marked the inventory task done. Two research agents still running — I'll synthesize the test plan as soon as their reports arrive.

2mo ago·15.0s

Waiting on the final research agent (PR/bugfix history) before writing the test plan.

2mo ago·3m

Done — I gathered data from three angles (existing test inventory, production remote code paths, and PR/bugfix history) and delivered the full test plan as a document above. The TLDR:

The two biggest structural gaps:

  1. The real pre-push hook is never asserted end-to-end. Integration tests invoke entire hooks git pre-push with nil stdin (real git feeds refspec lines), and GitPush in the test env always passes --no-verify. E2E pushes do run the installed hook, but every remote-flavored e2e test then calls PushCheckpointRefs explicitly — so a completely broken hook would still pass the suite.
  2. Integration tests have zero git-refs parameterization. The e2e suite has the E2E_CHECKPOINT_STORE axis, but the entire remote-operations integration surface (bare-remote pre-push, HTTPS/token, divergence recovery, clone+resume) runs only against git-branch. The git-refs push queue, fast-forward-only batch push, and fetch-and-replay recovery are covered only by strategy unit tests — and the single hook-driven e2e test (TestAlternates) skips under git-refs.

Other notable gaps: the read/fetch side hardcodes origin everywhere while the push side follows the hook's $1 remote (a push to upstream strands checkpoints where no read will find them — untested and arguably a product bug); OPF pre-push rewrite has no integration/e2e coverage at all; no worktree+remote tests despite the git-refs queue living in the shared common dir; and three past fixes shipped without tests (no-op-commit tree clobber 743c43f4c, >1000-commit replay cap 4cf01edb3, ls-remote TOCTOU 1e8628ade).

History strongly favors one area: destructive moves of the local entire/checkpoints/v1 ref (ahead/behind/diverged/disconnected × resume/explain/doctor/pre-push) is the most re-broken code in the repo — #953, #1251, #1252, #1260 all patched variants of it. The plan turns that into a systematic table-driven matrix run under both backends.

The plan itself has ~40 test cases in 8 groups (real-hook e2e, remote-name/upstream resolution, cross-machine clone flows, divergence matrix, OPF, degraded remotes, e2e additions, explicit non-goals like real sshd), each tagged with layer, backend, and the past bug it regresses. It leads with infrastructure enablers — an integration backend matrix (ENTIRE_CHECKPOINTS_PRIMARY on TestEnv), a GitPushWithHooks helper, realistic hook stdin, and a hermeticity tripwire (tests have previously hit live github.com and the macOS keychain) — and sequences the work as 5 PRs, with the first three carrying most of the risk reduction. It also flags three product decisions to make before pinning behavior: non-origin reads, git-refs queue clearing with multiple remotes, and the GHE/forge-map story.

ok, can you do a new branch and start implementing this, let's switch to opus for the implementation. Do meaningful commits.

2mo ago·3m

Worktrees live as siblings here (cli_experiments*). I'll create a fresh one for this work.

don't do a worktree, the current folder is clean now, you can just do a fresh branch of main

2mo ago·2m

Setup is done and implementation is underway:

  • Branch: soph/git-remote-test-coverage, cut from current main, checked out in this folder. First commit is the test plan itself at docs/testing/git-remote-test-plan.md so reviewers have the context.
  • Implementation: an Opus dev agent is now building the PR 1 infrastructure from the plan, as three meaningful commits:
    1. I-1 — integration-test backend matrix (ENTIRE_CHECKPOINTS_PRIMARY injection + ForEachBackend), wiring the remote-touching suites (remote_operations, http_remote, explain fetch-on-miss, diverged replay) under both backends with backend-aware assertions.
    2. I-2 — real-hook push helpers: GitPushWithHooks (no --no-verify), realistic stdin for RunPrePush, an e2e AssertCheckpointsOnRemote helper, plus a smoke test proving a plain git push alone lands checkpoints on a bare remote under both backends — the first real coverage of the installed hook.
    3. I-4 — hermeticity tripwire in the integration TestMain so no test can silently dial github.com or trigger keychain prompts again.

The agent is under instructions to verify each commit with mise run fmt && lint, the integration suite, and the vogon canary under both E2E_CHECKPOINT_STORE values — and, importantly, if running the existing suites under git-refs surfaces genuine production bugs, to mark them as explicit KNOWN BUG skips rather than papering over them. I'll report the commits, test results, and any surfaced bugs when it finishes.

2mo ago·2m

Status update:

PR 1 (infrastructure) is committed on soph/git-remote-test-coverage:

  • 2db474807 — integration checkpoint-backend matrix: TestEnv gets a CheckpointStore field injected into every spawned CLI and git hook process, ForEachBackend helper, backend-aware remote/local checkpoint assertions, and the remote-touching suites (pre-push, graceful degradation, HTTPS/token, explain fetch-on-miss) now run under both backends.
  • 12bd0500b — real-hook push helpers: GitPushWithHooks (no --no-verify), RunPrePush now feeds realistic stdin refspecs, plus the first-ever test proving a plain git push alone lands checkpoints on a bare remote under both backends, and an e2e AssertCheckpointsOnRemote helper.
  • aec192cfa — hermeticity tripwire: integration tests route github.com/gitlab.com HTTPS through a dead loopback proxy (an insteadOf rewrite broke forge detection in the trail tests, so it blocks at transport level instead), with a self-test proving external hosts fail in ~20ms instead of hitting the network or keychain.

All verified: lint clean, 414 integration tests green, vogon canary green under both E2E_CHECKPOINT_STORE values.

One real bug surfaced already: under git-refs, staging files after the stop hook produces no per-checkpoint ref at all (git-branch checkpoints fine in the same flow; only the v1 session-metadata branch updates). It's pinned with a KNOWN BUG skip in the graceful-degradation test.

Now running in parallel: an Opus agent implementing PR 2 (the P0 test cases — real-hook A-group, cross-machine clone C-group, and converting the remote e2e tests to rely on the real hook instead of explicit PushCheckpointRefs), and a second read-only Opus agent root-causing the git-refs missing-ref bug so we know whether it needs a production fix before the divergence-matrix tests (D-group). I'll report when they finish.

2mo ago·31.9s

Queued the test fix to apply once the PR 2 agent finishes (it owns those files right now). Waiting on its completion report.

2mo ago·8m

Integration suite running in the background. I'll wait for it, then run the canary under both backends and commit the two fixes.

2mo ago·29.0s

Canary running. I'll commit once it's green.

2mo ago·3m

PR 3 (divergence & recovery matrix) is now being implemented by an Opus agent: the systematic v1 local-ref state matrix (ahead/behind/diverged/disconnected/missing × resume/explain/pre-push/doctor), the three past fixes that shipped without tests (no-op replay tree clobber, >1000-commit replay, ls-remote TOCTOU), git-refs divergence/concurrency at integration level, multi-worktree shared-queue behavior, and a pinning test for the known two-remote queue-clearing gap. I'll report when it lands.

2mo ago·2m

Memory saved. PR 5 (OPF integration tests, degraded-remote/protocol edges, shallow/partial clones, e2e worktree + doctor scenarios) is running with Opus — I'll report when it completes. After that, the only remaining plan item is the B-group (non-origin/upstream pinning), which is waiting on your call on decision D-1: should checkpoint reads learn to follow the checkpoint-bearing remote (e.g. the last push target or the branch's configured upstream), or stay documented as origin-only with a warning on non-origin pushes?

2mo ago·1m

The test plan implementation is complete. The branch soph/git-remote-test-coverage now has 15 commits, all verified (457 integration tests passing, zero skips; vogon canary 61+4 green under both E2E_CHECKPOINT_STORE values; lint clean throughout; not pushed).

What landed, in order:

  1. Plan (816674ca1) — the gap analysis and coverage map, committed as docs/testing/git-remote-test-plan.md and now stamped with implementation status.
  2. Infrastructure (3 commits) — integration-test backend matrix (ForEachBackend running suites under both git-branch and git-refs), real-hook push helpers (GitPushWithHooks, realistic pre-push stdin), and a hermeticity tripwire blocking accidental live github.com access.
  3. P0 tests (3 commits) — the real pre-push hook finally asserted end-to-end (plain git push must land checkpoints, no explicit sync), cross-machine clone/fetch flows including git-refs on-demand exact-ref fetching, and the remote e2e tests converted to depend on the real hook.
  4. Two fixes — the "git-refs missing checkpoint" turned out to be a test false-positive (git-branch was passing on clone-inherited data), and a real production fix: explain's git-refs fallback no longer masks fetch failures as "checkpoint not found".
  5. Divergence matrix (3 commits) — the historically most re-broken area systematized: v1 ahead/behind/diverged/disconnected × pre-push/explain/doctor, replay-fidelity edges, git-refs fetch-and-replay recovery, concurrent pushers, and multi-worktree shared-queue semantics.
  6. OPF, degraded remotes, shallow/partial clones, e2e (4 commits) — OPF rewrite over a real remote (happy path, divergence abort, CAS, bootstrap cap, non-TTY), GH013 protected-branch banner, push-budget bounds, policy-block under git-refs, detached HEAD (works — no bug), --depth=1 and --filter=blob:none user clones, and e2e worktree-push-clone-resume plus doctor-vs-dead-remote.

Three things need your decision before the rest can proceed:

  • D-1 (blocks the B-group tests): pushes follow the hook's remote argument, but every read path hardcodes origin — should reads follow the checkpoint-bearing remote, or is origin-only the supported contract?
  • D-2: the git-refs push queue is drained by a push to any remote, so a second remote never receives those refs — pinned by a flip-when-fixed test.
  • The >1000-commit replay cap: the historical fix (4cf01edb3) was never merged — it's stranded on origin/no-limit — so a valid push still hard-fails past 1000 local-only metadata commits. Also pinned.

The branch is ready for review as-is, or I can split it into the stacked PRs the plan suggests — say the word.

let's do stacked PRs, can you open issues for d1+d2

2mo ago·7m

Done — the stack is up:

Stacked PRs (each based on the previous; retarget to main as parents merge):

  1. #1636 — test plan + infrastructure: integration backend matrix, real-hook push helpers, hermeticity tripwire (base: main)
  2. #1637 — P0 real-hook A-group + cross-machine C-group tests, the graceful-degradation test fix, and the explain fetch-error production fix
  3. #1638 — divergence & recovery matrix (v1 state matrix, replay-fidelity guards, git-refs divergence/concurrency, queue semantics)
  4. #1639 — OPF pre-push over a real remote, degraded remotes, shallow/partial clones, e2e worktree + doctor scenarios

Issues:

  • #1634 — decision D-1: reads hardcode origin while pushes follow the hook remote (with the file:line evidence, both resolution options, and a note that the B-group tests are blocked on it)
  • #1635 — decision D-2: the git-refs push queue is drained by the first successful push, starving a second remote (references the pinned test and sketches three fix options, cross-linked to #1634)

One loose end you may want a third issue for: the >1000-commit replay cap — the historical fix (4cf01edb3) was never merged and sits on the abandoned origin/no-limit branch, so a valid push still hard-fails past 1000 local-only metadata commits. It's mentioned in #1638/#1639 and pinned by a test, but has no dedicated issue. Want me to open one?

can you go through the copilot/bugbot review comments on the PR

2mo ago·24m

All 7 replies posted. Waiting on the full verification run (integration + both-backend canary) on the merged tip before calling it done.