Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix: stop bun run watch infinite rebuild loop (codegen self-trigger)#240

Merged
twschiller merged 1 commit into
mainfrom
fix/watch-rebuild-loop
Jun 9, 2026
Merged

Fix: stop bun run watch infinite rebuild loop (codegen self-trigger)#240
twschiller merged 1 commit into
mainfrom
fix/watch-rebuild-loop

Conversation

@twschiller

Copy link
Copy Markdown
Contributor

Problem

bun run watch (build.ts --watch) spins into an infinite rebuild loop, pegging CPU indefinitely. The symptoms reported were transient build failures:

  • dist/background.js not found — run the extension build first. (background-purity check)
  • ENOENT … copyfile 'icons/icon-16.png' -> 'dist/icons/icon-16.png' (icon copy)

These ENOENT errors are symptoms, not real missing files.

Root cause

build.ts --watch watches src/ recursively (build.ts:256). Every build runs generateSiteData() / generateInjectionPatterns(), which writeFileSync unconditionally into src/rules/site-data.generated.ts and src/rules/injection-patterns.generated.tsinside the watched tree. So each build's own write re-triggers the watcher → rebuild → write → loop forever.

The watcher also has no build mutex (just a 50ms debounce, build.ts:251), so builds overlap. Each build starts with await rm(DIST, …) (build.ts:122), so a newer build deletes dist/ out from under an in-flight one — producing the transient "background.js not found" at the purity check and the icon-copy race.

Fix

Guard each codegen write with a content comparison (scripts/file-has-content.ts) so an unchanged output no longer re-arms the watcher. A settled build stops triggering itself, breaking the loop.

Verification

  • Watch now does exactly one build, then idles at 0% CPU (was ~190%).
  • Two consecutive bun run builds are clean.
  • bun run check passes.
  • bun test scripts/ — 37 pass.

Note (out of scope)

The missing build mutex is a latent issue: rapid saves during a slow build could still overlap and race on rm(DIST). This PR removes the self-triggering case, which is what was actually biting. An in-flight guard to serialize concurrent builds could be a follow-up.

🤖 Generated with Claude Code

`build.ts --watch` watches `src/` recursively. Both codegen scripts
(`build-site-data`, `build-injection-patterns`) `writeFileSync` their
output into `src/rules/*.generated.ts` unconditionally on every build,
so each build's write re-triggers the watcher → rebuild → write → loop.
The watcher pegs CPU indefinitely, and because builds overlap with no
mutex, a newer build's `rm(DIST)` deletes files from under an in-flight
one — surfacing as transient `dist/background.js not found` (purity
check) and `icons/icon-16.png` ENOENT (cp race).

Guard each codegen write with a content comparison so an unchanged
output no longer re-arms the watcher. A settled build now stops
triggering itself.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-browser-shield-demo-site Ready Ready Preview, Comment Jun 9, 2026 11:41pm

Request Review

@twschiller twschiller merged commit 4cfe2a7 into main Jun 9, 2026
7 checks passed
@twschiller twschiller deleted the fix/watch-rebuild-loop branch June 9, 2026 23:47
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.

1 participant