feat(core): add pending transaction store (#193) - #227
Merged
Conversation
CommitLore — record lintTrailers: clean — 1 commit in Limits (2)
Ruled out (3)
Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR. |
Implements the monotonic prepare/verify/stage/apply/consume lifecycle from
ADR-0021. Every mutation is an atomic rename so no concurrent reader can
observe a partial file. Path resolution uses git rev-parse --git-path so
linked worktrees resolve correctly.
The nonce trust boundary validates ^[0-9a-f]{32}$ before any path join, so
no caller-supplied string reaches the filesystem unsanitised. expires_at is
null while the record is in prepared or verified phase and is stamped only
when stage succeeds, as staged_at + 5 minutes.
readPending returns null for absent files and throws a typed PendingFormatError
for corrupt or unknown-version content, distinguishing the two failure modes
that the hook must treat differently.
Ruled-out: setting expires_at at creation time with a longer window | a longer window hides staleness rather than preventing it, and the staged-diff-hash gate already catches real drift
Ruled-out: a shared atomicWriteJson utility exported from a utils module | three files already duplicate the pattern and the ticket scope does not include a cross-cutting refactor
Ruled-out: allowing stagePending on a prepared record when records are empty | skipping verification breaks the trust chain that prevents an MCP client from injecting arbitrary trailers
Limit: the test proves monotonic transitions but cannot prove absence of TOCTOU between read and rename on a loaded filesystem; atomic rename is the kernel-level guarantee
Blast: local
Undo: easy
Certainty: firm
Record-Id: r-t1001pend
Limit: the first attempt's Record-Id used hyphens, which the r-[a-z0-9]{6,} format rejects; both the lint action and the dogfood test caught it
MongLong0214
force-pushed
the
feat-issue-193
branch
from
July 30, 2026 09:03
623d8c5 to
0f5ef32
Compare
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
Implements T-1001: the pending transaction store from ADR-0021.
Changes
src/core/pending.ts— new module owning the monotonic prepare/verify/stage/apply/consume lifecycletest/pending.test.ts— 11 tests covering all phase transitions, trust boundary, CEO amendments, format errorsdist/— rebuiltKey decisions
expires_atis null in prepared/verified phases, stamped only on stage success (CEO amendment 1)^[0-9a-f]{32}$before any path resolution (CEO amendment 2)git rev-parse --git-path commitlore/pendingfor worktree correctnessTesting
Closes #193