summaryrefslogtreecommitdiffhomepage
path: root/src/core/chunks/selectors.test.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-10-21 15:36:54 +0900
committerAdam Malczewski <[email protected]>2026-10-21 15:36:54 +0900
commitac43e92d174ed1f081c387944e9044643ee9efc2 (patch)
tree3110ac7c1fa722ad6c092200ea02aead5384b5d3 /src/core/chunks/selectors.test.ts
parente9786bf1dbf258b68f793870d02378c390939d3d (diff)
downloaddispatch-web-ac43e92d174ed1f081c387944e9044643ee9efc2.tar.gz
dispatch-web-ac43e92d174ed1f081c387944e9044643ee9efc2.zip
fix(review-followup-fee): recover omitted chat payloads through history
Diffstat (limited to 'src/core/chunks/selectors.test.ts')
-rw-r--r--src/core/chunks/selectors.test.ts30
1 files changed, 29 insertions, 1 deletions
diff --git a/src/core/chunks/selectors.test.ts b/src/core/chunks/selectors.test.ts
index 57c1415..05dcc4e 100644
--- a/src/core/chunks/selectors.test.ts
+++ b/src/core/chunks/selectors.test.ts
@@ -1,6 +1,6 @@
import type { AgentEvent, StepId, StoredChunk } from "@dispatch/wire";
import { describe, expect, it } from "vitest";
-import { applyHistory, foldEvent, initialState } from "./reducer";
+import { applyHistory, foldEvent, initialState, markHistoryRecovering } from "./reducer";
import { selectChunks } from "./selectors";
import type { TranscriptState } from "./types";
@@ -131,6 +131,34 @@ describe("selectChunks — de-dup of a late-join replay against committed histor
expect(rendered.filter((r) => r.provisional)).toHaveLength(3);
});
+ it("preserves an uncommitted accumulating tail even when its text repeats history", () => {
+ const committed: StoredChunk[] = [
+ ...committedStep0,
+ { seq: 5, role: "assistant", chunk: { type: "text", text: "final" }, turnId: T },
+ ];
+ let s = applyHistory(initialState(), committed);
+ s = markHistoryRecovering(s, T);
+ s = fold(s, [userMsg, turnStart, think("plan"), call("a"), result("a"), text("final")]);
+ const rendered = selectChunks(s);
+ expect(rendered).toHaveLength(6);
+ expect(rendered.slice(0, 5).every((r) => !r.provisional)).toBe(true);
+ expect(rendered[5]).toMatchObject({
+ provisional: true,
+ streaming: true,
+ chunk: { type: "text", text: "final" },
+ });
+ });
+
+ it("reconciles the same step identity even when provisional payload differs", () => {
+ let s = applyHistory(initialState(), committedStep0);
+ s = markHistoryRecovering(s, T);
+ s = fold(s, [userMsg, turnStart, think("DIFFERENT"), call("a"), result("a")]);
+ const rendered = selectChunks(s);
+ // Authoritative identity wins; payload equality cannot identify omitted/truncated content.
+ expect(rendered.filter((r) => r.provisional)).toHaveLength(0);
+ expect(rendered.map((r) => r.chunk)).toEqual(committedStep0.map((r) => r.chunk));
+ });
+
it("does nothing when the committed tail belongs to another turn", () => {
const other = committedStep0.map((c) => ({ ...c, turnId: "older" }));
let s = applyHistory(initialState(), other);