From 3f03b35bf218c84a459c7aeb61d32406e78f2f25 Mon Sep 17 00:00:00 2001 From: Kawa Date: Mon, 13 Apr 2026 16:02:13 +0200 Subject: [PATCH] docs(08-03): add Phase 3 Nyquist Record to 03-VALIDATION.md - 10 rows (one per PRNT-01..10 success criterion), all pass - Row 3 (PRNT-03 Alpine.js IP->port) closed as pass citing Phase 9 UX-02 Playwright fixing commits 322fc20 (test) + 37a06da (docs) - Frontmatter: nyquist_compliant true, nyquist_audited 2026-04-13, nyquist_auditor Claude (gsd-executor, plan 08-03) - Preserves Test Infrastructure, Sampling Rate, Per-Task Verification Map, Wave 0, Manual-Only Verifications, Validation Sign-Off verbatim --- .../03-printer-configuration/03-VALIDATION.md | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.planning/phases/03-printer-configuration/03-VALIDATION.md b/.planning/phases/03-printer-configuration/03-VALIDATION.md index 2d8d9c6..6228649 100644 --- a/.planning/phases/03-printer-configuration/03-VALIDATION.md +++ b/.planning/phases/03-printer-configuration/03-VALIDATION.md @@ -2,9 +2,11 @@ phase: 3 slug: printer-configuration status: draft -nyquist_compliant: false +nyquist_compliant: true wave_0_complete: false created: 2026-04-10 +nyquist_audited: 2026-04-13 +nyquist_auditor: Claude (gsd-executor, plan 08-03) --- # Phase 3 — Validation Strategy @@ -69,6 +71,29 @@ created: 2026-04-10 --- +## Nyquist Record + +> Audited 2026-04-13 by Claude (gsd-executor, plan 08-03). One row per Phase 3 success criterion derived from `milestones/v1.0-ROADMAP.md` Phase 3 goal + plan outcomes (PRNT-01..10), cross-checked against `03-VERIFICATION.md` (10/10 observable truths verified 2026-04-10, 9 automated + 1 human-needed on PRNT-03) and `REQUIREMENTS.md` v1.0 PRNT-0x block. Evidence cites committed tests, source lines, and the dated VERIFICATION report. Status values: `pass` / `fail-fix-v1.1` / `deferred-v1.2` / `wont-do`. +> +> **Phase 3 goal (v1.0-ROADMAP.md):** *"Technicians configure all printer parameters, assign printers to clients, and regenerate saved configs without re-uploading drivers."* + +| # | Success Criterion | Observable Check | Evidence | Status | Notes | +|---|-------------------|------------------|----------|--------|-------| +| 1 | **PRNT-01** — User can set a printer display name | `pytest tests/test_printer_crud.py::test_create_printer_persisted` verifies `name` field posted to `POST /printers` is persisted and rendered in `GET /printers` | `tests/test_printer_crud.py::test_create_printer_persisted`; `imptune/api/printers.py` `POST /printers` handler (commit 356c2ee); `imptune/templates/partials/printer_form.html` `name` input; 03-VERIFICATION.md row 1 (2026-04-10) | pass | | +| 2 | **PRNT-02** — User can set a printer IP address or hostname | `pytest tests/test_printer_crud.py::test_create_printer_persisted` includes `ip_address` field in POST body; persisted value round-trips through `GET /printers` | `tests/test_printer_crud.py::test_create_printer_persisted`; `imptune/api/printers.py` POST handler (`ip_address: str = Form(...)`); `printer_form.html` IP field with `x-model`; 03-VERIFICATION.md row 1 | pass | | +| 3 | **PRNT-03** — System auto-suggests port name from IP (user can override, manual edits preserved) | `pytest tests/e2e/test_port_autofill.py` — real Chromium via Playwright, types IP into form, asserts port field auto-fills with `IP_x_x_x_x`, then edits port manually, changes IP, asserts manual value preserved | `tests/e2e/test_port_autofill.py` (Phase 9 UX-02 commit 322fc20 test, 37a06da docs); `imptune/templates/partials/printer_form.html` Alpine.js `x-data`/`x-model`/`portEdited` guard (commit 356c2ee); `.planning/phases/09-ux-tech-debt-closure/09-02-SUMMARY.md` (UX-02 complete 2026-04-13); REQUIREMENTS.md v1.1 UX-02 = Complete; 03-VERIFICATION.md row 2 | pass | **Historical gap closed via Phase 9 / UX-02 fixing commits.** At v1.0 audit (03-VERIFICATION.md 2026-04-10) this was the sole `NEEDS HUMAN` truth — Alpine.js reactivity cannot execute inside FastAPI TestClient. Phase 9 Plan 02 added a Playwright headless-chromium live-browser e2e test that exercises the @input handler and the `portEdited` manual-edit lock. Closed as `pass` citing the fixing commits, consistent with the 08-01 (row 14 → Phase 10 RTVAL-01) and 08-02 (row 6 → Phase 9 UX-01) precedents. | +| 4 | **PRNT-04** — User can set duplex mode | `pytest tests/test_printer_crud.py::test_create_printer_duplex` posts `duplex_mode=LongEdge` and verifies persisted value | `tests/test_printer_crud.py::test_create_printer_duplex`; `printer_form.html` `duplex_mode` select (OneSided/LongEdge/ShortEdge); `imptune/api/printers.py` POST handler mapping; 03-VERIFICATION.md row 1 + PRNT-04 coverage row | pass | | +| 5 | **PRNT-05** — User can set color vs. grayscale default | `pytest tests/test_printer_crud.py::test_create_printer_color_mode` posts form without the `color_mode` checkbox and asserts the persisted value is `False` (checkbox-to-bool conversion) | `tests/test_printer_crud.py::test_create_printer_color_mode`; `printer_form.html` `color_mode` checkbox; `imptune/api/printers.py` checkbox-to-bool conversion in POST handler; 03-VERIFICATION.md PRNT-05 row | pass | | +| 6 | **PRNT-06** — User can set paper size | `pytest tests/test_printer_crud.py::test_create_printer_paper_size` posts `paper_size=A4` (plus Letter/Legal variants) and verifies persisted value | `tests/test_printer_crud.py::test_create_printer_paper_size`; `printer_form.html` `paper_size` select (A4/Letter/Legal); 03-VERIFICATION.md PRNT-06 row | pass | | +| 7 | **PRNT-07** — User can set collate on/off | `pytest tests/test_printer_crud.py::test_create_printer_collate` posts form without `collate` checkbox and asserts persisted value is `False` | `tests/test_printer_crud.py::test_create_printer_collate`; `printer_form.html` `collate` checkbox; `imptune/api/printers.py` checkbox-to-bool conversion; 03-VERIFICATION.md PRNT-07 row | pass | | +| 8 | **PRNT-08** — User can assign a printer to a client/tenant label | `pytest tests/test_printer_crud.py::test_printer_grouped_by_client` creates printers under distinct clients and asserts `GET /printers` renders `

` group headers per client (LEFT OUTER JOIN) | `tests/test_printer_crud.py::test_printer_grouped_by_client`; `imptune/api/printers.py` `_render_printer_list` uses `Printer.select(Printer, Client).join(Client, JOIN.LEFT_OUTER)`; `printer_form.html` client select; `imptune/templates/partials/printer_list.html` group headers; 03-VERIFICATION.md rows 3 + 4 | pass | | +| 9 | **PRNT-09** — Printer configurations are persisted in SQLite across sessions | `pytest tests/test_printer_crud.py::test_printer_survives_page_refresh` (+ `test_create_printer_persisted`) — posts printer, re-queries via `GET /printers`, asserts DB count and rendered HTML both show the record | `tests/test_printer_crud.py::test_create_printer_persisted`, `::test_printer_survives_page_refresh`; `imptune/db/models.py` Printer model (Phase 1 schema); 03-VERIFICATION.md row 4 | pass | | +| 10 | **PRNT-10** — User can regenerate a package from saved config without re-uploading drivers (Phase 3 scope: detail page loads full config with driver FK intact; regenerate button placeholder until Phase 4) | `pytest tests/test_printer_crud.py::test_printer_detail_shows_driver` — `GET /printers/{id}` returns full-page detail with all 7 config fields and driver name (`HP Universal`) pre-populated; `::test_printer_detail_no_driver` covers missing-driver fallback | `tests/test_printer_crud.py::test_printer_detail_shows_driver`, `::test_printer_detail_no_driver`; `imptune/api/pages.py` `GET /printers/{id}` uses `.switch(Printer).join(Driver, JOIN.LEFT_OUTER)`; `imptune/templates/printer_detail.html` (disabled regenerate button, Phase-4 scoped); 03-VERIFICATION.md rows 6 + 7 + 8 | pass | Full regeneration workflow is a Phase 4 deliverable per 03 plan scope. Phase 3 scope = config retrievable with driver FK intact + placeholder button. Verified SATISFIED (partial) in 03-VERIFICATION.md; the "partial" refers to the Phase-4 button wiring, not a Phase 3 gap. | + +**Audit outcome:** 10/10 rows `pass`. No `fail-fix-v1.1`, `deferred-v1.2`, or `wont-do` rows. Phase 3 is Nyquist-compliant: every PRNT-0x success criterion has exactly one observable check with cited, committed evidence. The PRNT-03 Alpine.js IP→port live-browser gap (only `NEEDS HUMAN` truth in 03-VERIFICATION.md) is captured as row 3 and closed via Phase 9 / UX-02 Playwright e2e fixing commits — fully honoring the CONTEXT.md locked-decision pattern. + +--- + ## Validation Sign-Off - [ ] All tasks have `` verify or Wave 0 dependencies