Skip to content

fix(harness): single-flight pinned whip install + consolidate the patch into whip-binary.ts - #57

Merged
anish-inf merged 2 commits into
context-labs:mainfrom
anish-inf:fix-whip-singalflight
Sep 25, 2026
Merged

anish-inf merged 2 commits into
context-labs:mainfrom
anish-inf:fix-whip-singalflight

Conversation

@anish-inf

@anish-inf anish-inf commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #54/#55/#56: the merged single-process staging still failed on cold runners (monorepo run 36179981281): reviewers ran concurrently inside one loupe process, all shared one PID, so #55's "per-process" staging path whip.download-${process.pid} was actually one shared file — four simultaneous curls, the winner renamed first, the losers hit ENOENT and resolved null → "CLI is not installed" (migrations/code/zdr at ms 21.888–21.974; docs won and completed at 23.715). Reruns passed because the winner's binary became the cache hit.

Two changes in this PR:

1. Single-flight + safe fallback (fixes the race)

  • installPinnedWhip memoizes the in-flight promise — all concurrent reviewers in one process await a single download; the memo clears on completion/failure so nothing caches an error.
  • Each attempt stages in a unique mkdtempSync dir (same-process and cross-process safe) and renames atomically into ~/.loupe/bin/whip.
  • Every failure path re-checks dest: if a concurrent winner already installed a complete binary, return it instead of null — even a losing racer never reports "not installed" again.

2. One home for the patch logic (refactor)
The identity check, pinned download, staging, single-flight, and resolution grew across three PRs inside index.ts. Now all of it lives in packages/harness/src/whip-binary.ts as one focused module — PINNED_WHIP_TAG, isGenuineWhipOnPath, installPinnedWhip, and a single entry point resolveWhipBinary(logger) — which index.ts's whip harness imports and calls in exactly two places (available(), review()). Future changes (bumping the pin, adopting whipcode v1+) are one-file edits.

Verified: oxfmt --check, oxlint, tsc --build clean; 484/484 tests passing.


Note

Medium Risk
Changes how the whip CLI is downloaded and resolved on CI runners; bugs could still break concurrent reviews or leave a bad cache, but scope is isolated to harness whip fallback logic.

Overview
Fixes a cold-runner race when several whip reviewers start at once inside one loupe process: concurrent pinned installs no longer share one staging file and falsely report the CLI missing.

Single-flight install memoizes installPinnedWhip so parallel callers await one download; the memo clears when that attempt finishes or fails. Staging moves to a unique mkdtemp directory per attempt (instead of whip.download-${pid}), with atomic rename into ~/.loupe/bin/whip. Failed curls/renames re-check the cache path and return an already-installed binary when another attempt won.

Refactor: identity check, pin tag, download, and resolveWhipBinary move out of index.ts into whip-binary.ts; the whip harness only imports resolveWhipBinary for available() and review(). The “using pinned release” info log runs inside resolveWhipBinary rather than in the harness body.

Reviewed by Cursor Bugbot for commit adb6bb8. Bugbot is set up for automated code reviews on this repo. Configure here.

@anish-inf anish-inf changed the title fix(harness): single-flight the pinned whip install (concurrent reviewers raced one staging path) fix(harness): single-flight pinned whip install + consolidate the patch into whip-binary.ts Sep 25, 2026
@anish-inf
anish-inf merged commit d031b78 into context-labs:main Sep 25, 2026
3 checks passed
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