Adds an opt-in content search over session messages, alongside the
existing metadata search. An FTS5 index covers visible user and assistant
prose; the sidebar gains a scope toggle, and selecting a result opens the
matching message rather than the session tail.
Search scope is a two-state toggle rather than a dropdown: a 48x48 target
matching the clear endcap, distinct glyphs for session details vs message
text, tooltips naming the real scopes, and the active mode kept on the
collapsed chip (tiann/hapi#2081).
Dogfooded on a live 1178-session fleet. The scope toggle and reading
forward from a search result were both click-tested on that install —
the latter walking six bounded pages through a 1,507-message session and
stopping correctly at the session head.
The per-commit history does not survive this squash; the review trail —
including which commit closed which finding — is on the PR threads.
Fixes#1554Fixes#2081
Implement two-stage content codec: truncate oversized agent messages
(48KB head + 12KB tail + marker, idempotent, never user messages) and
compress message content JSON ≥256 bytes via zstd with fallback.
- contentCodec.ts: new codec with truncation and compression routines
- messages.ts: wire codec into addMessage (truncate+compress),
copyMessageToSession (lossless), toStoredMessage (decode both formats)
- index.ts: schema version 15→16 with no-op migration (enforces
schema match on downgrade, no DDL change)
- codexDesktop.ts: pass content through idempotent truncation for
canonical comparison in transcript-import
- cleanup-sessions.ts: decode compressed rows, replace full-scan with
per-session batched scan (LIMIT 50) stopping at first user message
- compact-db.ts: new offline compactor that retroactively applies
truncate+compress+VACUUM to existing DBs; guards against schema
version mismatch, symlink aliasing, and handles re-runs
- Tests: contentCodec round-trip + truncation + idempotence + legacy
decode; messages integration (compressed/truncated round-trip);
migration tests updated to version 16
- README.md: document codec and both maintenance scripts
Measured on 2.26GB production DB: 2159MB→768MB (-64%) in 12s,
748k messages intact, integrity verified.