fix(session-persistence): prevent stale Artifact session saves - #519
Conversation
Codex ReviewVerdict: needs changes [P1] Stale session saves are rejected without any conflict recovery pathsrc/main/session-persistence/coordinator.ts:384 Impact: When another lifecycle client updates the same session first (for example by finalizing an artifact or changing branches), this new validation rejects the lagging client's next save before any durable write. The renderer persistence bridge only logs save failures and then accepts the incoming Recommendation: Return a typed conflict for this validation failure and handle it in the renderer by preserving dirty state and rebasing/retrying on top of the latest durable session, or merge safe non-graph fields against the current durable session before rejecting the save. Summary: The new stale-graph guard closes the overwrite race, but it also introduces a blocking conflict path that the renderer does not recover from, so supported multi-client/session-update workflows can now lose unrelated user edits silently. |
Serialize store and Artifact finalization writes through one renderer queue. Validate finalized Artifact Message bindings before replacing durable Session JSON so late stale graphs fail closed.
bd60f67 to
2282cf5
Compare
|
Addressed the stale-save recovery concern in 2282cf5.
|
Codex ReviewVerdict: needs changes [P1] Discarded rebased session graph leaves renderer stalesrc/renderer/src/lib/session-persistence/session-persistence.ts:271 Impact: When the coordinator rebases a stale graph onto the authoritative session, Recommendation: Make durable projection distinguish a full conflict rebase from upload-only upgrades and replace the session graph and persisted fields when the saved source is still current; retain the existing merge-only behavior when newer renderer state exists. Summary: Static inspection found one blocking renderer/main integration defect in the new conflict-rebase flow. |
|
Addressed the renderer graph refresh concern in fc22b10. Autosaves that carry safe-field rebase intent now apply the returned durable Session as a full persisted projection only when the submitted source object is still current. This refreshes the renderer to the authoritative graph after a conflict rebase. If a newer renderer mutation has already replaced that source, the existing upload-identity-only merge remains in effect so the older response cannot roll back newer live state. Added regression coverage for both the authoritative replacement and newer-state fallback paths. |
Codex ReviewVerdict: needs changes [P1] Pre-save provenance lookup blocks durable session writes on database errorssrc/main/session-persistence/coordinator.ts:463 Impact: Every session save now requires a successful artifact-database query before writing session JSON. A transient database failure prevents ordinary conversation changes from becoming durable, unlike the existing post-save provenance/indexing flow. Recommendation: Preserve the authoritative JSON-first durability guarantee by separating conflict validation from transient provenance failures, or introduce an atomic authority mechanism that can validate bindings without blocking the session file commit. [P2] Forced write retries discard conflict-rebase intentsrc/renderer/src/lib/session-persistence/session-persistence.ts:262 Impact: After a save fails, the saver has already advanced previousSessions to the attempted snapshot. retryWrites then sees no changed safe fields and sends no conflictRebaseFields, so a stale-graph retry cannot rebase and can remain rejected until another preference mutation occurs. Recommendation: Retain the calculated rebase fields with each failed write target, or compare retries against the last acknowledged durable snapshot rather than the last attempted snapshot. Summary: Static inspection found two persistence regressions affecting durable session saves and conflict recovery. |
|
Addressed both persistence concerns in b87b0bf.
Added regression coverage for transient validation availability and forced retry intent. |
Codex ReviewVerdict: needs changes [P1] Avoid loading full artifact versions on every session savesrc/main/artifacts/provenance-message-snapshot.ts:141 Impact: The renderer autosaves on frequent store updates, including streamed message chunks. Each save now performs an unbounded Recommendation: Validate only when graph bindings could have changed, and use a narrow Prisma Summary: Static inspection found one performance and durability regression in the new provenance validation path. |
|
Addressed the binding-validation hot path in 026a0e1.
Added regression coverage for streaming saves, topology and Artifact-binding invalidation, transient lookup retries, and the narrow Prisma select. |
Codex ReviewVerdict: needs changes [P2] Rebase specialist binding writes during artifact conflictssrc/main/session-persistence/coordinator.ts:520 Impact: A concurrent renderer save or artifact finalization can cause the main-process specialist switch persistence to hit a finalized-binding conflict and fail because it supplies no rebase fields. Recommendation: Pass Summary: Static inspection found one integration defect. Branch and title prechecks are valid; no tests, lint, typecheck, builds, or project executables were run. |
|
Addressed the specialist binding conflict path in 60b5e66.
Focused tests, type checking, formatting, lint, and an independent Standards/Spec review passed. The full suite remains at one previously reproduced PermissionGrant runtime-DDL baseline failure, with 8,485 tests passing. |
Codex ReviewVerdict: needs changes [P2] Advance the revision when rebasing safe fieldssrc/main/session-persistence/coordinator.ts:186 Impact: If the authoritative session is newer than the submitted snapshot, rebasing a field keeps its existing updatedAt. Other renderer windows treat the lifecycle update as equal-revision and merge only upload identities, so rebased title, specialist, or preference changes remain stale until reload. Recommendation: Ensure a rebased safe-field change receives a strictly newer revision, or broadcast an explicit field update that equal-revision consumers apply. Summary: One cross-window persistence propagation defect blocks merging. |
|
Addressed cross-window safe-field propagation in 32f8807.
The regression test now asserts the rebased revision is greater than both inputs. Coordinator, renderer session-store, and lifecycle-sync tests pass, as do type checking, formatting, lint, and an independent Standards/Spec review. The full suite still has only the previously reproduced PermissionGrant runtime-DDL baseline failure, with 8,485 tests passing. |
Codex ReviewVerdict: mergeable No actionable findings. Summary: Static inspection found no concrete merge-blocking defects introduced by this pull request. Branch and title prechecks are valid. |
Problem
Renderer store autosaves used a local queue, while Artifact finalization called the Session IPC save path directly. An older queued snapshot could therefore arrive after the latest Artifact-bound Session, replace the durable JSON, and make provenance capture fail with Artifact-owning Message is outside its bound Branch.
Proposed change
Scope and non-goals
Acceptance criteria and validation
All listed checks ran after the last material edit.
One full-suite run hit unrelated timing failures in ProjectFilesView and notebook force-stop tests. Both files then passed independently, 209/209, and the subsequent full-suite rerun passed.
Uncovered risk: there is no real Electron end-to-end stress test for multi-window writers, and the main guard adds a bounded finalized-Version lookup to Session saves.
Review focus