Skip to content

Releases: systeminit/swamp

swamp 20260317.105237.0-sha.7095a535

17 Mar 10:53
Immutable release. Only release title and notes can be modified.
7095a53

Choose a tag to compare

What's Changed

  • fix: resolve stack overflow when loading extension bundles with large npm deps (#731)

Summary

Fixes #728.

  • Root cause: String.fromCharCode(...new TextEncoder().encode(js)) spreads every byte of a bundle onto the call stack as a function argument. Large inlined npm dependency trees (e.g., @octokit/rest, @slack/web-api) produce bundles of hundreds of KB, exceeding V8's maximum call stack size.
  • Cached bundles: Restore toFileUrl() imports (the pre-#724 approach) with on-disk zod rewriting so old cached bundles are fixed permanently.
  • Fallback path: Add uint8ArrayToBase64() which processes bytes in 8KB chunks, avoiding the stack overflow for the no-repo-dir codepath.
  • All three loaders fixed: UserModelLoader, UserDriverLoader, UserVaultLoader all had the identical bug from #724.

Test plan

  • deno check — type checking passes
  • deno lint — linting passes
  • deno fmt — formatting passes
  • deno run test — 3033/3033 tests pass
  • deno run compile — binary compiles
  • New uint8ArrayToBase64 unit tests (small input, empty input, 1MB input)
  • Manual verification: swamp repo initswamp extension pull @bixu/githubswamp model type search --json loads all 4 Octokit-based models without warnings

🤖 Generated with Claude Code

Co-authored-by: Blake Irvin blakeirvin@me.com


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.105237.0-sha.7095a535/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.105237.0-sha.7095a535/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.105237.0-sha.7095a535/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.105237.0-sha.7095a535/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.010646.0-sha.40d70e64

17 Mar 01:07
Immutable release. Only release title and notes can be modified.
40d70e6

Choose a tag to compare

What's Changed

  • feat: auto-trust collectives from user membership (#727)

Summary

  • Cache the user's collective memberships in auth.json during auth login and auth whoami, then merge them into the trusted collectives list at CLI startup
  • Removes friction of manually adding each collective to trustedCollectives in .swamp.yaml — if you're a member of a collective, its extensions auto-resolve automatically
  • Adds trustMemberCollectives option to .swamp.yaml for opt-out

Design Decisions

Cache at login time, not per-invocation. Calling the whoami API on every CLI invocation would add latency. Instead, collectives are cached in auth.json during auth login (already makes a whoami call) and refreshed on auth whoami. This means membership changes require a swamp auth whoami to take effect — an acceptable tradeoff for zero-latency startup.

Merge, don't replace. Membership collectives are merged with the explicit trustedCollectives list (deduplicated via Set). This means explicit config is never lost, and membership adds to it additively.

Opt-out via trustMemberCollectives: false. Defaults to true (absent = true). When set to false, only the explicit trustedCollectives list is used — exactly matching the previous behavior. This gives security-conscious users full control.

Graceful degradation. If not authenticated, auth.json is missing/unreadable, or the collectives field doesn't exist (old auth.json), the feature silently falls back to the current behavior with no errors.

User Impact

Before: Users who are members of collectives (e.g., their org's @myorg collective) had to manually add myorg to trustedCollectives in every repo's .swamp.yaml to get auto-resolution working. Without this, swamp model create @myorg/some-type my-model would fail with "Unknown model type".

After: After logging in, membership collectives are automatically trusted. Extensions from any collective the user belongs to auto-resolve on first use with zero configuration.

Changes

File Change
src/domain/auth/auth_credentials.ts Added collectives?: string[] to AuthCredentials
src/cli/commands/auth_login.ts Cache collectives from whoami response during login
src/cli/commands/auth_whoami.ts Refresh cached collectives on whoami
src/infrastructure/persistence/repo_marker_repository.ts Added trustMemberCollectives?: boolean to RepoMarkerData
src/cli/mod.ts Added resolveTrustedCollectives() to merge membership + explicit collectives; load auth at startup
src/cli/mod_test.ts 8 new tests for resolveTrustedCollectives
src/infrastructure/persistence/auth_repository_test.ts 2 new tests for collectives round-trip
Skills & design docs (5 files) Updated to document membership-based trust and trustMemberCollectives opt-out

Test Plan

  • deno check — all modified files pass type checking
  • deno lint — no lint errors
  • deno fmt --check — formatting clean
  • deno run test src/cli/mod_test.ts — 51 tests pass (8 new resolveTrustedCollectives tests)
  • deno run test src/infrastructure/persistence/auth_repository_test.ts — 7 tests pass (2 new)
  • Manual E2E test:
    1. Compiled binary with deno run compile
    2. Created fresh repo in /tmp/swamp-test-autotrust with swamp repo init
    3. Ran swamp auth whoami → cached collectives ["swamp", "system-initiative", "stack72"] in auth.json
    4. Ran swamp model create @stack72/unifi-traffic test-traffic → auto-resolved and installed @stack72/ubiquity extension successfully
    5. The stack72 collective was NOT in .swamp.yaml's trustedCollectives — it was trusted purely via membership

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.010646.0-sha.40d70e64/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.010646.0-sha.40d70e64/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.010646.0-sha.40d70e64/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.010646.0-sha.40d70e64/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.005011.0-sha.2f69cc55

17 Mar 00:51
Immutable release. Only release title and notes can be modified.
2f69cc5

Choose a tag to compare

What's Changed

  • fix: data GC never fully removes expired data from disk (#722)

Summary

Fixes #720

swamp data gc reported expired data but never reclaimed any disk space. The deleteExpiredData() method only called removeLatestMarker(), which removed the latest symlink but left all version directories and content files on disk.

This was a two-part problem:

  1. Phase 1 (expired data cleanup) only performed a soft-delete — no version directories were removed, zero bytes freed
  2. Phase 2 (collectGarbage()) always protects the latest version, and the single-version delete() path recreates the latest marker, effectively undoing Phase 1's soft-delete

User impact

Before this fix, running swamp data gc would report expired entries but disk usage would remain unchanged. Users had no way to reclaim space from expired data without manually deleting directories from the datastore.

After this fix, swamp data gc fully removes expired data directories, correctly reports versionsDeleted and bytesReclaimed, and actually frees disk space.

What changed

  • data_lifecycle_service.ts: Replaced removeLatestMarker() (soft-delete) with delete(type, modelId, dataName) (hard-delete) in deleteExpiredData(). Before deleting, stats each version's content file to report accurate bytes reclaimed. Updated LifecycleGCResult doc comments to reflect the new behavior.

  • data_lifecycle_service_test.ts: Added delete and getContentPath mocks to MockDataRepository. Added two new tests:

    • Verifies expired data triggers delete() (not removeLatestMarker()) and reports correct versionsDeleted
    • Verifies dry run does not call delete()

Why this is correct

The no-version delete(type, modelId, dataName) path in UnifiedDataRepository does a clean Deno.remove(dataNameDir, { recursive: true }) — it removes the entire data directory without recreating any markers. After Phase 1 hard-deletes expired entries, Phase 2's findAllForModel() naturally skips them since their directories no longer exist. No changes needed to collectGarbage() or the delete() implementation.

Test plan

  • deno check — type checking passes
  • deno lint — no lint errors
  • deno fmt — properly formatted
  • deno run test — all 2997 tests pass (including 2 new tests)
  • deno run compile — binary compiles successfully

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.005011.0-sha.2f69cc55/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.005011.0-sha.2f69cc55/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.005011.0-sha.2f69cc55/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.005011.0-sha.2f69cc55/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.003631.0-sha.7ef34bda

17 Mar 00:37
Immutable release. Only release title and notes can be modified.
7ef34bd

Choose a tag to compare

What's Changed

  • docs: update skills and design docs for auto-resolution feature (#726)

Summary

  • Add "Automatic Resolution" section to design/extension.md covering trusted collectives, resolution algorithm, hot-loading, re-entrancy guard, and architecture
  • Add trustedCollectives config option to design/repo.md and expand .swamp.yaml example in repo structure reference
  • Update extension-model skill with auto-resolution notes and new example decision flow showing auto-resolve in action
  • Add auto-resolution troubleshooting entries to both model and extension-model troubleshooting references
  • Add vault type auto-resolution note to vault skill

Test plan

  • deno fmt passes on all changed files
  • deno run compile succeeds with updated skills embedded

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.003631.0-sha.7ef34bda/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.003631.0-sha.7ef34bda/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.003631.0-sha.7ef34bda/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.003631.0-sha.7ef34bda/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.001439.0-sha.adf8dd48

17 Mar 00:15
Immutable release. Only release title and notes can be modified.
adf8dd4

Choose a tag to compare

What's Changed

  • feat: automatic extension resolution with trusted collectives (#725)

Summary

Closes #665

When users clone a repo with model or vault configurations referencing extension types that aren't installed locally, commands fail with cryptic "Unknown model type" or "Unsupported vault type" errors. This PR adds lazy auto-resolution: when swamp encounters an unknown type whose collective is on a trusted allowlist, it transparently searches the extension registry, installs the matching extension, hot-loads it into the live registries, and continues execution — no manual swamp extension pull needed.

What changes

  • New trustedCollectives config in .swamp.yaml — defaults to ["swamp", "si"] so official extensions auto-resolve out of the box. Users can add more collectives or set [] to disable.
  • ExtensionAutoResolver domain service — standalone service with port interfaces (ExtensionLookupPort, ExtensionInstallerPort, AutoResolveOutputPort) that keeps the domain layer clean of CLI/presentation imports.
  • resolveModelType() / resolveVaultType() helper functions — drop-in replacements for modelRegistry.get() at 7 choke points across CLI commands and the workflow execution service.
  • Hot-loading supportUserModelLoader.loadModels() and UserVaultLoader.loadVaults() gain a skipAlreadyRegistered option so re-running model discovery after install doesn't error on already-registered types.
  • Vault auto-resolution in VaultService.fromRepository() — resolves missing @-prefixed vault types before registerVault(), keeping registerVault() itself sync.
  • Clear UX output — users always see what's happening: searching, installing, installed (with model count), or actionable error messages for not-found/network failures. Both log and JSON output modes supported.

Design decisions

  1. Standalone helper, not embedded in registriesModelRegistry and VaultTypeRegistry remain pure sync data structures. Resolution is a domain service that choke points call explicitly. This is more DDD-aligned: the registry is a repository (stores/retrieves), resolution is a domain service (orchestrates).

  2. Port interfaces for clean architecture — The domain service defines ExtensionLookupPort, ExtensionInstallerPort, and AutoResolveOutputPort interfaces. Concrete adapters in the CLI layer wire the HTTP client, installExtension(), model loaders, and output renderers. This keeps domain → CLI/presentation dependency arrows pointing the right direction.

  3. Two-step type-to-extension resolution — First tries direct lookup by progressively stripping trailing segments (e.g., @swamp/aws/ec2/instance → try @swamp/aws/ec2, then @swamp/aws). Falls back to search with collective filter if direct lookup fails. This handles both exact extension names and partial matches.

  4. Always install latest — Auto-resolution always installs the latest version unless the user has explicitly pinned via extension pull @name@version. This is the right default for trusted collectives where you control releases.

  5. Re-entrancy guard — A Set<string> of types currently being resolved prevents infinite loops if transitive dependencies trigger further resolution.

  6. Collective not allowlisted = silent skip — No auto-resolution is attempted for non-allowlisted collectives. The existing "Unknown model type" error shows as-is. This is intentional — we don't want to suggest the feature exists for untrusted collectives.

User impact

  • Zero-friction onboarding: Clone a repo that uses @swamp/digitalocean/droplet, run swamp model method run, and it just works — the extension installs automatically on first use.
  • No breaking changes: Existing repos work identically. The default trustedCollectives: ["swamp", "si"] only kicks in for @swamp/* and @si/* types. Users who don't use extensions see no difference.
  • Explicit opt-out: Set trustedCollectives: [] in .swamp.yaml to disable entirely.
  • Transparent operation: Every auto-resolution step is logged so users understand why a command takes longer the first time.

Testing

Automated tests (14 new)

  • Skips non-allowlisted collectives (silent, no output)
  • Resolves via direct lookup (strips segments correctly)
  • Tries intermediate candidates before shorter ones (@swamp/aws/ec2 before @swamp/aws)
  • Falls back to search when direct lookup fails
  • Shows notFound output when nothing matches
  • Shows networkError output on fetch failures (TypeError, timeouts)
  • Re-entrancy guard prevents infinite loops
  • Handles non-@ prefixed types (e.g., swamp/echo/v2)
  • Skips types without a collective (single-word types)
  • resolveModelType returns existing definitions without resolver
  • resolveModelType returns undefined for unknown types without resolver
  • resolveVaultType returns true for existing vault types
  • resolveVaultType returns false for unknown types without resolver
  • resolveVaultType skips non-@ types

Manual end-to-end test

Compiled the binary, initialized a fresh repo in /tmp, and ran:

swamp model create @swamp/digitalocean/droplet my-droplet

Result: auto-resolved @swamp/digitalocean from the registry, installed @swamp/digitalocean@2026.03.16.1, hot-loaded 32 models, and successfully created the my-droplet definition — all in one command with clear status output:

INF extension·auto-resolve Extension type "@swamp/digitalocean/droplet" not found locally, searching registry...
INF extension·auto-resolve Found extension "@swamp/digitalocean" (DigitalOcean infrastructure models)
INF extension·auto-resolve Installing "@swamp/digitalocean"@"2026.03.16.1"...
INF extension·auto-resolve Installed "@swamp/digitalocean"@"2026.03.16.1" (32 models registered)
Created: my-droplet (@swamp/digitalocean/droplet)

Full suite

All 3018 tests pass (14 new + 3004 existing), including architecture boundary and DDD layer rule tests.

Verification

  • deno check — passes
  • deno lint — passes
  • deno fmt — passes
  • deno run test — 3018 passed, 0 failed
  • deno run compile — binary compiled successfully

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.001439.0-sha.adf8dd48/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.001439.0-sha.adf8dd48/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.001439.0-sha.adf8dd48/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.001439.0-sha.adf8dd48/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260316.225105.0-sha.210fdbaf

16 Mar 22:52
Immutable release. Only release title and notes can be modified.
210fdba

Choose a tag to compare

What's Changed

  • fix: resolve dual Zod instance in compiled binary (#724)

Summary

Fixes #723.

In the compiled binary (deno compile), extension bundles with externalized import { z } from "npm:zod@4" resolve to a different Zod module instance than swamp's own embedded Zod. This causes instanceof z.ZodType checks, z.toJSONSchema(), and _zod property lookups to fail — even though both are the same Zod version (4.3.6). Works fine in dev mode (deno run) because Deno resolves both to the same cached module.

Problem

The --external npm:zod@4 flag in deno bundle was meant to make extensions share swamp's Zod instance. In dev mode, the dynamic import("npm:zod@4") in the bundle resolves to the same cached module. But in the compiled binary, deno compile resolves it to a separate module instance, breaking:

  • schema instanceof z.ZodTypefalse
  • z.toJSONSchema(schema)Cannot read properties of undefined (reading '_zod')
  • Any cross-instance Zod operations (.passthrough(), .default(), etc.)

Fix

Post-process extension bundles to replace external Zod imports with references to swamp's Zod instance exposed via globalThis.__swamp_zod:

Before (bundle output):

import { z } from "npm:zod@4";

After (rewritten):

const { z } = globalThis.__swamp_zod;

Changes

  • src/domain/models/bundle.ts: Add installZodGlobal() (sets globalThis.__swamp_zod to swamp's Zod module) and rewriteZodImports() (regex replaces Zod imports — handles named, aliased, star imports, versioned/unversioned specifiers). Applied in bundleExtension() for non-selfContained bundles.
  • src/domain/models/user_model_loader.ts: Call installZodGlobal() before loading bundles; apply rewriteZodImports at import-time for old cached bundles.
  • src/domain/drivers/user_driver_loader.ts: Same pattern.
  • src/domain/vaults/user_vault_loader.ts: Same pattern.
  • src/domain/models/bundle_test.ts: 9 new tests — unit tests for rewriteZodImports (named, aliased, star, unversioned, multiple, non-zod untouched, idempotency, single-quoted) and end-to-end test verifying z.toJSONSchema() works on bundled schemas.

Design decisions

  • Rewrite at both bundle-time AND import-time: Bundle-time ensures new cached bundles are correct. Import-time catches old cached bundles that still have raw import statements. The rewrite is idempotent.
  • selfContained bundles are unaffected: They inline Zod and never have external imports.
  • No changes to extension author workflow: Extensions still write import { z } from "npm:zod@4" — the rewrite is transparent.

Alternatives rejected

  • Stop externalizing Zod: Bloats every bundle by ~500KB and doesn't fix the problem — swamp's own code still uses its z for instanceof/toJSONSchema.
  • Duck-typing instead of instanceof: Much larger change surface across 6+ files, fragile, loses Zod's built-in schema capabilities.
  • Import maps: Don't work in compiled binaries.

Test plan

  • deno check — type checking passes
  • deno lint — linting passes
  • deno fmt — formatting passes
  • deno run test — 3004/3004 tests pass
  • deno run compile — binary compiles
  • Standalone PoC validates approach in both dev mode and compiled binary
  • Manual test with compiled binary: swamp extension pull @dougschaefer/cisco-collaboration-endpointsswamp model type describe shows JSON schema without _zod errors

🤖 Generated with Claude Code

Co-authored-by: Douglas Schaefer dougschaefer6@users.noreply.github.com


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.225105.0-sha.210fdbaf/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.225105.0-sha.210fdbaf/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.225105.0-sha.210fdbaf/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.225105.0-sha.210fdbaf/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260316.173839.0-sha.1abd500d

16 Mar 17:39
Immutable release. Only release title and notes can be modified.
1abd500

Choose a tag to compare

What's Changed

  • feat: per-model datastore locks for concurrent model operations (#713)

Summary

Replaces the single global datastore lock with per-model locks so that operations on different models can run concurrently. This fixes the core issue where running model method run on one model blocked all other model operations, even on completely unrelated models.

  • Introduces per-model lock files at data/{modelType}/{modelId}/.lock — operations on different models no longer block each other
  • Refactors the sync coordinator from module-level singletons to a Map<string, SyncEntry> supporting multiple concurrent locks
  • Adds model-scoped S3 sync (pullChangedForModel) so S3 datastores only pull/push the relevant model's files
  • Extracts model references from workflows to acquire only the locks needed, with automatic fallback to global lock for dynamic CEL references
  • Updates breakglass commands (lock status, lock release --model) to show and manage per-model locks

Closes #706

Why per-model locks?

The global lock was designed for simplicity, but it creates an O(n) bottleneck for fleet operations. When managing 100+ VMs where each method call takes 30-90 seconds, a single global lock means:

  • Before: Running healthCheck on prod-vm-1 blocks a quick checkService on dev-vm-2 — the second command waits or times out
  • After: Both run concurrently because they acquire separate locks (data/command/shell/prod-vm-1/.lock and data/command/shell/dev-vm-2/.lock)

Structural commands (data gc, repo init, model create/delete) still use the global lock, and per-model lock acquisition checks for a held global lock first — so data integrity is preserved.

Impact on users

  • model method run on different models runs concurrently (the primary win)
  • workflow run acquires only the locks for models referenced in the workflow
  • model evaluate and workflow evaluate use per-model locks for single-model/workflow evaluation
  • S3 datastores benefit equally — model-scoped pull on lock acquisition, brief global lock only during push (seconds, not minutes)
  • No breaking changes — the lock file format and CLI interface are unchanged; existing repos work without migration
  • Deadlock prevention — locks are always acquired in sorted order when multiple models are involved

What changed

File Change
datastore_sync_coordinator.ts Refactored to Map<string, SyncEntry> with named lock support
repo_context.ts Added requireInitializedRepoUnlocked(), createModelLock(), acquireModelLocks()
s3_cache_sync.ts Added pullChangedForModel() for model-scoped S3 sync
model_method_run.ts Uses per-model lock instead of global lock
workflow_run.ts Extracts model refs, acquires per-model locks (falls back to global for dynamic refs)
model_evaluate.ts Single-model evaluate uses per-model lock; --all keeps global
workflow_evaluate.ts Single-workflow evaluate uses per-model lock; --all keeps global
datastore_lock.ts lock status scans per-model locks; lock release --model added
datastore_output.ts Shows lock scope (global vs per-model) in status output
model_reference_extractor.ts New: extracts model references from workflows for lock targeting

Test plan

  • All 2968 existing tests pass
  • deno check, deno lint, deno fmt clean
  • New unit tests for coordinator, repo context helpers, and model reference extractor
  • Manual verification: two concurrent model method run on different models both proceed without blocking, each with its own .lock file
  • Binary compiles successfully

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173839.0-sha.1abd500d/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173839.0-sha.1abd500d/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173839.0-sha.1abd500d/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173839.0-sha.1abd500d/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260316.173713.0-sha.6dc69231

16 Mar 17:38
Immutable release. Only release title and notes can be modified.
1abd500

Choose a tag to compare

What's Changed

  • docs: add z.infer type casts to readResource skill examples (#721)

Summary

  • Update all readResource() examples in the swamp-extension-model skill to use z.infer<typeof Schema> casts instead of accessing properties on untyped Record<string, unknown>
  • Fix outdated vault resolution docs in api.md — vault expressions have been automatically resolved since #712, not "returned as-is"
  • Add type aliases (VpcData, DropletData, CustomerData, BucketData) next to each Zod schema so the cast pattern is immediately visible

Why this is the right fix for #716

The issue asks for typed readResource() to eliminate as any casts in extension models. The root cause isn't a missing framework feature — it's that the skill examples Claude uses to generate extension models were accessing readResource() results without type narrowing. Since extension models already define Zod schemas for their resources, z.infer<typeof Schema> derives the TypeScript type at zero runtime cost (erased during bundling). The as cast is safe because data was already validated against that same schema on write.

By fixing the examples, Claude will generate typed code from the start, and extension authors won't hit the lint violations described in #716.

Closes #716

Test plan

  • Verify examples in api.md, examples.md, and scenarios.md are consistent — every readResource() call has a corresponding z.infer type alias and cast
  • Verify vault resolution docs in api.md match actual behavior from #712

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173713.0-sha.6dc69231/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173713.0-sha.6dc69231/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173713.0-sha.6dc69231/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.173713.0-sha.6dc69231/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260316.163214.0-sha.4955f3d2

16 Mar 16:33
Immutable release. Only release title and notes can be modified.
4955f3d

Choose a tag to compare

What's Changed

  • fix: resolve multi-line imports in local_import_resolver (#719)

Summary

  • Fix IMPORT_PATTERN regex in local_import_resolver.ts to match across newlines (.*?[\s\S]*?), resolving #715
  • The clover code generator writes multi-line imports (e.g., import {\n createResource,\n deleteResource,\n} from "./_lib/aws.ts"), which the previous single-line regex silently skipped
  • This caused shared dependencies like _lib/aws.ts to be excluded from extension packages during swamp extension push, making all @swamp/aws/* extensions fail on pull with Module not found errors

Changes

  • src/domain/models/local_import_resolver.ts: Changed IMPORT_PATTERN from /(?:import|export)\s+.*?from\s+["'](\.\.?\/[^"']+)["']/g to /(?:import|export)\s+[\s\S]*?from\s+["'](\.\.?\/[^"']+)["']/g so the regex matches import/export statements that span multiple lines
  • src/domain/extensions/extension_import_resolver_test.ts: Added test case "resolveLocalImports resolves multi-line imports" that creates a _lib/aws.ts dependency imported via a multi-line import statement and verifies it is correctly discovered

Test plan

  • New multi-line import test passes
  • All 8 import resolver tests pass
  • Full test suite passes (2979 tests)
  • deno check — type checking passes
  • deno lint — linting passes
  • deno fmt — formatting passes
  • deno run compile — binary compiles successfully

Fixes #715

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.163214.0-sha.4955f3d2/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.163214.0-sha.4955f3d2/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.163214.0-sha.4955f3d2/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.163214.0-sha.4955f3d2/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260316.161521.0-sha.7fc8a69a

16 Mar 16:16
Immutable release. Only release title and notes can be modified.
7fc8a69

Choose a tag to compare

What's Changed

  • fix: skip auth check in extension push --dry-run (#718)

Summary

  • swamp extension push --dry-run now works without authentication
  • Auth loading (step 3) and collective membership validation (step 4) are wrapped in a !dryRun guard so they only run for real pushes
  • Unblocks CI validation workflows that don't have swamp-club credentials

What changed

In src/cli/commands/extension_push.ts, the auth check and collective membership validation previously ran unconditionally before the dry-run exit point. Since --dry-run only builds the archive locally and never contacts the registry, authentication is unnecessary.

The credentials variable is now typed as | undefined and only populated when not in dry-run mode. The existing non-dry-run code paths (steps 13 and 17) already have their own if (!options.dryRun) guards, so credentials are never accessed in dry-run mode.

Trade-off

Dry-run will skip collective ownership validation. This is acceptable because:

  • Dry-run validates the build, not permissions — its purpose is to verify the extension compiles and packages correctly
  • The real push still enforces collective membership — no security bypass
  • CI pipelines just need to verify the extension archives correctly without needing registry credentials

Test plan

  • deno check passes
  • deno lint passes
  • deno fmt passes
  • deno run test passes
  • deno run compile passes
  • swamp extension push <manifest> --dry-run succeeds without auth
  • swamp extension push <manifest> without auth still fails with "Not authenticated"

Fixes #717

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.161521.0-sha.7fc8a69a/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.161521.0-sha.7fc8a69a/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.161521.0-sha.7fc8a69a/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260316.161521.0-sha.7fc8a69a/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/