fix: stop the pre-push tracker-leak check hanging on stdin

AN
1d ago
+48-11

Issue for this PR

Closes #1574

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

git push sometimes hung forever in the pre-push hook's tracker-leak check, so people had to bypass it with SKIP_TRACKER_CHECK=1.

What we know: one push stayed stuck for eight days (macOS, git 2.42, over ssh). In that push:

  • git was in wait4, waiting for the hook.
  • bun script/check-tracker-leaks.ts sat idle in its event loop (kevent) with no child process.
  • Its stdin pipe's writer was already closed: lsof showed no peer.

The script was awaiting something that had already finished: either the stdin stream (Bun.stdin.stream()) or a Bun.$ git call. The stuck process can't tell us which.

The fix: remove both waits.

  • stdin is read with a blocking readFileSync(0, "utf-8").
  • git() runs with Bun.spawnSync, with no stdin.

The script no longer waits on the event loop at all. Behaviour is otherwise unchanged: the TTY guard, the HEAD fallback when there is no input, deletion-only handling, and the fail-loud exit on unexpected git errors.

The hang never reproduced on demand, so there is no before/after reproduction.

How did you verify your code works?

  • New test in tracker-leak-check.test.ts: a real git push through a pre-push hook to a local bare repo. A clean ref pushes, and a leaky ref that isn't HEAD is rejected. This guards the stdin contract end to end. It passes on the old code too, so it is not a reproduction of the hang.
  • Tests: bun test test/skill/tracker-leak-check.test.ts gives 35 pass.
  • Same results as before: old and new scripts give byte-identical output on a 3,174-file, 596k-line diff (0.8 s).
  • Hook order: the hook's earlier steps (bun -e, bun typecheck) leave git's stdin unread.
  • Real pushes: both commits went to GitHub over ssh through the real husky hook, without the skip flag. Each took 12 s.
  • Reviews: Codex (gpt-6.1-sol) reviewed 0d0df4dc74 and found nothing. A second independent review pointed out that the root cause was unproven and that the test doesn't reproduce the hang; both are addressed in 4cd57d0c2f.

Cost side effects

None.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR
  • I checked for cost side effects (model calls, queries or cloud resources that grow with user data) and described them, or wrote "none"

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • The pre-push scan checks the refs being pushed, so branches containing tracker references are rejected even when the current checkout is clean. Clean pushes continue to succeed, and rejected pushes report the detected reference.
  • Tests
    • Added coverage for clean and tracker-containing pushes using a local Git repository, including the case where the pushed branch differs from the current checkout.