Skip to content

fix(home): queued recordings show Transcribing instead of Couldn't transcribe, and Try Again no longer runs the summary model on a recording with no transcript - #25426

Merged
Git-on-my-level merged 3 commits into
BasedHardware:mainfrom
Git-on-my-level:lane/q12-retry-pending
Nov 15, 2026

Conversation

@Git-on-my-level

@Git-on-my-level Git-on-my-level commented Nov 15, 2026 •

Copy link
Copy Markdown
Member

What users saw

Needs attention showed Couldn't transcribe for queued audio. Try Again ran the summary processor without a transcript, spun for a long time and returned to retry. First seal could arrive more than 24 hours after the wait began. Expired zero-content capture placeholders also appeared as failures.

What changes

  • Read-only Home/Activity presentation uses the later of the original wait and immutable first seal admission, plus the existing 24-hour maximum. Native seal and full-proof repair already stamp record_admitted_at once; no-job seal registration now does too. Reconnects, reseals, retries, requeues and reads do not renew it. A recording sealed 30h after capture shows Transcribing; a transcript arriving 2h later replaces that placeholder normally. No job lookup or write on reads.
  • Reprocess recognizes stamped batch captures without a transcript/receipt before any summary claim or model call. Stored structured.title is not transcript evidence. Inside the bounded wait it returns200 processing/transcribing; expired or explicit failures return409 transcription_pending. Build1563 at b78ea01 and main decode200 and remove the failed row into processing;409 keeps the existing error toast. No owner-click priority scheme exists, so jobs, priority, worker claims and backoffs remain intact.
  • Expired in_progress batch-live placeholders with has_content=false and no committed audio span, transcript, active producers, partial/upload failure, summary debt/receipt or curation are read-only noise after the existing 2h pending deadline. Home lists hide them; Activity/detail uses completed/noise/No summary. All recordings and audio are preserved. Late content or a new pending generation releases the rule. This is not a stored STT-empty result.

Existing queued rows and bounded one-off

Already-stamped queued rows use the new bound immediately. A ro-prod metadata-only dry-run found four legacy retained-audio retry rows lacking seal/admission clocks. The lead can first run:

source ~/.local/bin/gcp-agent-env.sh ro-prod
/Volumes/Ephemeral/scratch/worktrees/omi/omi-lane-q12-ctx-default-upstream-keep-clean/backend/.venv/bin/python /Volumes/Ephemeral/scratch/worktrees/omi/omi-lane-q12-retry-pending-upstream-keep-clean/backend/scripts/repair_legacy_transcription_wait.py --dry-run --days 5 --limit 1000 --max-updates 4

The tool defaults to dry-run. A separately authorized operator apply writes only home_transcription_queue_observed_at once after rechecking source and ready/retry retained-audio jobs in a transaction. It never fabricates a seal time, changes original pending generations, jobs, custody, or admission metrics. The scan processes at most1000 owner rows and32 jobs/row, using one extra sentinel row/header at each limit to refuse overflow; transactional checks reread only state metadata. Writes are capped by --max-updates (at most20). Every repeated invocation retains the first observation. At most two display renewals per stored capture: first seal once and the legacy observation once. Five still-record_pending shapes are ineligible and await a real seal. No one-off was applied by this lane.

Kill switches and rollback

All new behavior ships ON by default with config/refactor_modes default_on parsing. Set an individual switch false to restore that behavior's prior decision:

  • HOME_TRANSCRIPTION_SEAL_WAIT_ENABLED: ignore first-seal and one-off observation clocks.
  • CONVERSATION_PENDING_TRANSCRIPTION_RETRY_ENABLED: restore the old summary reprocess path.
  • HOME_STALE_EMPTY_CAPTURE_NOISE_ENABLED: restore the old placeholder wire.

Existing queue-hold and Home-step switches retain their roles. No new default-off gate, GPU change, capacity change, provider switch, or provider-backlog release. No new model path or paid attempt; pending retries avoid summary calls. HOME_TRANSCRIPTION_MAX_AGE_SECONDS remains86400 and HOME_TRANSCRIPTION_DEADLINE_SECONDS remains7200. No serving-time or transcription-throughput promise.

INV-CAP-1: no audio/recording deletion, producer-fence relaxation or seal-proof change.
INV-DATA-1: account/data-plane identity stays pinned; the optional repair tool is owner-scoped and prints counts only.

Verification

On head aa4b733:

  • Full normal scripts/pre-push passed, including45 shared preflight checks, canonical backend typecheck (0 errors), bounded40-file unit phase and CPU guard, OpenAPI/generated-client compatibility, and pinned formatting. No skip flags, test cap or CPU threshold changed. The selector requests the full2901-file suite for the new database helper; full CI remains authoritative.
  • Lead premerge_guards.sh sweep passed17 files with0 failures. Cross-service deployment contract:33 passed,3 skipped.
  • All105 new focused tests pass through backend/test.sh:48 pending retry/read,39 stale empty,18 strict transactional one-off. Highest reported new call CPU0.18s, below the brief's0.4s caution point.
  • The final-head affected-import native run passed3842 tests across92 files, with4 emulator skips and86 expected xfails; per-file counts are in q12-an-retry-pending.md and the evidence JSON. Four imported integration files were invoked;46 cases skipped without loopback Firestore. No live contention claim.
  • Tests use one pytest process per file through omi-heavy, with GOOGLE_APPLICATION_CREDENTIALS and CLOUDSDK_* unset. Existing Homebrew libopus discovery uses DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib; no host installation/change.

Source-checked the released1563 and main decoder/provider contract; HTTP wire and no-model regressions pass. No app file changed.

UI-Evidence: none -- backend only

Not verified: physical phone/cache rendering, exact-head GitHub CI, production rollout/identity, one-off apply, real Firestore contention or transcription scheduling/speed/recovery. No push, PR, merge, deploy or production mutation by this lane. The fix does not drain the backlog.

Failure-Class: FC-queue-sla-presented-as-terminal-failure

Line-Count-Exception: backend/routers/conversations.py | 2702 -> 2713 | The reprocess owner checks pending capture evidence before claiming existing summary work; all policy stays in the small shared helper.
Line-Count-Exception: backend/utils/episodes/home_read.py | 573 -> 578 | Shared evidence fields and a presentation-only empty-placeholder guard stay at the existing projector boundary.

🤖 Generated with Claude Code

View guided diff

Git-on-my-level and others added 3 commits November 16, 2026 03:09
…sing

Use immutable first seal admission for the bounded display wait. Guard pending capture reprocess before any summary claim, and render expired zero-content placeholders as read-only noise. Include a dry-run-first bounded repair for legacy queued audio without seal clocks.

Failure-Class: FC-queue-sla-presented-as-terminal-failure

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ll age bound before reading as noise

Review R23: a buffered first frame sets server_batch_audio_received before any span
commits and can still commit at teardown, so a 3-hour-old live row could be hidden.
Unclosed received audio now waits out the 24 h transcription age bound, a transcription
deadline still in the future always keeps the row live, and the shared read mask carries
the open-audio evidence. Test isolation: pin summary_delivery so a fresh handler load
does not re-register its counters.

Failure-Class: FC-queue-sla-presented-as-terminal-failure

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…red transcription read fields

Failure-Class: FC-queue-sla-presented-as-terminal-failure

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Git-on-my-level
Git-on-my-level merged commit 32ad562 into BasedHardware:main Nov 15, 2026
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant