| 📦 Turbo Go 3d7798b k33g 11h ago | 1 | # Handoff — 2026-08-31 — the installer's macOS reinstall failure |
| 2 | |
| 3 | ## State |
| 4 | |
| 5 | **Fixed**, on branch `feature/go-format-lint` alongside the Go-tools work, **uncommitted**. |
| 6 | |
| 7 | `scripts/install.sh` printed `✗ the installed binary does not run` after a clean build on macOS. The cause was `cp` writing into the existing binary's inode; macOS caches a code signature per inode, so the kernel refused to execute bytes that no longer matched. The installer now writes `.turbo-go.incoming.$$` inside `$prefix` and renames it over the target, giving the name a fresh inode — and making the install atomic. |
| 8 | |
| 9 | The verification also captures the binary's own stderr and prints it, so the next such failure names itself. |
| 10 | |
| 11 | - 3 new tests in `install_test.go` (13 total); the two behavioural ones were confirmed failing against the `cp` version. |
| 12 | - Whole suite green. Quality gate **PASS**: 0/0/0. |
| 13 | - `how-to/install.md` gained a "When something goes wrong" section in both languages. |
| 14 | |
| 15 | ## In flight |
| 16 | |
| 17 | Nothing. |
| 18 | |
| 19 | ## Next steps |
| 20 | |
| 21 | 1. **Ask the user to re-run `scripts/install.sh` on their Mac.** That is the only real confirmation available — see the blocker below. |
| 22 | 2. **Commit.** This sits on the same uncommitted branch as the Go tools work. |
| 23 | |
| 24 | ## Open questions / blockers |
| 25 | |
| 26 | - **The fix was never reproduced on macOS.** This sandbox is Linux. `darwin/arm64` and `darwin/amd64` cross-compile and vet cleanly, and the symptom — builds, installs, will not run, on a *reinstall* — matches the inode/signature failure exactly, but "matches exactly" is not "reproduced". If it recurs, the installer now prints the system's own message above the failure; that message is the thing to work from, not this diagnosis. |
| 27 | - **The user's `demo/.turbo-go/tools.toml` predates the `output` key** (written 13:57, before the key existed). It still works — an absent `output` means `popup` — but `Run` will be a popup there, which blocks on an interactive program. Deleting it and re-running **Go ▸ Create tools file** gets the commented file with `Run` set to `terminal`. It is their file; untouched. |
| 28 | |
| 29 | ## Watch out for |
| 30 | |
| 31 | - **Never install a binary with `cp` over an existing one.** It is the inode that carries the code signature on macOS, and the failure is silent, delayed, and looks like a build problem. Rename a complete file into place. |
| 32 | - **The temporary must be in `$prefix`, not in `$STAGING`.** A rename only works within one filesystem, and `mktemp -d` is usually somewhere else entirely. |
| 33 | - **`install -m 0755` is not a fix.** On some platforms it writes in place too. |
| 34 | - **`inodeOf` in `install_test.go` uses `syscall.Stat_t`** and skips where that is unavailable, so the test is Unix-only by construction rather than by accident. |