Skip to main content

Roadmap

What is being built, by release. Every item is a GitHub issue — this page is generated from the tracker, so it cannot describe work that is not tracked.

v0.5.0

Ship what is already builtShipped

Native diarization, corpus-scale chat, redaction and the identity overhaul, published without adding one more feature.

336/336
336 issues
ASR Engines
  • #455 fix(transcription): storage.py overwrites MediaFile.duration with 0.0, and speaker sets are non-deterministic
  • #456 fix(transcription): garbage-word cleanup edits text but not words, and rewrites whitespace on every segment
  • #470 ASR providers: real defects found writing #445 test coverage (punctuation loss, retry never fires, timeout bool discarded, wrong response_format)
  • #584 Lite mode: cloud-ASR speaker embeddings silently never complete (GPU-only queue, no lite worker)
  • #865 fix(tasks): speaker/embedding tasks silently drop on the gpu queue in --lite mode (no consumer check)
Desktop App
  • #889 docs(roadmap): the #48/#283 dependency direction is inverted in the developer guide
Docs & Release Ops
  • #772 fresh-destroy leaks the compose network, silently — 11 accumulated and exhausted Docker's address pool
  • #780 build(docs): docs image ships on EOL Node 20 while the frontend is on 26
  • #781 fix(release): release assets have no checksums, and the SBOM is attached by glob rather than gated
  • #783 fix(release): FROM_VERSIONS is documented but never implemented, and no skip-version upgrade policy is stated
  • #784 task(release): no patch/hotfix path exists — 4 of the last 5 minors needed one within 24 hours
  • #800 fix(ci): the install-path release gate fails intermittently on identical code
  • #847 docs(spec): summary-search spec still says "designed, not built" after shipping
  • #849 docs: "16 AST detectors" is stale against an actual 21, plus a false "only call site" claim
  • #850 docs(i18n): four files say 8 locales; it is 12
  • #851 docs: check:i18n is documented as CI-only but now runs in frontend-check.sh
  • #852 docs(frontend): npm run check is described as "type + a11y" but enforces neither a11y warning
  • #853 docs(ci): a pre-commit comment claims docs-site has no build hook, directly above the hook it denies
  • #854 docs(frontend): gallery/ and speakers/ CLAUDE.md lack an E2E-guarded selectors section
  • #855 docs: retire stale PLANS/ planning artifacts
  • #916 task(docs): docs image builds on EOL Node 20
  • #917 security(release): release assets ship with no checksums, SBOM attached by glob not gated
Document Ingestion
  • #362 feat: Document ingestion & knowledge base — parse, index, and chat over documents alongside transcripts
Frontend & UI
  • #174 Refactor: Split oversized frontend components (FileDetail, SettingsModal, TranscriptDisplay, Speakers)
  • #298 bug(upload): single-file limit is 15 GB but multi-file drop rejects at 2 GB
  • #301 bug(frontend): MediaFile status union is missing queued, downloading, and quarantined
  • #302 bug(frontend): audioExtractionService hashes on the main thread — tab freeze / OOM on large video
  • #326 i18n: ~65 remaining bypasses in the service/store layer + tag-shape contract disagreement
  • #327 upload: no browser-side presigned multipart or resume for multi-GB files (A2.9 remainder)
  • #335 bug(file-detail): tag changes never propagate — TagsSection says "re-emit to parent" but never dispatches
  • #338 cleanup: `reactiveFile` is a write-only store — 13 writes, zero readers
  • #342 bug(upload): client-side SHA-256 silently skips duplicate detection above ~4 GB
  • #352 bug(file-detail): renaming a speaker does not update the transcript until a full page reload
  • #376 Frontend dead-code cleanup: knip audit findings
  • #452 Responsive: nav overflows at 1280px and clips the user menu; 1280 is an untested breakpoint
  • #475 Test suite: frontend statement coverage is 14.27%; core service/store/api logic largely untested
  • #489 Watch sources: per-file management UI is entirely unbuilt despite full backend/API support
  • #490 Watch sources: per-source email-notification linking UI is entirely unbuilt despite full backend/API support
  • #527 Gallery: virtualized rendering and real thumbnails
  • #578 task(backend): confirm whether speaker rename/verify still live-updates other connected clients via WebSocket
  • #583 ShareCollectionModal hardcodes canManage=true regardless of collection ownership
  • #585 fix(frontend): file detail page canEdit fails open on missing/null my_permission
  • #645 Waveform seek can stall ~10-30s on a fresh page load before media metadata is ready
  • #649 Audit other interactive UI paths for the same premature-interaction timing bug class as #645
  • #739 fix(upload): upload wizard has a dead Skip button, resizes between steps, and chains scroll
  • #740 fix(transcript): "Add speaker" silently creates an auto-named speaker with no name entry
  • #741 fix(transcript): unconfirmed LLM speaker suggestions render as the speaker's name and overflow
  • #742 fix(search): clearing the search box leaves stale results on screen
  • #744 fix(gallery): the duration range filter does not apply
  • #745 fix(search): transcript modal header scrolls away, hiding the match count and prev/next
  • #746 fix(frontend): light/dark parity audit — icon buttons invisible in one theme
  • #786 fix(ux): diagnose preprocessing failures instead of surfacing the raw exception
  • #787 fix(transcript): unsaved speaker and transcript edits are lost silently on navigation
  • #835 fix(frontend): nine theme tokens have no dark value
  • #836 fix(i18n): five keys use single-brace interpolation and render literally in all 12 locales
  • #837 fix(frontend): speaker-match highlighting counts matches it never highlights
  • #838 chore(frontend): speakerColors store has zero component consumers
  • #840 refactor(frontend): three copies of the M:SS formatter and three of escapeHtml
  • #841 fix(frontend): TS/Pydantic drift on MediaFileDetail.error_message
  • #856 fix(frontend): UserFileStatus ships a hardcoded English data-tooltip
LLM Providers
  • #596 fix(llm-provider): Bedrock LLM provider is implemented but unreachable — no schema/UI wiring
  • #839 chore(llm-provider): custom provider is translated in 12 locales but unreachable from the UI
  • #873 fix(llm-provider): admin UI hardcodes a 4096-token context window on every new config
Native Diarizer
  • #193 [FEATURE] Improve diarization at boundaries
  • #299 bug(diarization): _normalize_speaker_label raises TypeError on every call (object.__new__ on an abstract class)
  • #482 speaker_processor.mark_overlapping_segments loses overlap data when a segment spans two overlap regions
  • #483 Duplicate normalize_speaker_label implementation in speaker_processor.py diverges from the canonical version
  • #520 diarization follow-ups that need a GPU window: speakrs boundary fixture twin + sidecar EP smoke test
  • #571 task(asr): migrate CPU-lite + speaker-embedding path off PyTorch/PyAnnote onto native diar-native
  • #579 diar-native: WAV write failure hard-fails the pipeline instead of degrading to PyAnnote fallback
  • #621 fix(frontend): local diarization settings/About/reprocess text still credit PyAnnote as primary, not diar-native
  • #639 Diarization backend defaults to native (diar-native sidecar) but the sidecar is never distributed to self-hosted installs — perpetual silent-ish PyAnnote fallback
  • #654 task(models): add a download-models diar-native group — the export four files already claim exists
  • #655 bug(docker): diar-native sidecar is unwired in gpu-scale, gpu-split, lite, offline, Windows, --fresh and CPU-only topologies
  • #656 task(asr): sidecar-unavailable retry policy, bounded timeout and status surface before the PyAnnote fallback is removed
  • #657 bug(search): v4 embedding migration loses profile voiceprints and crosses index dimensions mid-run
  • #660 task(asr): --lite adopts the diar-native CPU execution provider for speaker embeddings
  • #661 perf(pipeline): collapse the audio handoff — four decodes and ~2.1 GB of one signal per job
  • #662 bug(config): .env.example ships DIAR_NATIVE_GPU=0, restoring the bare-device-0 pin the compose comment exists to prevent
  • #663 docs(legal): add a NOTICE file — the native diarizer's weights are CC-BY-4.0 and still require pyannote attribution
  • #665 fix(gpu): overlap-diarization gate keys off the configured backend, not sidecar reachability — transcriber is never released on the PyAnnote fallback path
  • #669 task(testing): diarization test + gate coverage survives the PyAnnote removal (several would go green measuring nothing)
  • #670 bug(deploy): upgrading into a mandatory-sidecar release degrades silently instead of refusing
  • #671 docs(backend): transcription/ and services/diarization/ CLAUDE.md still describe PyAnnote as the engine
  • #672 bug(config): PYANNOTE_MODEL means two different things, the admin panel misreports the diarizer, and four diarizer symbols are dead
  • #679 Adopt diar-native 0.3.0: self-provisioning models, CPU/GPU routing, /readyz, and structured logs
  • #700 rebuild-backend drops the diar-native overlay: celery-worker loses /tmp/diar-native and diarization silently falls back to PyAnnote
  • #711 task(gpu): diar-native routing under gpu-scale and gpu-split is wired but never verified on real multi-GPU hardware
Platform & Operations
  • #21 [ENHANCEMENT] Implement Comprehensive Testing and Enable CI/CD Pipeline
  • #26 [FEATURE] Automatic Bucket Processing with User Access Controls
  • #123 E2E Test Expansion: Gallery, Upload, Settings, Transcription, Search & CI/CD
  • #189 [BUG] Quick Installation documenation incorrect
  • #190 [FEATURE] auto-ingest a file share or support api uploads
  • #234 Testing follow-ups: coverage ratchet, responsive E2E, deferred dep majors
  • #241 Modernize UUID columns: native pg uuid type + generation strategy review
  • #242 Backup extension: MinIO media mirror (OpenSearch snapshots DONE in #239)
  • #243 Back up encryption keys / .env alongside the database (or backups are unrecoverable)
  • #244 Surface scheduled-backup failures (Prometheus metric + notification)
  • #245 Operational: re-ingest the media corpus in place after #239 merges (GPU 1)
  • #272 Latent always-False FileStatus string comparisons (found by the py312 codemod audit)
  • #293 bug(watch-sources): SMB download size-mismatch check is unreachable — truncated downloads import silently
  • #294 bug(watch-sources): watch.fs_events_enabled is a no-op — no watchdog Observer exists
  • #295 bug(watch-sources): watch.max_concurrent_imports is a per-scan slice cap, not concurrency
  • #297 bug(tests): pytest.mark.gpu is unregistered and silently ungated — GPU tests run in fast CI, integration gate under-covers
  • #303 docs(release-tests): README claims hard isolation, but the scripts use live ports and stock container names
  • #320 perf/correctness: `async def` functions that never await block the event loop (OpenSearchSummaryService + 78 endpoint handlers)
  • #325 test: `@pytest.mark.unit` test downloads a HuggingFace model and randomly reddens CI
  • #334 bug(sse): bulk-export stream can hang forever — check-then-subscribe lost-wakeup race
  • #343 bug(opentr.sh): --port-offset does not offset — Compose appends port lists
  • #347 bug(opentr.sh): --fresh cannot isolate the ldap/smb/monitoring test overlays
  • #355 [BUG] Flower container always reports as unhealthy
  • #389 Flaky tests: cross-worker Postgres deadlocks + order-dependent failure in migration/settings tests
  • #397 test(routes): /api/auth/me/certificate has no frontend caller and no allow-list entry
  • #398 Pre-existing defects surfaced by the release-engineering gates (2 failing tests + 4 schema findings)
  • #399 fix(bench): engine/status gate on the dev stack's container names — the bench overlay renames everything to otbench-*
  • #407 Unattended install aborts at the final step: set -e + pipefail on an absent optional .env key
  • #408 Fresh-install release scenario is not repeatable: it reuses the previous run's database
  • #409 Unattended install never persists HUGGINGFACE_TOKEN: every transcription fails
  • #410 v0.5.0 BREAKING: existing v0.4.x deployments without REDIS_PASSWORD will fail to start after upgrade
  • #411 Every production container reports its version as "unknown": compose blanks the baked APP_VERSION
  • #412 rehearse stage can never reach Scenario B: Scenario A leaves its stack running
  • #413 SECURITY: the release scan gate is fail-open — finding CRITICAL CVEs makes it PASS
  • #414 SECURITY: the release scan gate scans the PREVIOUS release, not the release candidate
  • #423 Upgrade Docusaurus 3.9.2 → 3.10.2 (MDX v3 content migration required)
  • #431 Test suite: 81% of wall clock is one serialized worker + 8 lock barriers; 232 security tests never run; 113 modules untested
  • #434 pre-commit stashes the WHOLE tree on every run — it has destroyed in-flight work twice
  • #440 DB sessions held across slow work hang Alembic and wedge the database
  • #445 Test suite: 41% of backend modules have no test reference; four authz decorators untested
  • #446 Mutation testing: ~275 of 636 survivors are real gaps, not log noise — triage the top findings
  • #447 Visual regression: all 8 baselines failing
  • #450 auth_decorators.py + transcription_service.py are dead code (~650 LOC); require_verified_user doesn't verify
  • #451 Visual regression: all 8 baselines depend on live mutable dev data and cannot be honestly refreshed
  • #454 Test isolation: tests/unit fixtures vanish when a tests/*.py file is collected in the same run
  • #457 fix(recovery): the request cap stops bounding requests exactly when fetches are failing
  • #458 fix(gpu): a healthy GPU reports 'No GPU Available', and GPU_SCALE_DEFAULT_WORKER=true is silently False
  • #459 mutation --verify: class-method mutants always UNVERIFIABLE (dedented diff matched against un-dedented source)
  • #474 Test suite: 57 backend modules have zero test reference after #445/#470
  • #485 Celery apply_async() intermittently dispatches to the default AMQP broker instead of the configured Redis one — every admin "Run now" action 500s
  • #486 test_speaker_metadata.py fails intermittently under xdist parallelism (passes clean standalone)
  • #487 Golden-fixture drift: test_boundary_regression word-count mismatch (2282 ref vs 2251 hyp) — real accuracy drift or stale fixture?
  • #491 NLTK/offline: corpora fetched at runtime, airgap coverage incomplete
  • #492 requirements.txt pins almost nothing: venv and container diverged by 120 packages (18 major)
  • #493 Integration phase: 95 tests take >30 min, cannot pass on 12GB GPU, and has no per-test timeout
  • #500 Dockerfile.blackwell: huggingface_hub==0.23.5 downgrade makes `import transformers` fail outright
  • #522 Ingest real media into dev by pulling from the NAS store (first true ASR + diarization run)
  • #528 BUG: --no-bindmount can serve a stale image, silently invalidating measurements
  • #529 Final merge gate for feat/rag-transcript-intelligence: full suite, benchmarks, E2E
  • #538 opentr.sh: load the diar-native overlay so dev runs the primary diarization engine, not its fallback
  • #539 Audit every .env / .env.example variable: read-by-what, accurate, useful — and keep the template in sync
  • #541 E2E: a speaker test persists prediction state onto a real profile (data-hygiene violation)
  • #545 refactor(backend): audit duplicate public function names — two normalize_language implementations disagree
  • #553 bug(opentr.sh): a plain 'start dev' has no port pre-flight, so a collision half-starts the stack
  • #567 bug(config): five defects found by the .env audit — non-functional GPU clustering device, 3 phantom ASR aliases, unimplemented FedRAMP AC-2
  • #568 bug(testing): DIARIZATION_VRAM_BUDGET_MB perf-gate test asserts a propagation mechanism that doesn't exist
  • #577 task(testing): diarization GPU integration tests unrunnable via either documented path (venv torchaudio drift + benchmark container missing test deps)
  • #580 fix-shared-volume-perms.sh: default chown GID (1000) doesn't match the image's appuser GID (999)
  • #586 test(diarization): pyannote.ai cloud diarization provider has no direct test coverage
  • #590 refactor(scripts): replace hand-rolled bash .env parsing + ad-hoc smoke scripts with python-dotenv + pytest
  • #591 chore(docker): promote compose-only env vars to .env.example, fix TEMP_DIR name collision
  • #592 Upgrade rehearsal proves the happy path; there's no failure-recovery doc or in-script guidance for a failed ./opentranscribe.sh update
  • #597 CI: Release Validation dry-run fails on missing NAS mount, not a real deployment defect
  • #598 Release rehearsal matrix has no coverage for opentr.sh backup/restore or opentranscribe.sh update --rollback
  • #599 P0: opentr.sh restore silently fails to restore data — exits 0, reports success, changes nothing
  • #600 P0: scheduled backup_service.py produces -Fc custom-format dumps with NO restore path anywhere in the repo
  • #601 cleanup-test-users.py --execute (real DELETE FROM "user") has zero test coverage
  • #602 fix-model-permissions.sh / fix-shared-volume-perms.sh have zero test coverage (chown on real data volumes)
  • #604 backup.encrypt (scheduled/S3 backup gpg encryption) fails in production — gnupg not installed in backend image
  • #607 UserLLMSettings.is_active is vestigial (always defaults True, never reflects the real active config) — silently defeats the e2e ensure_llm_provider fixture
  • #608 docker-compose.llm-test.yml's default Gemma-4-E4B-AWQ config does not fit a 12GB GPU even with the entire card free — full-test-matrix.md's <=0.45 guidance is insufficient
  • #609 Flower /api/workers never shows threads-pool Celery workers (gpu-scaled@*, gpu-transcription@*) — gpu-scale-smoke.sh cannot pass
  • #610 opentr.sh restore silently lets the running (newer) app auto-migrate a just-restored older backup forward — blocks the rollback rehearsal's phase 15-17 chain
  • #612 fix(testing): search-quality suite fails 2 unrelated checks on a brand-new --fresh deployment (OpenSearch ML model not yet active)
  • #613 opentr.sh missing from release-manifest.txt while docs instruct operators to run it for restore/rollback
  • #614 MINIO_KMS_SECRET_KEY placeholder in .env.example isn't a format MinIO accepts, blocks a truly-fresh cp .env.example .env boot
  • #616 fix(docker): docker-compose.backup.yml is not shipped, so the in-app scheduled/S3 backup has no mounted destination in production
  • #617 Release rehearsal: dbs_diff_fingerprints() unguarded under set -e silently truncates phases 15-18
  • #618 Release rehearsal: unguarded curl to frontend under set -e silently kills phase 16→17→18 (same class as #617)
  • #619 fix(release-tests): test-upgrade.sh F-4 (media_file digest) and phase-06b backup-content-diff race async DB writes — same class as #617's Layer 1
  • #620 fix(security,testing): post-rehearsal adversarial review findings (8 items, 1 HIGH)
  • #622 fix(backend): detect_speaker_attributes and redaction_detect_task have no Task DB record
  • #629 task(testing): automatic, signature-scoped cleanup of orphaned e2e/test data across ALL leak classes
  • #630 task(testing): run-dev-tests.sh should dynamically start/stop auth-overlay containers (Keycloak, LDAP, etc.) like it does mock-llm
  • #631 Celery prefork pool death spiral: 10h46m of forked children failing to signal UP, root cause unknown
  • #640 setup-opentranscribe.sh doesn't read release-manifest.txt — fresh installs never get docker-compose.blackwell.yml or docker-compose.backup.yml despite the manifest's own header claiming it's a consumer
  • #680 bug(docker): the published arm64 backend image is not equivalent to amd64 — 765 MB vs 4,454 MB, dependency layer 8.4x smaller
  • #681 bug(ci-cd): an unscannable component yields "All security scans completed successfully!" — docs is already in this state
  • #683 [BUG] Can't install due to "❌ Failed to download release-manifest.txt from v0.4.1" - 404: Not Found
  • #693 bug(testing): running the backend suite DESTROYS a live dev stack — test_opentr_stop_container_scoping executes the real docker stop/rm loop
  • #782 fix(gpu): opentr.sh stop SIGKILLs GPU workers after 10s — no grace period, no shutdown handler
  • #792 task(deps): pin the deno base image, watch root compose images, record the #508 deferral as accepted risk
  • #809 fix(gpu): cooperative abort so a mid-decode transcription exits before the grace ceiling
  • #823 fix(tasks): revoke(terminate=True) is a no-op under --pool=threads
  • #846 fix(nginx): set the WebSocket timeout in every /api/ws location block, not just the overlay
  • #857 fix(config): .env is not reliably chmod 600
  • #858 fix(config): OpenSearch ships security-disabled with an admin/admin credential fallback
  • #893 fix(config): OPENSEARCH_EMBEDDING_MODE is not validated — an invalid value silently degrades to keyword-only search
Public Demo
  • #667 build(release): publish the CPU-only lite image as a multi-arch (amd64 + arm64) release artifact
  • #895 fix(deploy): docker-compose.lite.yml ignores OT_IMAGE_TAG, so a lite install cannot be pinned or upgraded
RAG & Chat Quality
  • #52 Feature: AI Interactive Chat with RAG System for Selected Transcripts
  • #78 Feature: Admin-Controlled Prompt Sharing System
  • #136 [Tip] Example AI summary for Q&A panel
  • #359 chat: per-conversation max_tokens and top_p
  • #360 chat: projects with pinned scope and project-level prompts
  • #383 feat(chat): corpus-scale RAG — summary tier, query routing, aggregation, model-tier parity, and a real eval harness
  • #384 fix(chat): sources frame is sent before the excerpt budget is known — UI can show citations the model never saw
  • #385 fix(chat): tag-scoped chat silently excludes shared files (tag scope is owner-only, collection scope is not)
  • #386 fix(chat): history_max_turns counts pairs in one place and messages in another, halving conversation depth
  • #387 fix(chat): first excerpt is always emitted even when it alone exceeds the prompt budget
  • #403 feat(rag): master orchestrator — ordered end-to-end implementation of corpus-scale RAG, retrieval tuning, and documents (#383 → #363 → #362)
  • #438 fix(chat): an unscoped conversation searches nothing — file_uuids defaults to [] (match nothing), not None (all accessible)
  • #439 fix(chat): Gemma reasoning and a raw <channel|> control token leak into the user-visible answer
  • #448 Backlog: multilingual RAG/chat — CJK transcripts produce one un-chunked blob (English-only is the current scope)
  • #453 Multilingual RAG and chat: four independent stages, none of them a setting
  • #461 RAG retrieval quality: what is measured, what is not, and what to do next
  • #463 eval: measure whether chat answers are actually useful — QMSum reference answers are already on disk and unused
  • #465 AI summaries are displayed and exported completely unmasked, ignoring the user's redaction policy
  • #495 RAG eval harness: synthetic corpus injection indexes no chunks on re-injection (test xfailed)
  • #514 Live query-trace panel: an animated, Redis-pushed execution tree for search and RAG
  • #515 Umbrella: RAG/chat/search/document-ingest completion — status, plan corrections, and open decisions
  • #517 eval: scope coverage — the metric no framework measures, and the bug it hides
  • #518 eval: calibrate the LLM judge with Cohen's Kappa before tuning anything on it
  • #519 eval: acceptance suite for the four real query shapes, over AMI ground truth
  • #521 eval: add ELITR-Bench (CC-BY-4.0) — first benchmark that tests speaker attribution directly
  • #524 RAG: the speaker axis silently disables itself at corpus scale (roster cap declines wholesale)
  • #525 RAG: widening the candidate pool changes nothing — ranking keeps selecting content-free fragments
  • #530 RAG: calibrate the answer judge with Cohen's Kappa (gates every quality claim)
  • #531 RAG: shipped 48/12/4 retrieval budget starves the chat — 2x recall available
  • #533 LLM settings: discover a model's context window instead of defaulting to 8192
  • #534 RAG: validate the budget finding on a second corpus (ELITR-Bench) before changing defaults
  • #535 RAG: standing acceptance suite over the four query shapes
  • #536 chat: base rules leak prompt-internal block vocabulary into answers when the block is absent
  • #589 bug(services): group_batch_by_topics miscounts a collection collision as a creation
  • #595 test(release-tests): lite-mode rehearsal chat-summary text comes back empty despite citations succeeding
  • #611 Lite-mode rehearsal: chat SSE stream sends the model's real answer inside an event: error frame's 'code' field
  • #830 fix(rag-chat): Citation.kind recurrence is fully rendered with no backend emitter
  • #832 fix(rag-chat): SNIPPET_CHARS=240 truncates citations, dropping pooled quote fidelity to 0.527
  • #833 fix(rag-chat): #533's measured LLM context window is ignored by the chat path
  • #848 docs(rag-chat): four RAG docs are stale in ways that misdirect an implementer
Search Infrastructure
  • #363 search: measure RRF vs score-based hybrid fusion, and record the speaker-turn chunking decision
  • #400 fix(search): re-running search indexing never deletes existing chunks — stale tail chunks survive a shorter re-chunk
  • #401 fix(search): ingest pipeline recreation compares only model_id — a field_map change is silently ignored on upgrade
  • #402 chore(docs): four doc-drift fixes found during the #383/#363 second-opinion review
  • #405 fix(search): speaker and title renames never propagate to transcript_chunks — chat speaker scope, search facets, and citations serve stale names until a full reindex
  • #432 fix(search): six more display_name writers still leave stale speaker names in transcript_chunks
  • #433 fix: ORDER BY start_time is not a total order — re-indexing the same transcript yields different chunks
  • #435 fix(search): chunk-prune count gate reads the searcher, so a re-index inside the refresh window leaks orphans permanently
  • #436 fix(search): indexing workers have no nltk_data mount — every production chunk was cut by the regex fallback
  • #437 fix(search): switching the embedding model silently leaves a mixed-vector index, and embedding_model records the mode not the model
  • #449 Chunk boundaries depend on whether NLTK punkt loaded — and on a 5-minute global cooldown
  • #501 Bulk indexing fails intermittently: ML Commons circuit breaker false-trips on young-gen garbage
  • #502 Offline embedding-model registration is broken on OpenSearch 3.4 (400 'model config is null')
  • #503 Verify at setup that the selected embedding model actually works, and size heap per machine
  • #504 Embedding model registry offered paraphrase-multilingual-mpnet-base-v2, which OpenSearch does not provide
  • #540 OpenSearch startup maintenance: probe the kNN plane and self-heal — vector corruption survives restarts silently
  • #542 Dead ANN branch in opensearch_service/transcripts.py::search_transcripts would 400 if ever called
  • #606 Semantic search fails to find the obvious gold file for 'space exploration' query, surfaces both anti-gold files instead
  • #625 fix(search): neural-search bootstrap is one-shot with no retry, can permanently lose model deployment on a cold OpenSearch boot
  • #626 task(search): operator-triggered re-embed for files indexed during a neural-search degraded window
  • #627 fix(search): admin "Reindex all" only re-indexes the admin's own files, not the whole corpus
  • #638 Offline model registration (file://) is dead in every deployment mode: missing opensearch-ml volume mount + missing config.json
  • #658 bug(operations): speaker voiceprints live only in OpenSearch and no backup covers them
  • #666 fix(search): a transcript text edit never reindexes OpenSearch — search, RAG retrieval and citations serve pre-edit text indefinitely
  • #691 fix(search): reindex/stop is still per-owner while reindex now fans out corpus-wide — an admin cannot cancel what they started
  • #692 fix(search): index_health logs 'dispatched' but the helper returns 'reindex_users' — the repair log always reads 0 owners
  • #698 fix(search): semantic_confidence compares three different score spaces against one absolute threshold
  • #822 security(api): /api/search has no rate limiting, and the summary leg re-runs redaction uncached
  • #831 fix(search): summary leg ignores all filters, has no ranking, and breaks result_type=all pagination
  • #834 fix(search): ChunkHit.language is not round-tripped by the retrieval cache
  • #844 fix(speakers): PUT /speakers/{uuid} updates chunk keyword fields but not the kNN vector
  • #871 fix(files): file_type filter fails open, returning every file for an unrecognized value
Security & Compliance
  • #188 [BUG] LDAP cn not parsed correctly
  • #262 Post-0.5.0 hardening follow-ups from the cloud-seams security review
  • #284 Improvements & Security Review
  • #296 docs(redaction): redaction_task.py docstring claims unconditional detection — dispatch is actually gated
  • #300 bug(asr): AWS access_key_id is dropped when building the provider for a job (test-connection passes, transcription doesn't)
  • #324 security: six remaining fail-open paths deferred from #284 Phase 3B
  • #353 [BUG] Generic OIDC / Authentik does not work because OpenTranscribe hardcodes Keycloak realm URLs
  • #354 [FEATURE] Disable self-registration via environment variable
  • #441 JWT algorithm decision is duplicated 3x with different gates; issuers and verifiers disagree
  • #442 GDPR Art. 17: no erasure ledger, legal-hold data never re-erased, backup restore resurrects subjects
  • #443 Audit log: split user_id into actor and target (schema change, not a convention)
  • #444 chat_completion — the production LLM path — has no SSRF validation at all
  • #471 Replace gender-guesser (GPLv3) with a permissively-licensed alternative
  • #473 Compile a minimal, license-confirmed FFmpeg.wasm core (replace generic @ffmpeg/core CDN fetch)
  • #484 directory_sync (LDAP deprovisioning sweep) has no admin settings endpoint — unreachable in any real deployment
  • #497 Cross-tenant authorization gap: update_comment and delete_comment run no tenant check
  • #498 Five PKI revocation settings are writable in the Settings UI and read by nothing
  • #499 PII masking misses names spaCy labels ORGANIZATION, which the default policy excludes
  • #513 perf(redaction): ONNX-convert toxic-bert and the search embedding model (and why Presidio should stay in Python)
  • #573 docs(compliance): FIPS_140_3_COMPLIANCE.md claims 'FIPS 140-3 compliant' but only implements FIPS-approved algorithms, not a validated module
  • #575 docs(compliance): password policy (forced expiry + composition rules) contradicts current NIST SP 800-63B Rev. 4, not FedRAMP IA-5 best practice
  • #582 SCIM PUT does not implement RFC 7644 replace semantics
  • #587 test(services): AutoLabelService tenancy-scoping and per-user cache paths are untested
  • #588 fix(auth): viewer-permission users can reprocess/summarize shared files via API
  • #593 PKI E2E admin-cert fixture collides with super_admin email-link protection
  • #594 ASR UserASRSettings.base_url is validated and persisted but never consumed — wiring it needs an SSRF guard first
  • #615 PKI_TRUSTED_PROXIES default CIDR doesn't cover the full range Docker can assign to a compose network (breaks mTLS header trust under --fresh)
  • #623 fix(frontend): PKI/proxy trusted-CIDR admin UI still suggests the now-fixed vulnerable range
  • #632 Session accumulation: refresh_token rows for one user hit 272x the configured max_concurrent_sessions limit
  • #633 refresh_token rows accumulate unbounded on admin@example.com (5,504+ observed)
  • #664 fix(security): retention sweep and purge_media_file have no legal_hold guard — a legal-held file can be permanently deleted
  • #668 security(deploy): nginx/reverse-proxy hardening — trusted-proxy rate-limit collapse, pre-auth body buffering, missing robots.txt
  • #673 fix(redaction): export_locked is enforced only for subtitles — the admin forced-redacted-export policy is bypassable via every other export format
  • #676 security(api): LLM connection-test and model-discovery handlers make user-supplied outbound requests with no rate limit
  • #689 fix(security): admin user-deletion bulk-deletes MediaFile rows with no legal_hold guard — a held file can still be destroyed
  • #695 fix(storage): deleting a user orphans every one of their objects — media_file rows go, MinIO objects stay forever
  • #817 security(files): quarantined public files still stream thumbnails to unauthenticated callers
  • #818 security(files): six read surfaces do not honour quarantine
  • #819 fix(docs): abuse-and-takedown.md asserts a takedown property that does not hold
  • #821 security(export): client-side clipboard copy bypasses the server-side export_locked floor
  • #824 fix(files): #664 item 3 was not completed
  • #825 fix(admin): legal-hold release endpoint has no frontend caller
  • #862 fix(legal): ship the AGPL license text, surface it in-app, and add an AGPL §13 source offer
  • #863 fix(chat): export resolves no redaction policy and bypasses the admin export floor
  • #870 fix(gdpr): DATA_DIR is unmounted, so the erasure journal does not survive a container recreate
  • #872 fix(files): reprocessing a media-less file deletes the only copy of its transcript
  • #876 security(search): the facet quarantine exclusion fails open on DB error and is silently capped
  • #877 fix(security): AUDIT_LOG_FALLBACK_PATH is mounted by zero compose files
  • #878 security(docker): a benchmark run writes into the live GDPR erasure journal
  • #886 chore(build): no package manifest declares the project's license, so the SBOM omits it
  • #887 fix(legal): the Windows installer presents a 2.3 KB summary as the license, not the AGPL text
  • #903 security(ws): the WebSocket accepts before authenticating, with no Origin check and no connection or frame caps
  • #904 security(api): any authenticated user can enumerate every account in their tenant
Speaker Intelligence
  • #512 feat(speakers): cross-file speaker clustering — ANN index over speaker embeddings + batch re-resolution
  • #543 SpeakerProfile.predicted_gender is written but never read — confirming a gender on a member-less profile is silently invisible
  • #603 Speaker confirm-gender/merge don't propagate to other open tabs (cosmetic, self-correcting on reload)
  • #605 Live speaker chunk-index label drifts from canonical_speaker_label() resolver (speaker_id=74070)
  • #674 fix(speakers): auto-accept threshold is passed as OpenSearch min_score in cosinesimil space — the effective gate is raw cosine 0.50, not 0.75
  • #675 fix(search): speaker profile rename never propagates to transcript_chunks — the one rename path that skips dispatch_speaker_rename
  • #690 fix(speakers): SimilarityService clamps cosine to [0,1] in two methods but not a third, and boost_recent is a documented no-op
  • #702 chore(speakers): delete SimilarityService.batch_cosine_similarity — no production caller
  • #743 fix(speakers): the speaker filter is empty unless speakers have been manually renamed
Test Suite Health
  • #793 fix(ci): deploy-docs.yml has no pull_request trigger, so a broken docs build merges unchecked
  • #826 fix(testing): both auditors document a mandatory written reason that is never enforced
  • #827 fix(testing): the theme-parity guard cannot see .css files
  • #828 fix(testing): _ADMINISTRATIVE_EVENTS is a two-name set, so audit-attribution coverage is mostly unasserted

v0.6.0

Interface polish, and chat measuredIn progress

A full UI pass over what v0.5.0 shipped, plus real metrics for search and chat answer quality instead of assumptions.

14/74
74 issues
ASR Engines
  • #1198 fix(speakers): saved speaker range is overridden on watch-source, cloud re-diarize and reprocess paths, and "use defaults" uses the wrong values
  • #1199 fix(transcription): the user garbage-cleanup setting does nothing; the pipeline reads an admin value that has no UI
  • #1200 fix(speakers): gender-detection and show-on-cards toggles are never read, and sidecar gender is stored even with attribute detection off
  • #1202 fix(api): reprocess, prepare-upload and bulk requests accept per-file diarization, language and model options and silently drop them
  • #1203 fix(files): retry rewrites a file's diarization source and drops its requested model and speaker range
  • #1204 fix(speakers): the pyannote.ai diarization choice can never work; no endpoint stores its credential and the fallback is silent
  • #1205 fix(gpu): acoustic boundary re-check settings only apply on the local fast path; gpu-split ignores the admin values
  • #1228 feat(lite): lite is cloud-only for transcription and speaker detection, voiceprints stay local (pipeline WP6)
Docs & Release Ops
  • #758 docs(site): homepage polish — install copy button, comparison table, hero blurb
  • #1209 docs: Settings paths in five docs pages name sidebar rows that no longer exist
  • #1230 docs(architecture): regenerate pipeline diagrams and docs pages for the shipped mix-and-match flow (pipeline WP8)
Frontend & UI
  • #569 feat(notifications): wire persistent download notifications into the live notification bell
  • #570 feat(admin): expose locked-account management (view and reset)
  • #576 feat(admin): quarantine/release admin UI for the existing backend (legal-hold risk FIXED via #664)
  • #682 fix(frontend): UI bug backlog for the v0.6.0 UI refresh (filters, modal styling, button states)
  • #747 feat(gallery): redesign the gallery/list toolbar into a two-row layout
  • #748 feat(file-detail): reorganize the file detail page around speaker editing
  • #749 feat(gallery): unify grid/list status indicators and fix GRID typography (grid is the outlier, not list)
  • #750 feat(gallery): overhaul the filter panel — spacing, quick chips, keyboard dates, ownership search
  • #751 feat(upload): fit wizard step widths and clarify the model options (summary-toggle item is a phantom)
  • #752 fix(upload): five defects in the EXISTING upload tray — contrast, drag, z-index, persistence, class collisions
  • #753 feat(notifications): notification panel duration chip and icon parity pass
  • #754 feat(navbar): restyle, relabel Chat as "AI chat", and fix the file-status icon
  • #755 feat(search): consolidate the transcript modal onto the file-detail transcript components
  • #757 feat(ui): unify the tags/collections multi-select
  • #785 fix(a11y): re-key the axe baseline as a per-surface ratchet and scan every main screen
  • #788 feat(ux): surface Retry-After so rate limits show a wait time instead of a generic error
  • #861 feat(ui): regroup the settings sidebar
  • #960 fix(i18n): backend error prose is English-only, so 11 of 12 locales show an untranslated failure reason
  • #966 feat(gallery): ownership filter — searchable multi-select by specific owner
  • #1086 feat(ui): name a speaker inline from the segment speaker dropdown; clarify 'Add speaker'
  • #1121 fix(upload): model chosen in the upload wizard is never sent to the server
  • #1149 fix(ui): suggested-speaker-name chips in the transcript view render very large
  • #1201 fix(upload): speaker counts and model are dropped for URL import, in-wizard recording and the extracted-audio fallback; Speakers step shown when it cannot apply
  • #1208 fix(ui): Speaker Embedding System is shown to admins but its migration routes are super_admin, so admins see "Admin access required"
  • #1217 feat(notifications): decide and build notification auto-clear (UX review item 15)
  • #1218 feat(ui): file detail header and gallery toolbar rows need the designer's mockup (UX review items 39, 40)
  • #1219 feat(settings): show which ASR providers also diarize and warn on Automatic speaker detection without it
  • #1220 chore(i18n): fix the English source strings the 11 translation reviewers flagged, then re-review
  • #1227 feat(settings): Processing pipeline view with Local/Cloud chips, speakers-included badges and warnings (pipeline WP5, absorbs #1219)
  • #1229 feat(files): per-file processing provenance on file details and file status (pipeline WP7)
  • #1234 fix(i18n): ~130 admin-settings strings ship as English in 7+ locales; check:i18n only enforces parity
LLM Providers
  • #644 feat(llm-provider): surface discoverable local base URLs in admin LLM provider setup
  • #1148 feat(llm): settings to disable automatic topic extraction and automatic LLM speaker identification
Native Diarizer
  • #1223 fix(speakers): refuse pyannote.ai speaker detection with local transcription instead of silently ignoring it (pipeline WP1)
  • #1224 feat(pipeline): PipelinePlan resolver, validity matrix and GET /user-settings/pipeline (pipeline WP2)
  • #1225 feat(pipeline): post-transcription speaker detection stage so transcription and speaker detection mix and match (pipeline WP3)
  • #1226 feat(pipeline): use any cloud vendor as the speaker detector via an adapter, one merge path (pipeline WP4)
  • #1236 fix(pipeline): close the gaps WP3 left (silent local fallback for an unbuildable cloud provider, config delete response, segment-timing merge test)
Platform & Operations
  • #961 fix(docker): a --fresh stack started from a git worktree fails twice — no .env, and the second Vite dev server hits EMFILE
  • #962 fix(docker): ./opentr.sh start exits 0 when a core service crash-loops, so automation proceeds onto a dead stack
  • #968 fix(docker): WebSocket is rejected with 403 on any --port-offset stack — CORS_ORIGINS keeps the unoffset port
  • #1134 perf: structured per-stage timing for every processing task (where does the time go?)
RAG & Chat Quality
  • #462 feat(search): make AI summaries searchable and citable in the search page
  • #464 feat(rag-chat): emit kind:"summary" citations — tiering is built, only the emitter is missing
  • #506 task(rag-chat): measure dropping the stemmed BM25 leg for non-English queries (deferred from #453)
  • #523 task(rag-chat): short speaker turns become content-free chunks — route speaker questions, expand context at read time
  • #526 task(rag-chat): context expansion decouples citations from their source chunk (snippet longer than the chunk it cites)
  • #532 task(rag-chat): retrieval offers 99% of scope but the answer cites 75% — synthesis, not retrieval
  • #963 feat(search): rebuild OpenSearch summary indexing as a proper leg (single source of truth, no duplicate writes)
  • #990 task(rag-chat): #975's min_file_score=0.0 file-pruning neutralizes #523's speaker-resolver router-fix
Search Infrastructure
  • #760 feat(search): multi-select result sources on the search page — title, transcript, summary, speaker
Security & Compliance
  • #1122 security(tenancy): decide whether the platform-admin bypass should be organization-scoped in multi-tenant deployments
Speaker Intelligence
  • #756 feat(speakers): speaker management surface pass — banner, gender labels, "Review" rename
  • #1233 fix(speakers): follow-ups to the shared speaker cleanup (#1214): promoted-cluster unassign, drift paths, reindex residuals, teardown
Test Suite Health
  • #789 test(coverage): the backend ratchet sits 36 points below actual, and the frontend threshold is never evaluated
  • #810 test(auth): lockout re-probe boundary flake — order-dependence RULED OUT, investigate concurrency
  • #829 test(eval): AMI-81 has no corpus-scale scope, so ranking-vs-mapping divergence is untested
  • #965 fix(testing): E2E silently tests the live stack — pytest.ini's base_url beats E2E_FRONTEND_URL and run-e2e.sh hardcodes 5173/5174
  • #972 fix(a11y): the axe suite scans light theme only, so a dark-only contrast failure ships green
  • #973 Visual-baseline capture seeds an empty corpus in a worktree and its processing gate passes with zero completed files
  • #976 bug(testing): quote_fidelity harness false-negatives on AMI/QMSum's space-before-punctuation tokenization
  • #1221 chore(release): v0.6.0 final verification on the combined branch (backend gate, a11y, e2e, visual, stack restart, cleanup)
  • #1222 chore(testing): remaining leaks and gaps from the #1195 test-hygiene pass

v0.7.0

Run it in publicUp next

Publish the inert public demo, and put in place the spend limits, alerting and dependency hygiene you only miss once strangers are using it.

4/28
28 issues
ASR Engines
  • #1206 task(config): transcription config has duplicated defaults and env vars that are always shadowed on the task path
  • #1207 fix(asr): disabling user ASR providers also removes local-model pinning, and UserASRSettings.is_active is ignored
Data Safety
  • #1091 feat(data-safety): per-user hide, recoverable org trash, and ownership transfer instead of destructive delete
  • #1101 feat(data-safety): soft-delete organization trash with restore and scheduled purge
  • #1102 feat(data-safety): per-user hide (remove from my view) for media files
  • #1104 feat(data-safety): transfer organization content to an admin on member removal
  • #1105 feat(data-safety): owner-only delayed org/member erase with cancellation and audit log
Document Ingestion
  • #1150 feat(watch-sources): Google Drive, Dropbox, OneDrive/SharePoint and Box sources, plus event-driven triggers
Frontend & UI
  • #794 feat(frontend): no performance budget — a bundle-size regression cannot be caught
  • #1210 fix(a11y): ChatSettingsPanel tabs have no keyboard support or tabpanel; Watch Sources has no initialTab deep link
LLM Providers
  • #820 security(llm): local-provider classification accepts dot-free hostnames without resolving them
Platform & Operations
  • #468 task(governance): set up a CLA and gate contributions on it
  • #566 task(config): move UI-worthy env vars into the admin UI, then drop them from .env.example
  • #791 feat(ops): monitoring is instrumented but inert — no alert rules, readiness probe is not the healthcheck, correlation IDs off by default
  • #864 feat(deploy): ship a Helm chart for Kubernetes self-hosting
  • #866 fix(auth): reconcile the auth_type migration allowlist with the pluggable provider registry
  • #869 feat(auth): shared rate-limiter storage — BLOCKED BY #894, no consumer exists today
  • #894 fix(core): elect a leader for backend startup maintenance so replicas are safe (docs half DONE)
  • #920 perf(backend): add caching where it is provably safe, and write down where it is not
  • #931 task(storage): re-evaluate the S3-compatible object store — MinIO has ended community distribution
  • #1019 Add anonymous opt-in usage telemetry (installs/versions/features), non-invasive, PII-free
  • #1174 test(scale): multi-user load framework, seeded large-dataset builder and a scaling & sizing guide
Public Demo
  • #628 feat(deploy): publish a public read-only demo instance (Immich-style, inert)
  • #790 feat(llm): cap LLM spend and surface it to self-hosters
  • #898 feat(core): ship an in-process assert-inert capability with a NOT-MEASURED red state
RAG & Chat Quality
  • #991 sections_budget divides characters by files, not sections — contradicts its own docstring at corpus scale
Security & Compliance
  • #559 security(dependencies): evaluate replacing Perl exiftool (16 of 20 CRITICAL CVEs) — ffprobe-only vs exiftool-rs
Test Suite Health
  • #1099 ci: backend pytest (~18 min) and pre-commit (~13 min) dominate PR turnaround

v0.8.0

Native inference, and small GPUsLater

Replace the Python/PyTorch inference stack end to end, and prove it on the cards people actually have.

1/21
21 issues
ASR Engines
  • #69 feat(asr): live transcription with real-time speaker identification
  • #366 feat(asr): NVIDIA NeMo (Parakeet / Canary) as a first-class local transcription engine
  • #776 feat(asr): native Rust transcription backend as a sidecar container, in the diar-native shape (crate boundary must be decided first — #882)
  • #860 feat(asr): browser-side speaker segmentation + embedding worker (WASM/WebGPU) for live sessions
  • #880 task(asr): write score_asr_parity.py — the shared word-timing parity scorer
  • #881 task(asr): choose one streaming ASR runtime and assign an owner for #69's live engine
  • #883 feat(asr): add an OpenAI-compatible BYO ASR provider
Native Diarizer
  • #511 perf(gpu): measure what hybrid mode already delivers at low VRAM — then design the sequenced tier (unload_model is a no-op)
  • #572 task(asr): roadmap for removing PyTorch/PyAnnote diarization once native diar-native has parity
  • #659 feat(search): a real rollback path for the v3→v4 speaker-index alias swap
  • #1231 feat(lite): Rust voiceprint extractor for cloud-only lite installs (replaces the CPU embedding task)
Platform & Operations
  • #274 build(docker): validate the ALREADY-LANDED Blackwell base (26.07) + torchaudio 2.11 on real hardware
  • #369 perf(gpu): calibrate transcriber eviction + concurrency from measurement, not magic numbers (limited-VRAM cards)
  • #1073 perf(gpu): size GPU concurrency by host RAM too, and stop decoding whole files into memory per task
  • #1171 perf: per-stage timing, part 2 — persisted stage records, waterfall view, realtime factor, benchmark CLI
Search Infrastructure
  • #845 feat(search): embedding-model fingerprint on speaker index docs — DUPLICATE of #659 §5, land it there
  • #978 feat(search): app-side text embeddings decoupled from OpenSearch ML Commons, then a multi-model serving layer with per-user/org model selection
  • #1076 epic(search): web-search-grade results — fast, comprehensive, smart queries on top of OpenSearch
Test Suite Health
  • #713 task(testing): hardware matrix — only arm64/Blackwell are truly blocked; multi-GPU rows are runnable now
  • #778 perf(testing): pytest collection dominates the backend suite and is repeated on every worker
  • #779 test(quality): pay down 25 BACKLOG allowlist findings + rule on 5 UNMARKED failure-masking exemptions

v0.9.0

Federal government and FIPSLater

The compliance posture public-sector deployment requires: HIPAA, SOC 2, GDPR, and real FIPS 140-3 module validation.

0/6
6 issues
Security & Compliance
  • #98 security(compliance): RE-DERIVE the HIPAA/SOC2/GDPR gap set — body inventory is 10 months stale
  • #574 task(security): achieve real FIPS 140-3 module validation (not just approved algorithms) for FedRAMP High/DoD IL4+
  • #775 security(dependencies): standing accepted risk — unfixed CRITICAL CVEs from libimage-exiftool-perl (supersedes #415, #559)
  • #795 security(release): published images are UNSIGNED and carry no SBOM (mode=min provenance already exists)
  • #796 feat(gdpr): add an account-level Article 15/20 data export
  • #1132 feat(privacy): consent, per-profile retention, deletion and export for voiceprints and personal data

v0.10.0

Bring your own model, and your own formatLater

Use the LLM you already pay for, and get transcripts out in the shape your workflow wants.

1/8
8 issues
Document Ingestion
  • #797 feat(import): bring existing transcripts in from SRT, WebVTT and JSON (Otter/Rev/Fireflies migration)
Frontend & UI
  • #564 feat(export): Markdown export for the FULL TRANSCRIPT (summary Markdown already shipped in #885)
LLM Providers
  • #378 feat(llm): add Tinfoil confidential-computing provider
  • #379 feat(llm): add Google Gemini as a first-class provider
  • #380 feat(llm): add Groq as a low-latency first-class provider
  • #382 feat(llm): add GCP Vertex AI as an ADC-credentialed enterprise provider
  • #562 feat(llm): add per-meeting-type note templates (standup, 1:1, interview)
  • #897 refactor(frontend): delete the two dead LLMSettingsApi methods and consolidate four provider display-name maps

v0.11.0

Document ingestionLater

Re-land the document vertical as a release of its own, and make documents first-class in the gallery, search and chat.

0/4
4 issues
Document Ingestion
  • #516 feat(documents): unified gallery with type filter, uniform status, recovery and takedown parity
  • #546 fix(documents): Document.file_hash is written by both ingest paths and read by neither [BLOCKED BY #552]
  • #547 fix(documents): watch-imported documents are unrepresentable in the watch-source API (no document_uuid; two statuses missing from the enums) [BLOCKED BY #552]
  • #552 task(documents): re-land doc ingestion — 13 conflicting files, NO migration renumbering needed, cost grows daily

v0.12.0

The library knows thingsLater

Intelligence across the corpus rather than within one file: who speaks, about what, how much, and what changed.

0/4
4 issues
Frontend & UI
  • #20 feat(analytics): add analytics dashboard to gallery view
Search Infrastructure
  • #46 feat(transcript): add transcript version control and change tracking
Speaker Intelligence
  • #550 feat(speakers): add corpus-level speaker persona profiles grounded in deterministic conversation metrics
  • #624 task(speakers): profile speaker-matching kNN performance at scale + add a decision-parity fixture

v0.13.0

OpenTranscribe in your workflowLater

Meetings arrive on their own, and other software can ask OpenTranscribe questions.

1/6
6 issues
Meeting Capture
  • #365 feat(asr): Recall.ai meeting capture — ingest meetings, transcripts, speakers and metadata into the same library
  • #563 feat(calendar): sync events and match them to recordings
  • #565 feat(rag-chat): generate pre-meeting briefs from calendar and past transcripts
Platform & Operations
  • #560 feat(api): MCP server for transcript/RAG-chat access by external AI agents
  • #561 feat(backend): plugin/post-processing hook architecture for transcription pipeline
  • #798 task(api): add /api/v1 and a public stability statement (OpenAPI snapshot gate DONE — 3 of 4 criteria closed)

v1.0.0

Commit to itLater

Interfaces, platform support and performance become promises: native engines, live transcription, and a desktop application.

0/7
7 issues
ASR Engines
  • #48 feat(asr): native Apple Silicon transcription and diarization (Metal/CoreML) via the shared native core
  • #879 task(asr): run a P0 engine bake-off on the M2 Max to decide the macOS Whisper runtime
  • #882 refactor(asr): port assign/smooth/segments/words into the diar-native workspace behind a golden-fixture gate
Desktop App
  • #283 feat(desktop): standalone desktop app (Tauri + SQLite/FTS5/sqlite-vec + in-process native core), macOS first
  • #888 feat(frontend): desktop-edition capability map must fail closed, and the session needs a platform field
Frontend & UI
  • #1055 Video playback: transcode undecodable video (AVI/WMV/MPEG/FLV/…) to H.264/AAC — costs, NVENC, plan
Meeting Capture
  • #1136 feat(recording): capture meeting audio — microphone + system/tab audio in the browser recorder

Backlog

Not yet scheduledShipped

Tracked and grouped, but not assigned to a release. These move into a version as the work ahead of them lands.

4/4
4 issues
Docs & Release Ops
  • #937 Publish should verify the pushed digest matches the scanned one, not re-scan blindly
  • #938 Publish rebuilds amd64 legs the local build already made (separate buildx caches)
  • #939 Smoke's fresh install stays running and blocks smoke's own re-run
Platform & Operations
  • #940 v0.5.1 dependency maintenance: triage the 7 Dependabot PRs and close the 2 critical alerts

Backlog

Not yet scheduledUnscheduled

Tracked and grouped, but not assigned to a release. These move into a version as the work ahead of them lands.

7/9
9 issues
ASR Engines
  • #1153 precision-2: pyannoteAI asks to migrate by October 17, 2026
Platform & Operations
  • #868 fix(core): capability resolver merge fails open on a partial/incomplete resolver result
  • #1002 security(deps): 5 fixable HIGH CVEs in backend image (transformers <5.10, msgpack, setuptools)
  • #1151 feat(asr): setting to disable the shared-volume WAV handoff for multi-node deployments
  • #1152 GET /api/files/{uuid} returns 500 on a Postgres deadlock: the file-detail read writes speaker rows (add_computed_status + commit)
  • #1159 Worker-loss recovery for remaining early-ack user tasks (downloads, index updates, speaker edits)
  • #1169 Upload-size validation runs the tenant-limit resolver synchronously on the event loop
  • #1172 perf(metrics): measure Celery queue wait — per-task histogram at task start + oldest-waiting-message age per queue
RAG & Chat Quality
  • #975 bug(rag-chat): corpus-scale retrieval collapses to 2 files regardless of scope, independent of #532's synthesis gap

Releases are ordered by dependency, not scheduled to dates — a later release is blocked on the one before it. Scope moves between releases as work is understood. For the reasoning behind any item, open its issue: that is where the detail lives.