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

#210 feat: swamp extension verify — opaque extension-lifecycle verification primitive

Opened by stack72 · 5/1/2026

Problem

The swamp-extension-model and swamp-troubleshooting skills currently tell agents to invoke deno check, deno test, deno fmt, and deno lint directly when developing an extension. This works on a developer's box that already has a system Deno, but it has two underlying problems:

  1. Implementation lock-in. Inviting agents (and humans) to invoke Deno directly implicitly contracts that the runtime is Deno, that its CLI surface is part of swamp's public API, and that flag/output changes across Deno major versions are swamp's problem to absorb. Any future change to the bundled runtime — version bump with breaking CLI changes, or a swap to a different runtime entirely — becomes a user-visible break.
  2. Version skew on extension code. Extensions are bundled and executed by swamp using its bundled deno. Tests run on a developer's system Deno are tested against a different runtime than the one swamp will actually use in production. Most of the time the difference is invisible; sometimes it surfaces as npm: resolution drift, JSR caching differences, or stdlib semantics mismatches.

This is the architectural follow-up to #195, which is being closed won't-fix. #195 proposed exposing ~/.swamp/deno/deno (or a swamp deno test passthrough) so agents could find swamp's bundled runtime when no system Deno was on PATH. That fix would have made both problems above worse, not better — it would have publicly committed swamp to "the bundled runtime is Deno, the binary lives at this path."

The right shape is a swamp-owned operation that runs the extension developer loop without exposing any Deno-shaped surface.

Proposed solution

Add swamp extension verify <manifest-or-extension-path> as an opaque extension-lifecycle verification primitive.

What it does (internally, today)

  • Type check (deno check against the extension file using the bundled deno + swamp's import-map context)
  • Lint (deno lint)
  • Format check (deno fmt --check)
  • Run colocated unit tests (*_test.ts next to the extension file, using the bundled deno with the same permission policy swamp uses for execution)
  • Quality rubric scoring (the same checks swamp extension push --dry-run already runs)

All of these already exist somewhere in swamp's internals (src/libswamp/extensions/fmt.ts, quality.ts, push.ts, EmbeddedDenoRuntime). verify is composition over existing infra, not new infrastructure.

What it deliberately does NOT do

  • Expose any Deno flags, paths, or runner semantics.
  • Accept arbitrary test-runner options (--filter, --reporter, --shuffle, --parallel, --no-check). The escape hatch for that is "bring your own Deno."
  • Become a generic Deno wrapper (swamp deno <args>).
  • Run smoke tests against live APIs — that's the existing swamp model method run smoke-testing protocol, separate concern.

The principle: the primitive must be extension-shaped, not deno-shaped. If it ever drifts toward swamp extension test, swamp extension check, swamp extension lint, etc. — separate per-tool subcommands — we've just rebranded the Deno CLI under a swamp prefix and inherited every flag the original surface had. That's worse than direct exposure: same lock-in, more code to maintain.

CLI shape

swamp extension verify <manifest-or-extension-path>
  --json              # structured output
  --skip-tests        # quick lint-only checks during iteration
  --skip-quality      # skip rubric scoring during iteration

Default exit codes: 0 = all stages pass, non-zero = at least one stage failed. JSON mode returns a { stages: [{ name, passed, output }], passed: bool } envelope so CI and agents can pivot on individual failures.

Skill update (in scope for the same PR)

Once verify exists, every place in .claude/skills/swamp-extension-model/ and .claude/skills/swamp-troubleshooting/ that currently says deno check / deno test / deno fmt / deno lint against extension code flips to swamp extension verify. That's a sweep, not a one-line edit, and it's the actual user-visible value of the new primitive — without it, agents keep reaching for the raw Deno commands and the abstraction does nothing.

The bundled-deno path (~/.swamp/deno/deno) stays undocumented and unsupported as a public path.

Alternatives considered

  1. Expose ~/.swamp/deno/deno directly in skills. The original ask in #195. Rejected: locks swamp into "the runtime is Deno, the binary is at this path" forever.
  2. swamp deno <args> passthrough command. Same lock-in as the path, just dressed up as a swamp subcommand. Every Deno flag becomes part of swamp's contract.
  3. Per-tool subcommands (swamp extension test, swamp extension check, swamp extension fmt, swamp extension lint). Rebrands the Deno CLI under a swamp prefix without removing the lock-in.
  4. Tell agents to install a system Deno. The "do nothing" option for the bundled binary, but it leaves the version-skew problem for extension tests unsolved and adds friction for users who'd rather not.
  5. Fold test execution into swamp extension push --dry-run. Tempting because --dry-run already runs quality checks. Rejected because verify should be runnable mid-development, not only as a pre-publish step. (Worth checking during triage that --dry-run and verify end up sharing implementation rather than duplicating it.)

Open questions to settle during triage

  1. Test discovery rule. Colocated *_test.ts next to the extension file is the obvious answer, but extensions sometimes have shared _lib/ test fixtures. Need to define what counts as "the extension's tests."
  2. Permissions. What --allow-* set should verify pass to the bundled deno when running tests? Probably --allow-all (matching how swamp executes models), but worth being explicit so we don't surprise users whose tests touch the network or filesystem.
  3. Bundle cache interaction. Should verify invalidate the model's bundle cache, run tests against the cached bundle, or run against source? Source is the obvious answer for tests-of-the-source; bundle is what runs in production. Possibly both in different stages.
  4. Relationship to swamp extension push --dry-run. --dry-run already runs quality checks. Either verify is --dry-run minus the upload, or --dry-run becomes verify + upload simulation. Worth deduping rather than ending up with two near-identical commands.
  5. Skill rewrite scope. The sweep across swamp-extension-model and swamp-troubleshooting should land in the same PR as the new primitive. The exact list of files touched should fall out during planning.

Impact

Closes the architectural gap that #195 surfaced. After this lands:

  • The original incident from #195 (an agent on a no-system-deno machine couldn't run deno test) becomes a non-issue: the agent runs swamp extension verify, swamp owns the runtime invocation, no Deno path lookup needed.
  • swamp keeps the freedom to upgrade the bundled Deno (or replace it) without coordinating with users.
  • Extension tests run on the runtime they'll actually execute on in production, eliminating the version-skew failure mode.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

5/1/2026, 10:46:38 PM

No activity in this phase yet.

03Sludge Pulse
Editable. Press Enter to edit.

bixu commented 5/4/2026, 12:21:02 PM

I like!

bixu commented 5/10/2026, 4:44:02 PM

Ran into another situation today where this would have been great (not having to think about where Deno is).

Sign in to post a ripple.