#202 swamp extension install/pull does not prune source files dropped between versions, causing catalog to re-index orphans
Opened by bixu · 5/1/2026· Shipped 5/1/2026
Summary
When an extension drops a source file between versions, swamp extension install (lockfile-driven) and swamp extension pull --force both fail to remove the orphan files from .swamp/pulled-extensions/<name>/. The catalog rebuild then re-indexes those orphans, which means even a full cache wipe (rm -rf .swamp/bundles && rm .swamp/_extension_catalog.db*) followed by swamp extension install does NOT actually repair the system — the next model method run still resolves to the orphaned older bundle entry.
This is upstream of the bug filed in swamp Lab #201. That issue describes the catalog retaining stale rows; this one explains why the catalog keeps coming back broken even after a wipe: the source-of-truth filesystem is dirty, and install treats source files as additive.
Reproduction
- Pull
@hivemq/harvester/[email protected]— ships two files:models/harvester/kubeconfig.tsandmodels/harvester/fetch_kubeconfig.ts. - Update to
@hivemq/harvester/[email protected](or pull --force) — the new version manifest only declaresmodels/harvester/kubeconfig.ts. - Verify:
ls .swamp/pulled-extensions/@hivemq/harvester/kubeconfig/models/harvester/shows BOTH files.fetch_kubeconfig.tsis the orphan from the older version; install/pull never removed it. - Even a hard reset does not help. Sequence we tried (in order):
rm -rf .swamp/bundles— clears bundle dir.rm -f .swamp/_extension_catalog.db*— clears the catalog.swamp extension install— recreates everything from the lockfile.- Result:
pulled-extensionsSTILL has both files, catalog STILL has twobundle_typesrows for the same model type, andmodel method runstill non-deterministically resolves to the older row's bundle path.
- The only repair that worked was:
rm -rf .swamp/pulled-extensions/@hivemq/harvester/kubeconfig+swamp extension pull --force. Once the orphan source file was physically gone from disk, the catalog rebuild produced exactly one row and resolution worked.
Why this matters
Combined with swamp Lab #201, the user-visible failure mode is:
- An extension legitimately removes a file in a new version.
- The user runs
swamp extension update(orpull --force, orrm+pull, or wipes.swamp/bundles+extension install) — every "correct" recovery path. - All of them silently leave the orphan source file on disk.
- The catalog re-indexes the orphan and still resolves to the old version's bundle.
- The user / agent has no way to discover this without inspecting
pulled-extensionsmanually.
In our session this consumed ~30 minutes and required filesystem surgery on a directory swamp owns. An agent that respects swamp's boundaries had no path to fix it via swamp commands.
Asks
swamp extension installshould compute the set of source files declared by the lockfile-pinned version and remove anything else underpulled-extensions/<name>/that does not appear in that set. Same for nested directories that become empty.swamp extension pull --forceshould do the same — treat the manifest as authoritative and prune the destination directory to match.swamp extension updatelikewise.swamp doctor extensionsshould report orphan source files (files underpulled-extensions/<name>/that aren't declared by the manifest) as a warning with a fix-it hint.
Environment
- swamp
20260501.010449.0-sha.c24fb601 - Repro extension:
@hivemq/harvester/kubeconfig(versions 2026.04.24.32 → 2026.05.01.39)
Related
- swamp Lab #199 — warn on outdated extensions
- swamp Lab #200 — surface native cache-refresh path
- swamp Lab #201 — catalog retains stale rows; this issue is the underlying root cause for why the rebuild path described in #201 doesn't recover
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.