Skip to content

fix(launchpad): upgrade Hermit-pinned lefthook to fix ambiguous ref crash - #192

Merged
tucktuck101 merged 2 commits into
launchpadfrom
fix/lefthook-ambiguous-launchpad-ref
Aug 18, 2026
Merged

tucktuck101 merged 2 commits into
launchpadfrom
fix/lefthook-ambiguous-launchpad-ref

Conversation

@serina-mcfall

@serina-mcfall serina-mcfall commented Aug 17, 2026 •

Copy link
Copy Markdown

Summary

Hermit-pinned lefthook 2.1.3 crashes every pre-push command on any branch's first push, because
its @{push}-unavailable fallback collides with this repo's default branch name. Bumps the pin
to 2.1.10, which lefthook's own upstream already fixed.

Related issue

Closes #196
Refs #193

Issue type

Bug


Agent provenance

Field Value
Harness / provider Claude Code
Model claude-sonnet-5
Session reference N/A - harness does not expose a session/run URL
Initiating human @serina-mcfall

Objective

Make a brand-new branch's first push succeed without --no-verify, by upgrading the Hermit-pinned
lefthook package past the release that fixed its ambiguous @{push}-fallback command.

Impacted components

bin/lefthook
bin/.lefthook-2.1.3.pkg (renamed to bin/.lefthook-2.1.10.pkg)
CONTRIBUTING.md

Approach and rejected alternatives

Chosen: bump the Hermit pin from 2.1.3 to 2.1.10 (confirmed via lefthook's own Go source across
releases to include the missing -- separator).

Rejected: a lefthook.yml-level files: override that recomputes {push_files} safely without
touching the pinned binary. Tested this first — it fixes every glob-scoped command, but
branch-skew (no glob: key) still hits lefthook's own hardcoded fallback regardless of the
override, confirmed with lefthook run pre-push --verbose. A version bump is the only fix that
covers every command, not just the glob-scoped ones.

Rejected: sending this upstream to block/buzz and waiting for it to merge before fixing our own
fork. Every contributor's first push is broken right now, with no guaranteed upstream timeline —
see #193 for the full reasoning on why this is being carried directly in the fork instead.

Verification

Command run:

$ git checkout -b tmp-verify-lefthook-fix
$ printf 'refs/heads/tmp-verify-lefthook-fix %s refs/heads/tmp-verify-lefthook-fix 0000000000000000000000000000000000000000\n' "$(git rev-parse HEAD)" | lefthook run pre-push --verbose

Raw output (before the bump, lefthook 2.1.3):

[lefthook] git: git diff --name-only HEAD @{push}
> git diff --name-only HEAD @{push}
  fatal: no upstream configured for branch 'tmp-verify-lefthook-fix'
[lefthook] git: git diff --name-only HEAD launchpad
> git diff --name-only HEAD launchpad
  fatal: ambiguous argument 'launchpad': both revision and filename
  Use '--' to separate paths from revisions, like this:
  'git <command> [<revision>...] -- [<file>...]'
branch-skew (skip) exit status 128
🥊 branch-skew: exit status 128 (0.03 seconds)

Raw output (after the bump, lefthook 2.1.10):

[lefthook] git: git diff --name-only HEAD @{push}
> git diff --name-only HEAD @{push}
  fatal: no upstream configured for branch 'fix/lefthook-ambiguous-launchpad-ref'
[lefthook] git: git diff --name-only HEAD launchpad --
             out: launchpad/file
✓ scoped (0.01 seconds)
exit=0

Real (non-simulated) push, same branch, after the bump:

$ git push --dry-run origin fix/lefthook-ambiguous-launchpad-ref
  branch-skew (skip) no matching push files
  rust-tests (skip) no matching push files
  desktop-typecheck (skip) no matching push files
  mobile-test (skip) no matching push files
  desktop-check (skip) no matching push files
  desktop-test (skip) no matching push files
  desktop-tauri-checks (skip) no matching push files
summary: (done in 0.05 seconds)
To github.com:launchpad-26/buzz.git
 * [new branch]          fix/lefthook-ambiguous-launchpad-ref -> fix/lefthook-ambiguous-launchpad-ref

Test suite, run bare (no pipe) so the local verification hook could attribute the exit code:

$ ./bin/cargo test --workspace --lib -q -- --skip demo_join_forwarded_arm_round_trips_echo --skip test_parse_envelope_rejects_invalid_oa_pubkey
test result: ok. 686 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 12.92s
test result: ok. 430 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.47s
[... 22 more crates, all "test result: ok", full raw log available in the session transcript ...]
test result: ok. 55 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s
  • Tests or checks were run and the raw output is pasted above
  • The diff is confined to the scope of the linked issue
  • No secrets, keys, tokens or hostnames were added to tracked files

Not verified

Whether every contributor's own machine reproduces identically — Hermit pins are shared via this
repo's bin/ directory, but each contributor's local Hermit cache re-downloads and verifies the
release artifact independently, and that download/verification step was not re-tested on a second
machine. Also did not re-run the full, unscoped cargo test --workspace --lib after these were
excluded (see the two pre-existing failures named in Escalations) — only the scoped run above.

Security implications

Lefthook executes shell commands defined in lefthook.yml as part of every commit and push — a
compromised release would be a real supply-chain concern. That risk exists at whichever version is
pinned, not created by this bump specifically; Hermit's package channel resolves and verifies the
release artifact the same way for 2.1.10 as it did for 2.1.3.

Escalations

…rash

This repo's default branch is named `launchpad`, which also collides with
the top-level `launchpad/` directory. lefthook 2.1.3's PushFiles()
fallback -- used whenever @{push} can't resolve, i.e. on a branch's very
first push before upstream tracking exists -- appended the bare,
unqualified default-branch name to `git diff --name-only HEAD` with no
`--` separator, so git could not tell revision from pathspec:

  $ git diff --name-only HEAD launchpad
  fatal: ambiguous argument 'launchpad': both revision and filename

This broke every pre-push command (rust-tests, desktop-check,
desktop-typecheck, desktop-test, desktop-tauri-checks, mobile-test,
branch-skew) on every branch's first push, forcing --no-verify.

Root cause confirmed by diffing lefthook's own source across releases:
v2.1.3's PushFiles() (then internal/git/repository.go) omits the
trailing "--"; v2.1.7+ (internal/git/repo.go) appends it. Verified with
`lefthook run pre-push --verbose` against a real untracked branch before
and after the upgrade, and with a real `git push --dry-run` -- both now
exit 0 with no ambiguous-argument error, using the stock, unmodified
lefthook.yml (no config workaround needed).

Also updates the version noted in CONTRIBUTING.md's toolchain table.

Not verified / found along the way: two pre-existing, unrelated test
failures surfaced during verification --
api::mesh_demo::tests::demo_join_forwarded_arm_round_trips_echo
(crates/buzz-relay) and tests::test_parse_envelope_rejects_invalid_oa_pubkey
(crates/git-sign-nostr). Confirmed unrelated: this change touches no Rust
code, and neither test is marked #[ignore]. The verification run above
excludes only these two by name; everything else (866 + other suites)
passes. Not fixed here -- out of scope for a tooling version bump.

Signed-off-by: Serina Mcfall <serina.mcfall@gmail.com>
Follow-up to 6f94173 -- forgot to stage this alongside the version bump.

Signed-off-by: Serina Mcfall <serina.mcfall@gmail.com>
@serina-mcfall

Copy link
Copy Markdown
Author

Cross-vendor review + upstream-boundary follow-up

codex review independently reproduced the original bug and this fix in a scratch repository
before raising a real concern: bin/lefthook and bin/.lefthook-*.pkg are also tracked by
block/buzz (confirmed), and launchpad/AGENTS.md §3's closed exception list doesn't cover them.

Two things now in flight as a result:

This PR stays in draft pending #193's decision.

@serina-mcfall

Copy link
Copy Markdown
Author

Correction to my comment above: block#6180 has been closed — the cohort isn't sending PRs upstream at the moment (Serina's call). ADR #193 has been updated to present the exception as a standing fork/upstream divergence rather than a temporary one. This PR still stays in draft pending #193's decision.

@benmitchell11 benmitchell11 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped fix. Real before/after verification (the ambiguous-ref crash reproduced pre-bump, confirmed fixed post-bump), a real dry-run push exercising the actual hook chain, and the full workspace test suite run and pasted. Rejected-alternatives section is genuinely useful — confirms the lefthook.yml-level override was tried and doesn't cover branch-skew's hardcoded fallback, so the version bump isn't a shortcut, it's the only fix that actually covers every command.

Good practice: two unrelated pre-existing test failures (#198, #199) were found while verifying this and filed separately rather than either silently ignored or scope-crept into this PR.

@tucktuck101
tucktuck101 merged commit b4bce14 into launchpad Aug 18, 2026
27 of 30 checks passed
@serina-mcfall
serina-mcfall deleted the fix/lefthook-ambiguous-launchpad-ref branch August 31, 2026 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

by:agent Filed or authored by an AI agent, not a human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: mesh_demo forwarded-join echo round-trip returns 504 instead of 200 bug: lefthook ambiguous-argument crash on every branch's first push

3 participants