--- phase: 2 slug: driver-management status: draft nyquist_compliant: true wave_0_complete: false created: 2026-04-10 nyquist_audited: 2026-04-13 nyquist_auditor: Claude (gsd-executor, plan 08-02) --- # Phase 2 — Validation Strategy > Per-phase validation contract for feedback sampling during execution. --- ## Test Infrastructure | Property | Value | |----------|-------| | **Framework** | pytest (already installed in requirements-dev.txt from Phase 1) | | **Config file** | None — uses pytest auto-discovery | | **Quick run command** | `pytest tests/ -x -q` | | **Full suite command** | `pytest tests/ -v` | | **Estimated runtime** | ~5 seconds | --- ## Sampling Rate - **After every task commit:** Run `pytest tests/ -x -q` - **After every plan wave:** Run `pytest tests/ -v` - **Before `/gsd:verify-work`:** Full suite must be green - **Max feedback latency:** 10 seconds --- ## Per-Task Verification Map | Task ID | Plan | Wave | Requirement | Test Type | Automated Command | File Exists | Status | |---------|------|------|-------------|-----------|-------------------|-------------|--------| | 02-01-01 | 01 | 1 | DRV-01 | integration | `pytest tests/test_driver_upload.py::test_upload_valid_zip -x` | ❌ W0 | ⬜ pending | | 02-01-02 | 01 | 1 | DRV-01 | unit | `pytest tests/test_driver_upload.py::test_upload_non_zip -x` | ❌ W0 | ⬜ pending | | 02-01-03 | 01 | 1 | DRV-01 | unit | `pytest tests/test_driver_upload.py::test_upload_no_inf -x` | ❌ W0 | ⬜ pending | | 02-02-01 | 02 | 1 | DRV-02 | unit | `pytest tests/test_inf_parser.py::test_simple_driver_desc -x` | ❌ W0 | ⬜ pending | | 02-02-02 | 02 | 1 | DRV-02 | unit | `pytest tests/test_inf_parser.py::test_token_resolution -x` | ❌ W0 | ⬜ pending | | 02-02-03 | 02 | 1 | DRV-02 | unit | `pytest tests/test_inf_parser.py::test_utf16_encoding -x` | ❌ W0 | ⬜ pending | | 02-02-04 | 02 | 1 | DRV-02 | unit | `pytest tests/test_inf_parser.py::test_multi_model_inf -x` | ❌ W0 | ⬜ pending | | 02-03-01 | 03 | 2 | DRV-03 | integration | `pytest tests/test_driver_upload.py::test_drivers_page -x` | ❌ W0 | ⬜ pending | | 02-03-02 | 03 | 2 | DRV-03 | integration | `pytest tests/test_driver_upload.py::test_upload_returns_select -x` | ❌ W0 | ⬜ pending | | 02-04-01 | 01 | 1 | DRV-04 | integration | `pytest tests/test_driver_upload.py::test_driver_persisted -x` | ❌ W0 | ⬜ pending | | 02-04-02 | 01 | 1 | DRV-04 | integration | `pytest tests/test_driver_upload.py::test_dedup_upload -x` | ❌ W0 | ⬜ pending | | 02-05-01 | 02 | 1 | DRV-05 | unit | `pytest tests/test_inf_parser.py::test_unused_files -x` | ❌ W0 | ⬜ pending | | 02-05-02 | 03 | 2 | DRV-05 | integration | `pytest tests/test_driver_upload.py::test_unused_files_in_response -x` | ❌ W0 | ⬜ pending | *Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* --- ## Wave 0 Requirements - [ ] `tests/test_inf_parser.py` — stubs for DRV-02 (INF parsing, token resolution, encoding, multi-model) - [ ] `tests/test_driver_upload.py` — stubs for DRV-01, DRV-03, DRV-04, DRV-05 (upload endpoint integration tests) - [ ] `tests/fixtures/sample.inf` — minimal valid INF fixture with `%TOKEN%` values - [ ] `tests/fixtures/sample_utf16.inf` — UTF-16 LE encoded INF fixture - [ ] `tests/fixtures/sample_multi_model.inf` — INF with NTamd64 and undecorated sections - [ ] `imptune/services/__init__.py` — package marker (services/ directory) *Framework already installed; conftest.py with `tmp_data_dir` fixture already covers DB isolation* --- ## Manual-Only Verifications | Behavior | Requirement | Why Manual | Test Instructions | |----------|-------------|------------|-------------------| | Upload form renders correctly in browser | DRV-03 | Visual layout verification | Open /drivers, verify file input and submit button visible | | Dropdown populated after upload in browser | DRV-03 | HTMX swap visual verification | Upload sample ZIP, verify `` even for single-name drivers (decision in 02-02-SUMMARY). Real-browser HTMX swap covered by row 6. | | 4 | **DRV-04** — Uploaded driver packages are persisted to the Docker volume (`DRIVERS_DIR`) under SHA256 content-addressed names and survive container restart; re-uploading the same ZIP does not duplicate the Driver record | `pytest tests/test_driver_upload.py::test_driver_persisted` (file lands on disk under `tmp_data_dir/drivers/`) and `::test_dedup_upload` (2 uploads → `Driver.select().where(sha256==...).count() == 1`) | `tests/test_driver_upload.py::test_driver_persisted`, `::test_dedup_upload`; `imptune/storage/driver_store.py::DriverStore.save` (SHA256-named files); `imptune/api/drivers.py` lines 85-99 (`DriverStore(_cfg.DRIVERS_DIR).save(data)` → `Driver.get_or_create(sha256=…)`); 02-VERIFICATION.md rows 11 + 12 | pass | Content-addressed storage gives dedup for free. `_cfg.DRIVERS_DIR` read dynamically at call time so monkeypatch works in tests (02-02-SUMMARY decision). | | 5 | **DRV-05** — System flags unused files (files in ZIP not referenced by the INF) to help technicians reduce driver package size | `pytest tests/test_inf_parser.py::test_unused_files` (parser returns `unused_files` list) and `pytest tests/test_driver_upload.py::test_unused_files_in_response` (word "unused" present in response HTML) | `tests/test_inf_parser.py::test_unused_files`; `tests/test_driver_upload.py::test_unused_files_in_response`; `imptune/services/inf_parser.py` `ParsedInf.unused_files`; `imptune/templates/partials/driver_list.html` unused-files notice; 02-VERIFICATION.md rows 5 + 13 | pass | | | 6 | **DRV-01 runtime gap** — `POST /drivers/upload` must not return HTTP 500 on real driver ZIPs uploaded via the browser (reported 2026-04-13 during Phase 8 kickoff; parallel to the v1.1 UX-01 DriverDesc-refresh requirement) | `pytest tests/test_driver_upload.py::test_upload_500_regression` (two parametrized variants: plain UTF-8 and UTF-16 LE BOM) returns 200, never 500; plus OOB refresh covered by `::test_upload_oob_*` contract tests | Phase 9 commit `10ee09a` (fix handler: `caller: str = Form("")` + OOB branch in `imptune/api/drivers.py`); Phase 9 commit `d1de839` (regression + OOB RED tests); Phase 9 commit `72c6a98` (printer_form.html wiring); `.planning/phases/09-ux-tech-debt-closure/09-01-SUMMARY.md` (UX-01 complete 2026-04-13); REQUIREMENTS.md v1.1 UX-01 = Complete | pass | **Historical gap recorded per CONTEXT.md locked decision.** At Phase 8 kickoff this was slated as `fail-fix-v1.1` linked to Phase 9 / UX-01. Resolved 2026-04-13 in Phase 9 Plan 01 (commits d1de839 + 10ee09a + 72c6a98); 112 tests green post-fix. Closed as `pass` citing the fixing commits, consistent with the 08-01 precedent (row 14 Phase 1 spike → Phase 10 RTVAL-01). | **Audit outcome:** 6/6 rows `pass`. No `fail-fix-v1.1`, `deferred-v1.2`, or `wont-do` rows. Phase 2 is Nyquist-compliant: every DRV-0x success criterion has exactly one observable check with cited, committed evidence. The Phase 8 kickoff-surfaced `POST /drivers/upload` 500 gap is captured as row 6 and closed via Phase 9 / UX-01 fixing commits — fully honoring the CONTEXT.md locked-decision mandate. --- ## Validation Sign-Off - [ ] All tasks have `` verify or Wave 0 dependencies - [ ] Sampling continuity: no 3 consecutive tasks without automated verify - [ ] Wave 0 covers all MISSING references - [ ] No watch-mode flags - [ ] Feedback latency < 10s - [ ] `nyquist_compliant: true` set in frontmatter **Approval:** pending