Releases: systeminit/swamp
swamp 20260305.011558.0-sha.b591ba6a
What's Changed
- fix: invalidate bundle cache when local dependencies change (#607)
Summary
Fixes #605.
When iterating on extensions, swamp serves stale bundled code because bundleWithCache only checks the entry point file's mtime against the cached bundle. If a locally imported dependency changes, the cache is incorrectly treated as fresh — the dependency change is invisible to the cache check.
The fix
Replace the single-file mtime check with a full dependency graph mtime check:
- Stat the cached bundle to get its mtime
- Use
resolveLocalImports()to walk the entry point's local import graph and collect all.tsdependencies - Stat every dependency and find the newest mtime
- Only use the cache if the bundle is newer than all dependencies
This is correct because resolveLocalImports already existed and is well-tested — it recursively follows relative import/export statements within a boundary directory, which is exactly the set of files that deno bundle would process.
Architecture boundary
resolveLocalImports previously lived in extensions/. Importing it directly into models/ would have introduced a new extensions <-> models mutual dependency, caught by the architecture boundary ratchet test. To avoid this, the function was moved to models/local_import_resolver.ts (a natural home alongside bundle.ts), with extensions/extension_import_resolver.ts re-exporting for backward compatibility. No new cross-context dependencies.
Future optimisation
The current approach re-resolves the import graph on every cache check by reading each dependency file to parse its imports. For small-to-moderate extensions this is negligible, but for large dependency trees with many files it adds I/O. A future optimisation would be to persist the resolved dependency list alongside the cached bundle (e.g. a .deps.json sidecar file), so cache checks only need stat calls rather than file reads + regex parsing. This would reduce the cache-hit path to N stat calls with no file reads. This isn't necessary today but is a clear path forward if profiling shows it matters.
Test plan
- New test: model loader invalidates cache when dependency file changes
- New test: vault loader invalidates cache when dependency file changes
- All 2689 existing tests pass
- Architecture boundary ratchet test passes (no new mutual dependencies)
-
deno check,deno lint,deno fmtall pass -
deno run compilesucceeds
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260305.011558.0-sha.b591ba6a/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/v20260305.011558.0-sha.b591ba6a/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/v20260305.011558.0-sha.b591ba6a/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/v20260305.011558.0-sha.b591ba6a/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260305.002807.0-sha.56e4175a
What's Changed
- fix: bundle missing skill files in repo init and upgrade (#606)
Summary
- Add
swamp-extension-model/references/publishing.mdandswamp-vault/references/user-defined-vaults.mdtoBUNDLED_SKILLS— these files existed on disk but were never copied duringswamp repo initorswamp repo upgrade - Add a formatting requirement callout to the publishing guide so agents know
swamp extension fmtis a hard gate before push
Test Plan
-
deno fmt --checkpasses -
deno lintpasses -
deno run testpasses (2674/2674) - Run
swamp repo initin a fresh directory and verify both files are present
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260305.002807.0-sha.56e4175a/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/v20260305.002807.0-sha.56e4175a/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/v20260305.002807.0-sha.56e4175a/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/v20260305.002807.0-sha.56e4175a/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260304.213352.0-sha.2bb8ca15
What's Changed
- feat: add swamp summarise command (#604)
Summary
Closes #460
Adds a new swamp summarise command that gives users a single, high-level overview of all repo activity over a configurable time window — method executions, workflow runs, and data produced. Previously, understanding what happened in a repo required running multiple siloed commands.
Usage
swamp summarise [--since <duration>] [-v] [--json]
--since: Time window (e.g.1h,1d,7d,1w). Defaults to7d.-v: Verbose mode — shows per-run detail beneath each group.--json: Full structured JSON output for scripting/integration.
Default output
Activity summary (last 7d)
Direct Model Method Executions (6 total: 6 succeeded)
Model: echo-test (command/shell)
execute ✓ 5
Model: list-files (command/shell)
execute ✓ 1
Workflow Runs (2 total: 2 succeeded)
test-pipeline ✓ 2
Data (4 items, 12 versions, 2 models)
Verbose output (-v)
Activity summary (last 7d)
Direct Model Method Executions (6 total: 6 succeeded)
Model: echo-test (command/shell)
execute ✓ 5
2026-03-04 19:26 succeeded 11ms workflow
2026-03-04 19:26 succeeded 12ms workflow
2026-03-04 19:25 succeeded 11ms manual
2026-03-04 19:25 succeeded 11ms manual
2026-03-04 19:25 succeeded 14ms manual
Model: list-files (command/shell)
execute ✓ 1
2026-03-04 19:25 succeeded 12ms manual
Workflow Runs (2 total: 2 succeeded)
test-pipeline ✓ 2
2026-03-04 19:26 succeeded
main > example (echo-test) succeeded 15ms
2026-03-04 19:26 succeeded
main > example (echo-test) succeeded 17ms
Data (4 items, 12 versions, 2 models)
command/shell 4 items, 12 versions
Design decisions
- Model-centric grouping: Method executions are grouped by model name (e.g.
echo-test), not by underlying type (command/shell.execute). Users think in terms of their models. UsesDefinitionRepositoryto resolve definition IDs to names. - Workflow step breakdown: Verbose mode shows job/step detail within each workflow run, including which model each step invoked and its duration. Uses
WorkflowRepositoryto map step names back to their task definitions. - Domain layer purity: A
DataRepositoryReaderinterface is defined in the domain layer to avoid importingUnifiedDataRepositoryfrom infrastructure (enforced by DDD ratchet tests). - Version-aware data counting:
totalVersionssums each item'sversionfield (version N = N versions exist), giving accurate data churn visibility. - Load-all-then-filter: Consistent with other commands; fine for local repo scale.
Test plan
-
deno checkpasses -
deno lintpasses -
deno fmtpasses -
deno run testpasses (2681 tests, 0 failures) -
deno run compilesucceeds - End-to-end tested with compiled binary: log, verbose, JSON, and empty window modes
- DDD layer ratchet tests pass (presentation→infra bumped 36→37 for logger consistency)
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260304.213352.0-sha.2bb8ca15/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/v20260304.213352.0-sha.2bb8ca15/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/v20260304.213352.0-sha.2bb8ca15/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/v20260304.213352.0-sha.2bb8ca15/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260304.212925.0-sha.65fba57a
What's Changed
- feat: allow all namespaces for local model and vault loading (#603)
Summary
- Remove reserved namespace blocking from local model and vault loaders
- All namespace combinations (
@swamp/*,@si/*,swamp/*,si/*,myorg/*) are now valid for local loading - Only validation remaining is the minimum 2-segment requirement (e.g.,
myorg/my-model)
Why
This is a follow-up to #600. That PR relaxed the @ prefix requirement but still blocked swamp/* and si/* without @ prefix locally, and blocked @swamp/*/@si/* for vaults. The model loader already allowed @swamp/* and @si/* for local development, but the vault loader didn't — and neither loader allowed bare swamp/* or si/*.
For local development, developers need to build and test extensions with any namespace. Reserved namespace enforcement should only happen at the extension push boundary, not during local loading.
What still blocks reserved namespaces
The extension push pipeline is unchanged and still blocks @swamp/*, @si/*, swamp/*, and si/* when publishing to the registry:
src/domain/extensions/extension_manifest.ts— manifest validationsrc/domain/extensions/extension_namespace_validator.ts— content namespace validationsrc/domain/extensions/extension_dependency_resolver.ts— dependency resolution
This separation allows developers to build and test extensions locally with any namespace while preventing unauthorized use of reserved namespaces in the public registry.
Changes
| File | Change |
|---|---|
src/domain/models/user_model_loader.ts |
Remove reserved namespace check from validateUserNamespace() — only segment count validation remains |
src/domain/vaults/user_vault_loader.ts |
Remove RESERVED_NAMESPACES constant and validateUserNamespace() method entirely |
src/domain/models/user_model_loader_test.ts |
Change swamp/* and si/* rejection tests to acceptance tests |
src/domain/vaults/user_vault_loader_test.ts |
Change @swamp/* rejection test to acceptance test; change swamp/* and si/* rejection tests to acceptance tests |
Test plan
-
deno check— type checking passes -
deno lint— clean -
deno fmt— clean -
deno run test— all 50 tests pass (41 model loader + 9 vault loader)
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260304.212925.0-sha.65fba57a/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/v20260304.212925.0-sha.65fba57a/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/v20260304.212925.0-sha.65fba57a/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/v20260304.212925.0-sha.65fba57a/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260304.202030.0-sha.3596ccf4
What's Changed
- feat: relax namespace validation for local models and vaults (#600)
Summary
- Remove the
@prefix requirement for user-defined extension model and vault types - Non-
@types likedigitalocean/app-platformare now valid (implicitly@swamp/digitalocean/app-platform) - Reserved namespaces (
swamp/*,si/*) remain blocked for non-@types @swamp/*and@si/*remain allowed for local development
Why
Swamp-managed extensions are moving from @swamp/aws/ec2 to just aws/ec2 — a missing @ namespace is implicitly treated as @swamp. This means user-defined extension models without the @ prefix should also be valid, but loading extensions/models/app_platform.ts with type: "digitalocean/app-platform" previously failed with "Model type must use '@' prefix".
This change is scoped to local model/vault loading only. Extension push validation (manifest, namespace validator) is deferred.
Changes
| File | Change |
|---|---|
src/domain/models/user_model_loader.ts |
Remove @ prefix check, add reserved namespace check for non-@ types |
src/domain/vaults/user_vault_loader.ts |
Make @ optional in type pattern, extend reserved namespace list |
src/domain/models/user_model_loader_test.ts |
Update 3 existing tests, add 2 new tests |
src/domain/vaults/user_vault_loader_test.ts |
Add 3 new tests for non-@ vault types |
.claude/skills/swamp-extension-model/SKILL.md |
Update type naming docs |
.claude/skills/swamp-extension-model/references/troubleshooting.md |
Replace @ prefix error section with reserved namespace guidance |
.claude/skills/swamp-vault/references/user-defined-vaults.md |
Update vault type format docs |
Test plan
-
deno check— type checking passes -
deno lint— clean -
deno fmt— clean -
deno run test— all 50 tests pass (41 model loader + 9 vault loader) -
deno run compile— binary compiles - Verified no UAT tests broken by this change
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260304.202030.0-sha.3596ccf4/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/v20260304.202030.0-sha.3596ccf4/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/v20260304.202030.0-sha.3596ccf4/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/v20260304.202030.0-sha.3596ccf4/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260304.180533.0-sha.2e4f52b9
What's Changed
- feat: add per-version releaseNotes field to extension push (#599)
Summary
Closes #567
Adds an optional releaseNotes field so extension authors can attach per-version changelogs when publishing with swamp extension push, without overloading the description field.
Why this design
Previously, the only way to communicate what changed in a version was to modify description, which conflates the stable extension summary with ephemeral patch notes. This adds a dedicated releaseNotes string (max 5000 chars) that flows through the full push pipeline alongside existing metadata like description, labels, and platforms.
Two input methods are supported:
- Manifest field (
releaseNotesinmanifest.yaml) — for checked-in release notes - CLI flag (
--release-notes <text>) — for ad-hoc or CI-generated notes; takes precedence over the manifest value
This mirrors the precedence pattern already used for other fields like version.
User impact
Extension authors can now include release notes when pushing:
# manifest.yaml
releaseNotes: |
- Fixed deployment timeout bug
- Added retry logic for transient failuresOr via the CLI:
swamp extension push --release-notes "Hotfix for auth token refresh" manifest.yamlRelease notes are displayed in the resolved bundle output before push confirmation, giving authors a chance to verify.
Backward compatibility
releaseNotesis optional everywhere — existing manifests and workflows continue to work unchanged- Older CLI versions that don't send
releaseNoteswill simply havenullstored on the registry side (the registry uses the established?? nullfallback pattern) - No breaking changes to the API contract; the field is additive only
Registry-side changes are tracked separately in systeminit/swamp-club#196.
Files changed
| File | Change |
|---|---|
src/domain/extensions/extension_manifest.ts |
Zod schema + interface |
src/cli/commands/extension_push.ts |
CLI flag + metadata wiring |
src/infrastructure/http/extension_api_client.ts |
PushMetadata type |
src/presentation/output/extension_push_output.ts |
Resolved bundle display |
src/domain/extensions/extension_manifest_test.ts |
Tests for presence/absence |
Test plan
-
deno check— type checking passes -
deno lint— clean -
deno fmt— clean -
deno run test— all 19 manifest tests pass (including new releaseNotes test) -
deno run compile— binary compiles successfully
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260304.180533.0-sha.2e4f52b9/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/v20260304.180533.0-sha.2e4f52b9/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/v20260304.180533.0-sha.2e4f52b9/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/v20260304.180533.0-sha.2e4f52b9/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260304.144355.0-sha.1e71245f
What's Changed
- fix: use index-based naming for forEach over object arrays with static step names (#598)
Summary
Fixes #597
- When a
forEachiterates over an array of objects and the step name has no${{ }}expression, the fallback naming usedString(item)which produced[object Object]for every item — all expanded steps got identical names, causing the topological sort to report a spurious cyclic dependency error - Now detects object/array items in the fallback path and uses index-based suffixes (
step-0,step-1, ...) instead. Scalar items (strings, numbers, booleans) keep the existingString(item)behavior - Logs a warning when falling back to index-based naming, suggesting the user add a
${{ self.<item>.<field> }}expression to the step name for better observability
How it works
In expandForEachSteps(), the array iteration loop now tracks the index. When the step name has no expression template and the current item is an object or array, it falls back to ${step.name}-${index} instead of ${step.name}-${String(item)}.
Testing
Automated
- Added integration test in
integration/foreach_test.tsthat creates a workflow withforEachover an array of 3 objects using a static step name, verifies no cyclic dependency error, and confirms index-based step names (deploy-server-0,deploy-server-1,deploy-server-2) - All 2668 tests pass
Manual (compiled binary)
Tested with a real swamp repo in /tmp:
Bug scenario — forEach over object array with static step name:
workflow run test-foreach-object-static \
--input '{"servers": [{"host": "web1", "port": 8080}, {"host": "web2", "port": 8081}, {"host": "web3", "port": 8082}]}'
Result: status: "succeeded", steps named deploy-server-0, deploy-server-1, deploy-server-2
Existing scenario — forEach over string array with expression:
workflow run test-foreach-string-expr \
--input '{"environments": ["dev", "staging", "production"]}'
Result: status: "succeeded", steps named deploy-dev, deploy-staging, deploy-production (no regression)
Test plan
-
deno check— passes -
deno lint— passes -
deno fmt— passes -
deno run test— 2668 passed, 0 failed -
deno run compile— compiles successfully - Manual test with compiled binary confirms fix and no regression
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260304.144355.0-sha.1e71245f/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/v20260304.144355.0-sha.1e71245f/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/v20260304.144355.0-sha.1e71245f/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/v20260304.144355.0-sha.1e71245f/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260304.014630.0-sha.88b753fc
What's Changed
- feat: validate extension content namespaces during push (#595)
Fixes: #594
Summary
Prevents namespace squatting by validating that all content items (models, vaults, workflows) inside an extension use the same namespace as the extension package itself during extension push.
Why this matters
Previously, extension push only validated the manifest name field against reserved namespaces (@swamp, @si) and the authenticated user. But models, vaults, and workflows inside the extension could claim any namespace — e.g., a model with type @swamp/echo inside @stack72/my-extension. This is a namespace squatting risk that could allow:
- Impersonation: An extension under
@stack72/could register model types under@swamp/or@si/, making them appear official - Namespace pollution: Content could use arbitrary namespaces like
aws/ec2without any@prefix at all - User spoofing: An extension under
@stack72/could register content under@eviluser/, squatting on another user's namespace
How it works
A new domain validation function validateContentNamespaces() runs after content metadata extraction during push. It extracts the namespace prefix from the extension name (e.g., @stack72/ from @stack72/my-extension) and checks that every:
- Model type starts with the prefix
- Vault type starts with the prefix
- Workflow name starts with the prefix
Validation runs after the manifest name may have been rewritten to match the authenticated user (when the user accepts the namespace correction prompt), so it always checks against the correct namespace.
Changes
- NEW
src/domain/extensions/extension_namespace_validator.ts— Pure domain function withNamespaceMismatchandNamespaceValidationResulttypes - NEW
src/domain/extensions/extension_namespace_validator_test.ts— 9 unit tests (pure function, no filesystem) - MODIFIED
src/domain/extensions/extension_content.ts— AddedfileNametoExtractedWorkflowfor error reporting - MODIFIED
src/domain/extensions/extension_content_extractor.ts— PopulatesfileNameon workflows usingarchiveName - MODIFIED
src/presentation/output/extension_push_output.ts— AddedrenderExtensionPushNamespaceErrors()for both log and JSON output modes - MODIFIED
src/cli/commands/extension_push.ts— Inserted validation step (9c) after content metadata extraction - MODIFIED
src/domain/extensions/extension_content_extractor_test.ts— Updated 3 workflow tests for newfileNamefield - MODIFIED
integration/extension_push_test.ts— Updated 4 workflow names in 2 integration tests to use@test/namespace prefix
Test scenarios
All scenarios were verified end-to-end with extension push --dry-run against a real compiled binary, authenticated as @stack72:
| # | Scenario | Expected | Result |
|---|---|---|---|
| 1 | All content uses @stack72/ (model + vault + workflow) |
Pass | Dry run complete |
| 2 | Model squats @swamp/sneaky-model |
Block | model: "@swamp/sneaky-model" in bad-squatter.ts |
| 3 | Model uses aws/ec2 (no @ prefix) |
Block | model: "aws/ec2" in bad-no-namespace.ts |
| 4 | Vault squats @si/stolen-vault |
Block | vault: "@si/stolen-vault" in bad-vault.ts |
| 5 | Workflow uses no-namespace-workflow (no prefix) |
Block | workflow: "no-namespace-workflow" in bad-wf.yaml |
| 6 | Mixed: wrong model + wrong vault + wrong workflow | Block | All 3 mismatches reported together |
| 7 | Same as #6 with --json output |
Block | Structured JSON with namespaceErrors object |
Test plan
-
deno check— type checking passes -
deno lint— linting passes -
deno fmt— formatting passes -
deno run test— all 2667 tests pass (0 failed) -
deno run compile— binary compiles - E2E dry-run scenarios verified against compiled binary
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260304.014630.0-sha.88b753fc/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/v20260304.014630.0-sha.88b753fc/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/v20260304.014630.0-sha.88b753fc/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/v20260304.014630.0-sha.88b753fc/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260304.001341.0-sha.5a407e45
What's Changed
Summary
- Local extension models using
@swamp/*or@si/*namespaces were incorrectly rejected during loading with "uses a reserved namespace" errors - Removed the reserved namespace check from the user model loader — users should be free to use any
@-prefixed namespace locally since we don't enforce namespace ownership on publish - The extension manifest validation (for
extension push) still blocks publishing under@swampor@si
Test plan
- Updated 4 tests:
swamp/*andsi/*(no@) now check for "must use '@' prefix" error;@swamp/*and@si/*now expect successful loading - All 39 user model loader tests pass
- All 80 extension tests pass (manifest still enforces reserved namespaces for publishing)
-
deno fmt --checkpasses -
deno lintpasses -
deno run compileproduces working binary
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260304.001341.0-sha.5a407e45/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/v20260304.001341.0-sha.5a407e45/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/v20260304.001341.0-sha.5a407e45/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/v20260304.001341.0-sha.5a407e45/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260303.215804.0-sha.809428ec
What's Changed
- feat: show model types and vault metadata in extension push display (#592)
Summary
Fixes the extension push resolved display to show model type strings
(e.g., @adam/cfgmgmt/link) instead of raw filenames (e.g.,
cfgmgmt/link.ts). Also adds Global Arguments to the model display and
enriches vault entries with type, name, and config field metadata.
Additionally, the ExtensionContentMetadata system now extracts vault
metadata from extensions/vaults/ source files, closing the gap where
models and workflows were indexed but vaults were not.
Closes #589
What changed
Modified files (6)
| File | Changes |
|---|---|
src/domain/extensions/extension_content.ts |
Added globalArguments to ExtractedModel; added ExtractedVault interface; added vaults to ExtensionContentMetadata |
src/domain/extensions/extension_content_extractor.ts |
Added extractGlobalArguments() and extractVaultFromSource() functions; added vaultFiles/vaultsDir params to extractContentMetadata() |
src/domain/extensions/extension_content_extractor_test.ts |
Updated 13 existing tests for new return shape; added 6 new tests (globalArguments inline, globalArguments named ref, vault extraction, vault configSchema, skip non-vault, skip vault without type) |
src/cli/commands/extension_push.ts |
Moved content metadata extraction before the resolved display; maps extracted metadata to presentation DTOs with fallback to file paths |
src/presentation/output/extension_push_output.ts |
Replaced modelFiles/vaultFiles string arrays with rich ResolvedModelEntry/ResolvedVaultEntry types; display shows type strings, global arguments, vault names, and config fields |
src/presentation/output/extension_push_output_test.ts |
Updated resolved display test to use new models/vaults fields |
Design decisions
Content metadata extraction moved earlier in push flow
Previously, extractContentMetadata() ran after the resolved display
(step 12b) and was only used for the registry push. Now it runs before
the display (step 9b) so the same extracted data enriches both the local
display and the registry payload — no double extraction.
Map-based lookup instead of endsWith matching
The resolved display maps file paths to extracted metadata using a Map
keyed by the relative path from models/vaults dir. This avoids false
matches when files share a suffix (e.g., models/instance.ts and
models/aws/instance.ts both ending with instance.ts).
Vault extraction uses createProvider as discriminator
Following the same approach as the registry (swamp-club #184), vault
files are identified by the presence of createProvider in the source.
This cleanly distinguishes vault files from utility modules that may
also live in the vaults directory.
hasConfigSchema boolean aligns with registry expectations
The ExtractedVault type includes both hasConfigSchema (boolean for
the registry's indexed shape) and configFields (detailed field array
for local display). The registry stores whatever is present but only
requires the boolean.
Default parameters preserve backward compatibility
extractContentMetadata() uses default parameter values (vaultFiles = [], vaultsDir = "") so all existing callers continue to work without
modification.
Tradeoffs
Workflow inputs not extracted
Workflow YAML files can define an inputs schema (JSON Schema with
properties, required fields, defaults) but the extractor does not
capture this. Adding it is straightforward but was out of scope for this
issue. This means the registry doesn't know what parameters a workflow
accepts — tracked as a follow-up.
Regex-based extraction, not AST parsing
All extraction (models, vaults, globalArguments) uses regex with
balanced-brace matching rather than a TypeScript AST parser. This is
consistent with the existing extractor design — fast, zero-dependency,
and sufficient for the canonical patterns. The tradeoff is that unusual
formatting or dynamic expressions won't be captured, but extraction is
best-effort by design (failures are silently skipped).
No display enrichment for workflows
Workflows still display as raw file paths. Enriching them with extracted
name/description would be a natural follow-up but was not part of the
issue scope.
User impact
Push display now shows model types instead of filenames
Before:
Models (2):
extensions/models/cfgmgmt/link.ts
extensions/models/cfgmgmt/apply.ts
After:
Models (2):
@adam/cfgmgmt/link (extensions/models/cfgmgmt/link.ts)
Global Arguments:
region: string
profile: string (optional)
@adam/cfgmgmt/apply (extensions/models/cfgmgmt/apply.ts)
Push display now shows vault metadata instead of filenames
Before:
Vaults (1):
extensions/vaults/hashicorp.ts
After:
Vaults (1):
@hashicorp/vault - HashiCorp Vault (extensions/vaults/hashicorp.ts)
Config Fields:
address: string
token_env: string (optional)
Registry receives vault content metadata
The contentMetadata payload sent during extension push confirm phase
now includes a vaults array alongside the existing models and
workflows arrays, enabling the registry to index vault types without
re-parsing the archive.
Graceful fallback
If metadata extraction fails for any file, the display falls back to
showing file paths (the previous behavior). Push is never blocked by
extraction failures.
Test plan
- 21 extractor tests pass (13 existing updated + 6 new vault/globalArguments + 2 assertion additions)
- 7 push output tests pass (1 updated for new shape)
- All 2658 tests pass
-
deno checkpasses -
deno lintpasses -
deno fmt --checkpasses -
deno run compileproduces working binary
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260303.215804.0-sha.809428ec/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/v20260303.215804.0-sha.809428ec/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/v20260303.215804.0-sha.809428ec/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/v20260303.215804.0-sha.809428ec/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/