Skip to content

Releases: systeminit/swamp

swamp 20260311.210849.0-sha.1db81d92

11 Mar 21:09
Immutable release. Only release title and notes can be modified.
1db81d9

Choose a tag to compare

What's Changed

  • feat: add data rename command with forward-reference resolution (#689)

Closes #621

Summary

Adds swamp data rename <model> <old_name> <new_name> — a non-destructive rename command that preserves version history and maintains backwards compatibility through forward-reference resolution.

Why this is useful

Data instance names in swamp are permanent once created. Before this change, renaming a data instance (e.g., web-vpcdev-web-vpc) required deleting the old data and recreating it under the new name. This is destructive: you lose all version history, and any workflows, CEL expressions, or model inputs referencing the old name break immediately.

Scenarios where rename is needed

  • Refactoring naming conventions — As a project grows, early naming choices (vpc, subnet) need to become more specific (dev-web-vpc, prod-private-subnet) to avoid ambiguity
  • Reorganizing after a model's purpose evolves — A model initially managing one resource expands scope, and its data names no longer reflect what they contain
  • Fixing typos — A misspelled data name (deplyoment-state) can be corrected without losing history or breaking consumers
  • Multi-environment setups — When splitting a single model into per-environment variants, existing data needs environment-prefixed names

How it works

The implementation uses a Copy + Tombstone with Forward Reference strategy:

  1. Copy: The latest version of the old data is copied to the new name as version 1
  2. Tombstone: A new version is written on the old name with lifecycle: "deleted" and a renamedTo metadata field pointing to the new name
  3. Forward resolution: When any consumer looks up the old name (via findByName, CEL expressions like data.latest(), or model.* expressions), the repository layer detects the tombstone and transparently follows the forward reference to the new name
  4. History preserved: Version-specific lookups (data.version("model", "old-name", 2)) bypass forwarding and return the original historical data

User impact

  • Zero-downtime rename: Existing workflows and expressions referencing the old name continue to work immediately after rename — no manual updates required for things to keep running
  • Gradual migration: Users can update references at their own pace; the forward reference handles the transition
  • Full audit trail: The old name's version history is preserved; the tombstone version clearly marks when the rename occurred
  • CEL expression compatibility: data.latest(), data.version(), data.findByTag(), and model.* resource expressions all work transparently

Design decisions

  • Forward reference depth limit of 5: Prevents infinite loops from chained renames (A→B→C→D→E→F stops resolving)
  • Repository-level resolution: Forwarding happens in UnifiedDataRepository.findByName(), so every consumer benefits without code changes
  • Deduplication in list operations: After rename, directory scans would return both old (forwarded) and new names; findAllForModel deduplicates by resolved name using a Set
  • Tombstone skipping in expressions: The model resolver's eager population loop skips renamed tombstones to avoid polluting expression contexts
  • Warning on rename: Users are warned that re-running a model that writes to the old name will overwrite the forward reference

What changed

New files

  • src/cli/commands/data_rename.ts — CLI command definition
  • src/cli/commands/data_rename_test.ts — CLI command unit tests
  • src/domain/data/data_rename_service.ts — Domain service orchestrating the rename
  • src/presentation/output/data_rename_output.ts — Output rendering (logger for log mode, JSON for json mode)

Modified files

  • src/domain/data/data.ts — Added renamedTo field, isRenamed getter, withRenameMarker() factory method
  • src/domain/data/data_metadata.ts — Added renamedTo to Zod schema
  • src/infrastructure/persistence/unified_data_repository.ts — Added rename() method, forward-reference following in findByName/findByNameSync, deduplication in findAllForModel/findAllForModelSync
  • src/cli/commands/data.ts — Registered rename subcommand
  • src/cli/commands/data_get.ts — Fixed content path to use resolved name after forwarding
  • src/domain/expressions/model_resolver.ts — Skip renamed tombstones in eager population
  • integration/ddd_layer_rules_test.ts — Bumped ratchet counts for new service/output files
  • 5 test mock files — Added rename stub to mock UnifiedDataRepository implementations

Skill documentation

  • .claude/skills/swamp-data/SKILL.md — Added rename to quick reference, new "Rename Data" section
  • .claude/skills/swamp-data/references/examples.md — Added rename scenarios
  • .claude/skills/swamp-data/references/troubleshooting.md — Added rename troubleshooting, removed defunct index/symlink section

Test plan

Unit tests added (in data_test.ts)

  • withRenameMarker creates correct tombstone with lifecycle: "deleted" and renamedTo
  • isRenamed returns true only for deleted data with renamedTo set
  • isRenamed returns false for deleted data without renamedTo
  • isRenamed returns false for active data with renamedTo (edge case)
  • toData/fromData roundtrip preserves renamedTo
  • toData omits renamedTo when not set
  • withNewVersion preserves renamedTo field

CLI tests added (in data_rename_test.ts)

  • Module loads without error
  • Command has correct description
  • Command is registered as rename subcommand of data
  • --repo-dir option is available
  • Command requires three positional arguments

E2E testing performed manually

  • swamp data rename copies data to new name correctly
  • Forward reference resolves: swamp data get model old-name returns new name's data
  • swamp data list shows renamed data only once (no duplicates)
  • Historical version access: swamp data get model old-name --version 1 returns original
  • data.latest() in CEL expressions resolves through forward reference
  • Workflow re-run after rename produces data under new name correctly

Verification

  • deno fmt — passed
  • deno lint — passed
  • deno check — passed
  • deno run test — 2835 passed, 0 failed
  • deno run compile — successful

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.210849.0-sha.1db81d92/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/v20260311.210849.0-sha.1db81d92/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/v20260311.210849.0-sha.1db81d92/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/v20260311.210849.0-sha.1db81d92/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.190346.0-sha.980e703f

11 Mar 19:04
Immutable release. Only release title and notes can be modified.
980e703

Choose a tag to compare

What's Changed

  • ci: add skill review CI step (#688)

Summary

  • Add scripts/review_skills.ts — reviews all bundled skills via npx tessl skill review, builds a markdown summary table for GITHUB_STEP_SUMMARY, and exits 1 if any skill's average score drops below 90%
  • Add review-skills task to deno.json
  • Add skill-review CI job (Deno + Node.js) to .github/workflows/ci.yml
  • Update needs arrays for claude-review, claude-adversarial-review, and auto-merge to gate on skill-review
  • Update skill descriptions and add data-ownership.md and expressions.md reference docs to swamp-data and swamp-model skills
  • Register new reference files in skill_assets.ts and update tests

Test plan

  • Ran deno run review-skills locally — all 8 skills pass at 100%
  • CI skill-review job passes on this PR
  • Existing test, deps-audit, and review jobs still pass

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.190346.0-sha.980e703f/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/v20260311.190346.0-sha.980e703f/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/v20260311.190346.0-sha.980e703f/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/v20260311.190346.0-sha.980e703f/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.170115.0-sha.0c667d10

11 Mar 17:02
Immutable release. Only release title and notes can be modified.
0c667d1

Choose a tag to compare

What's Changed

  • docs: remove logical views and fix .swamp/ references in design docs (#687)

docs: remove logical views and fix .swamp/ references in design docs

Summary

The datastore refactor moved source-of-truth files from .swamp/ to top-level models/, workflows/, vaults/ directories and replaced symlink-based "logical views" with a NoopRepoIndexService. The design docs were stale — they still referenced logical views and .swamp/ as the canonical storage for definitions/workflows/vaults.

This PR updates all 9 design docs to reflect the current architecture:

  • high-level.md: Replace .swamp/ aggregate storage + logical views with top-level source-of-truth dirs + datastore
  • repo.md: Remove .swamp/ internal storage and logical view sections; document NoopRepoIndexService; replace symlink directory structure with real file layout
  • agent.md: Replace logical views + .swamp/ direct access with source-of-truth directories + datastore + CLI abstraction
  • models.md: Fix definition paths (models/), data paths (datastore), output paths (datastore); remove logical views section
  • workflow.md: Fix workflow paths (workflows/), run paths (datastore), data paths (datastore); remove logical views section
  • vaults.md: Fix vault config path (vaults/{type}/{id}.yaml); remove logical views; update secret storage to note datastore paths
  • expressions.md: Add datastore path notes for data/ and evaluated directories
  • extension.md: Note .swamp/bundles/ as a datastore path
  • datastores.md: Emphasize source-of-truth files are always top-level

Test plan

  • All paths verified against src/infrastructure/persistence/paths.ts, src/cli/repo_context.ts, and repository implementations
  • No remaining stale references to /.swamp/definitions/, /.swamp/workflows/, or /.swamp/vault/
  • Remaining "symlink" references are appropriate (latest data symlinks, extension safety checks, noop explanation)
  • Docs-only change — no code changes, no tests/compilation needed

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.170115.0-sha.0c667d10/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/v20260311.170115.0-sha.0c667d10/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/v20260311.170115.0-sha.0c667d10/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/v20260311.170115.0-sha.0c667d10/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.165546.0-sha.5d8b2333

11 Mar 16:56
Immutable release. Only release title and notes can be modified.
5d8b233

Choose a tag to compare

What's Changed

  • fix: prevent 1Password CLI from reading exhausted stdin pipe (#686)

Summary

Fixes #668swamp vault put to a 1Password-backed vault stores an empty password field when the secret value is piped via stdin.

Root cause: The runOp() helper in OnePasswordVaultProvider spawned op subprocesses without setting stdin: "null", so they inherited the parent process's stdin. When stdin was a pipe (already consumed by readStdin()), the op CLI detected the pipe and attempted to read from it, getting an empty string that overwrote the field=value command-line argument.

Fix: Add stdin: "null" to both Deno.Command calls in the 1Password vault provider (runOp and checkOpInstalled) so child processes never inherit the parent's stdin. No other vault providers are affected — only the 1Password provider shells out to a CLI tool.

The inline KEY=VALUE syntax was unaffected because stdin remains a TTY in that path, so op never tries to read from it.

Test Plan

  • Existing unit tests pass (deno run test)
  • deno check, deno lint, deno fmt all clean
  • The fix can be verified manually with: echo "test-value" | swamp vault put <1p-vault> TEST_KEY

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.165546.0-sha.5d8b2333/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/v20260311.165546.0-sha.5d8b2333/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/v20260311.165546.0-sha.5d8b2333/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/v20260311.165546.0-sha.5d8b2333/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.162257.0-sha.7f330d44

11 Mar 16:23
Immutable release. Only release title and notes can be modified.
7f330d4

Choose a tag to compare

What's Changed

  • fix: handle symlinks and YAML type field in definition repository (#685)

Summary

Fixes #683 — after the datastore refactor, model definitions using symlinks or scoped extension types (e.g., @smith/kibana-dev) were no longer discovered.

Two bugs in yaml_definition_repository.ts:

  • Symlinks silently skipped: Deno.readDir() returns isFile: false for symlinks, so findAll(), findByNameGlobal(), and findAllGlobal() all missed symlinked YAML files. Fixed by also checking entry.isSymlink, with assertSafePath() guarding against symlinks that escape the repo boundary.

  • Type reconstructed from path instead of YAML: collectAllDefinitions() and searchDefinitionByName() reconstructed the model type from directory path segments, ignoring the type field in the parsed YAML. This produced wrong types for scoped extensions where the directory name doesn't match the full type (e.g., path says kibana-dev but YAML says @smith/kibana-dev). Fixed by preferring definition.type from the YAML, falling back to path-based type only when absent.

Important: The path traversal boundary uses repoDir (not baseDir/models/) so that symlinks targeting extensions/models/ or .swamp/definitions/ — inside the repo but outside models/ — are correctly allowed while symlinks escaping the repo are still rejected.

User impact

Users with extension models installed via symlinks (or legacy symlink layouts from before repo upgrade) will have their models discovered again. Users with scoped extension types will see the correct type reported instead of a truncated path-based type.

Test plan

  • Symlinked YAML file discovered by findAll() (target outside models/, in .swamp/definitions/)
  • Symlinked YAML file discovered by findAllGlobal() (target in extensions/models/)
  • Symlinked YAML file discovered by findByNameGlobal() (target in extensions/models/)
  • Combined scenario: symlinked extension with scoped type @smith/kibana-dev — both symlink discovery and type resolution work together
  • Type read from YAML type field, not path, when present
  • Path-based type used as fallback when YAML type field is missing
  • Symlink pointing outside repo boundary is rejected (path traversal protection)
  • All 2823 existing tests pass
  • deno check, deno lint, deno fmt, deno run compile pass

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.162257.0-sha.7f330d44/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/v20260311.162257.0-sha.7f330d44/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/v20260311.162257.0-sha.7f330d44/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/v20260311.162257.0-sha.7f330d44/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.151803.0-sha.f73d7a6d

11 Mar 15:19
Immutable release. Only release title and notes can be modified.
f73d7a6

Choose a tag to compare

What's Changed

  • fix: respect --repo-dir for user model and vault loading (#684)

Summary

Fixes #682.

loadUserModels(), loadUserVaults(), and initTelemetryService() in src/cli/mod.ts hardcoded Deno.cwd() to locate the swamp repo at CLI startup — before Cliffy parses command options. This meant --repo-dir was completely ignored for:

  • Extension model type registration → "Unknown model type" when running from a different directory
  • User vault implementation loading
  • Telemetry config and log level resolution from .swamp.yaml

Approach

Pre-parse --repo-dir from the raw args array (following the existing getOutputModeFromArgs pattern for --json) and thread the resolved path through all four startup functions. This is the minimal fix — no command-level changes, no changes to requireInitializedRepo, and behavior is identical when --repo-dir is not specified.

Changes

  • src/cli/context.ts — Added getRepoDirFromArgs(args) that extracts --repo-dir from raw CLI args (supports both --repo-dir <value> and --repo-dir=<value> forms), resolves to an absolute path, defaults to cwd
  • src/cli/mod.ts — Call getRepoDirFromArgs(args) once at the top of runCli(), pass the result to loadUserModels(repoDir), loadUserVaults(repoDir), initTelemetryService(repoDir), and the marker read block
  • src/cli/context_test.ts — 6 new tests for the pre-parser (no flag, space separator, equals separator, relative path resolution, missing value, flag among other args)

Test Plan

  • 6 new unit tests for getRepoDirFromArgs covering all arg forms and edge cases
  • Full test suite passes (2811 tests, 0 failures)

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.151803.0-sha.f73d7a6d/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/v20260311.151803.0-sha.f73d7a6d/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/v20260311.151803.0-sha.f73d7a6d/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/v20260311.151803.0-sha.f73d7a6d/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.151523.0-sha.5c71d81f

11 Mar 15:16
Immutable release. Only release title and notes can be modified.
5c71d81

Choose a tag to compare

What's Changed

  • fix: reject path traversal in workflow names (#681)

Summary

  • WorkflowSchema.name was missing the path-traversal validation that DefinitionSchema already has — swamp workflow create "../../etc/passwd" silently succeeded (exit 0) instead of failing
  • Added .refine() guard rejecting .., /, \, and null bytes (matching the DefinitionSchema pattern)
  • Added eager name validation in Workflow.create() so path traversal is caught even when the full schema parse is skipped (empty-jobs code path)
  • 4 new unit tests covering all rejection cases

Test plan

  • 26 workflow unit tests pass (including 4 new path traversal tests)
  • deno check passes
  • deno lint passes
  • deno fmt --check passes

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.151523.0-sha.5c71d81f/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/v20260311.151523.0-sha.5c71d81f/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/v20260311.151523.0-sha.5c71d81f/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/v20260311.151523.0-sha.5c71d81f/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.135022.0-sha.55361247

11 Mar 13:51
Immutable release. Only release title and notes can be modified.
5536124

Choose a tag to compare

What's Changed

  • fix: address review findings from PRs #678 and #675 (#680)

Summary

Follow-up to #678 (datastore lock deadlock fix) and #675 (non-TTY interactive command fix). Addresses three issues identified in adversarial review of those PRs:

  • TOCTOU race in lock release (datastore_lock.ts): Added forceRelease(expectedNonce) to the DistributedLock interface so each backend (S3Lock, FileLock) can verify the nonce and delete in the tightest possible sequence. The datastore lock release command now delegates to this method instead of branching on config type with separate delete logic. This also removed the redundant S3Client instantiation and join import from the command handler.

  • Double marker file read in requireInitializedRepo (repo_context.ts): The refactoring in #678 caused requireInitializedRepo to read the .swamp.yaml marker file twice — once inside resolveDatastoreForRepo and again directly. resolveDatastoreForRepo now returns the marker it already read, and requireInitializedRepo reuses it, eliminating the redundant I/O.

  • extension_search.ts missed in #675: PR #675 updated 10 interactive search commands to use interactiveOutputMode() but missed extension_search. Applied the same pattern so it won't crash with "Raw mode is not supported" in non-TTY contexts (e.g. echo "" | swamp extension search aws).

Test plan

  • 6 new tests for forceRelease (3 per lock backend): matching nonce, mismatched nonce, no lock exists
  • Updated resolveDatastoreForRepo test to verify marker is returned
  • All 2805 tests pass
  • deno check passes
  • deno lint passes
  • deno fmt --check passes

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.135022.0-sha.55361247/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/v20260311.135022.0-sha.55361247/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/v20260311.135022.0-sha.55361247/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/v20260311.135022.0-sha.55361247/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.132338.0-sha.398857eb

11 Mar 13:24
Immutable release. Only release title and notes can be modified.
398857e

Choose a tag to compare

What's Changed

  • fix: prevent datastore lock commands from deadlocking on stuck lock (#678)

Fixes #676

Summary

  • datastore lock status and datastore lock release --force called requireInitializedRepo() which acquires the datastore lock via registerDatastoreSync() — causing the breakglass commands to deadlock on the very lock they were meant to inspect or release
  • Added resolveDatastoreForRepo() to src/cli/repo_context.ts — a lightweight function that resolves repo path + datastore config without acquiring the lock. The lock commands now use this instead
  • Refactored requireInitializedRepo() to call resolveDatastoreForRepo() internally, keeping a single source of truth for repo validation and datastore config resolution
  • Zero user impact for normal usage — only the two broken breakglass commands are affected, and they now work

Test Plan

  • New tests for resolveDatastoreForRepo: returns correct config without acquiring lock, throws UserError for non-initialized repos
  • All 2799 tests pass
  • deno fmt --check passes
  • deno lint passes
  • deno check passes
  • Verified no UAT test impact — no UAT tests exercise datastore lock commands

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.132338.0-sha.398857eb/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/v20260311.132338.0-sha.398857eb/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/v20260311.132338.0-sha.398857eb/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/v20260311.132338.0-sha.398857eb/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260311.105043.0-sha.fa48cb0c

11 Mar 10:51
Immutable release. Only release title and notes can be modified.
fa48cb0

Choose a tag to compare

What's Changed

  • fix: gracefully handle non-TTY context in interactive commands (#675)

Fixes #674

Summary

  • Interactive search commands (model search, type search, workflow search, etc.) use Ink for terminal UIs which requires raw mode on stdin. In non-TTY contexts (piped input, CI, AI agents), Ink crashes with "Raw mode is not supported". This was a pre-existing bug — it existed before datastores — but the introduction of the datastore lock made it much worse: the crash now leaks the lock, blocking all subsequent swamp commands for ~60 seconds until timeout.

  • Fix 1 — interactiveOutputMode() helper (src/cli/context.ts): A new function that returns "json" when ctx.outputMode is "json" OR when stdin is not a TTY. Applied surgically to all 10 interactive search commands so they fall back to structured JSON output instead of crashing. Non-interactive commands (version, model get, workflow run, etc.) are unaffected — they keep their normal output mode.

  • Fix 2 — Safety net in main.ts: Added flushDatastoreSync() to the top-level catch block so the datastore lock is released even on unexpected crashes that bypass runCli()'s own error handling. flushDatastoreSync() is idempotent (nulls its state on first call), so calling it a second time is harmless.

Commands updated with interactiveOutputMode:

  • model search, type search, vault search, vault type search
  • workflow search, workflow run search, workflow history search
  • model method history search, model output search, data search

Test Plan

  • All 2797 tests pass (zero failures)
  • deno fmt --check passes
  • deno lint passes
  • deno check passes
  • Verified the global outputMode approach (auto-switching all commands) caused 6 test failures — confirmed the surgical per-command approach is correct
  • Verified non-interactive commands retain log-mode output in non-TTY contexts

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260311.105043.0-sha.fa48cb0c/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/v20260311.105043.0-sha.fa48cb0c/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/v20260311.105043.0-sha.fa48cb0c/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/v20260311.105043.0-sha.fa48cb0c/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/