Files
ImpTune/.planning/phases/03-printer-configuration/03-VALIDATION.md
T
2026-04-15 17:57:12 +02:00

11 KiB

phase, slug, status, nyquist_compliant, wave_0_complete, created, nyquist_audited, nyquist_auditor
phase slug status nyquist_compliant wave_0_complete created nyquist_audited nyquist_auditor
3 printer-configuration draft true false 2026-04-10 2026-04-13 Claude (gsd-executor, plan 08-03)

Phase 3 — Validation Strategy

Per-phase validation contract for feedback sampling during execution.


Test Infrastructure

Property Value
Framework pytest 8.x
Config file none — discovered via standard pytest directory scan
Quick run command pytest tests/test_printer_crud.py -x -q
Full suite command pytest tests/ -v
Estimated runtime ~5 seconds

Sampling Rate

  • After every task commit: Run pytest tests/test_printer_crud.py -x -q
  • After every plan wave: Run pytest tests/ -v
  • Before /gsd:verify-work: Full suite must be green
  • Max feedback latency: 5 seconds

Per-Task Verification Map

Task ID Plan Wave Requirement Test Type Automated Command File Exists Status
03-01-01 01 1 PRNT-01, PRNT-02 integration pytest tests/test_printer_crud.py::test_create_printer_persisted -x W0 pending
03-01-02 01 1 PRNT-04 integration pytest tests/test_printer_crud.py::test_create_printer_duplex -x W0 pending
03-01-03 01 1 PRNT-05 integration pytest tests/test_printer_crud.py::test_create_printer_color_mode -x W0 pending
03-01-04 01 1 PRNT-06 integration pytest tests/test_printer_crud.py::test_create_printer_paper_size -x W0 pending
03-01-05 01 1 PRNT-07 integration pytest tests/test_printer_crud.py::test_create_printer_collate -x W0 pending
03-01-06 01 1 PRNT-09 integration pytest tests/test_printer_crud.py::test_printer_survives_page_refresh -x W0 pending
03-02-01 02 1 PRNT-08 integration pytest tests/test_printer_crud.py::test_printer_grouped_by_client -x W0 pending
03-03-01 03 2 PRNT-10 integration pytest tests/test_printer_crud.py::test_printer_detail_shows_driver -x W0 pending
03-01-XX 01 1 PRNT-03 manual Manual browser test n/a pending

Status: pending · green · red · ⚠️ flaky


Wave 0 Requirements

  • tests/test_printer_crud.py — stubs for PRNT-01 through PRNT-10 (integration tests)
  • tests/test_client_crud.py — stubs for client creation and listing (can merge into test_printer_crud.py)

Existing infrastructure covers framework and conftest.py — no new infrastructure needed.


Manual-Only Verifications

Behavior Requirement Why Manual Test Instructions
Alpine.js auto-populates port name from IP PRNT-03 Browser-side Alpine.js reactivity cannot be tested with pytest TestClient 1. Open /printers/new 2. Type "192.168.1.100" in IP field 3. Verify port field shows "IP_192_168_1_100" 4. Edit port field manually 5. Change IP field 6. Verify port field keeps manual value

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 <h3> 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_driverGET /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 <automated> 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 < 5s
  • nyquist_compliant: true set in frontmatter
  • Nyquist audit complete — 2026-04-13 — Sébastien QUEROL

Approval: Nyquist-audited 2026-04-13 by Claude (gsd-executor, plan 08-03) — 10/10 pass; signed off 2026-04-13 by Sébastien QUEROL (index: v1.0-VALIDATION-INDEX.md)