diff --git a/packages/client-runtime/src/state/shellReducer.test.ts b/packages/client-runtime/src/state/shellReducer.test.ts index 4689c1408f7..a069460e63c 100644 --- a/packages/client-runtime/src/state/shellReducer.test.ts +++ b/packages/client-runtime/src/state/shellReducer.test.ts @@ -44,6 +44,26 @@ const stubThread = { } as const; describe("applyShellStreamEvent", () => { + it("ignores stale project upserts without mutating the snapshot", () => { + const snapshotWithProject: OrchestrationShellSnapshot = { + ...baseSnapshot, + snapshotSequence: 4, + projects: [stubProject], + }; + + for (const sequence of [3, 4]) { + const next = applyShellStreamEvent(snapshotWithProject, { + kind: "project-upserted", + sequence, + project: { ...stubProject, title: "Stale Title" }, + }); + + expect(next).toBe(snapshotWithProject); + expect(next.snapshotSequence).toBe(4); + expect(next.projects[0]?.title).toBe("Test Project"); + } + }); + describe("project-upserted", () => { it("adds a new project", () => { const event: OrchestrationShellStreamEvent = { diff --git a/packages/client-runtime/src/state/shellReducer.ts b/packages/client-runtime/src/state/shellReducer.ts index 71c8a6b0eb3..3d3b22a1289 100644 --- a/packages/client-runtime/src/state/shellReducer.ts +++ b/packages/client-runtime/src/state/shellReducer.ts @@ -13,6 +13,8 @@ export function applyShellStreamEvent( snapshot: OrchestrationShellSnapshot, event: OrchestrationShellStreamEvent, ): OrchestrationShellSnapshot { + if (event.sequence <= snapshot.snapshotSequence) return snapshot; + switch (event.kind) { case "project-upserted": { const projects = snapshot.projects.some((p) => p.id === event.project.id)