Skip to main content
← Back to list
01Issue
BugClosedSwamp CLI
AssigneesNone

#282 Local extension edits don't reliably trigger rebundle

Opened by keeb · 5/7/2026

Description

When iterating on a TypeScript extension model loaded via a local source path (a .swamp-sources.yaml path: entry), edits to the source .ts file don't reliably trigger a rebundle. The model continues to execute with code from a stale bundle even after the source has been modified.

The freshness check uses source mtime plus a stored fingerprint in the extension catalog, but in practice these can get out of sync with the actual source contents. Result: editing a model and re-running its method still executes the old code.

Steps to reproduce

  1. Configure a local source in .swamp-sources.yaml with a path: entry.
  2. Run any model method from that source — bundle is created and cached.
  3. Edit the model's .ts file (any non-comment code change).
  4. Re-run the same model method.
  5. Observed: the model executes pre-edit code; the cached bundle is still loaded.

Workaround

All three cache layers must be wiped manually:

  1. Deno transpile cache: rm ~/.cache/deno/gen/file/<absolute-source-path>/<file>.ts.js
  2. Swamp bundle: rm ~/.swamp/repos/<repo-id>/bundles/<hash>/<file>.js
  3. Catalog row: sqlite3 .swamp/_extension_catalog.db "DELETE FROM bundle_types WHERE source_path LIKE '%<file>%';"

Only after wiping all three does the next invocation rebundle from the edited source. Skipping any one of them (most commonly the deno gen cache) leaves the bundle stale.

Environment

  • Source loaded via .swamp-sources.yaml with path: (not a pulled extension)
  • Edits made directly to the .ts file in that path
  • Catalog source_fingerprint was observed to be stale (didn't match the source file's actual sha256) even though source_mtime had advanced

Impact

Adds a multi-step manual workaround to every iteration of local extension development. Easy to forget a layer and waste debugging time on a fix that already worked but isn't loaded.

02Bog Flow
OPENTRIAGEDIN PROGRESSCLOSED

Closed

5/7/2026, 5:18:18 PM

No activity in this phase yet.

03Sludge Pulse
Editable. Press Enter to edit.

stack72 commented 5/7/2026, 5:17:54 PM

Thanks for the detailed reproduction @keeb — closing this as a duplicate of swamp-club#274.

Same bug class: source-mounted extension's bundle silently fails to rebuild when source edits should trigger it. Root cause is the isExpectedBundleFailure fast-path returning stale cached bundles for user-developed extensions. The stale source_fingerprint you observed is the visible symptom of that path firing without a rebuild attempt.

#274 is in implementation now with two coordinated fixes:

  • Path-based bypass of isExpectedBundleFailure for non-pulled origins (locals + source-mounted), so user-developed extensions actually attempt to rebuild on every staleness check
  • One-time BUNDLE_LAYOUT_VERSION bump to repair any catalogs poisoned by the pre-#265 fingerprint bug

After #274 ships (likely within ~3-5 days), please re-verify on current main:

  1. Configure the same .swamp-sources.yaml path entry
  2. Run a method (materializes bundle)
  3. Edit the source file
  4. Re-run — confirm the new code executes without manual cache wiping

One observation worth flagging for the post-#274 re-verification: your workaround wiped the Deno gen cache (~/.cache/deno/gen/...) in addition to the swamp bundle + catalog row. Layers 2 and 3 are what #274 fixes. Layer 1 (Deno gen cache) is unlikely to be load-bearing — deno bundle reads source files directly and shouldn't hit the gen cache. But if after #274 ships, you find the Deno gen cache wipe is still needed to pick up edits, that's a separate concern (likely Deno import-cache aliasing, which is W5's territory in the rearchitecture). File a fresh tracker in that case.

Most likely outcome: #274 fully closes this. The Deno gen cache step turns out to be a red herring from debugging.

Tracking via swamp-club#274 from here. Apologies for the multi-step workaround — visibility on what's actually load-bearing during these failures is exactly what the rearchitecture is supposed to clean up.

Sign in to post a ripple.