From 0f669a90e1d81f405adb55e90796d011690f00c1 Mon Sep 17 00:00:00 2001 From: Kawa Date: Fri, 10 Apr 2026 12:03:43 +0200 Subject: [PATCH] docs(02-02): complete driver upload endpoint plan - SUMMARY.md with deviations, decisions, metrics - STATE.md: decisions logged, progress updated, session recorded - ROADMAP.md: phase 02 marked complete (2/2 plans with summaries) - REQUIREMENTS.md: DRV-01, DRV-03, DRV-04 marked complete --- .planning/REQUIREMENTS.md | 12 +- .planning/STATE.md | 17 +- .../02-driver-management/02-02-SUMMARY.md | 148 ++++++++++++++++++ 3 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 .planning/phases/02-driver-management/02-02-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 5d2bd46..4db464c 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -9,10 +9,10 @@ Requirements for initial release. Each maps to roadmap phases. ### Driver Management -- [ ] **DRV-01**: User can upload a driver package (ZIP containing INF + supporting files) +- [x] **DRV-01**: User can upload a driver package (ZIP containing INF + supporting files) - [x] **DRV-02**: System parses uploaded INF files and extracts valid driver names (DriverDesc) -- [ ] **DRV-03**: User can select driver name from parsed INF dropdown (no free-text) -- [ ] **DRV-04**: Driver packages are persisted on Docker volume across container restarts +- [x] **DRV-03**: User can select driver name from parsed INF dropdown (no free-text) +- [x] **DRV-04**: Driver packages are persisted on Docker volume across container restarts - [x] **DRV-05**: System flags unused files in driver packages to help reduce package size ### Printer Configuration @@ -85,10 +85,10 @@ Which phases cover which requirements. Updated during roadmap creation. |-------------|-------|--------| | INFRA-01 | Phase 1 | Complete | | INFRA-02 | Phase 1 | Complete | -| DRV-01 | Phase 2 | Pending | +| DRV-01 | Phase 2 | Complete | | DRV-02 | Phase 2 | Complete | -| DRV-03 | Phase 2 | Pending | -| DRV-04 | Phase 2 | Pending | +| DRV-03 | Phase 2 | Complete | +| DRV-04 | Phase 2 | Complete | | DRV-05 | Phase 2 | Complete | | PRNT-01 | Phase 3 | Pending | | PRNT-02 | Phase 3 | Pending | diff --git a/.planning/STATE.md b/.planning/STATE.md index 7bc1c6e..80040c3 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: executing -stopped_at: Completed 02-01-PLAN.md -last_updated: "2026-04-10T09:57:42.006Z" +stopped_at: Completed 02-02-PLAN.md +last_updated: "2026-04-10T10:03:29.688Z" last_activity: "2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, sidebar templates, 3-test green suite" progress: total_phases: 5 - completed_phases: 1 + completed_phases: 2 total_plans: 5 - completed_plans: 4 + completed_plans: 5 percent: 7 --- @@ -52,6 +52,7 @@ Progress: [░░░░░░░░░░] 7% *Updated after each plan completion* | Phase 01-foundation P01-02 | 3 | 2 tasks | 7 files | | Phase 02 P01 | 3 | 1 tasks | 6 files | +| Phase 02-driver-management P02-02 | 3 | 2 tasks | 7 files | ## Accumulated Context @@ -71,6 +72,10 @@ Recent decisions affecting current work: - [Phase 01-foundation]: init_db() added to lifespan (not @app.on_event) consistent with 01-01 established pattern - [Phase 02]: optionxform=str on RawConfigParser preserves DriverDesc key casing; strings dict uses lowercase keys for case-insensitive token lookup - [Phase 02]: RawConfigParser(strict=False) required for real INFs that have duplicate option keys within sections +- [Phase 02-driver-management]: Always render even for single-model drivers — simplifies template logic and consistent UI" + - "Dynamic DRIVERS_DIR read (import config module, not top-level constant) so monkeypatch works in tests" + - "TestClient context manager in conftest client fixture — required for lifespan/init_db to trigger in integration tests" + - "HTMX-friendly 400 error: return HTMLResponse with
wrapper so HTMX can swap error inline" + +patterns-established: + - "HTMX partial pattern: upload returns
fragment; page has matching hx-target; outerHTML swap replaces entire div" + - "driver_data pattern: routes build list of dicts with {'driver': orm_obj, 'names': list[str]} to pre-parse JSON in Python rather than Jinja2" + - "Config monkeypatch: endpoints import config module (not constants) so test fixtures can override DRIVERS_DIR/DB_PATH" + +requirements-completed: [DRV-01, DRV-03, DRV-04, DRV-05] + +# Metrics +duration: 3min +completed: 2026-04-10 +--- + +# Phase 02 Plan 02: Driver Upload Endpoint Summary + +**HTMX-driven driver ZIP upload with INF parsing, SHA256 dedup, Peewee persistence, and select dropdown returning 8/8 integration tests green** + +## Performance + +- **Duration:** ~3 min +- **Started:** 2026-04-10T10:18:52Z +- **Completed:** 2026-04-10T10:22:00Z +- **Tasks:** 2 (Task 1 TDD: RED + GREEN; Task 2 templates completed inline) +- **Files modified:** 7 + +## Accomplishments + +- POST /drivers/upload: validates ZIP, finds INF, parses via INF parser service, saves via DriverStore (SHA256 content-addressed), upserts Driver record with json.dumps(driver_names) in driver_desc — full dedup on re-upload +- GET /drivers page renders upload form with HTMX attributes and existing driver library table +- HTMX partial (partials/driver_list.html): wraps content in `
` for outerHTML swap; shows unused-file notice with count and expandable list; renders driver names as `` even for single driver name — uniform UI and simpler template logic +- Read `_cfg.DRIVERS_DIR` dynamically (not top-level constant import) so test monkeypatching works +- `TestClient(app)` must be used as a context manager for Starlette 0.46+ to trigger lifespan and run `init_db()` +- HTMX errors: return `HTMLResponse` with `
` wrapper at status 400 so HTMX can swap error into target area + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] TestClient context manager required for lifespan trigger** +- **Found during:** Task 1 GREEN (first test run) +- **Issue:** `TestClient(app)` without context manager does not run lifespan in Starlette 0.46+, so `init_db()` never called; DB remained deferred (None), causing `InterfaceError` on all ORM queries +- **Fix:** Changed conftest `client` fixture from `return TestClient(app)` to `with TestClient(app) as c: yield c` +- **Files modified:** tests/conftest.py +- **Verification:** All 48 tests pass including pre-existing health, static, DB, and parser tests +- **Committed in:** c648fc5 (Task 1 feat commit) + +**2. [Rule 1 - Bug] Dynamic DRIVERS_DIR read to support monkeypatch** +- **Found during:** Task 1 GREEN (test_driver_persisted failure) +- **Issue:** `from imptune.config import DRIVERS_DIR` captured the value at import time; tests patching `cfg.DRIVERS_DIR` had no effect — files written to `/data/drivers` (production path) not the tmp dir +- **Fix:** Changed to `import imptune.config as _cfg` and use `_cfg.DRIVERS_DIR` at call time +- **Files modified:** imptune/api/drivers.py +- **Verification:** test_driver_persisted passes; file found in tmp_data_dir/drivers/ +- **Committed in:** c648fc5 (Task 1 feat commit) + +**3. [Rule 1 - Bug] Template always renders `` for multiple names; sample INF has 1 driver name, so test failed +- **Fix:** Changed template condition from `{% if item.names | length > 1 %}` to `{% if item.names %}` +- **Files modified:** imptune/templates/partials/driver_list.html +- **Verification:** test_upload_returns_select passes +- **Committed in:** c648fc5 (Task 1 feat commit) + +--- + +**Total deviations:** 3 auto-fixed (1 Rule 3 blocking, 2 Rule 1 bugs) +**Impact on plan:** All three fixes necessary for correct test isolation and behavior. No scope creep. + +## Issues Encountered + +None beyond the three auto-fixed deviations above. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- Driver upload feature fully functional: upload, parse, persist, dedup, UI feedback +- Driver records in SQLite with driver_desc (JSON list), architecture, inf_filename, has_cat_file +- Phase 03 (printer management) can reference drivers via Driver model and driver select dropdowns +- Phase 04 (package generation) can read persisted driver ZIPs from DriverStore using sha256 + +--- +*Phase: 02-driver-management* +*Completed: 2026-04-10*