diff options
Diffstat (limited to 'docs/design')
| -rw-r--r-- | docs/design/2026-06-29-waybar-network-module-spec.org | 267 |
1 files changed, 263 insertions, 4 deletions
diff --git a/docs/design/2026-06-29-waybar-network-module-spec.org b/docs/design/2026-06-29-waybar-network-module-spec.org index b4ba1f2..298ebe6 100644 --- a/docs/design/2026-06-29-waybar-network-module-spec.org +++ b/docs/design/2026-06-29-waybar-network-module-spec.org @@ -45,9 +45,12 @@ reverses two earlier choices and widens coverage: success) and *detect + respond to every failure mode* — the full ~44-mode catalog, edge cases included, lives in the redesign task and supersedes the table below. -Phase 4 (docs / rollout) and Phase 5 (VPN) remain. The three Codex review rounds + -Craig's cj comments from the original spec are all incorporated ([31/31], no open -decisions). Phases 1-3's manual live checks are under todo.org "Manual testing and +Phase 4 (docs / rollout) and Phase 5 (VPN) remain. Review incorporated (Codex, +2026-06-30): four review rounds + Craig's cj comments are all dispositioned +([40/40], no open findings) — the fourth round reshaped the V2 panel UX (single nav +target, saved-vs-available groups, join-from-row, the auth matrix, progressive +loading, a findable diagnostics report, and the Waybar visual contract; see "V2 panel +UX"). Phases 1-3's manual live checks are under todo.org "Manual testing and validation". * Goal @@ -676,6 +679,82 @@ individual repair tiers (renamed, with tooltips) plus a *Debug capture on/off* toggle (the manual side of the verbose-capture feature; a failing diagnose triggers it automatically). Speed test moves under Performance. +** V2 panel UX — the target design + +The shipped four-page stack (Connections / Diagnose / Repair / Speed test) is +*history*, not active design. V2 is the sole current target: one panel opened from +the bar, three top tabs — Connections | Diagnostics | Performance — and the page +model below is the contract for what gets built and what gets deleted, not just for +labels. + +*** Connections — saved vs available, join-from-row +Three labelled groups, never one merged list: +- *Saved* — saved NM profiles, MRU-first, rendered instantly without a scan. +- *Available now* — scan-backed in-range SSIDs with signal + security; may carry a + loading/stale hint; unsaved networks appear here. +- *Wired* — ethernet when a wired device is present. +=net list= already yields this (=connections.py= lists saved MRU-first, merges live +signal/security for in-range saved profiles, then appends unsaved in-range SSIDs with +=uuid: nil=); the panel groups and labels it. *Rescan refreshes only the +availability/signal layer* — it never gates or reloads the Saved list. + +*Progressive loading:* render the Saved group immediately on open, then overlay +availability, signal, and the unsaved Available-now rows when the scan returns. Show a +small scan-in-progress state (elapsed + last-scan age). A slow or bad radio scan must +not make the whole panel feel stuck — this is the direct answer to "why does it take +so long to see my connections?" + +*Join-from-row (no Add page):* selecting an unsaved Available-now row *is* the join +flow — SSID and security come prefilled from the scan, never retyped. Open networks +connect (confirm only if needed); WPA/WPA2/WPA3-Personal ask only for the password. +The standalone Add button + modal are deleted for visible networks. A hidden/manual +SSID join lives behind an Advanced "Join hidden network" affordance. + +*** Supported authentication classes (the join matrix) +From the scanned NM =SECURITY= value, V2 handles: +- *Inline-supported* — open, open-with-captive-portal, WPA/WPA2/WPA3-Personal + (PSK/SAE), and WPA2/WPA3 transition mode. The row shows the security label so the + user knows why a password is or isn't asked. +- *Activate-only* — 802.1X / enterprise: connect if already saved, else "edit in + nmtui/nmcli" (no add form in v1/V2, per decision 9). +- *Hidden / manual* — behind the Advanced "Join hidden network" affordance. +- *Rare / unsupported* — WEP, OWE/enhanced-open, MAC-registration, voucher, or + proxy-required: a clear in-panel explanation ("not supported here yet") plus a + non-terminal next step, never a hand-off to a terminal tool. + +*** Diagnostics owns the diagnostic story +Diagnostics holds the read-only checks, the repair stream, Get Me Online, debug +capture (Advanced), and the doctor report. A *lightweight* latency/throughput probe +runs inline as a Diagnose evidence row when internet is available (skipped offline, on +a metered/hotspot warning, or with no backend), and its result is stored in the doctor +report. The *full* speed test stays under Performance (decision 19) — which is also +the home for future throughput history, so Performance earns its tab rather than being +a lone button. + +*** Forget confirmation — future tense + verified +The destructive copy is future tense and names the scope: "This will remove the saved +NetworkManager profile and its stored password from this machine." After the op, +verify the UUID is gone, refresh the Saved list, and report "Forgot <SSID>" or "Could +not forget <SSID>; nothing changed / partial <evidence>" — the verify-every-action +decision applied to a destructive op. + +*** Findable diagnostics report +Every diagnose, repair, and speed/performance run ends with a "Copy report" / "Open +report" action in Diagnostics. The report carries the step statuses + elapsed, the +final classification, the last speed/latency result when available, scan age, +route/interface owner, the redacted event-log tail, and the bundle path when verbose +capture ran. It states explicitly whether any repair mutated state and whether +cleanup/verification passed. "Logs exist somewhere" isn't enough when the network is +already down — the report is the one artifact the user copies to hand over. + +*** Visual contract — a Waybar-attached popup +The panel reads as part of the bar, not a separate app. Match the live Waybar theme: +the dark rounded capsule (=border-radius: 1rem=), the golden border, compact monospace +text, and the =custom/net= state colors. Avoid square corners next to rounded UI, keep +cards out of cards, and use compact icon+label controls with tooltips for the advanced +repairs. Reuse any existing archsetup-owned GTK/panel conventions. (Non-blocking for +engine work; blocks final V2 UX acceptance.) + ** Panel state, cancellation, permissions State machines for: connection-list loading, rescan-in-progress, activation-in-progress, diagnose-running, repair-running, speedtest-running. Plus @@ -1096,7 +1175,7 @@ back in the config and restoring their scripts. The panel is additive — not wiring its clicks leaves the bar working as before. No credential store to roll back (secrets stay in NM throughout). -* Review findings [31/31] +* Review findings [40/40] ** DONE Define the structured diagnostics contract :blocking: The spec says the engine "emits JSON" and that diagnostics "reuse =captive= @@ -1608,6 +1687,144 @@ state), row content, one primary button per section, disabled-state rules, exact confirmation wording for reset/bounce/DNS-override/remove, the live "Get me online" escalation reporting, what survives panel close, and keyboard nav. +** DONE Reconcile the panel navigation source of truth :blocking: +Disposition: accept — folded into "V2 panel UX". V2 (Connections | Diagnostics | +Performance) is the sole current target; the shipped four-page stack is marked history, +not active design. +The spec now names at least three navigation shapes: the shipped four-page stack +(Connections / Diagnose / Repair / Speed test), the V2 three-tab plan +(Connections / Diagnostics / Performance), and the redesign task's Diagnostics +sub-row (Diagnose / Get Me Online / Advanced). That leaves an implementer free +to keep extra pages and buttons even though Craig is explicitly asking for the +opposite. Make V2 the sole current target: one panel opened from the bar, top +tabs =Connections | Diagnostics | Performance=, with Diagnostics owning the +read-only checks, repair stream, debug capture, doctor report, and related +diagnostic evidence. Mark the old four-page stack as shipped history only, not +active design. This blocks the redesign because the page model determines what +code is deleted, not just labels. + +** DONE Fold speed tests into the diagnostic story :blocking: +Disposition: modify — Craig pre-decided Speed test lives under Performance (decision +19), and Performance carries future throughput history, which meets this finding's own +"keep the tab only if it carries ongoing throughput" condition. Accepted the rest: +Diagnostics runs a lightweight inline latency/throughput probe as a Diagnose evidence +row (with skip conditions for offline / metered / no-backend), and the full speed +result is stored in the doctor report. Folded into "V2 panel UX → Diagnostics owns the +diagnostic story". +Speed test is currently isolated under =Performance=, while the Goal and user +mental model treat speed, latency, and packet loss as part of "diagnostics." +That split risks another top-level button/page whose only job is a diagnostic +measurement. Keep the top-level =Performance= tab only if it carries ongoing +throughput/history later; for V2, specify that Diagnostics can run a lightweight +performance check from the same Diagnose/Get Me Online flow when internet is +available, and that the full speed test is presented as a diagnostic evidence +row or secondary action rather than a separate repair-adjacent workflow. Define +when it is skipped (offline, metered/hotspot warning, missing backend) and how +the result is stored in the doctor report. This is blocking because otherwise +the implementation preserves avoidable navigation and misses a useful failure +signal. + +** DONE Define saved-list vs available-scan semantics :blocking: +Disposition: accept — folded into "V2 panel UX → Connections". Saved / Available now / +Wired groups; Rescan refreshes only the availability/signal layer, never the Saved +list. +=net list= merges saved profiles with in-range scanned networks, while the panel +copy calls the page "Connections" and the control "Rescan." It is not clear to a +user whether they are looking at saved connections, currently available +networks, or both. The current implementation confirms the ambiguity: +=connections.py= lists saved profiles MRU-first, merges live signal/security for +saved profiles that are in range, then appends unsaved in-range SSIDs with +=uuid: nil=. Rename and specify the groups: e.g. =Saved= (instant, does not +require scan), =Available now= (scan-backed, may still be loading/stale), and +=Wired=. =Scan= should refresh only the availability/signal layer, not gate the +saved profile list. This blocks readiness because it affects loading behavior, +button enablement, and whether unsaved rows can be selected. + +** DONE Replace the Add page with join-from-row behavior :blocking: +Disposition: accept — folded into "V2 panel UX → Connections". Selecting an unsaved +Available-now row is the join flow (SSID/security prefilled); the standalone Add modal +is deleted for visible networks; hidden/manual join lives behind Advanced. +The current Add dialog asks for an SSID as free text even though a scan usually +already found the SSID and security type. That is redundant UI and a common +network-manager mistake: it turns "join this visible network" into "copy a name +from the list and type it again." V2 should remove the standalone Add button and +modal for normal visible networks. Selecting an unsaved available row should +become the join flow: the SSID/security are prefilled from the row, open +networks connect with a confirmation only if needed, WPA/WPA2/WPA3-Personal ask +only for the password, and hidden/manual SSID is tucked behind an Advanced +"Join hidden network" affordance. Keep edit/create for enterprise profiles out +of v1/V2 unless explicitly added later. This blocks the redesign because it +changes the primary connection workflow and deletes a whole page/control. + +** DONE Pin the supported authentication types in the join flow :blocking: +Disposition: accept — folded into "V2 panel UX → Supported authentication classes". +The spec says "open + WPA-PSK" and "enterprise activate-only," but cafe/hotel +networks also commonly appear as open captive portals, WPA/WPA2/WPA3-Personal +(PSK/SAE), and sometimes transition-mode networks; less commonly they use +enterprise/802.1X, WEP, OWE/enhanced-open, MAC registration, voucher portals, or +proxy-required networks. Define the V2 join matrix from the scanned NM +=SECURITY= value: supported inline (open, captive/open, WPA/WPA2/WPA3 Personal), +activate-only if already saved (802.1X/enterprise), hidden-manual behind +Advanced, and unsupported/rare types with a clear in-panel explanation plus a +non-terminal next step. If an auth type is common enough to support, support it +in the panel; if it is too rare for V2, say "not supported here yet" and keep +the user in the same UI rather than sending them to a terminal tool. Also define +what security label appears in the row so the user knows why a password is or is +not requested. This blocks because the Add/Join deletion above cannot be +implemented safely without knowing which auth classes the simplified flow covers. + +** DONE Fix destructive confirmation tense and verification +Disposition: accept — folded into "V2 panel UX → Forget confirmation". +The Forget confirmation says "The saved password is deleted" before the user has +clicked Forget. That reads as if the destructive action already happened. Change +the copy to future tense and name the scope, e.g. "This will remove the saved +NetworkManager profile and its stored password from this machine." After the +operation, verify the UUID is gone, refresh the Saved list, and report either +"Forgot <SSID>" or "Could not forget <SSID>; nothing changed / partial state +<evidence>." This is non-blocking because the existing confirm prevents an +accidental click, but the wording is misleading and the V2 "verify every action" +decision should cover it. + +** DONE Make connection loading progressive and observable :blocking: +Disposition: accept — folded into "V2 panel UX → Connections (progressive loading)". +Opening the panel currently says "Loading connections..." while =net list= +collects both saved profiles and the WiFi scan. Saved profiles do not require a +network scan, so a slow scan should not delay the saved list. Split loading into +two phases: render saved NM profiles immediately, then overlay availability, +signal, and unsaved in-range rows when the scan completes. Show a small +scan-in-progress state with elapsed time and stale-last-scan age, and make +Rescan update only the scan-backed fields. This blocks because it is the direct +answer to "why does it take so long to see the list of connections?" and keeps a +bad radio scan from making the whole panel feel broken. + +** DONE Define the visual contract with Waybar and existing Archsetup UI +Disposition: accept — folded into "V2 panel UX → Visual contract". +The panel is a layer-shell popup anchored under Waybar, but the spec does not +state the visual contract. The live Waybar theme uses a dark rounded capsule +(=border-radius: 1rem=), golden border, compact monospace text, and state colors +for =custom/net=; the GTK panel currently has a generic title, stack switcher, +default GTK controls, and square-ish/default widget corners. Add a short style +section: panel should read as a Waybar-attached popup, not a separate app; match +Waybar's palette, border/radius, spacing density, and state colors; avoid square +corners where surrounding UI is rounded; keep cards out of cards; use compact +icon+label controls with tooltips for advanced repairs. Also cite any existing +Archsetup-owned GTK/panel conventions that should be reused. This is +non-blocking for engine work but should block final V2 UX acceptance. + +** DONE Add a diagnostics report affordance that users can actually find +Disposition: accept — folded into "V2 panel UX → Findable diagnostics report". +The observability design has a JSONL event log, =diagnose --json=, automatic +verbose capture, and redacted bundles, but the panel flow does not yet define +the user affordance that turns those into an inspectable diagnosis. Add a +Diagnostics-side "Copy report" / "Open report" action after every diagnose, +repair, and speed/performance run. The report should include the current step +statuses, elapsed time, final classification, last speed/latency result when +available, scan age, route/interface owner, relevant redacted event-log tail, +and bundle path when verbose capture ran. It must explicitly say whether any +repair mutated state and whether cleanup/verification passed. This is blocking +for observability because "logs exist somewhere" is not enough when the network +is already failing. + * Review and iteration history ** 2026-06-29 Mon @ 17:00:39 -0400 — Codex — reviewer @@ -1777,3 +1994,45 @@ online" escalation reporting, what survives panel close, and keyboard nav. Failure-mode coverage, Interactions, Panel, Resolved decisions, Implementation phases. Shipped commits referenced: dotfiles =a7d7559=, =eef6b0b=, =450b7f0=. Full catalog + redesign children in todo.org "Network panel redesign". + +** 2026-06-30 Tue @ 17:29:29 -0400 — Codex — reviewer + +- *What changed or was recommended:* Rubric: =Not ready= for the V2 redesign until + the new blocking findings are dispositioned. Added a fourth review batch focused on + diagnostics/observability and the simple UX questions Craig raised: reconcile the + active panel nav, fold performance/speed testing into the diagnostics story, make + saved-vs-available list semantics explicit, replace the Add page with join-from-row, + pin supported WiFi authentication classes, fix Forget confirmation tense, make + connection loading progressive, define the Waybar/Archsetup visual contract, and add + a findable redacted diagnostics report affordance. +- *Why:* The spec has strong engine and failure-mode coverage, but the current doc and + shipped implementation still replicate common network-manager UX mistakes: ambiguous + mixed lists, scan-gated saved data, redundant SSID entry, misleading destructive + copy, diagnostics split across too many pages, and observability that exists in logs + more than in the user's workflow. +- *Artifacts:* Findings appended under =Review findings= after reading the + spec-review workflow, the target spec, todo.org's redesign task, and current + dotfiles implementation files =net/src/net/connections.py=, + =net/src/net/gui.py=, =net/src/net/panel.py=, and Waybar =style.css=. + +** 2026-06-30 Tue @ 17:36:40 -0400 — Claude Code (archsetup) — responder (4th review) + +- *What changed:* Dispositioned all nine fourth-review findings (8 accept, 1 modify, + 0 reject) and wove them into a new "V2 panel UX — the target design" section. + Accepts: V2's three-tab nav is the sole target (the four-page stack is history); + Connections splits into Saved / Available now / Wired with Rescan touching only the + scan layer; selecting an unsaved row is the join flow (the Add modal is deleted); + a join matrix pins which NM SECURITY classes are inline-supported / activate-only / + hidden / unsupported; loading renders Saved first and overlays the scan; the Forget + copy goes future-tense + verified; every run ends with a Copy/Open redacted report; + and a Waybar visual contract (rounded capsule, golden border, state colors). Modify: + the speed-test finding kept Craig's decision-19 placement (full speed test under + Performance, which carries future history) while accepting a lightweight inline + latency probe as Diagnose evidence stored in the doctor report. Cookie [40/40]. +- *Why:* Codex read the live implementation and caught the UX places where the module + still replicated common network-manager mistakes — mixed lists, scan-gated saved + data, redundant SSID entry, misleading destructive copy, diagnostics scattered + across pages, observability that lived in logs more than the workflow. +- *Artifacts:* Findings 32-40 completed in place with dispositions; the modify reason + on the speed-test finding. New "V2 panel UX" section under Panel. todo.org redesign + task updated to point the V2 build at the dispositioned design. |
