diff options
| author | Adam Malczewski <[email protected]> | 2026-06-12 19:00:29 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-12 19:00:29 +0900 |
| commit | d66585333ee5764700c67a81eaec015b0026f8f1 (patch) | |
| tree | 6e1ac455c2ecbf3c442fce9f73fdaed8fb71fade /src/core/chunks/trim.test.ts | |
| parent | 1764e3e5dff836255d121a933dd92542368346f9 (diff) | |
| download | dispatch-web-d66585333ee5764700c67a81eaec015b0026f8f1.tar.gz dispatch-web-d66585333ee5764700c67a81eaec015b0026f8f1.zip | |
feat(chat): consume CR-5 history windowing — server-windowed cold loads + show-earlier backfill
Re-pinned [email protected]>0.10.0 + [email protected]>0.6.1 (reply
frontend-history-windowing-handoff.md); re-mirrored both .dispatch references.
- HistorySync port gains optional { limit?, beforeSeq? } (CR-5 params); the
app's createHistorySync appends them to GET /conversations/:id.
- COLD-cache fresh load now fetches ?sinceSeq=0&limit=<floor(0.75xL)> — a huge
conversation no longer ships whole to show 192 chunks. A warm-cache tail sync
stays unwindowed (windowing a tail that outgrew the limit would leave a
silent seq gap behind the cache).
- hasEarlier now derives from the [email protected] CONTRACT (1-based gap-free seqs):
loaded window starting above seq 1 => older history exists — covering both
locally-trimmed AND server-windowed transcripts (the watermark stays as the
merge floor only).
- showEarlier(): local cache first; when the cache doesn't reach far enough
back, backfills the missing older run via ?beforeSeq=<oldestKnown>&limit=
and persists it (next page-in is local). latestSeq windowed-read caveat is
satisfied structurally (tail cursor derives from the cache's max seq).
- live-probe: +6 CR-5 checks (seq origin, newest-k ascending, short-chat
exactness, beforeSeq paging, 400 validation x2). NOT yet run live — backend
was down at commit time; run pending.
- backend-handoff.md: CR-5 RESOLVED, pins/mirrors current. 602 tests green x2.
Diffstat (limited to 'src/core/chunks/trim.test.ts')
| -rw-r--r-- | src/core/chunks/trim.test.ts | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/src/core/chunks/trim.test.ts b/src/core/chunks/trim.test.ts index 091b646..7914f35 100644 --- a/src/core/chunks/trim.test.ts +++ b/src/core/chunks/trim.test.ts @@ -177,28 +177,43 @@ describe("restoreEarlier", () => { expect(selectHasEarlier(restored)).toBe(true); }); - it("clears the watermark when the restore exhausts known earlier history", () => { + it("restoring down to seq 1 reaches the contractual origin (hasEarlier clears)", () => { const windowed = windowTranscript(stateWith(chunks(1, 100)), 75); // hidden: 1..25 const restored = restoreEarlier(windowed, chunks(1, 100), 64); expect(restored.committed).toHaveLength(100); expect(restored.committed[0]?.seq).toBe(1); - expect(restored.hiddenBeforeSeq).toBe(0); + expect(restored.hiddenBeforeSeq).toBe(1); // floor at the origin — inert expect(restored.hiddenThinkingCount).toBe(0); expect(selectHasEarlier(restored)).toBe(false); }); - it("clears the watermark when nothing is actually below it", () => { + it("is the identity when nothing older is known locally (server may still hold more)", () => { const windowed = windowTranscript(stateWith(chunks(50, 200)), 75); const restored = restoreEarlier(windowed, [], 64); - expect(restored.hiddenBeforeSeq).toBe(0); - expect(restored.committed).toEqual(windowed.committed); + expect(restored).toBe(windowed); + // seqs are 1-based gap-free: window starts at 126 ⇒ older chunks DO exist. + expect(selectHasEarlier(restored)).toBe(true); }); - it("is the identity when nothing is hidden", () => { + it("is the identity when the window already starts at seq 1", () => { const state = stateWith(chunks(1, 10)); expect(restoreEarlier(state, chunks(1, 10), 5)).toBe(state); }); + it("works on a server-windowed transcript (no local watermark)", () => { + // A cold-cache fresh load with `?limit=` commits a suffix (seq 809..1000) + // with hiddenBeforeSeq still 0 — hasEarlier derives from seq > 1, and a + // backfilled run merges below it. + const state = stateWith(chunks(809, 1000)); + expect(state.hiddenBeforeSeq).toBe(0); + expect(selectHasEarlier(state)).toBe(true); + const restored = restoreEarlier(state, chunks(745, 808), 64); + expect(restored.committed[0]?.seq).toBe(745); + expect(restored.committed).toHaveLength(192 + 64); + expect(restored.hiddenBeforeSeq).toBe(745); + expect(selectHasEarlier(restored)).toBe(true); + }); + it("decrements the hidden thinking count by the restored thinking chunks", () => { const committed = [chunk(1, "thinking"), chunk(2), chunk(3, "thinking"), ...chunks(4, 12)]; const trimmed = trimTranscript(stateWith(committed), 10); // drops 3: seqs 1..3 (2 thinking) @@ -213,6 +228,7 @@ describe("restoreEarlier", () => { const trimmed = trimTranscript(stateWith(original), 100); const restored = restoreEarlier(trimmed, original, 1000); expect(restored.committed).toEqual(original); - expect(restored.hiddenBeforeSeq).toBe(0); + expect(restored.hiddenBeforeSeq).toBe(1); + expect(selectHasEarlier(restored)).toBe(false); }); }); |
