Skip to content

Releases: systeminit/swamp

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/

swamp 20260310.230813.0-sha.fcc69c53

10 Mar 23:09
Immutable release. Only release title and notes can be modified.
fcc69c5

Choose a tag to compare

What's Changed

  • fix: address adversarial review findings for distributed locking and S3 sync (#672)

Summary

Addresses findings from two rounds of adversarial review on the datastore PR.

Changes

Critical: Path traversal in S3 cache sync

  • Added assertSafePath() that validates resolved paths stay within the cache directory
  • Applied to pullFile(), pullChanged(), pushFile(), and getCachePath()
  • Prevents malicious S3 keys (e.g., ../../../home/user/.bashrc) from writing outside the cache

High: Lock theft via unconditional heartbeat overwrites

  • Added nonce-based fencing tokens to distributed locks
  • LockInfo now includes an optional nonce field (UUID generated on acquire)
  • extend() reads the current lock and verifies the nonce matches before writing
  • If another process has acquired the lock (different nonce), the old holder self-revokes
  • This prevents a paused process from overwriting a legitimately acquired lock after recovery

High: Stale lock detection TOCTOU

  • Simplified stale lock cleanup to best-effort delete + conditional write retry
  • The nonce fencing makes this safe: even if we accidentally delete a fresh lock, the old holder's extend() will see the wrong nonce and self-revoke
  • Removed the ineffective double-check pattern that didn't actually close the race window

High: Degraded mode silently allows corruption

  • Lock acquisition failure now throws instead of logging a warning and continuing
  • Concurrent commands without locks would corrupt data; failing fast is the correct behavior

Medium: Hidden file exclusion asymmetry

  • pushChanged() and pushAll() now skip only specific metadata files (.datastore-index.json, .push-queue.json, .datastore.lock) instead of all dot-files
  • Matches pullAll() behavior so hidden files like .gitkeep sync correctly

Medium: S3 bucket name validation

  • Added regex validation for S3 bucket names (3-63 chars, lowercase, alphanumeric/hyphens/dots)
  • Applied to both SWAMP_DATASTORE env var parsing and .swamp.yaml config loading

Medium: S3 client null body check

  • Replaced response.Body! non-null assertion with explicit null check and descriptive error

Medium: SIGINT handler timeout

  • Lock release on Ctrl-C now has a 5-second timeout before force-exiting
  • Prevents the process from hanging if S3 is unreachable

Medium: Force release holder verification

  • swamp datastore lock release --force now re-verifies the lock holder (via nonce) before deleting
  • Prevents accidentally deleting a lock that was legitimately acquired between inspect and delete

Test plan

  • deno check passes
  • deno lint passes
  • deno fmt passes
  • deno run test — 2797 tests pass
  • deno run compile succeeds

Installation

macOS (Apple Silicon):

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

swamp 20260310.230044.0-sha.2610458f

10 Mar 23:01
Immutable release. Only release title and notes can be modified.
2610458

Choose a tag to compare

What's Changed

  • fix: prevent auto-merge race with adversarial review (#673)

Summary

  • Replaces gh pr merge --auto --squash with gh pr merge --squash in the CI auto-merge job
  • The --auto flag enables GitHub's persistent auto-merge, which merges based on branch protection rules rather than the YAML needs: dependencies
  • This caused PR #669 to auto-merge after the normal review passed but before the adversarial review completed

Root cause

The auto-merge job has needs: [test, deps-audit, claude-review, claude-adversarial-review], but --auto tells GitHub "merge this PR whenever branch protection requirements are met." If claude-adversarial-review isn't a required status check in branch protection settings, GitHub merges as soon as the other checks pass — ignoring the YAML dependency.

Fix

Remove --auto so the merge command executes directly when the job runs. Since the job is gated by needs:, it only runs after all four dependencies (including adversarial review) succeed.

Test plan

  • Verify CI workflow passes on this PR
  • Confirm PRs no longer merge before adversarial review completes

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

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