`update.sh --pull` could abort with "Your local changes to the following files
would be overwritten by merge: web/bun.nix" — before a single service was
restarted — and the only way past it was to delete the file by hand.
The updater did it to itself. web/bun.nix is generated (bun2nix, a pure
function of web/bun.lock) but committed, because the Nix build fetches
node_modules only from it. The web step ran `bun install --frozen-lockfile`
without --ignore-scripts, so web's `postinstall` (`bun2nix -o bun.nix`)
rewrote that tracked file on every update. Harmless while the committed file
is in sync — but main carried a stale web/bun.nix from 1db8f763 to b79d90b4,
so any Deck updated in that window had it rewritten to the *correct* content
and has been sitting dirty ever since. The SDK step has always passed
--ignore-scripts, which is why only web/bun.nix ever went dirty.
Two changes, both in install.sh and update.sh:
* the web install now passes --ignore-scripts and runs `bun run codegen`
explicitly. web has two install lifecycle scripts and we want exactly one:
`prepare` IS `bun run codegen` (orval + paraglide + the i18n check) and is
required, since src/api/gen, src/paraglide and src/routeTree.gen.ts are
gitignored and `prebuild` only re-runs orval; `postinstall` is the one that
writes a committed file. Equivalent to the old behaviour minus bun2nix.
* --pull restores web/bun.nix and sdk/bun.nix before pulling, which unsticks
the installs already broken out there. Deliberately NOT `git reset --hard`:
$SRC is the operator's own checkout and may carry real local work, so a
still-dirty tree now fails with a message that names the files and the way
out instead of git's raw abort. Discarding these two is provably lossless —
regenerating them from the lockfiles is exactly what bun2nix does.
CI already gates the drift that made this visible (scripts/ci/check-bun-nix.sh,
ci.yml), so main cannot ship a stale bun.nix again.