Plans the next two releases following the V4.6 architecture remediation. Documentation only - no code or schema changes. V4.7 is an architectural cleanup and evidence-model re-alignment release, scoped from measurements taken against the live database: - job_source and execution_attempt duplicate the same evidence. Measured 77/77 identical on raw_transcription, ai_metadata vs normalized_metadata, and raw_api_response vs sdk_response_snapshot. job_source is stripped to its original junction role plus queue state (9 columns -> 4); all evidence reads move to execution_attempt. - job_source is stripped rather than deleted because it is also the work queue: rows are created PENDING before any provider call, and cancellation writes a terminal state with no provider call at all. An append-only evidence table cannot express either. - JobSourceStatus.CANCELLED is added so cancellation stops overloading FAILED plus free text, which retires job_source.error_detail. This absorbs the dual-spelling fix [45], since both rewrite the same persistence. - ProcessingArtifact is removed. Two rows exist against 77 successful transcriptions, so the subsystem has effectively never run. Orientation normalization moves to ingest, where it is applied once and needs no derivative. - Orientation normalization itself is retained: 58 of 79 stored images carry EXIF orientation 3, and their raw decoded pixels are genuinely inverted. Rotation switches to quantization-table reuse, measured better than the current quality=95 settings on both fidelity (51.5-55.0 dB PSNR vs 50.0-53.5) and size (-6% vs +38%). - The planned services/artifacts.py extraction is cancelled. The cluster is deleted rather than moved, establishing a delete-before-refactor ordering. V4.8 parks feature work: pan and zoom, homepage gallery, multi-portrait support, image descriptions, and the model-performance rollup, which stays gated on the V4.7 run-time measurement fix. Co-authored-by: Copilot App <[email protected]>
7.3 KiB
V4.8 Feature Backlog
Status: not scoped. This is a parking document, not a frozen boundary. It records feature work deferred out of V4.6 and V4.7 together with the evidence gathered so far, so that scoping V4.8 does not start from a blank page.
V4.8 is the first release since V4.5 to add new user-facing behavior. V4.6 was pure remediation and V4.7 is architectural cleanup; both were held to "no new features." That constraint ends here, which means V4.8 needs a different verification gate: V4.6 and V4.7 could be validated by "the suite still passes unchanged," and V4.8 cannot.
Dependency on V4.7
The model-performance rollup below must not begin until V4.7 Phase 4 lands. duration_ms currently measures provider call plus image normalization, artifact persistence, and a DB commit, while the timeout governs only the provider call. A rollup built on it would chart preprocessing time mixed with provider latency and look authoritative while quietly misleading. V4.7 Phase 1 removes normalization and artifact persistence from that window, but the commit remains inside it until Phase 4. See V4.7 scope boundary section 4.
Candidate Features
1. Pan and Zoom on Source Detail
Practicality: high. Effort: S.
ui/components/document_panzoom.py existed and was deleted in V4.6 Phase 5 (6a3ee26) because it was exported but wired to no page. It is 136 lines and recoverable:
git show 6a3ee26^:src/transcription/ui/components/document_panzoom.py
It already handled both images and PDFs (the latter via an iframe).
Two things must change on reintroduction - this is not a straight revert:
- It loaded Panzoom from the unpkg CDN. For an archival application the library should be vendored locally, otherwise the viewer breaks offline and depends on a third party staying available.
- It carried its own
_document_url()helper. V4.6 Phase 5 extracted exactly that logic intoui/components/media_urls.pyasresolve_media_url. Reintroducing the old helper would recreate the duplication Phase 5 removed.
Scope note: apply it to Source Detail only. dark_room_viewer (ui/components/viewers.py) is shared by four pages - sources_page.py:268, home_page.py:25 and :88, people_page.py:453, documents_page.py:524 - so a flag on it would leak pan-zoom into the homepage and document detail, which is not wanted. Add a separate component and use it only at sources_page.py:268.
Numbering note: the Phase 5 commit message states pan-zoom would return "in V4.7 alongside the other photo/image work." Moving it to V4.8 preserves that intent - it stays grouped with the photo work - and changes only the release number.
2. Homepage Image Gallery
Practicality: high. Effort: S. Recommended first feature.
The storage layer is already built:
ui/homepage_store.py:82list_homepage_images()already returns every stored image, sorted by modification time.store_homepage_image()already accumulates files rather than overwriting.- Today the UI calls only
latest_homepage_image()and displays one image.list_homepage_images()is currently exercised only by tests.
So multi-image upload is effectively done; what is missing is presentation. NiceGUI 3.13.0 provides ui.carousel for left/right navigation and ui.timer for rotation.
Sub-items:
- Multi-image display with left/right navigation - small, mostly wiring.
- Optional slideshow rotating every ~10 minutes.
Performance caveat: list_homepage_images() performs a directory scan with a stat() per file on every call, and home_page.py already performs blocking I/O in the page handler (V4.6 review log [25], which was deliberately left alone). A rotating timer that re-enumerates on every tick would repeat that scan indefinitely. Enumerate once at page load and cache the list.
3. Multiple Person Portraits
Practicality: medium. Effort: M/L. Defer behind item 2.
Person.portrait_path is a single string column. Supporting multiple portraits requires a new table, a data migration, and upload UI - a materially larger job than item 2, and a different one.
4. Image Descriptions
Practicality: medium, conditional. Effort: M.
Homepage images are filesystem-only with no metadata store, so a caption has nowhere to live today. This needs either a sidecar JSON file or a real table.
This is cheap only if item 3 is being done at the same time, since both need the same metadata layer. Designing that layer twice would be wasteful; design it once or not at all.
5. Model-Performance Rollup (V4.6 review log [54])
Practicality: high, but blocked. Effort: M.
Run-time telemetry is already captured and is per page: execution_attempt.duration_ms is a required non-null field written on all three paths in workflows.py (success 278, TimeoutError 295, general failure 330), with failures using a monotonic clock. Verified against the live database: 80 rows across 80 distinct (job, source, attempt) combinations, one row per page - the largest job has 60 attempts across 60 distinct pages - and zero nulls. Token counts live on the same row in normalized_metadata.usage, so tokens-per-second is already derivable without a join.
What is missing is aggregation. The figure is visible only for the latest attempt of one source at a time (sources_page.py:400), rendered raw as "27612 ms". There is no rollup by model, prompt, or document.
The gap is concrete: calibrating the provider timeout on 2026-08-18 required hand-written SQL against the database, because the application could not answer "which model is slow."
Proposed shape: median / p95 / max duration, tokens per second, and a timeout rate, grouped by model. Blocked on V4.7 Phase 4.
6. Desaturated Background Wallpaper
Practicality: low. Recommendation: do not build, or gate behind a setting defaulted off.
Trivial to implement (ui.add_css with a CSS filter), but this is a dense archival data application - transcripts, JSON evidence panels, data tables. A background image behind all of that costs contrast and legibility on every page, for aesthetic gain only.
Suggested Grouping
If V4.8 is scoped as one release, the natural split is:
Track A - image experience: items 1 and 2. Both are small, both are self-contained UI work, and item 2's storage layer already exists. This is the highest value for the least risk.
Track B - metadata layer: items 3 and 4 together, since they share a table. Only worth starting if both are wanted.
Track C - telemetry: item 5, gated on V4.7 Phase 4.
Item 6 is not recommended.
Open Questions for Scoping
- Should Track B happen at all, or is one portrait per person sufficient?
- Should the slideshow interval be configurable, or fixed?
- Should the model-performance rollup be its own page, or a panel on an existing one?
- Should vendored Panzoom be committed to the repository, or fetched at build time?
Related Local References
- V4.7 Scope Boundary - the blocking dependency for item 5
- V4.6 Scope Boundary
- Architecture & Code Review Report
.github/instructions/ui.instructions.mdsrc/transcription/ui/homepage_store.py- existing multi-image storagesrc/transcription/ui/components/media_urls.py- canonical URL resolution