diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-10 07:12:16 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-10 07:12:16 -0500 |
| commit | 3e3e9885b87cdccb8c831a8cacf8d2a97a12d62c (patch) | |
| tree | 057c849163d545c76f2a25e9cacd4b8251d3a143 | |
| parent | 186b27d3ab10ffa40fff8103f35bf1226e05ab3a (diff) | |
| download | archsetup-3e3e9885b87cdccb8c831a8cacf8d2a97a12d62c.tar.gz archsetup-3e3e9885b87cdccb8c831a8cacf8d2a97a12d62c.zip | |
docs: close the audio-doctor spec and its task
The doctor shipped end to end, so the spec goes to IMPLEMENTED and the task closes with a dated record of what landed.
Three things the Decisions did not anticipate are written into the history rather than left for a reader to infer. A tenth verdict for missing tooling, because an absent pactl is an unobserved stack and not a broken one. A re-probed marker between a fix run's two row blocks. And DIAGNOSE as the read-only key's name, which Craig settled after asking why this panel carries two keys where the net panel carries one.
I filed the wall-controls convergence as its own task. Craig wants the net panel's copy and close pair on every output wall, and today no two of the four agree.
| -rw-r--r-- | docs/specs/2026-07-09-audio-doctor-spec.org | 24 | ||||
| -rw-r--r-- | todo.org | 22 |
2 files changed, 36 insertions, 10 deletions
diff --git a/docs/specs/2026-07-09-audio-doctor-spec.org b/docs/specs/2026-07-09-audio-doctor-spec.org index 028fe8c..7860dac 100644 --- a/docs/specs/2026-07-09-audio-doctor-spec.org +++ b/docs/specs/2026-07-09-audio-doctor-spec.org @@ -4,16 +4,20 @@ #+TODO: TODO | DONE #+TODO: DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED -* READY Audio Doctor — diagnose and repair a broken sound stack +* IMPLEMENTED Audio Doctor — diagnose and repair a broken sound stack :PROPERTIES: :ID: 6ce3f2ef-052e-40cb-9067-42f8e665f813 :END: +- [2026-07-10 Fri] IMPLEMENTED — Phases 0 through 4 shipped (dotfiles =4d42eb3=, =01a1d80=, =76857e3=, =7223c51=, =1550ac8=, =4320255=, =bd33440=). Xruns stayed out of v1 as decided. Per-application stream routing remains a Non-Goal. The wall carries the net panel's copy + close controls, added past the spec at Craig's request; standardizing them across the other panels is tracked as its own task. - [2026-07-09 Thu] READY — all eight Decisions closed. Written from the roam-inbox ask "look into a doctor button for the audio panel: what happens if pulseaudio or its equivalent is borked? would we know? how could we test for it? what remedies would we have?" Probe set, classifier, and remedy tiers are grounded in a live survey of ratio's stack. Phase 0 shipped ahead of the rest. -* READY Status +* IMPLEMENTED Status :PROPERTIES: :ID: 1cc2b355-9450-4ace-bdb3-b935f7051918 :END: +- [2026-07-10 Fri] IMPLEMENTED — the build closed three things the Decisions did not anticipate. A tenth verdict =tooling-missing= (=remedy: None=), because an absent =pactl= is an unobserved stack rather than a broken one. A =re-probed= marker between a fix run's two row blocks, because unlabelled they read as the doctor contradicting itself. And the read-only key is named DIAGNOSE beside the engraved DOCTOR header rather than being named DOCTOR itself (Craig's call, 2026-07-10, after asking why the panel carries two keys where net's carries one; the two presses stand on the audibility decision, and net's single key auto-fixes because its remedies are cheap). + + Live verification on ratio replaced the planned VM run for remedies 1, 4 and 5, and immediately found two bugs no fake could surface: =pactl get-default-sink= prints the literal =@DEFAULT_SINK@= placeholder when no default is set, and remedy 1 re-probed before WirePlumber had re-created the devices, reporting a repaired stack as broken. Both fixed. - [2026-07-09 Thu] READY — Craig closed the six open Decisions, all to the recommended option: DOCTOR is a section-header key; CLI-first with the GUI as a face; hung and dead are two verdicts sharing one remedy; tiers stay Auto/Confirm/Arm as drafted; a stream-active guard refuses the audible remedies and is overridable by pressing again; xruns are out of v1. Two consequences worth naming, because they were not obvious when the questions were asked. Taking the guard is *why* remedy 4 can stay at Confirm — the danger lives in the state of the machine, not the identity of the remedy. And the guard must read its stream state from =pw-dump= rather than =pactl=, because the remedies it protects are exactly the ones you reach for when the Pulse layer is dead; a =pactl=-fed guard would go blind precisely when it is needed. @@ -24,7 +28,7 @@ | Field | Value | |--------+-------------------------------------------------------------------------------------------------------------| -| Status | ready | +| Status | implemented | |--------+-------------------------------------------------------------------------------------------------------------| | Owner | Craig Jennings | |--------+-------------------------------------------------------------------------------------------------------------| @@ -268,17 +272,19 @@ Sequenced so each phase is independently green and independently useful. Nothing CLOSED: [2026-07-09 Thu] Shipped ahead of the rest (dotfiles =4d42eb3=). =build_status()= now guards all four pactl reads, not just the two list reads, so a half-wedged server dims the bar's audio module instead of killing it. =fake-pactl= grew =FAKE_PACTL_SLEEP_DEFAULTS= to express "answers the lists, hangs on the defaults" — the blanket sleep knob cannot, because the first call would hang and mask the bug. -** Phase 1 — =diag.py=, the four probe tiers +** DONE Phase 1 — =diag.py=, the four probe tiers Bounded probes, a context dict, fakes for every outcome including hung. No classifier, no GUI. =audio diag --json= prints the context. -** Phase 2 — =classify.py=, the verdict +** DONE Phase 2 — =classify.py=, the verdict Pure function, fixture-driven, pairwise over the parameter space. =audio doctor= (read-only) prints findings and a verdict in the CLI. Already useful from a TTY at this point. -** Phase 3 — =repair.py= + =doctor.py=, the fix path +** DONE Phase 3 — =repair.py= + =doctor.py=, the fix path One function per remedy, each re-probing what it claims to fix. =audio doctor --fix= applies the lightest matching remedy. VM-tested for remedies 1, 4, and 5. -** Phase 4 — the DOCTOR key and the results wall -GUI face over the CLI. Streams events to a wall, off the GTK thread. AT-SPI smoke over the key, the wall, and the fix path on fixtures. +** DONE Phase 4 — the DOCTOR key and the results wall +CLOSED: [2026-07-10 Fri] +Shipped (dotfiles =4320255=). GUI face over the CLI. Streams events to a wall, off the GTK thread. AT-SPI smoke over the key, the wall, and the fix path on fixtures. -** Phase 5 — flip this spec to IMPLEMENTED +** DONE Phase 5 — flip this spec to IMPLEMENTED +CLOSED: [2026-07-10 Fri] With a history line naming what shipped and what was left out. @@ -62,6 +62,18 @@ Scope note (Craig, 2026-07-07): realtime lamp *behavior* only. The maintenance c Addendum (Craig, 2026-07-07): DO backport the 3.5-entry height convention — every panel's output well caps at 3.5 visible entries, the half-visible entry being the scroll cue, with the dark slate-on-black scrollbar. Layout stays compact per above; only the height cap + scroll affordance carries over. +** TODO [#B] One copy + close control pair on every output wall :feature:dotfiles:solo: +Converge all four instrument-console output walls on the net panel's well controls: a copy glyph and a ✕ close, as an overlay at the top right, hidden until content lands. Craig's call, 2026-07-10, while reviewing the audio doctor's wall: "network panels as standard across all others, make it consistent." + +Where they stand today, no two alike. net has copy + ✕ (=net/src/net/gui.py=, the =o-copy= / =o-clear= overlay). bluetooth has ✕ but no copy. maint has COPY + HIDE as keys in a header row, and no ✕. audio just gained copy + ✕ (dotfiles =bd33440=). + +Work: give bluetooth a copy key, give maint the overlay pair, and lift the four hand-rolled =_copy_output= implementations into one shared helper rather than a fifth copy. maint keeps HIDE alongside close, because its wall is a persistent session action log you collapse and keep, where net's, bt's, and audio's are per-run results you dismiss. + +Copy text is per panel but one rule: it pastes as that panel's CLI prints, so the paste lines up with the terminal a user is already looking at. audio's =viewmodel.wall_copy_text()= is the worked example. + +Consistent with the 2026-07-07 scope note on the sibling task above: net's compact glyph overlay is what standardizes, not maint's wide COPY-key header row. + + ** TODO [#B] Scrolling/Carousel layout: frame fit + wrap-around :hyprland: :PROPERTIES: :LAST_REVIEWED: 2026-07-06 @@ -1125,7 +1137,8 @@ Rewrote the bare =if $var= boolean conditionals (=show_status_only=, =fresh_inst *** 2026-05-26 Tue @ 15:27:09 -0500 eval task moot — the line-434 eval is gone, the survivor is deliberate Verified: the only =eval= left in =archsetup= is line 578 in =retry_install=, and it's intentional and documented — it captures =$?= directly from =eval "$cmd"= to dodge the if-compound-swallows-exit-code trap. Replacing it with an array would reintroduce that bug. The line-434 eval this task pointed at no longer exists. Nothing to change. -** TODO [#B] Doctor button for the audio panel :feature:audio: +** DONE [#B] Doctor button for the audio panel :feature:audio: +CLOSED: [2026-07-10 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-09 :END: @@ -1140,6 +1153,13 @@ The real bug, found by driving it: =build_status()= guarded its two device-list A server that hangs on the *first* call never exposes this — =list_sinks= raises inside the guard and masks the unguarded reads behind it — so the obvious regression test passes against broken code. =fake-pactl= grew =FAKE_PACTL_SLEEP_DEFAULTS= to express "answers the lists, hangs on the defaults". Verified end to end: =waybar-audio= now emits =class: degraded= / "Audio graph unavailable" and exits 0. dotfiles =4d42eb3=; full =make test= green. +*** 2026-07-10 Fri @ 06:41:00 -0500 Shipped: the audio doctor, phases 1 through 4 +=audio diag=, =audio doctor=, =audio doctor --fix=, and the panel's DOCTOR section header with DIAGNOSE / FIX keys streaming into a results wall (copy + close). Spec is IMPLEMENTED. dotfiles =01a1d80=, =76857e3=, =7223c51=, =1550ac8=, =4320255=, =bd33440=. + +Live verification on ratio replaced the planned VM run for remedies 1, 4 and 5, and found two bugs no fake could surface: =pactl get-default-sink= prints the literal =@DEFAULT_SINK@= placeholder when no default is set, and remedy 1 re-probed before WirePlumber had re-created the devices, calling a repaired stack broken. Both fixed. + +Left open, not a v1 gap: mpv played silently while the doctor read healthy. The stack was genuinely fine, and per-application stream routing is an explicit spec Non-Goal. Worth a task only if it recurs. + ** TODO [#D] Telega coredump recurrence tell :bug:maint: :PROPERTIES: :LAST_REVIEWED: 2026-07-09 |
