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

cleanup for repoDriver

Opened by keeb · 4/24/2026· Shipped 4/24/2026

Problem

PR #1219 (swamp-club#159) shipped repo-level defaultDriver for workflow execution, but the fix is incomplete and reviewer feedback surfaced additional gaps. This issue tracks the cleanup work.

Scope (in)

1. Direct swamp model method run doesn't honor defaultDriver

The primary gap. src/libswamp/models/run.ts passes driver: input.driver straight through; src/domain/models/method_execution_service.ts:604 resolves via context.driver ?? "raw" and never calls resolveDriverConfig. Repo default only applies to workflow execution today — direct method runs always default to "raw" when no CLI flag is passed. This also means serve/HTTP method-run paths (src/serve/connection.ts:266, src/serve/open/http.ts:1780) don't pick up the repo default.

Fix: route the direct method-run path through resolveDriverConfig with an effective chain of cli > definition > repo > "raw" (no step/job/workflow tiers outside a workflow).

2. Proper memoization — fix the race, and extend it to the direct path

src/domain/workflows/execution_service.ts:1169-1175 memoizes the resolved marker value, not the promise. Two concurrent run() calls both see this.repoMarker === undefined, both issue a file read. Harmless (same data) but breaks the "at most once" contract. Worse, the direct method-run path has no memoization at all — every modelMethodRun invocation would re-read .swamp.yaml unless addressed.

Fix: promise-memoize (this.markerPromise ??= this.markerRepo.read(...)) and share the same primitive via a loadRepoMarker dep in ModelMethodRunDeps so both paths use it without duplicating infrastructure instantiation inside libswamp.

3. Fix the definition tier consistently across paths

src/domain/workflows/execution_service.ts:523 has ctx.driver ?? evaluatedDefinition.driver — dead code, since ctx.driver is always defined after resolveDriverConfig returns "raw" as its fallback. Model definitions with driver: set are silently ignored during workflow execution. In the in-flight direct-method-run follow-up I opportunistically wired evaluatedDefinition.driver into the direct path, which would make direct and workflow paths diverge.

Fix: decide symmetrically — either wire the definition tier properly into both paths via resolveDriverConfig, or drop it from both. Don't let them diverge.

4. Audit pre-flight check path

Pre-flight checks build their own MethodContext somewhere. Verify they don't carry stale driver semantics after the above changes.

5. Acknowledge and document the new failure mode

After this lands, malformed .swamp.yaml will fail every swamp model method run with a parse error (previously direct runs didn't read the marker). Consistent with workflow behavior, but worth calling out in design/execution-drivers.md.

Scope (out — file as separate follow-ups)

  • Named-fields object for resolveDriverConfig (src/domain/drivers/driver_resolution.ts:44-51). Six positional DriverSource | undefined params is fragile; call sites like execution_service.ts:1843-1853 pass undefined for definition just to reach repo. Move to { cli?, step?, job?, workflow?, definition?, repo? } in a separate refactor issue.
  • WorkflowExecutionService.execute() forwards full run() options (execution_service.ts:1389-1405). Currently drops driver (and others). Ergonomics fix; separate issue.
  • Runtime validation of RepoMarkerData fields. parseYaml(...) as RepoMarkerData is an unchecked type assertion. defaultDriver: 123 would survive parsing. Pre-existing pattern across all marker fields — needs a broader schema-validation pass rather than point fixes.

Acceptance criteria

  • swamp model method run <name> <method> in a repo with defaultDriver: docker in .swamp.yaml runs via the docker driver without passing --driver.
  • --driver raw override still wins.
  • Serve/HTTP method-run paths behave the same way (inherit for free via modelMethodRun).
  • Marker is read at most once per service instance / request lifecycle (promise-memoized), no concurrent double-reads.
  • Direct path and workflow path handle the definition tier identically.
  • Pre-flight checks verified unaffected or updated symmetrically.
  • Tests: unit + service-level for the direct path (mirroring the ones added for the workflow path in #1219); one concurrency test demonstrating the promise-memoize property; one integration test across both paths.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 3 MOREPR_MERGEDSHIPPED

Shipped

4/24/2026, 6:24:28 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
keeb assigned keeb4/24/2026, 5:18:27 PM

Sign in to post a ripple.