feat(desktop): give processing conversations an identity, a bounded wait, and an exit - #12595
feat(desktop): give processing conversations an identity, a bounded wait, and an exit#12595Git-on-my-level wants to merge 1 commit into
Conversation
…ait, and an exit A conversation that is still being summarized used to render as "Processing…" with a fallback 💬, a pulsing pill that promised "shortly" without a bound, and a client that stopped checking after ~230s. The transcript was already on disk and the reprocess route already worked from a processing row; the UI just never used either. Row identity - The title slot carries the first substantive transcript line (or the recording time when no transcript is loaded). Status moves to the badge. - No fake emoji while the pipeline has not produced one: a waveform tile. - List refreshes keep an already-loaded transcript when the server list omits transcript_segments (omitted means "not loaded", not "empty"). Bounded wait - Pill reads Summarizing → Taking longer than usual (2 min) → Stuck (10 min), driven by a 15s TimelineView only on live-pipeline rows. - Stuck rows show Reprocess inline; the detail banner does the same. - ProcessingConversationWatcher follows every visible processing row to a terminal state with backoff (3s→60s) and never gives up while the row is visible; the detail view's poll uses the same backoff instead of 15×2s. Two waves - After status flips to completed the row shows "Adding memories & tasks…" for a 45s grace and refetches once so action items land without a manual refresh. Four meanings, split - Deferred free-tier desktop rows (`deferred=true`, `processing` on the wire, nothing running) now read "Tap to summarize" instead of "Processing…", are not timed, and are not polled. Continuity - The Live card's slot stays occupied by a "Saving" card until the capture is a row in the list; row insertion animates. Telemetry - "Conversation Processing Completed" (elapsed_seconds, outcome) and "Conversation Processing Stalled" (elapsed_seconds), so the thresholds can be re-set from a measured p95 instead of a guess. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
b3b9205 to
553e993
Compare
|
Rebased onto current Root cause: the only failing suite was Verification on the rebased head
Desktop Swift CI on the new head was queued behind the shared hosted-macOS runner queue at post time (6 runs pending); no failures reported. |
Why
A conversation that is still being summarized renders as "Processing…" with a fallback 💬, a pulsing pill that promises "shortly" without a bound, and a client that silently stops checking after ~230 s. Meanwhile the transcript is already in the local cache and on the detail endpoint, the backend flips
completedbefore memories/action items run,/reprocessworks from aprocessingrow, and free-tier desktop rows sit onprocessingforever by design (deferred=true, nothing running). None of that reached the UI. "Pending/zombie conversations" is a top user-complaint cluster, and the 2026‑08‑30 finalization outage ran six hours with every row looking like this screenshot.What changes (macOS only, no backend changes)
1. Status is never the title. The title slot shows the first substantive transcript line (
Let's go over the launch timeline for next week), orRecording at 11:12 PMwhen no transcript is loaded. The pill carries status. No fake 💬: a waveform tile until the pipeline produces an emoji. List refreshes keep an already-loaded transcript when the server list omitstranscript_segments(omitted = not loaded, not empty).2. Bounded wait with an exit. Pill reads
Summarizing→Taking longer than usual(2 min, orange) →Stuck(10 min, red) on a 15 sTimelineViewthat only live-pipeline rows pay for. Stuck rows show Reprocess inline on the row and in the detail banner. A newProcessingConversationWatcherfollows every visible processing row to a terminal state with 3→60 s backoff and never gives up while the row is visible; the detail view's poll uses the same backoff instead of 15×2 s.3. Two waves. When status flips to
completedthe row gets its real title and shows· Adding memories & tasks…for a 45 s grace, then refetches once so action items land without a manual refresh.4. Deferred ≠ processing. Free-tier desktop rows now read Tap to summarize, are not timed, and are not polled. The detail banner says "Summarizing now…" for them, which is what opening actually does.
5. Continuity. When a capture stops, the Live card's slot is held by a "Saving" card (last transcript line) until the next conversations load lands the row; row insertion animates. The flag is set where a finished recording enters the lifecycle and cleared in
loadConversations, so every stop path (user stop, automation stop, max-duration rotation) shares one clear.6. Telemetry to tune the thresholds.
Conversation Processing Completed {elapsed_seconds, outcome}andConversation Processing Stalled {elapsed_seconds}, emitted once per conversation by the watcher. Nothing measures processing latency today; the 2/10 min thresholds are a starting point to be re-set from the measured p95.Product invariants affected
ConversationRowView.swift,ConversationsPage.swift). The Conversations page keeps every control and destination; this adds row states and a transient card above the list, it does not introduce a reduced copy or occlude top-navigation controls.Not in scope
Percentage progress (no honest denominator), streaming partial summaries, and the
mergingstate for overlapping phone + desktop captures.Verification
xcrun swift build -c debuggreen on the rebased tree.ConversationProcessingProgressTests,ProcessingConversationWatcherTests,ConversationProcessingTelemetryTests; extendedConversationDisplayStateTests,ConversationReconciliationPolicyTests. 88 tests across the touched suites +ShellGlassChromeTestspass.ConversationProcessingBanner), the two analytics methods live inAnalyticsManager+ConversationProcessing, andAppState+Transcription.swiftis untouched.check_desktop_test_quality.pyreports the same pre-existing baseline drift (55/149 vs 54/147) with this branch stashed, so it is not introduced here.OMI_APP_NAME=omi-processing-row ./run.sh, stop a recording, and confirm: Saving card → row with transcript-line title andSummarizingpill → real title →Adding memories & tasks…→ clears.🤖 Generated with Claude Code