App-created sessions (started by sending a message from cloudcli) were
titled with placeholder names — "Untitled Codex Session" from the disk
indexer and, briefly, "New session" from the empty canonical upsert —
before a later sync finally settled on the right text, causing the
sidebar title to flicker.
- Codex/OpenCode synchronizers now title app-created sessions (distinct
app id mapped to a provider id) from the first user message, while
sessions found purely by indexing keep their existing setup. Claude
keeps its AI-generated titles; Cursor already used the first message.
- Decode OpenCode's JSON-string-literal prompts so titles no longer
surface wrapped in quotes; hoist unwrapJsonStringLiteral into
shared/utils since it's now used by both the reader and synchronizer.
- Guard the sidebar upsert merge so an empty summary can never blank out
a title that is already set.
- Add codex/opencode synchronizer tests for the app-created vs indexed
naming paths.