--- phase: 7 slug: dashboard-nav-polish 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-07) --- # Phase 7 — Validation Strategy > Per-phase validation contract for feedback sampling during execution. --- ## Test Infrastructure | Property | Value | |----------|-------| | **Framework** | pytest | | **Config file** | none — discovered via convention | | **Quick run command** | `pytest tests/test_static.py -x` | | **Full suite command** | `pytest tests/ -x` | | **Estimated runtime** | ~5 seconds | --- ## Sampling Rate - **After every task commit:** Run `pytest tests/test_static.py -x` - **After every plan wave:** Run `pytest tests/ -x` - **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 | |---------|------|------|-------------|-----------|-------------------|-------------|--------| | 07-01-01 | 01 | 0 | SC-1,2,3 | integration | `pytest tests/test_static.py -x` | ✅ (add tests) | ⬜ pending | | 07-01-02 | 01 | 1 | SC-1 | integration | `pytest tests/test_static.py::test_packages_returns_200 -x` | ❌ W0 | ⬜ pending | | 07-01-03 | 01 | 1 | SC-2,3 | integration | `pytest tests/test_static.py::test_dashboard_shows_recent_printers -x` | ❌ W0 | ⬜ pending | *Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* --- ## Wave 0 Requirements - [ ] `tests/test_static.py` — add `test_packages_returns_200`, `test_dashboard_shows_recent_printers`, `test_dashboard_shows_recent_packages` (file exists, add to it) - [ ] `imptune/templates/packages.html` — new template file needed *Existing infrastructure covers framework install — pytest already available.* --- ## Manual-Only Verifications | Behavior | Requirement | Why Manual | Test Instructions | |----------|-------------|------------|-------------------| | Nav link highlights active on /packages | UX polish | CSS active-class visual state | 1. Navigate to /packages 2. Verify nav item is visually highlighted | --- ## Nyquist Record > Audited 2026-04-13 by Claude (gsd-executor, plan 08-07). Phase 7 is the **second gap-closure phase** (sibling of Phase 6), added after the first v1.0 milestone audit flagged `base.html -> /packages` as a 404 and the dashboard as rendering hard-coded `[]` despite real DB records. One row per Phase 7 success criterion, derived from `milestones/v1.0-ROADMAP.md` Phase 7 goal block ("Navigation links work correctly and the dashboard shows real data instead of empty placeholders") cross-checked against `07-VERIFICATION.md` (4/4 observable truths VERIFIED 2026-04-13) and `07-01-SUMMARY.md`. Phase 7 declares `requirements: []` — it is a pure UX/integration fix phase with no REQUIREMENTS.md IDs to satisfy. > > **Phase 7 goal (v1.0-ROADMAP.md):** *"Navigation links work correctly and dashboard shows real data instead of empty placeholders."* > > **Row decomposition:** 07-VERIFICATION.md's single goal was decomposed into 3 observable truths (Truth 1 = /packages returns 200 with driver-assigned printers; Truth 2 = dashboard recent_printers live query; Truth 3 = dashboard recent_packages filtered to driver-assigned). Truth 4 (regression guard — full suite green) is not a standalone criterion but a sampling discipline, so it folds into every row's evidence. The Nyquist Record therefore contains **3 rows** — one per observable behavior the phase claims to deliver. > > **UX-03 scope clarification:** STATE.md and the 08-07 plan note UX-03 (individual script download links on printer detail page) as a "carried-over gap from Phase 7". Historically accurate this is **not** — UX-03 originates from Phase 5 (`milestones/v1.0-ROADMAP.md` "Issues Deferred to v1.1" row 3: *"No UI links to individual script downloads — only accessible via package export or direct URL (Phase 5)"*) and was closed in Phase 9 / Plan 09-03 (commits `d359001` RED + `68a2935` GREEN). It is recorded as **row 4** of this Nyquist Record for continuity with the plan specification, but flagged in Notes as a Phase-5-origin gap that was simply discovered during the same milestone audit pass that produced Phase 7. Status: pass (closed in Phase 9). > > **Runtime evidence:** Phase 7 is a pure web-UI HTMX/FastAPI integration fix — no runtime validation on a real Intune tenant is relevant. RTVAL-01 does not apply because the /packages listing page and dashboard live queries never travel to Intune; they are server-side Jinja2 renders consumed by the technician's browser only. No transitive runtime citation is needed. > > **Sibling symmetry with Phase 6:** Phase 6 produced a 1-row record because it decomposed to exactly one REQUIREMENTS.md criterion (PKG-04). Phase 7 produces a 3-row (+1 carry-over) record because its single narrative goal fans out into three distinct observable web behaviors even though it owns zero REQUIREMENTS.md IDs. Row count asymmetry reflects real scope, not audit inconsistency. | # | Criterion | Observable Check | Evidence | Status | Notes | |---|-----------|-----------------|----------|--------|-------| | 1 | **Nav / packages listing:** `GET /packages` returns 200 and renders the list of printers that have a driver assigned (closes the `base.html -> /packages` 404 gap flagged in the first milestone audit) | `python -m pytest tests/test_static.py::test_packages_returns_200 -x -q` | Test: `tests/test_static.py::test_packages_returns_200` (lines 40-43) — asserts `client.get("/packages").status_code == 200`. Source: `imptune/api/pages.py:142` (`@router.get("/packages")` route decorator), lines 143-158 (`packages_page` handler with `Printer.driver.is_null(False)` filter + LEFT_OUTER join on Client + Driver + `switch(Printer)`, rendering `packages.html` at lines 154-157). Template: `imptune/templates/packages.html` (created this phase, extends `base.html`, Pico table with printer/client/driver/download columns). Nav link target: `imptune/templates/base.html:23` ``. Commits: `8cf47f5` (07-01 TDD RED — failing test) + `91910ad` (07-01 TDD GREEN — route + template + live queries). 07-VERIFICATION.md (2026-04-13) Truth 1 VERIFIED with explicit `pages.py:142-158` citation. | pass | Manual-only follow-up: nav link active-class highlight when on /packages (listed in Manual-Only Verifications section above, cosmetic — not part of this row). Closes milestone-audit `/packages` 404 gap entirely. | | 2 | **Dashboard recent printers live query:** Dashboard shows the 5 most recently created printers from the database (replaces the hard-coded empty list that shipped in Phase 1 dashboard scaffold) | `python -m pytest tests/test_static.py::test_dashboard_shows_recent_printers -x -q` | Test: `tests/test_static.py::test_dashboard_shows_recent_printers` (lines 46-65) — creates two `Printer` rows, GETs `/`, asserts both names appear in response text and `"No printers configured yet"` empty-state string is absent. Source: `imptune/api/pages.py:20-22` — `Printer.select().order_by(Printer.created_at.desc()).limit(5)` wrapped in `list(...)`. Template: `imptune/templates/dashboard.html:17-25` renders the list as anchor links to `/printers/{id}` detail pages. Commits: `8cf47f5` (RED) + `91910ad` (GREEN). 07-VERIFICATION.md Truth 2 VERIFIED with `pages.py:20-22` + `dashboard.html:17-25` citations. Full suite 99/99 green after landing. | pass | Dashboard UX polish also wired Quick Actions (New Printer / Upload Driver / Export Package) to real routes with `aria-disabled` removed — not a separately-audited criterion because it falls inside Truth 2's "dashboard shows real data" scope. | | 3 | **Dashboard recent packages live query:** Dashboard shows the 5 most recently created printers **filtered to those with a driver assigned** (distinct from row 2: this section represents "exportable packages", not "all printers") | `python -m pytest tests/test_static.py::test_dashboard_shows_recent_packages -x -q` | Test: `tests/test_static.py::test_dashboard_shows_recent_packages` (lines 68-93) — creates one `Driver` row, two `Printer` rows (one with driver FK, one without), GETs `/`, asserts the driver-assigned printer name appears AND `"No packages exported yet"` empty-state is absent; the no-driver printer is implicitly excluded by the filter. Source: `imptune/api/pages.py:23-28` — `Printer.select().where(Printer.driver.is_null(False)).order_by(created_at.desc()).limit(5)` wrapped in `list(...)`. Template: `imptune/templates/dashboard.html:30-39`. Commits: `8cf47f5` (RED) + `91910ad` (GREEN). 07-VERIFICATION.md Truth 3 VERIFIED with `pages.py:23-28` + `dashboard.html:30-39` citations. | pass | Row 3 and row 2 share the same TDD commit pair but are distinct Nyquist criteria because they measure two different DB queries against two different dashboard sections with two different filter predicates. Folding them into a single row would hide the filter-correctness observation. | | 4 | **UX-03 carry-over (Phase 5 origin):** Technician has a UI affordance to download each PowerShell script (install/uninstall/detect) individually from the printer detail page, not only as part of a full package export | `python -m pytest tests/test_script_download.py -x -q` + `python -m pytest tests/test_packages.py::TestCommandPreview::test_detail_page_shows_script_links -x -q` | Origin: `milestones/v1.0-ROADMAP.md` "Issues Deferred to v1.1 (Tech Debt)" row 3 explicitly tags this as a **Phase 5** deferral, not a Phase 7 deliverable. Listed here per 08-07 plan directive as a closed-loop citation. Resolution: Phase 9 Plan 09-03 (`09-03-SUMMARY.md` 2026-04-13, `requirements-completed: [UX-03]`). Implementation: `imptune/api/scripts.py` — added `.ps1`-suffixed route aliases for install/uninstall/detect via shared `_install_response()` / `_uninstall_response()` / `_detect_response()` helper pattern; `imptune/templates/printer_detail.html` — added Scripts section inside `{% if has_driver %}` guard with 3 direct download anchors before the Export section. Tests: `tests/test_script_download.py` (5 integration tests, all three `.ps1` routes + 404 + 422), `tests/test_packages.py::TestCommandPreview::test_detail_page_shows_script_links` (template-level link presence). Commits: `d359001` (09-03 TDD RED) + `68a2935` (09-03 TDD GREEN). Phase 9 full non-e2e suite 106/106 green post-landing. | pass | **Scope note:** This row does NOT invalidate the Phase-7-only scope of the 07-VALIDATION.md document; it is included purely because the 08-07 plan directive requested an explicit closed-loop citation to Phase 9 UX-03 from this file. The STATE.md entry describing UX-03 as a "carried-over gap from Phase 7" is recorded as an imprecise restatement of the v1.0-ROADMAP.md tech-debt ledger, which lists UX-03 under Phase 5. Historical provenance does not affect the pass status. | ### Audit Outcome | Status | Count | |---------------|-------| | pass | 4 | | fail-fix-v1.1 | 0 | | deferred-v1.2 | 0 | | wont-do | 0 | Phase 7 is Nyquist-compliant. The three in-scope observable behaviors (rows 1-3) are all backed by passing integration tests landed in the TDD commit pair `8cf47f5` + `91910ad`, cross-verified by 07-VERIFICATION.md 2026-04-13 with line-number source citations. The carry-over UX-03 row (row 4) is closed via Phase 9 commits `d359001` + `68a2935`. All 4 rows pass; zero audit items roll forward to v1.1. **Final audit-track note:** Plan 08-07 completes per-phase Nyquist coverage for all 7 v1.0 phases (Phase 1 = 14 rows, Phase 2 = 6, Phase 3 = 10, Phase 4 = 5, Phase 5 = 5, Phase 6 = 1, Phase 7 = 4 = **45 total audit rows**). NYQ-01 per-phase work is complete; plan 08-08 rollup is the remaining task and will aggregate these counts into `.planning/milestones/v1.0-NYQUIST-ROLLUP.md` (or equivalent) per the Phase 08 context. --- ## Validation Sign-Off - [x] All tasks have `` verify or Wave 0 dependencies - [x] Sampling continuity: no 3 consecutive tasks without automated verify - [x] Wave 0 covers all MISSING references - [x] No watch-mode flags - [x] Feedback latency < 5s - [x] `nyquist_compliant: true` set in frontmatter **Approval:** Nyquist-audited 2026-04-13 by Claude (gsd-executor, plan 08-07) — 4/4 pass