docs(08-02): add Phase 2 Nyquist Record (6 rows, all pass)
- Append Nyquist Record table to 02-VALIDATION.md (DRV-01..05 + upload-500 historical gap) - Flip frontmatter nyquist_compliant=true; add nyquist_audited + nyquist_auditor - Row 6 records the Phase 8 kickoff POST /drivers/upload 500 as pass via Phase 9 / UX-01 fixing commits (d1de839,10ee09a,72c6a98) - Follows the 08-01 precedent (Phase 1 row 14 closed via Phase 10 RTVAL-01)
This commit is contained in:
@@ -2,9 +2,11 @@
|
|||||||
phase: 2
|
phase: 2
|
||||||
slug: driver-management
|
slug: driver-management
|
||||||
status: draft
|
status: draft
|
||||||
nyquist_compliant: false
|
nyquist_compliant: true
|
||||||
wave_0_complete: false
|
wave_0_complete: false
|
||||||
created: 2026-04-10
|
created: 2026-04-10
|
||||||
|
nyquist_audited: 2026-04-13
|
||||||
|
nyquist_auditor: Claude (gsd-executor, plan 08-02)
|
||||||
---
|
---
|
||||||
|
|
||||||
# Phase 2 — Validation Strategy
|
# Phase 2 — Validation Strategy
|
||||||
@@ -78,6 +80,25 @@ created: 2026-04-10
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Nyquist Record
|
||||||
|
|
||||||
|
> Audited 2026-04-13 by Claude (gsd-executor, plan 08-02). One row per Phase 2 success criterion derived from `milestones/v1.0-ROADMAP.md` Phase 2 goal + plan outcomes (DRV-01..05), cross-checked against `02-VERIFICATION.md` (14/14 observable truths verified 2026-04-10) and `REQUIREMENTS.md` v1.0 DRV-0x block. Evidence cites committed tests, source lines, or the dated VERIFICATION report. Status values: `pass` / `fail-fix-v1.1` / `deferred-v1.2` / `wont-do`.
|
||||||
|
>
|
||||||
|
> **Phase 2 goal (v1.0-ROADMAP.md):** *"Technicians upload driver packages and select driver names from parsed INF data — no free-text entry."*
|
||||||
|
|
||||||
|
| # | Success Criterion | Observable Check | Evidence | Status | Notes |
|
||||||
|
|---|-------------------|------------------|----------|--------|-------|
|
||||||
|
| 1 | **DRV-01** — User can upload a driver package (ZIP containing INF + supporting files) via the web UI | `pytest tests/test_driver_upload.py::test_upload_valid_zip` returns 200 on POST /drivers/upload with a synthetic ZIP; `::test_upload_non_zip` and `::test_upload_no_inf` both return 400 | `tests/test_driver_upload.py::test_upload_valid_zip`, `::test_upload_non_zip`, `::test_upload_no_inf`; `imptune/api/drivers.py` POST `/drivers/upload` handler (commit c648fc5); 02-VERIFICATION.md rows 8 + 10 (2026-04-10) | pass | Three-path coverage (success, non-ZIP, ZIP without INF). |
|
||||||
|
| 2 | **DRV-02** — System parses uploaded INF files and extracts valid driver names (DriverDesc), resolving %TOKEN% references, handling UTF-16/UTF-8/ANSI encodings, and deduping multi-model entries | `pytest tests/test_inf_parser.py` — 16 tests covering `test_simple_driver_desc`, `test_token_resolution`, `test_detect_encoding_utf16le/be/utf8bom/ansi`, `test_utf16_encoding`, `test_multi_model_inf`, `test_architecture_detection_*`, `test_cat_file_detection_*` | `tests/test_inf_parser.py` (16 tests, 281 lines); `imptune/services/inf_parser.py` — `parse_inf`, `_detect_encoding`, `_resolve_tokens` (commits 290106d RED, 5056922 GREEN); 02-VERIFICATION.md rows 1-7 | pass | `RawConfigParser(strict=False)` + `optionxform=str` preserves DriverDesc casing; BOM-sniffing for encoding detection. |
|
||||||
|
| 3 | **DRV-03** — User can select a driver name from a parsed-INF dropdown on the drivers page (no free-text entry) | `pytest tests/test_driver_upload.py::test_drivers_page` (form present) and `::test_upload_returns_select` (response contains `<select` and a parsed driver name) | `tests/test_driver_upload.py::test_drivers_page`, `::test_upload_returns_select`; `imptune/templates/drivers.html` (`hx-post="/drivers/upload"`, `hx-target="#driver-list"`); `imptune/templates/partials/driver_list.html` (`<select aria-label="Driver names">`); 02-VERIFICATION.md rows 9 + 14 | pass | Template always renders `<select>` 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
|
## Validation Sign-Off
|
||||||
|
|
||||||
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
|
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
|
||||||
|
|||||||
Reference in New Issue
Block a user