Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLI
Assigneesstack72

Relationships

#600 Local source-loading should discover a report co-located with its model in a paths.base:manifest extension

Opened by stateless · 6/9/2026· Shipped 6/9/2026

Problem

A report is, in MVC terms, the view for a model — it naturally belongs in the same extension as the model it summarizes. Publishing supports that (the manifest reports: field bundles the report alongside the model). Local source development does not.

In a self-contained extension using paths.base: manifest — manifest, model, README, LICENSE all in one directory under extensions/models/<name>/ — a report listed in reports: and placed in that same directory:

  • bundles and loads correctly once pulled, but
  • is NOT discovered during local source development: the model loads (it matches the extensions/models/** discovery glob) while the co-located report does not (report discovery only globs extensions/reports/**).

So the extension loads partially from source (model yes, report no) even though it loads fully when pulled — a dev/prod parity gap. And the manifest can't point at extensions/reports/ instead, because manifest paths reject .. ("Path must be relative and must not contain '..' components").

Reproduce

  1. extensions/models/myext/ with manifest.yaml (paths.base: manifest), a model .ts, and a report .ts listed under reports:.
  2. swamp doctor extensions --verbose — the model registers; the report does not (no report row for it).
  3. A method whose definition has reports.require: [<that report>] does not run it locally.
  4. swamp extension source add <that dir> does not help — a path already covered by the repo-root layout is ignored to prevent double-loading.

(Confirmed by dropping .swamp/_extension_catalog.db and rescanning — the report never registers from the model dir.)

Proposed

Local source-loading should honor a discovered manifest's declared files — load all declared components (models, reports, vaults, drivers, …) from the manifest's own directory — so source/dev loading matches the published bundle. (Alternatively, the per-type discovery globs could include paths.base: manifest extension subdirectories.)

Impact / workaround

Today, a bundled report can't be exercised from source. The workarounds are to keep the report in extensions/reports/ (separated from the extension it ships in) or publish it as a standalone companion extension — both of which defeat the "view ships with its model" layout the manifest otherwise supports.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 3 MOREPR_MERGED+ 1 MORECONTRIBUTOR_NOTIFIED

Shipped

6/9/2026, 7:50:17 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack726/9/2026, 12:57:03 PM
Editable. Press Enter to edit.

stateless commented 6/9/2026, 9:54:04 AM

Scope note: this isn't report-specific — the root cause is that local source-loading discovers each extension type from its own directory (extensions/reports/, top-level workflows/, extensions/vaults/, …), so any non-model file co-located in a paths.base: manifest extension dir is missed locally, even though it's declared in the manifest and bundles correctly when pulled. It applies to reports, workflows, vaults, and drivers, not just reports.

One caveat worth confirming: the publishing path-resolution docs give workflows under manifest mode a "manifest dir first, then repo-root fallback" resolution that reports don't have — so workflows may already behave differently for discovery. Worth verifying as part of the fix.

Suggested framing: local source-loading should honor a discovered manifest's declared files across all types (load every declared component from the manifest dir), so source/dev loading matches the published bundle uniformly.

stack72 commented 6/9/2026, 7:58:34 PM

Thanks @stateless for reporting this! The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.