From 2cdba5f1d255d218a1877b6ec2ed67292beb16af Mon Sep 17 00:00:00 2001 From: Jim Lancaster <40281233+zoltan57@users.noreply.github.com> Date: Wed, 24 Jun 2026 19:50:18 -0500 Subject: [PATCH] Step 5 implementation plan --- docs/step5.md | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 docs/step5.md diff --git a/docs/step5.md b/docs/step5.md new file mode 100644 index 0000000..1865a17 --- /dev/null +++ b/docs/step5.md @@ -0,0 +1,267 @@ +## Step 5: `app.py` + UI Pages (NiceGUI + FastAPI composition) + +## Objective + +Implement the MVP user-facing application layer so users can: + +1. Upload a document from the UI +2. Trigger Step 4 upload/job creation flow +3. See live job lifecycle status (`queued`, `processing`, `transcribed`, `failed`) +4. Open a job detail view to read transcript text or failure details + +This step composes Steps 1–4 into a usable UI. + +--- + +## Architecture Summary (NiceGUI-aligned) + +Step 5 uses a **FastAPI app factory + lifespan orchestration** and mounts/registers NiceGUI pages via explicit page modules. + +### Core architecture decisions + +- **App factory:** `create_app()` +- **Lifespan-managed resources:** worker start/stop managed in startup/shutdown +- **Modular pages:** upload and jobs pages in separate modules (no monolithic UI file) +- **Health endpoint:** FastAPI-side `/healthz` +- **Dependency direction (one-way):** + - `app` -> `config/logging/db/worker/ui/api` + - `ui/pages` -> `services` + - `services` -> `db/models/providers` + - no reverse imports from services into UI/API + +### DB and AI stance (explicit) + +- **DB:** already enabled (SQLModel + SQLite), session lifecycle remains request/service-scoped as built in prior steps. +- **AI workflow:** already in place via Step 3 transcription service + Step 4 worker; UI does not call provider SDK directly. + +--- + +## Scope + +### In scope +- `src/transcription/app.py` +- `src/transcription/ui/upload_page.py` +- `src/transcription/ui/jobs_page.py` +- `src/transcription/ui/__init__.py` +- `src/transcription/api/health.py` (or equivalent FastAPI health route module) +- UI/app tests with MCP scaffold->fill flow + +### Out of scope +- Auth +- advanced filtering/search UX +- batch upload UX beyond MVP +- deployment/container hardening + +--- + +## Planned Deliverables + +### Source files +- `src/transcription/app.py` (app factory + lifespan wiring) +- `src/transcription/api/health.py` (GET `/healthz`) +- `src/transcription/ui/upload_page.py` (upload flow) +- `src/transcription/ui/jobs_page.py` (status list + detail) +- `src/transcription/ui/__init__.py` (explicit `register_pages(...)` export) + +### Test files +- `tests/test_app.py` +- `tests/api/test_health.py` +- `tests/ui/test_pages_registration.py` +- `tests/ui/test_upload_page.py` +- `tests/ui/test_jobs_page.py` + +--- + +## Implementation Plan + Checklist + +## Phase A — App factory and lifespan orchestration + +- [ ] Create `create_app()` in `src/transcription/app.py` +- [ ] Add FastAPI lifespan startup/shutdown handlers +- [ ] Startup responsibilities: + - [ ] `setup_logging()` + - [ ] `create_all()` + - [ ] ensure directories exist (`upload_dir`, `prompt_dir`) + - [ ] create worker stop event + - [ ] start worker background thread/task +- [ ] Shutdown responsibilities: + - [ ] signal stop event + - [ ] join/cleanup worker thread/task cleanly +- [ ] Register API router(s), including health route +- [ ] Register NiceGUI pages via explicit page registration function + +## Phase B — FastAPI health endpoint + +- [ ] Create `src/transcription/api/health.py` +- [ ] Add `GET /healthz` returning simple healthy payload +- [ ] Wire route into app factory + +## Phase C — Upload page (`ui/upload_page.py`) + +- [ ] Add upload route/page registration function +- [ ] Render file input accepting supported extensions +- [ ] On submit: + - [ ] show loading/progress state + - [ ] call `create_upload_job(filename, file_bytes, ...)` + - [ ] show success state with job reference/link +- [ ] On error: + - [ ] show user-safe error message + - [ ] restore ready UI state +- [ ] Ensure no blocking calls in UI event handlers beyond bounded service interaction + +## Phase D — Jobs page (`ui/jobs_page.py`) + +- [ ] Add jobs list route/page registration function +- [ ] Display jobs with status + timestamps +- [ ] Add job detail route/view +- [ ] Show transcript on success, error detail on failure +- [ ] Include explicit refresh action and loading state +- [ ] Ensure error states are surfaced to user and logged + +## Phase E — UI registration module + +- [ ] Update `src/transcription/ui/__init__.py` +- [ ] Export `register_pages(...)` +- [ ] Ensure each page module exports `register_page(...)` +- [ ] Keep page registration explicit and modular + +--- + +## MCP Testing Workflow (Required) + +Use these resources directly: + +- `resource://catalog/prompts/pytest-scaffold` +- `resource://prompts/pytest-scaffold/document` +- `resource://catalog/prompts/pytest-fill-scaffold` +- `resource://prompts/pytest-fill-scaffold/document` + +## E1 — Scaffold tests first (structure only) + +Target modules: +- `src/transcription/app.py` +- `src/transcription/api/health.py` +- `src/transcription/ui/upload_page.py` +- `src/transcription/ui/jobs_page.py` + +Scaffold test files: +- `tests/test_app.py` +- `tests/api/test_health.py` +- `tests/ui/test_pages_registration.py` +- `tests/ui/test_upload_page.py` +- `tests/ui/test_jobs_page.py` + +Scaffold constraints: +- [ ] class/method skeletons only +- [ ] one-line docstrings +- [ ] concise behavior-focused names +- [ ] no implementation assertions yet + +Validation: +- [ ] `uv run pytest --collect-only -q` + +## E2 — Fill scaffold tests + +Fill constraints from MCP guidance: +- [ ] preserve scaffold class/method names and docstrings (locked baseline) +- [ ] one behavior target per method +- [ ] deterministic tests preferred +- [ ] minimal mocking; only nondeterministic boundaries + +Stack: +- [ ] `fastapi` (or `mixed` if needed for UI+DB fixture combination) + +Suggested coverage: + +### `tests/api/test_health.py` +- [ ] `/healthz` returns success status and expected payload shape + +### `tests/ui/test_pages_registration.py` +- [ ] page registration wiring succeeds +- [ ] expected routes are present + +### `tests/test_app.py` +- [ ] startup path initializes runtime dependencies +- [ ] worker start is invoked on startup +- [ ] worker shutdown signal/cleanup is invoked on shutdown + +### `tests/ui/test_upload_page.py` +- [ ] upload action calls upload service +- [ ] success feedback displayed +- [ ] error feedback displayed for `UploadError` +- [ ] loading/progress state behavior covered + +### `tests/ui/test_jobs_page.py` +- [ ] list renders job statuses +- [ ] detail shows transcript text for successful job +- [ ] detail shows error detail for failed job +- [ ] refresh/loading state behavior covered + +Marker strategy: +- [ ] `unit` for pure helpers/state formatting +- [ ] `integration` for app/page/service+DB contracts +- [ ] `external` not required for default Step 5 lane + +--- + +## Validation Sequence (strict) + +- [ ] `uv run pytest --collect-only -q` +- [ ] `uv run pytest -m unit -q` *(if unit tests touched)* +- [ ] `uv run pytest tests/api/test_health.py -q` +- [ ] `uv run pytest tests/ui/test_pages_registration.py -q` +- [ ] `uv run pytest tests/test_app.py -q` +- [ ] `uv run pytest tests/ui/test_upload_page.py -q` +- [ ] `uv run pytest tests/ui/test_jobs_page.py -q` +- [ ] `uv run pytest -q` + +--- + +## Guardrails (NiceGUI + MVP) + +- [ ] Do not collapse pages into one file. +- [ ] Do not use implicit global side effects for runtime wiring. +- [ ] Keep UI responsive with explicit loading/progress/error states. +- [ ] Do not place provider SDK calls in UI handlers. +- [ ] Keep dependency direction one-way and maintainable. + +--- + +## Definition of Done + +- [ ] App factory + lifespan are in place +- [ ] Health endpoint exists and is tested +- [ ] Upload page creates queued jobs through service boundary +- [ ] Jobs list/detail pages render status/transcript/failure data +- [ ] Worker lifecycle is started/stopped by app lifespan +- [ ] Scaffold->fill testing flow completed and validated +- [ ] Full suite passes: `uv run pytest -q` + +--- + +## PR Checklist (Integrated) + +### Implementation +- [ ] `app.py` app factory + lifespan implemented +- [ ] FastAPI health route (`/healthz`) implemented +- [ ] `ui/upload_page.py` implemented +- [ ] `ui/jobs_page.py` implemented +- [ ] `ui/__init__.py` explicit page registration implemented +- [ ] Worker startup/shutdown managed by lifespan + +### Testing (MCP-compliant) +- [ ] Scaffold phase completed first for all Step 5 tests +- [ ] `--collect-only` passed on scaffolds +- [ ] Fill phase completed without renaming/re-nesting scaffolded tests +- [ ] Marker decisions documented (`unit` vs `integration`) +- [ ] Targeted tests passed +- [ ] Full suite passed + +### Evidence +- [ ] Validation command outputs captured +- [ ] Files created/updated listed +- [ ] MCP prompt resources referenced in implementation notes +- [ ] Any residual risks/questions documented + +--- +