refactor(dev): EpochStore staging/leases/recovery on Effect Semaphore + Exit-aware saga (wave 3.5 stage 3, PR 4) - #161
Merged
Conversation
🦋 Changeset detectedLatest commit: f6038ea The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This was referenced Sep 1, 2026
ScriptedAlchemy
added a commit
that referenced
this pull request
Sep 1, 2026
Rebased survivors of the stranded deslop/wave-3.5 commit (5a8723423) onto current main. Applied: - finalizers: sqlite connection close and Flight reader cancel no longer mask the original failure when teardown itself throws - state drivers: shared pending-open tracker replaces the verbatim trackPendingOpen/close-drain duplication; drop runPromise(Effect.fail) ceremony in favor of direct rejections - boundaries: remove the unused runSyncExit export from both seams, the dead ScopedEffectRuntime E type parameter from the rsc-runtime copy (matching the dev-seam copy), and the redundant string ternary in toDevError/toRuntimeError - delete dead epoch-lease-registry.ts (zero importers; #161 rewrote the same concept in epoch-store.ts); dedupe boundRenderEventStream through emitBoundRenderEvent; trim migration-narration comments Dropped as superseded: the reconciler progress-queue rework (#172 rebuilt that path with a demand-bounded design), the dev-seam trim of interruptWhenAborted/runPromiseExit (#164 fixed and kept them with tests), the sqlite #commit self-rewrite (#171 rewrote #commit), and the lint-plugin inlining (#164 expanded the plugin around those helpers).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Final subsystem of #152 stage 3, sequenced last per the blast-radius audit: EpochStore carries the repo's cross-process durability contracts (injected
durabilityStorage/move/cleanupRemoveseams pin exact fs-operation order), so it went after the three smaller seams..agent-bundlelease queue becomeSemaphore(1)permits (withPermit, FIFO like the serial queues they replace). Cross-instance lease sharing is unchanged: one mutex + one reference-count map per project path, so leases survive across store instances.EpochPostCommitDurabilityError/EpochPostCommitCleanupError, pre-rename failures roll back the moved paths and the publisher-owned receipt concurrently with per-compensationExitcapture, aggregating into the identicalAggregateErrorshape.finallylet a removal failure replace the outcome, and Effect finalizers must be infallible (stage-2 lesson) — so the publish path captures the attempt'sExit, removes the root, then unwraps.#cleanupUnderLease) runs eligible deletions concurrently viaEffect.forEach+ per-elementExit, keeping the labeled, sortedEpochCleanupErroraggregation and the sidecar-before-directory-before-metadata retry ordering.#verifyStaging,#validateActiveEpoch,#syncTree, atomic JSON writes) stay imperative and identity-lifted — their operation order is the durability contract the seam tests pin.Parity (all suites unchanged, zero pin flips)
epoch-store.test.ts(43 cases incl. fsync commit order, cross-store leases, concurrent final-release, post-commit classification, publisher-rollback races): greenmcp-session-service+target-mcp-runtime: 35 passed / 0 failedpnpm lint+pnpm typecheck: greenRefs #152.