generated from john/python-template
Step 5 implementation plan
This commit is contained in:
+267
@@ -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
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user