Skip to content

feat(native): migrate SwarmPinService onto DbClient (#176, stacked on #209)#210

Open
Dewinator wants to merge 1 commit into
agent/db-client-factoryfrom
agent/swarm-pin-dbclient-stacked
Open

feat(native): migrate SwarmPinService onto DbClient (#176, stacked on #209)#210
Dewinator wants to merge 1 commit into
agent/db-client-factoryfrom
agent/swarm-pin-dbclient-stacked

Conversation

@Dewinator

Copy link
Copy Markdown
Owner

Summary

First service migrated off the (supabaseUrl, supabaseKey) constructor pattern and onto the shared DbClient surface that PR #209 introduced. Stacked on agent/db-client-factory — that PR must merge first.

Why

PR #209 landed the DbClient factory + MYCELIUM_USE_PGLITE switch as the foundation. The next step is migrating ~17 services off the legacy (url, key) pattern, one at a time, so each migration is reviewable on its own. SwarmPinService is the smallest service still on the legacy shape (~250 LOC, 14 tests, narrow surface) — ideal first target.

Changes

  • mcp-server/src/services/swarm-pin.ts:
    • Constructor takes DbClient (PostgrestClient | PGliteAdapter) instead of url + key. Service no longer constructs its own SupabaseClient.
    • defaultDeps() widens db locally because TypeScript can't unify the .from() generics across the two backends. Runtime chain shape is identical (gated by pglite-adapter.contract.test.ts). Widening is local to the closure — does not leak.
    • Dropped @supabase/supabase-js import.
  • mcp-server/src/index.ts:
    • Constructs a single PostgrestClient inline for swarm-pin, in the same style as middleware/{absorber,digester,prime-fetcher}.ts. The other ~17 service constructors still take (url, key) — they will migrate one-by-one.
    • Comment marker explains why MYCELIUM_USE_PGLITE mode-switch isn't yet wired here: it lights up when index.ts boot goes async (await createDbClient()), and the async refactor is worth doing once enough services consume DbClient to make the blast radius pay off.
  • mcp-server/src/__tests__/swarm-pin.test.ts:
    • Constructor calls now pass a typed-but-empty STUB_DB cast. Orchestration tests inject SwarmPinDeps so the underlying client is never touched — the cast purely satisfies the new signature.

Validation

rm -rf dist && npm run build                  → clean
node --test dist/__tests__/swarm-pin.test.js  → 14/14 passed (buildPinReason 5, pinLesson 6, swarmPinLesson 2, schema 1)
node --test dist/__tests__/db-client.test.js  → 4/4 passed (no regression in the parent factory)

Stacking

Base: agent/db-client-factory (PR #209). When #209 merges to main, GitHub will auto-rebase this PR's base to main.

Test plan

Related

🤖 Generated with Claude Code

…ollow-up to PR #209

First service migrated off the `(supabaseUrl, supabaseKey)` pattern and
onto the shared DbClient surface that PR #209 introduced. Stacked on
top of `agent/db-client-factory` (PR #209) — that branch must merge
first.

`mcp-server/src/services/swarm-pin.ts`:
  - Constructor now takes `DbClient` (PostgrestClient | PGliteAdapter)
    instead of url + key. The service no longer constructs its own
    SupabaseClient; it consumes the one its caller hands in.
  - `defaultDeps()` widens `db` locally because TypeScript can't unify
    the .from() generic signatures across the two backends, even though
    the chain shape is runtime-identical (gated by pglite-adapter
    contract tests). The widening is local to the closure so it doesn't
    leak into the rest of the service.
  - Dropped the `@supabase/supabase-js` import — the service now lives
    entirely on the DbClient abstraction.

`mcp-server/src/index.ts`:
  - Constructs a single PostgrestClient inline for swarm-pin, in the
    same style as middleware/{absorber,digester,prime-fetcher}.ts. The
    other ~17 service constructors still take (url, key) — they will
    migrate one-by-one, with the index.ts module-level boot moved to
    `await createDbClient()` once enough services are on the DbClient
    surface to make the async refactor worth its blast radius.
  - Comment marker explains why the mode-switch (MYCELIUM_USE_PGLITE=1)
    isn't yet wired here — that lights up when index.ts goes async.

`mcp-server/src/__tests__/swarm-pin.test.ts`:
  - Constructor calls now pass a typed-but-empty STUB_DB cast. The
    orchestration tests inject SwarmPinDeps so the underlying client is
    never touched — the cast is purely to satisfy the new signature.
  - All 14 tests still pass: buildPinReason (5), pinLesson orchestration
    (6), swarmPinLesson ethics-gate (2), schema validation (1).

Validation:
  npm run build                                 → clean
  node --test dist/__tests__/swarm-pin.test.js  → 14/14 passed
  node --test dist/__tests__/db-client.test.js  → 4/4 passed (no regression)
  node --test dist/__tests__/*.test.js          → 1010/1011 passed, 1 skipped, 0 failures

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dewinator added a commit that referenced this pull request May 4, 2026
The previous "0 PRs offen" snapshot is stale: the agent itself opened a
4-PR queue in the last 4 ticks (#208 standalone + #209#210#211 stack).
Refresh the Aktiver-Code-Bestand block to credit landed sub-tasks (#202
DATA_DIR, #203 Tauri shell, #204 CI gate, #205 migration helpers) and
add a Queue-Stand note that names the open stack, the linear merge
constraint, and the ~19 still-supabase-direct services that the
DbClient migration sub-story will work through atomically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dewinator added a commit that referenced this pull request May 4, 2026
…ture) + 26h Reed-lag

Last refresh (ec8a088, tick 173) captured the 4-PR native-app cluster (#208/#209/#210/#211)
right after Reed drained #202-#207. Tick 174 then opened PR #212 (W4.1 echo-chamber row 4),
which is off-track from the native-app cluster — it's a Wave-4 fixture PR against issue #196,
not a DbClient or sidecar-bundle PR. CLAUDE.md still framed the queue as 4 PRs all in one
narrative; this corrects it to 5 PRs with the fixture-PR called out separately, and surfaces
the empirical Reed-lag (≈26 h since the 2026-05-03 10:24 UTC merge wave) so the next tick has
the right baseline for the queue-too-deep guard.

Also corrects ~21 → 22 (true grep count today on main) for the Supabase-direct service file
count, with explicit "verbleibend nach Merge: 20" so the next DbClient-migration tick can
locate the right service to pick.

No production code touched; pure CLAUDE.md doc-accuracy fix, direct-to-main per the
agent-loop convention for risk-free doc refreshes.
Dewinator added a commit that referenced this pull request May 4, 2026
The bird's-eye doc lagged the 2026-05-03 merge wave (PRs #202#207
landing sub-tasks 1, 2, 3-scaffold, 4, 5, 7-core) and the W3 spike
chain that settled the empirical mDNS budgets on `main`.

Changes:
- Wave 1 row: 9-PR queue → 5-PR queue (#208 sidecar bundling closing
  sub-task 3; #209#210#211 linear DbClient migration stack;
  unrelated W4.1 fixture #212). Note the 22-services DbClient sub-story
  with 2 already in flight.
- Wave 3 row: design-spike-only → 11-spike chain on `main` with named
  empirical budgets (64 KiB / 2 000 ms hostile-fetch, 5-s/3-fail
  heartbeat → 15 s eviction, ~1.3 s cold-rebrowse settle, 260 ms wake
  republish, 4 000 ms blocked-network threshold from K=10 trials).
  Cross-platform re-validation (Linux/Avahi, Windows) named as the
  open item before locking the library pick.
- Wave 1 narrative: matches the 5-PR reality, removes stale "9 PRs
  998/999 tests green" claim, keeps the queue-drain gate on sub-tasks
  6/8/9/10.

Verified: 11 spike files in experiments/swarm-discovery/, PRs
#202#207 all merged (gh pr list --state merged), 5 open PRs all
CLEAN+MERGEABLE. Refresh date bumped to 2026-05-04.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dewinator added a commit that referenced this pull request May 4, 2026
…sub-task 3

After PR #210 (SwarmPin) and #211 (Skills) the canonical native-app-track.md
just says "20 services remain" — but doesn't tell Reed which one to pick
next, what shape each one is (Group A constructor-only vs Group B full
SwarmPin-style swap), or how big it is.

Adds docs/native-dbclient-migration-tracker.md with a per-service table:
LOC, .from() / .rpc() callsite counts, current import (PostgrestClient vs
SupabaseClient), and a recommended PR order (Group A smallest-first, then
Group B smallest-first, then the agent-bus layer last).

Linked from native-app-track.md DbClient sub-story section so it surfaces
when Reed (or the next agent tick) picks PR #213.

Empirical counts via grep against main HEAD a1fb5de — methodology block
included so the table is reproducible. The numbers are upper bounds (some
hits are in comments/strings); order-of-magnitude is what matters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Dewinator

Copy link
Copy Markdown
Owner Author

Local empirical validation 2026-05-05 (227th-tick) — first SwarmPin DbClient migration green

PR #210 had no prior comments; the stack-base PR #209 was revalidated against 8b6a203 earlier today, so this comment closes the gap on the stacked piece itself.

Setup

  • Fresh checkout of agent/swarm-pin-dbclient-stacked at HEAD 1bf6d3f
  • Mac M4, 16 GB RAM
  • rm -rf dist && npm run build && npm test against the existing .env (Docker/Supabase backend; the migrated service uses the PostgrestClient branch of DbClient)

Results

> tsc                         # build clean, no diagnostics
ℹ tests 1047
ℹ pass 1046
ℹ fail 0
ℹ skipped 1                   # same baseline as PR #209 — no new skips, no regression
ℹ duration_ms 67642

Focused replay of the SwarmPin suite:

node --test dist/__tests__/swarm-pin.test.js
ℹ tests 14
ℹ pass 14
ℹ fail 0
ℹ duration_ms 357

Migration shape — empirical cross-check

Diff vs. 8b6a203 (PR #209 head): services/swarm-pin.ts constructor goes from (supabaseUrl, supabaseKey) to (db: DbClient) (L103). The service no longer constructs its own SupabaseClient — it consumes the one its caller hands in. defaultDeps() widens db to { from(t: string): any } locally (L152-L153) because TS can't unify the .from() generic across PostgrestClient and PGliteAdapter — the chain shape itself (.select()/.insert()/.update().eq().maybeSingle()) is identical at runtime, and that runtime equivalence is what the PR #209 pglite-adapter contract tests assert.

Stack readiness — no blockers from this PR

Recommendation

Merge order remains #209#210#211 (linear stack). #210 is locally clean against today's main and the stack-base; no merge-conflict signals from git log.

🤖 Posted by autonomous tick (mycelium 227th — local PR-validation, no new PR opened, queue-bound)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant