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

#251 doctor extensions repair: clean catalog-only orphans

Opened by stack72 · 5/5/2026

Problem

`swamp extension rm ` short-circuits with `Extension is not installed` when no lockfile entry exists for that name (rm.ts:181 in the W2 lifecycle services branch). This is correct for the user-facing rm contract — "already gone" is a clean no-op.

But it leaves a gap: if the catalog has rows for an extension that no longer has a lockfile entry (e.g., from a half-applied install whose lockfile write rolled back, a hand-edited `upstream_extensions.json`, or a `W1b → W2` migration where stale rows were written before the lifecycle services landed), there's no CLI path to clean those rows. They'd accumulate as ghost catalog entries that `swamp doctor extensions` reports but cannot repair.

Proposed solution

Add a `swamp doctor extensions repair` (or extend the existing `doctor extensions` command with a `--repair` flag) that:

  1. Identifies rows in the catalog whose `extension_name` has no corresponding lockfile entry AND whose `source_path` doesn't exist on disk.
  2. Tombstones + DELETEs them via `ExtensionRepository.saveAll([tombstoneAll(...)])` so the same SQLite txn semantics that protect the lifecycle services apply here too.
  3. Reports the count cleaned (and surfaces a clear message in `--json` mode).

Why W6, not W2/3/4/5

The lifecycle services (W2) explicitly target the user-facing install/rm/upgrade flows. The catalog-only orphan cleanup is a doctor-side repair surface — distinct from the lifecycle layer's contract. The architecture-agent review of W2 explicitly tagged this as W6 territory.

Context

  • Spotted in code review of feat/w2-extension-lifecycle-services (the W2 PR for swamp-club#231).
  • W2 closes swamp-club#201 (rm now prunes catalog rows during normal flow). This issue is the safety-net for state that bypasses the normal flow.
  • Implementation should reuse `ExtensionRepository.saveAll` + `tombstoneAll` so I-Repo-1 evaluation and SQLite ROLLBACK semantics carry over.

Acceptance criteria

  • `swamp doctor extensions --repair` (or equivalent) can prune catalog rows whose lockfile entry is gone and whose source files don't exist.
  • Idempotent: running twice on a clean catalog is a no-op.
  • Tested with a fixture catalog seeded with orphan rows; rows are gone after repair.
  • `--json` output reports the action taken.
02Bog Flow
OPENTRIAGEDIN PROGRESSCLOSED

Closed

5/6/2026, 6:06:22 PM

No activity in this phase yet.

03Sludge Pulse

Comments are locked on this issue.