webui-run-state-consistency-contract.mdWebUI can reach the same conversation through several browser-facing entrypoints:
/session/<session_id>,?session=<session_id> or ?session_id=<session_id>,localStorage active-session value,/api/sessions,After automatic compression, those entrypoints can point at different rows in one logical conversation lineage. A pre-compression parent snapshot can remain a valid archived session while the user-facing conversation tip has moved to a newer continuation. If each caller resolves IDs independently, the UI can appear to lose the session, reopen an old one-message snapshot, duplicate sidebar rows, or prefer the wrong transcript even though durable data is still present.
This contract defines the expected resolution semantics for those entrypoints. It is intentionally narrower than the run adapter RFC: this is about choosing the correct visible session target, not moving execution ownership.
pre_compression_snapshot rows.| Term | Meaning |
|---|---|
| Requested session ID | The ID supplied by route, query parameter, localStorage, sidebar click, or direct session open. |
| Canonical visible session | The session row WebUI should display by default for normal chat navigation. |
canonical_visible_session_id |
Proposed field/name for an API or helper output that identifies the canonical visible session. |
| Compression snapshot | A preserved archived parent row with pre_compression_snapshot set. |
| Continuation session | The active child/tip created after compression, usually represented by continuation_session_id, _lineage_tip_id, or newer lineage metadata. |
| Lineage relation | Links such as parent_session_id, _lineage_root_id, _lineage_tip_id, and _compression_segment_count that connect rows belonging to one logical conversation. |
pre_compression_snapshot, it should normally resolve to
itself.pre_compression_snapshot and the session list has a newer
non-snapshot continuation in the same lineage, normal chat navigation should
resolve to that continuation as the canonical_visible_session_id.localStorage may remember the last active
ID, but browser boot restore must treat it as a requested session ID and still
run canonical resolution before rendering.?session=..., ?session_id=...,
and /session/... should feed the same requested-ID path instead of carrying
separate precedence rules.loadSession()
for that lineage during ordinary navigation.| Entry point | Input | Expected resolution |
|---|---|---|
| URL route | /session/<id> |
Treat <id> as requested; resolve to canonical visible session before ordinary render. |
| Query parameter | ?session=<id> or ?session_id=<id> |
Same as URL route. Query spelling must not change the target semantics. |
| localStorage | last active session ID | Advisory requested ID during browser boot restore; canonicalize before render. |
| Sidebar click | visible row ID or lineage representative | Open the same canonical visible session that the row represents. |
| Direct session open | programmatic call/search/import link | Use the shared requested-ID resolver unless the caller explicitly opts into archive inspection. |
| Browser boot restore | URL and/or localStorage state after reload/auth/PWA resume | Prefer explicit URL/query input, then localStorage, then canonicalize the requested ID. |
For PRs that touch session routing, compression lineage, sidebar collapse, boot restore, direct session open, or URL parsing, answer:
pre_compression_snapshot become the default active chat when a
non-snapshot continuation_session_id / _lineage_tip_id exists?loadSession() pick the same visible representative?canonical_visible_session_id, make the
frontend resolver prefer the backend value while preserving client fallback for
older WebUI servers.