fix(ci): codesign + verify + smoke-test macOS binaries (fixes #84)#88
Conversation
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>
jcfischer
left a comment
There was a problem hiding this comment.
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 -dvverification in the PR body proves it. - Belt-and-suspenders signing.
--remove-signaturebefore--force --sign -handles both unsigned and malformed-signature states.--verifyafter 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 pipefailon 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>
jcfischer
left a comment
There was a problem hiding this comment.
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 GNUtimeoutdependency. set -uo pipefail(not-e) on smoke-test step — correct, sincekill/waitreturn non-zero on happy path- Step ordering: build → codesign → smoke-test → package → upload
- No Linux/Windows regression: changes scoped to
build-macosjob only - Rosetta fallback: gracefully skips x64 execution when unavailable; codesign --verify still covers signatures
Non-blocking observations
- 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.
</dev/nullon smoke launch prevents stdin hangs — good defensive practice.- 2s timeout is generous for
--versionbut tight if any binary does slow init. Fine for SIGKILL detection (immediate).
Ready to merge (can't self-approve, submitting as comment).
…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>
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:
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: latestand relied on Bun's--compileto 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
codesign --remove-signaturefirst (clears any malformed partial signature that otherwise makes--forcefail with "invalid format"), thencodesign --force --sign - --timestamp=none, thencodesign --verify.--versionon 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