SIGN IN SIGN UP

fix: don't let a transient empty read defeat exclude_unchanged (#924)

Generators that write by truncating first (shell redirection such as
`cat > gen.go <<EOF`) leave the file at zero bytes for a moment. A watcher
event fired at that instant made fileChecksum return an error, and
isModified turns any error into "the file changed". That silently bypassed
the checksum comparison, so air rebuilt, the build regenerated the file, and
the loop never settled even though the generated content was identical on
every run.

Retry the read a bounded number of times (5 x 20ms) when a file comes back
empty, and only on live change events. Seeding the checksum cache at startup
uses the new primeChecksum helper, which does not wait: nothing is being
written then, so every wait would be pure startup latency.

A file that stays empty for the whole budget is still reported as modified,
and errors other than empty reads are propagated untouched. isModified only
runs when exclude_unchanged is enabled, so default setups are unaffected.

Closes #527

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
X
xiantang committed
6fbfb5d72274e6876a04f4deba00b243ed79a057
Parent: e9fc14d
Committed by GitHub <noreply@github.com> on 7/20/2026, 1:04:01 PM