Skip to main content
← Back to list
01Issue
BugOpenSwamp CLIPublic
AssigneesNone

Relationships

#2269 Periodic worker GC sweep prunes outside the sync gate

Opened by skunk-ape · 9/18/2026

Found while triaging #2268, which fixes the same race on the interactive worker.prune handler. This is the second instance, on the server's periodic sweep, and is not covered by that fix.

What is wrong

The Worker GC block in src/cli/commands/serve.ts (around line 5164) builds prune deps whose deleteWorker calls modelDelete with createModelDeleteDeps(repoDir, datastoreResolver, undefined, repoContext.markDirty), then hands them to WorkerGcService, which sweeps every hour. The sweep deletes worker model definitions from the local cache and marks them dirty, entirely outside the sync gate. A poller pull landing between the local delete and whichever later push flushes the dirty path puts the file back on disk, so the push re-uploads it instead of deleting it and the delete is silently undone — the exact failure mode documented for swamp-club#2247 in design/enablers/datastores.md.

Why the fitness test does not catch it

The rule in integration/serve_deps_rules_test.ts walks src/serve only, and flags functions that call pushChangedToRemote(ctx) or syncService.pushChanged(. The GC sweep lives in src/cli/commands/serve.ts and performs no push of its own — it relies on a later flush — so it is invisible to the rule on both counts.

Suggested fix

syncGate is already in scope in the same action body (declared around line 1591, same indentation level, and the body does not close until line 5284), so the sweep can be wrapped in withSyncGate(syncGate, ...) directly. Consider also widening the fitness rule to cover local-cache deletes that mark dirty without pushing, not just explicit pushers — otherwise this class stays invisible wherever the push is deferred.

  • #2268 — the same race on the interactive handler
  • swamp-club#2247 — the original delete-vs-pull race

Note that buildPruneDeps in src/cli/commands/serve.ts and the pruneDeps literal in handleWorkerPrune are near-identical duplicates; a shared factory would have meant fixing this in one place.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

9/18/2026, 12:15:23 AM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.