Skip to content

fix(ci): codesign + verify + smoke-test macOS binaries (fixes #84)#88

Merged
jcfischer merged 2 commits into
mainfrom
fix/macos-binary-codesign
May 31, 2026
Merged

fix(ci): codesign + verify + smoke-test macOS binaries (fixes #84)#88
jcfischer merged 2 commits into
mainfrom
fix/macos-binary-codesign

Conversation

@jcfischer
Copy link
Copy Markdown
Owner

Fixes #84.

Problem

All pre-built macOS binaries (supertag, supertag-lite, supertag-mcp) exit 137 (SIGKILL) immediately on Apple Silicon / macOS 26 — no Gatekeeper dialog, quarantine removal has no effect, killed even from Terminal. Reported by two users; open ~1 month.

Root cause (verified empirically on a macOS 26 / Apple Silicon host)

The shipped binaries are completely unsigned:

$ codesign -dv supertag      # from v2.5.7 release asset
supertag: code object is not signed at all
$ ./supertag --version; echo $?
137

On Apple Silicon the kernel (AMFI) SIGKILLs any unsigned Mach-O at exec. Not JIT/entitlements/LanceDB — just a missing signature.

The release workflow built with bun-version: latest and relied on Bun's --compile to ad-hoc-sign automatically. Some Bun versions stopped doing that → unsigned binaries shipped. Nothing in CI executed or signature-checked the output, so it went unnoticed for a month.

Fix

  • Explicit ad-hoc codesign of every macOS binary: codesign --remove-signature first (clears any malformed partial signature that otherwise makes --force fail with "invalid format"), then codesign --force --sign - --timestamp=none, then codesign --verify.
  • Smoke-test gate: execute --version on the built binaries (arm64 natively on the macos-latest runner; x64 via Rosetta when available). This is the check that would have caught [BUG] supertag and supertag-lite binaries exit 137 on macOS 26.4 (Sequoia, Apple Silicon) #84 in CI rather than in users' hands.

Verification

On macOS 26 / Apple Silicon: remove-sig + ad-hoc sign + verify + run → exit 0. The same procedure salvages already-downloaded binaries (documented as an immediate workaround in #84).

Scope / follow-up

Ad-hoc signing stops the SIGKILL but downloaders still get a one-time Gatekeeper "unidentified developer" prompt. Zero-friction distribution needs Developer ID signing + notarization (Apple Developer account + CI secrets) — separate, larger task; worth a follow-up issue.

🤖 Generated with Claude Code

Pre-built macOS binaries shipped completely unsigned, so Apple Silicon
(and macOS 26+) killed them with SIGKILL (exit 137) at exec — no
Gatekeeper dialog, quarantine removal having no effect. Verified against
the v2.5.7 release asset: `codesign -dv` reported "code object is not
signed at all" and the binary exited 137.

Root cause: the release workflow built with `bun-version: latest` and
relied on Bun's --compile to ad-hoc-sign automatically. Some Bun versions
stopped doing that, the binaries went out unsigned, and nothing in CI
executed or signature-checked them — so #84 went unnoticed for a month.

Fix:
- Explicitly ad-hoc codesign every macOS binary (--remove-signature first
  to clear any malformed partial signature, then --force --sign -), then
  codesign --verify.
- Add a smoke-test step that EXECUTES `--version` on the built binaries
  (arm64 natively, x64 via Rosetta when available). This is the gate that
  would have caught #84 in CI instead of in users' hands.

Verified on a macOS 26 / Apple Silicon host: remove-sig + ad-hoc sign +
verify + run yields exit 0, and salvages even already-downloaded binaries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Owner Author

@jcfischer jcfischer left a comment

Choose a reason for hiding this comment

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

Review: fix(ci): codesign + verify + smoke-test macOS binaries

Verdict: approve — blockers=0 majors=0 nits=1

Clean, well-scoped fix for a real user-facing breakage. Root cause analysis is thorough, the fix is minimal and correct, and the PR body is exemplary.

What's good

  • Correct root cause. AMFI on Apple Silicon SIGKILLs unsigned Mach-O — not a Gatekeeper/quarantine issue. The codesign -dv verification in the PR body proves it.
  • Belt-and-suspenders signing. --remove-signature before --force --sign - handles both unsigned and malformed-signature states. --verify after signing catches codesign failures before packaging.
  • Smoke-test gate. Actually executing the binary is the right check — signature verification alone doesn't catch runtime issues. Rosetta fallback with graceful skip for x64 is pragmatic.
  • set -euo pipefail on both steps — any failure fails the job. Good.

Nit (non-blocking)

Smoke test covers 2 of 4 binaries. The codesign step signs all four (supertag, supertag-lite, supertag-mcp, supertag-export), but the smoke test only executes supertag and supertag-lite. If supertag-mcp or supertag-export had a build issue that made --version crash, the gate wouldn't catch it. Might be intentional (export has external playwright deps that may not be available in CI), but supertag-mcp --version should be safe to add. Author's call — the signing verification already covers the SIGKILL scenario that motivated this PR.

No other findings. The change is additive, correctly placed after build steps and before packaging, and doesn't affect Linux/Windows matrix legs. Ready to merge.

Addresses review nit on #88: smoke-test covered only supertag and
supertag-lite. Now execs all four via a uniform background guard that
tolerates supertag-mcp running as a stdio server (still-alive after 2s =
started fine, killed) while still failing on exit 137 (kernel SIGKILL of
an unsigned binary). No GNU timeout dependency. Validated locally on
macOS 26 arm64: signed binaries pass, mcp passes, an unsigned binary
fails with 137.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Owner Author

@jcfischer jcfischer left a comment

Choose a reason for hiding this comment

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

Review: fix(ci): codesign + verify + smoke-test macOS binaries

Verdict: approve — blockers=0 majors=0 nits=0

Prior review's nit (smoke test only covering 2/4 binaries) is resolved by the second commit. All four binaries now covered in both the codesign loop and the smoke-test loop.

Verified

  • Codesign + smoke-test parity: both loops iterate supertag supertag-lite supertag-mcp supertag-export
  • MCP handling: background guard pattern (launch → 2s grace → kill-0 check) correctly handles the stdio server that doesn't exit on --version. No GNU timeout dependency.
  • set -uo pipefail (not -e) on smoke-test step — correct, since kill/wait return non-zero on happy path
  • Step ordering: build → codesign → smoke-test → package → upload
  • No Linux/Windows regression: changes scoped to build-macos job only
  • Rosetta fallback: gracefully skips x64 execution when unavailable; codesign --verify still covers signatures

Non-blocking observations

  1. Non-137 signal exits (SIGSEGV=139, SIGABRT=134) pass as "ok" — acceptable scope since this PR targets the codesign/SIGKILL issue specifically. Future enhancement could fail on any signal-kill exit.
  2. </dev/null on smoke launch prevents stdin hangs — good defensive practice.
  3. 2s timeout is generous for --version but tight if any binary does slow init. Fine for SIGKILL detection (immediate).

Ready to merge (can't self-approve, submitting as comment).

@jcfischer jcfischer merged commit 3299416 into main May 31, 2026
1 check passed
@jcfischer jcfischer deleted the fix/macos-binary-codesign branch May 31, 2026 13:27
jcfischer added a commit that referenced this pull request May 31, 2026
…e resilience (#86)

- Fix: macOS binaries shipped unsigned → SIGKILL (137) on Apple Silicon; CI now codesigns + verifies + smoke-runs all binaries (#84/#88)
- Fix: delta-sync wedge on Tana Local API HTTP 500 poison node; isolate/skip + advance watermark + failure-streak escalation (#86)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

[BUG] supertag and supertag-lite binaries exit 137 on macOS 26.4 (Sequoia, Apple Silicon)

1 participant