diff --git a/.project/concepts/data-layer/contract_polyfill-surface.md b/.project/concepts/data-layer/contract_polyfill-surface.md index 075fb68..68d9606 100644 --- a/.project/concepts/data-layer/contract_polyfill-surface.md +++ b/.project/concepts/data-layer/contract_polyfill-surface.md @@ -2,7 +2,7 @@ type: contract summary: The API @ng-eventually/polyfill exposes to an application — signatures, guaranteed behaviour, and what it does not offer pulled_from: https://gitea.reconnexion.apps.gueraud.net/Reconnexion/ng-eventually.git/.project/concepts/app-contract/contract_polyfill-surface.md -pulled_version: 1ecf511e9d8de8e0feb007f3a88f2c0d56ce455a +pulled_version: a33fb8a21464194227668fd703edd35f685bb3c1 pulled_at: 2026-08-16 --- diff --git a/.project/concepts/tech-stack/caveat_polyfill-overlay-needs-a-dev-restart.md b/.project/concepts/tech-stack/caveat_polyfill-overlay-needs-a-dev-restart.md new file mode 100644 index 0000000..efef6ff --- /dev/null +++ b/.project/concepts/tech-stack/caveat_polyfill-overlay-needs-a-dev-restart.md @@ -0,0 +1,31 @@ +--- +type: caveat +summary: A running `bun run dev` never picks up a refreshed data-layer package — the overlay lives in node_modules, which watchers exclude, so the server keeps serving whatever it loaded at startup. Restart after every `link:polyfill`, and suspect a stale server before suspecting the code. +last_checked: 2026-08-16 +--- + +# Pitfall: refreshing the data-layer package does not reach a running dev server + +`pnpm run link:polyfill` overlays the local package into `node_modules/@ng-eventually/polyfill/` as real files, and keeps them current. **That is all it does.** A `bun run dev` already running goes on serving the package it loaded at startup, however many times the overlay is rewritten underneath it — `node_modules` is excluded by file watchers as a matter of convention, so the change happens in the one place nothing is looking. + +**So: restart `bun run dev` after every refresh of the package.** There is no signal that you needed to; a stale server looks exactly like a current one. + +## Why this is worth a leaf + +VERIFIED 2026-08-16, and it cost about an hour. A defect had been fixed on the provider's side, the overlay was refreshed, and an automated probe on a freshly launched server confirmed the fix — 3 runs out of 3, clean. The same sequence performed by hand in a browser reproduced the defect immediately. The two observations looked irreconcilable, and the search went to the wallet, to prior state, to timing. + +The dev server had been running for **six days**. It predated the package rename and the whole migration, and it was serving code from before the fix. The browser was running a different application from the one under test. + +Two things made it hard to see. The failure mode is **silence** — nothing warns that the served code is old. And `scripts/link-polyfill.ts` explicitly promised the opposite, that `bun --hot` would reload the copied file live; that claim is now corrected in the script, but a reader who trusted it would rule out the true cause first, which is exactly what happened. + +## The reflex to build + +When a fix does not appear to take effect, or when a hand-run and an automated run disagree, **check how long the server has been up before anything else**. It is one command, and it eliminates the cheapest hypothesis first: + +```bash +ps -o lstart= -p $(pgrep -f 'bun --hot src/index.ts' | head -1) +``` + +The same reasoning applies to anything else served out of `node_modules` — the trap is the location, not this package. + +Related: [[cookbook_live-probe]] (bdd-testing) — a probe answers only for the code the server actually holds, so a stale server invalidates the probe's conclusion, not the product's behaviour. diff --git a/scripts/link-polyfill.ts b/scripts/link-polyfill.ts index faaa1ef..e7552b8 100644 --- a/scripts/link-polyfill.ts +++ b/scripts/link-polyfill.ts @@ -18,13 +18,20 @@ * directory holding the local polyfill's package.json + src (NO node_modules). * 2. Asserts the single-instance invariant (same @ng-org/web realpath from Festipod and * from the overlay) — aborts if it would break. - * 3. Watches the local polyfill src and copies each change into the overlay, so - * `bun --hot` (bun run dev) reloads the edited file live. + * 3. Watches the local polyfill src and copies each change into the overlay. + * + * ⚠️ RESTART `bun run dev` AFTER THIS SCRIPT WRITES. The overlay lives inside + * node_modules, which file watchers exclude by convention — so a running dev + * server keeps serving the polyfill it loaded at startup, however many times + * this script rewrites the files underneath it. VERIFIED the hard way: a dev + * server six days old served pre-fix code while the overlay on disk was current, + * and an hour went into hunting a defect that had already been fixed. Watching + * copies the files; it does not make anything reload them. * * USAGE (reactive dev): * Terminal 1: pnpm run link:polyfill # overlays local source, then watches * Terminal 2: bun run dev # portless festipod bun --hot src/index.ts - * Edit files under packages/polyfill/src → they land in node_modules → bun --hot reloads. + * Edit files under packages/polyfill/src → they land in node_modules → RESTART dev to pick them up. * * pnpm run link:polyfill --once # overlay + verify, no watch (CI / one-shot) * Return to the committed git-installed dependency: pnpm install @@ -85,7 +92,8 @@ if (ONCE) { process.exit(0); } -// 3. Watch and copy on change so `bun --hot` sees live edits. +// 3. Watch and copy on change. This keeps the overlay CURRENT; it does not make a +// running dev server notice (node_modules is outside the watcher) — restart it. console.log(`👀 watching ${SRC_LOCAL} → ${SRC_TARGET} (Ctrl-C to stop)`); watch(SRC_LOCAL, { recursive: true }, (_event, filename) => { if (!filename) return;