Relationships
#2613 extension push: workflows listed with a shared directory prefix collapse into one workflows.yaml; all but the last are silently dropped
Opened by swamp_lord · 9/28/2026· Shipped 10/5/2026
Summary
When a manifest lists several workflows under the same directory (e.g. workflows/a.yaml, workflows/b.yaml, workflows/c.yaml), swamp extension push writes every one of them to the same archive path, extension/workflows/workflows.yaml. Each copy overwrites the previous one, so the published package contains only the last listed workflow. Push and --dry-run succeed with no warning, and the dry-run still reports Workflows (3).
Listing the same files by bare file name (a.yaml, b.yaml, c.yaml) packages all three.
Environment
- swamp
20260928.160203.0-sha.b76c8a82(also observed with20260917.193606.0-sha.6bf7f212publishing and20260925.013241.0-sha.4489c40dpulling via--server)
Steps to reproduce
swamp repo init repro && cd repro; add a no-op model atextensions/models/noop.tsand three workflowsworkflows/workflow-repro-{alpha,beta,gamma}.yaml(each a singleassertstep).manifest-prefixed.yaml:manifestVersion: 1 name: "@<collective>/wf-collapse-repro" version: "2026.01.01.1" paths: base: manifest models: - extensions/models/noop.ts workflows: - workflows/workflow-repro-alpha.yaml - workflows/workflow-repro-beta.yaml - workflows/workflow-repro-gamma.yaml
manifest-bare.yamlis identical except the workflow entries areworkflow-repro-{alpha,beta,gamma}.yaml.swamp extension push manifest-<variant>.yaml --dry-run --visibility private --yes --json— both exit 0, no warning, both listWorkflows (3); debug log saysExtracted content metadata: … 3 workflowsfor both.swamp extension quality manifest-<variant>.yaml --json, then open the cached archive.swamp/cache/packages/<hash>/extension.tar.gz(the same tarball push uploads).
Observed
| Manifest | extension/workflows/ in the archive |
Workflows inside |
|---|---|---|
| prefixed | workflows.yaml only |
gamma only |
| bare (control) | workflow-repro-alpha.yaml, -beta.yaml, -gamma.yaml |
alpha, beta, gamma |
The prefixed archive's own manifest.yaml still lists all three paths.
In production this shipped a private package whose pulled workflows/ held a single workflows.yaml (the last-listed workflow); the other two returned Workflow not found. Pull itself loses nothing — it installs what the archive contains.
Expected
Either all listed workflows are packaged (keeping each file's basename), or push/--dry-run fails with a clear error. A package must never silently drop workflows, and the dry-run count should match the archive.
Cause (from source)
src/cli/resolve_extension_files.ts:313-317names each workflow in the archive after the directory in its manifest path — intended for one-workflow-per-folder layouts (namespace-debug/workflow.yaml→namespace-debug.yaml). Withworkflows/a.yaml,workflows/b.yaml,workflows/c.yaml, all three resolve toworkflows.yaml.- The copy loop in
src/libswamp/extensions/push.ts:1425-1428then overwrites that file each time; nothing checks for the name clash. src/libswamp/extensions/pull.ts:1108copies the archive'sworkflows/folder as-is.
Suggested fix
- Apply the directory-name rule only to one-workflow-per-folder layouts; otherwise keep each file's basename.
- Fail at push and
--dry-runwhen two entries resolve to the same archive name. - Make the dry-run's workflow count reflect what is actually archived.
Not a duplicate of #2092 / #2434 (serve reload registering pulled workflows).
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.