## Audit outcome
- Audited commit `500fc56b5f3cf27413ff2d449279bef3bad191e0`.
- Read source, schemas, synthetic fixtures, and tests only; no production data inspected.
- Made no file changes.
- Existing Sprint 6H-B unit coverage passes with the required import path:
- `PYTHONPATH=scripts/health ... tests/test_dashboard_v5_sprint6h_b.py`
- **5 passed**
- Playwright successfully discovered **11 tests** across the 6H-B and 6I-A specs.
## Existing implementation map
### Capture and media
- `dashboard-v5-capture.js`
- Six capture types and URL/history-driven dialogs.
- One file input with `multiple`, `capture="environment"`, and image-only `accept`.
- Maximum three images, 12 MB each.
- Local image previews and removal.
- Sequential uploads followed by action queue submission and status polling.
- `capture_media.py`
- JPEG/PNG only; HEIC/HEIF is explicitly rejected.
- Magic validation, Pillow decode, private quarantine, SHA-256 dedupe, and JPEG thumbnails.
- `capture_contract.py`
- Version 1 payload with at most three attachment tokens.
- `health_dashboard_server.py`
- `POST /api/v1/capture/upload`: authenticated, same-origin, one-time CSRF, raw octet stream.
- `GET /api/v1/capture/status/{idempotency_key}`.
- `GET /api/v1/capture/media/{attachment}/thumbnail`.
- `health_dashboard_action_worker.py`
- Append-only correction/withdrawal versions.
- Corrections inherit all previous media only when no new files are supplied.
- New files replace inherited attachments as a group; selective retain/remove is unavailable.
### Today, day, calendar, and record
- **Today:** bundle-rendered snapshot, tasks, and medication. It does not display capture chronology/media.
- **Day:** canonical day data is rendered by `dashboard-v5-day-controller.js`; capture chronology is loaded separately by `dashboard-v5-capture.js`.
- **Chronicle:** sorted timed/undated entries, thumbnails, correction/withdrawal controls, and basic version/status history.
- **Calendar:** counts canonical sources plus active captured supplements and photos. Other capture types generally rely on worker mirroring into legacy canonical tables.
- **Record:** tabs for overview, labs, medications, appointments, documents, and report. No capture/chronicle tab.
- **Doctor report timeline:** sourced from the legacy events API, not `capture_entries`.
## Material gaps
1. `capture="environment"` on the only picker does not provide explicit **Camera Roll versus direct capture** choices.
2. No video intake, validation, poster generation, playback endpoint, or browser rendering.
3. Client accepts HEIC/HEIF while the backend always rejects it—misleading UI contract.
4. Upload progress is text-only; `fetch` provides no per-file byte progress.
5. Token tracking is positional. Removing a file resets every token and can cause redundant uploads and temporary quarantine orphans.
6. Capture date/time defaults from browser `Date` and browser timezone, rather than authoritative Zurich/user-selected day context.
7. Chronicle loading uses delays and click matching rather than a date-keyed abort/version contract; a stale response can render after rapid day navigation.
8. Version history exposes only version/status/time, not the media attached to each historical version.
9. Selective media retention/removal during correction is impossible.
10. Today and Record omit captured media/chronology.
11. The 6H-B browser spec is not wired into `run_v5_isolated_matrix.sh` or package scripts. The generic matrix fixture does not seed the three capture timeline rows expected by that spec.
12. Existing browser coverage previews an image but does not exercise a complete upload → queue → worker → regenerated display path.
## Smallest Sprint 6I-B path
1. **Explicit source controls**
- Replace the single input with:
- Camera Roll: no `capture`, `multiple`, image/video allowlist.
- Take photo: image input with `capture="environment"`.
- Record video: video input with `capture="environment"`.
- Preserve the current cap as **three images plus one video**.
- Remove HEIC/HEIF from visible acceptance unless local decoding is added.
2. **Authoritative capture context**
- Add a small authenticated `/api/v1/capture/context` response containing Zurich `today`, local time, and allowed selected-day context.
- A capture launched from Day defaults to that explicit day; all other launches default to server-authoritative Zurich today.
- Do not derive the date from browser timezone or browser storage.
3. **Versioned attachment contract**
- Introduce contract v2 with typed attachments and an explicit:
- `retained_attachment_refs` list for correction;
- `live_photo_pairs` list linking one selected image and video token/ref.
- Never infer Live Photo pairing from names, timestamps, or file order.
- Validate retained refs belong to the corrected active entry.
4. **Private video handling**
- Add a new additive 6I-B migration rather than mutating the frozen 6H-B migration.
- Extend attachment metadata with media kind, safe MIME, duration, poster, and optional explicit Live Photo relation.
- Locally inspect MOV/MP4 with bounded `ffprobe`, enforce size/duration/dimensions/codecs, then normalize to a fixed MP4 and generate a poster with bounded `ffmpeg`.
- Strip metadata and make no external conversion requests.
5. **Preview, remove, and progress**
- Track state per item: `{file, kind, objectURL, token, progress, error}`.
- Use XHR upload progress for each card and an aggregate status.
- Removing one item must retain other uploaded tokens.
- Show `
` for images and muted local `