Commit Graph
4 Commits
Author SHA1 Message Date
weishu 5ef4304a4a fix: synchronize read state across web and native clients
Track readable content revisions and durable read cursors in the hub. Acknowledge only rendered foreground tails, persist offline read operations, and preserve newer manual unread choices across devices.

Migrate existing history to a read baseline and cover pagination receipts with shared native conformance fixtures.
2026-11-01 09:52:51 +08:00
AnanovoandGitHub b41b9293e9 fix(web): render cold sessions from a small initial page (#1809)
* fix(web): speed up cold session first paint

* test(web): update pagination fixtures for cold page

* test(web): wait for cold page before loading history

* feat(native): match cold session pagination

* test(native): cover cached re-entry page size
2026-09-14 09:07:14 +08:00
weishu c2e3d16b7e feat(native): improve anchored chat scrolling and history loading
Add viewport-driven paging with layout acknowledgements, bounded retries, cancellation gates, and epoch-safe history retention.

Preserve transcript anchors and expansion state, fix tool-group identity collisions, and serialize Android history coordination on Main.

Reduce per-scroll composition and layout work; add native regression tests, CI coverage, and profiling guidance.
2026-09-10 16:22:36 +08:00
weishu 7712a92f51 feat(ios): message window store port + pagination fixture harness (A-M2d)
HapiProtocol/Window/ — pure port of web/src/lib/message-window-store.ts +
messages.ts, mirroring the Android reference port 1:1:
- MessageWindowState: constants (400/600/800/800/200), MessagePosition,
  OlderLoadOutcome, full InternalState fields, persisted v2 snapshot shape
- MessageWindowLogic: every transition (merge/trim preserving queued rows,
  latest replace with request-baseline identity preservation, tail sync
  begin/apply/finish, older pages + epoch-mismatch reset, enterTailMode
  that deliberately keeps requiresLatestReset, activate, SSE ingest with
  hidden-row cursor advance, markConsumed stamping server rows to 'sent',
  optimistic lifecycle, queued reconcile, hydrate/persist, seededState)
- MessageMerge: position comparator (ASCII tie-break), localId echo
  replacement preserving status/invokedAt, 10s sent-dedup fallback
- MessageRetention: calls the fixtures-green chat pipeline's
  normalizeDecryptedMessage directly (no hand-mirrored tree to drift)
- WindowMessage: identity-carrying final class (web's !== baseline
  classification), tri-state invokedAt, buildOptimisticMessage

HapiClient/Stores/ — async half:
- MessagesProviding seam (three-variant MessagesPageQuery; APIClient
  conforms via its existing endpoints)
- MessageWindowController actor: single-flight tail controller with
  trailing drain and a synchronous generation bump before the first await
  (the web runs to its first suspension; Android used UNDISPATCHED),
  fetchOlder with onBeforeApply veto, SSE hooks, optimistic append/status/
  cancel-invoked, queued-state reconciliation in 1000-id batches, seedFrom
- WindowSnapshotStore: per-session JSON snapshots, LRU 10 (dedup TODO with
  the session-list package's cache) + MessageWindowControllers registry

Tests (swift-testing):
- PaginationFixtureTests: parameterized replay of shared/fixtures/
  pagination/*.json against the real controller via a scripted provider;
  asserts expectedRequests (canonical JSON incl. explicit-null untils),
  expectedOutcome, expectedCandidates, and the final expectedState
  projection with per-op labels and first-differing-line diffs
- MessageWindowControllerTests: tail-sync coalescing + trailing drain,
  concurrent-SSE preservation across a reset replace, cursor-no-advance
  guard, snapshot round-trip/LRU, seedFrom

All 11 fixtures verified green against a line-by-line Python mirror of
these exact algorithms (no local Swift toolchain; CI runs the real suite).
2026-08-17 20:18:05 +08:00