fix(core): resume provider marker replays after interruption - #140
fix(core): resume provider marker replays after interruption#140kongtou20070406 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped, preserves transactional rollback semantics, and includes a regression test that reproduces and verifies the intended interruption-resume behavior.
Pull request overview
This PR fixes an interruption edge case in provider replay planning: when a provider’s index-version marker is missing, the next build can repeatedly reset unit cursors to null, causing replays to restart from byte zero after each interruption. The change makes the replay schedule durable as soon as the first unit transaction successfully commits, so subsequent runs can resume from already-persisted per-unit cursors even if a later transaction defers and finalize is skipped.
Changes:
- Persist the replay schedule (clear affected unit cursors + write pending version markers) in the same transaction as the first successfully persisted unit.
- Clear replay keys derived from prior session provenance that may no longer be discoverable.
- Add a regression test that deletes the Claude marker, injects a
SQLITE_BUSYon a later transaction, and verifies restart resumes without replaying already-committed work.
File summaries
| File | Description |
|---|---|
packages/core/src/provider-indexing.ts |
Commits marker replay scheduling (cursor clears + marker writes) atomically with the first successfully committed unit to ensure reliable resumption after interruptions. |
tests/app-rollback-guard.test.mjs |
Adds a regression test covering marker-missing replay resumption across an injected deferred transaction. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
What and why
When an index-version marker is missing for a provider that already has indexed sessions, planning intentionally schedules a full provider replay. Today the marker is written only during finalize. If a later per-unit transaction is deferred after earlier units committed, finalize is skipped, the marker remains missing, and the next build sets every cursor to
nullagain. The provider therefore restarts from byte zero after every interruption.This change commits the replay schedule atomically with the first successfully persisted unit:
sessionsprovenance;If the first unit transaction fails, all schedule changes roll back. Once one unit commits, subsequent interruptions resume from the per-unit cursors already written. Existing failed/incomplete-inventory retry handling remains unchanged.
No schema, provider parsing, query, public API, or dependency changes.
Reproduction and ablation
The regression fixture creates one Claude main transcript plus one subagent transcript, seeds a complete index, deletes the canonical marker, and injects
SQLITE_BUSYat the second unit transaction.fb4a8efparent implementation): the marker count before restart is0; the new test fails with0 !== 1, so the next plan treats both units as a fresh full replay.02b4638): the marker count is1; restart reportsfiles === 1, and the final snapshot remains exactly 1 session / 2 messages.The subagent unit is deliberately absent from
sessionsprovenance, so this also guards against clearing only provenance-derived keys.Verification
npm test— 659 pass / 0 fail on Ubuntu WSL2 (Node 24.14.1), current headnpm run typecheck— 0 errors (root + app)npm run lint— 0 errors, 11 pre-existing/generated warningsDeliberately out of scope