generated from john/python-template
110 lines
7.1 KiB
Markdown
110 lines
7.1 KiB
Markdown
# 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.
|
|
|
|
## 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 into `ui/components/media_urls.py` as `resolve_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:82` `list_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
|
|
|
|
- [Architecture & Code Review Report](../architecture_code_review_2026-08-17.md)
|
|
- `.github/instructions/ui.instructions.md`
|
|
- `src/transcription/ui/homepage_store.py` - existing multi-image storage
|
|
- `src/transcription/ui/components/media_urls.py` - canonical URL resolution
|