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

Relationships

↔ sibling #479

#486 feat: giga-swamp phase 3 — Path resolver + per-namespace locking

Opened by stack72 · 5/29/2026· Shipped 5/29/2026

Problem

Phases 1 and 2 established the Namespace value object, config plumbing, catalog schema v4, and repository interface. The data model understands namespaces but the filesystem layout is unchanged — data still lands at the same paths regardless of namespace config. Phase 3 makes the storage layout namespace-aware and introduces per-namespace locking so repos sharing a datastore don't block each other.

Proposed Solution

1. Path resolver namespace prefixing

Update DefaultDatastorePathResolver to accept namespace. When namespace is non-empty, resolvePath() prepends {namespace}/ to the resolved path. Solo mode (empty namespace) produces identical paths to today — no prefix, no behavior change.

Example: with namespace 'infra', data lands at {datastore}/infra/data/... instead of {datastore}/data/...

The namespace is the OUTERMOST path segment — {namespace}/data/{type}/{modelId}/{dataName}/{version}/, not data/{namespace}/...

2. Per-namespace locking

Change the lock path from the single .datastore.lock to .locks/{namespace}.lock when namespace is set. Two repos writing to different namespaces never contend. The existing lock protocol (symmetric drain, TOCTOU rechecks) works unchanged within a namespace. Solo mode keeps the current single lock.

3. Wire namespace through repo_context.ts

Pass namespace into the path resolver and lock factory from the resolved datastore config. This is the coordination point — the path resolver, the lock, and the repository (from Phase 2) must all agree on which namespace they're operating in.

4. Thread namespace through the ~15 direct repository construction sites

Phase 2 documented these as a tracked dependency: libswamp/models/, libswamp/data/, libswamp/workflows/evaluate, domain/workflows/execution_service, etc. These sites currently default to SOLO_NAMESPACE. Now that paths are namespace-prefixed, these must receive the configured namespace so storage layout and catalog namespace stay in lockstep.

Boundary constraints

  • Do NOT change CEL expression parsing or query semantics — that is Phase 4
  • Do NOT add CLI output columns or namespace commands — that is Phase 5
  • Do NOT change sync behavior — that is Phase 6
  • Do NOT change the markDirty contract — it has 8 load-bearing rules extension authors depend on
  • Do NOT change DEFAULT_DATASTORE_SUBDIRS — destructive migration side effects
  • Do NOT restructure the lock lifecycle (symmetric drain) — just change the lock PATH

Ship Gate

  • deno check, deno lint, deno fmt, deno run test all pass
  • Solo mode invariant: existing repos with no namespace produce identical paths, identical locks, identical behavior
  • Namespaced repo test: create a repo with namespace: test, run a model, verify data lands under {datastore}/test/data/... not {datastore}/data/test/...
  • Lock isolation test: two different namespaces can acquire locks concurrently without contention
  • Compile the binary with deno run compile and smoke test against a real repo — swamp data list, swamp data query, and a model method that writes data must all work identically to before
  • If S3 datastore is available, verify the namespace prefix appears in the S3 key structure

Design Context

Full design doc: resources/giga-swamp.md

This is Phase 3 of 7. Depends on Phase 2 (#479). This is the first phase where a configured namespace produces a physically different storage structure. The path resolver, locking, and repository must all change in lockstep.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 5 MOREFINDINGS+ 3 MOREPR_MERGED+ 1 MORENOTIFICATION_SKIPPED

Shipped

5/29/2026, 5:31:15 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack725/29/2026, 3:42:20 PM
stack72 linked related to #4795/29/2026, 4:31:32 PM

Sign in to post a ripple.