<feed xmlns='http://www.w3.org/2005/Atom'>
<title>archsetup/docs/specs/2026-07-10-audio-doctor-input-side-spec.org, branch claude/hungry-franklin-09fffc</title>
<subtitle>Builds a full dev workstation from a bare Arch Linux install.
</subtitle>
<id>https://git.cjennings.net/archsetup/atom?h=claude%2Fhungry-franklin-09fffc</id>
<link rel='self' href='https://git.cjennings.net/archsetup/atom?h=claude%2Fhungry-franklin-09fffc'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/'/>
<updated>2026-07-11T04:43:23+00:00</updated>
<entry>
<title>docs: fold the failure taxonomy into the input-side spec</title>
<updated>2026-07-11T04:43:23+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-11T04:43:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=7ac0c363c830840090ad81b5e9f07f350c6f6e57'/>
<id>urn:sha1:7ac0c363c830840090ad81b5e9f07f350c6f6e57</id>
<content type='text'>
I grounded the spec in the taxonomy and its triage. A new "Verdict clusters and remedy classes" section maps the doctor's verdicts onto the nine saturation-tested symptom clusters, ties the four remedy classes to the run-time privilege decision, and names the three new probes the taxonomy implies: dmesg hints, the unmute-doesn't-stick signature, and re-probe-after-idle.

v1 stays the buildable core, phases 0 through 4. The rest of the taxonomy is staged as later phases so v1 isn't blocked on it.
</content>
</entry>
<entry>
<title>docs: add the run-time privilege model as a doctor decision</title>
<updated>2026-07-11T04:07:14+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-11T04:07:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=4ca80d788246aeab024bb2f5d18a1819ddfb1d15'/>
<id>urn:sha1:4ca80d788246aeab024bb2f5d18a1819ddfb1d15</id>
<content type='text'>
The input and output doctor reaches firmware, ALSA saved state, modprobe, and packages, which need root. The parent spec decided "no sudo anywhere," correct when the feature was user-scope PipeWire. This supersedes that.

The doctor resolves its privilege at run time from three signals: passwordless sudo (sudo -n true, which never hangs), a tty to prompt at, and whether it is the GUI panel. Four remedy classes follow. Auto is user-scope and runs anywhere. Privileged needs sudo, so it runs where passwordless sudo exists, prompts on a CLI, and degrades to Guide otherwise. Reboot-tail runs the applicable part, then instructs the reboot. Guide is physical, BIOS, or wait-for-upstream. Passwordless sudo is not consequence-free, so every Privileged and Reboot-tail remedy defaults to Confirm or Arm, never silent Auto.

This was Craig's call, and he wants it as a cross-panel standard. I filed a task to factor the privilege resolution into a shared helper the net, bluetooth, maint, and audio doctors all use.
</content>
</entry>
<entry>
<title>docs: record the second review pass on the input-side spec</title>
<updated>2026-07-11T01:17:13+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-11T01:17:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=ba2d18b26d751cad42c59ab8e0f2eb2d4b95a858'/>
<id>urn:sha1:ba2d18b26d751cad42c59ab8e0f2eb2d4b95a858</id>
<content type='text'>
I ran a second pass across four critical lenses: buildability, technical correctness, adversarial failure-modes, and internal consistency. The technical foundations held. I verified every load-bearing code and /proc/asound claim against the real tree.

I recorded eight findings, two of them blocking. The mic-unmute remedy fails open on an unreadable graph, and a privacy event must fail closed. A Bluetooth or USB-non-ALSA mic classifies as no-mic-hardware because it never appears under /proc/asound. I also fixed three mechanical inconsistencies in place: a remedy miscount, and two stray OUTPUT/INPUT doctor-key labels the SPEAKERS/MICROPHONE rename missed.

The spec stays DRAFT. The blocking findings gate it from READY.
</content>
</entry>
<entry>
<title>docs: fold Craig's spec notes and a review finding into the input-side spec</title>
<updated>2026-07-10T22:54:51+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-10T22:54:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=c101b80fc2a07d0fa718fe48a2d9b12bece5b756'/>
<id>urn:sha1:c101b80fc2a07d0fa718fe48a2d9b12bece5b756</id>
<content type='text'>
Craig left four notes on the draft. This closes all of them.

He ratified two open decisions: don't rebuild push-to-talk, since the source-mute is the safety property, and read /proc/asound directly for the kernel tier. Both close DONE.

He flagged a naming collision. The doctor keys can't be OUTPUT/INPUT, because the CONTROLS section already carries INPUT/OUTPUT mute toggles. They become SPEAKERS and MICROPHONE, with a distinct diagnostic style held consistent across every panel. I recorded it as a new decision and left the visual treatment open for his eye.

He asked for a failure-modes map, so the spec gains a table of every fault by probe tier with its verdict and remedy, output and input together.

A spec-review had also left two blocking findings. The kernel-to-graph one was real: ALSA card ids and PipeWire node names are different namespaces, so "compare the sets" was undefined. I took the reviewer's coarse rule as the v1 definition. mic-unrecognized fires when the kernel capture set is non-empty and the graph has zero non-monitor hardware sources. Per-device correlation is logged as vNext. That finding closes. The open-decisions one stays until the last three land.
</content>
</entry>
<entry>
<title>docs: close the audio-doctor CLI decision, symmetric direction flags</title>
<updated>2026-07-10T15:50:51+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-10T15:50:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=b9fa29b03b0bc6bfcdf853fbd752212460a0698a'/>
<id>urn:sha1:b9fa29b03b0bc6bfcdf853fbd752212460a0698a</id>
<content type='text'>
audio doctor takes only --fix and --force today, so a lone --input would read as a special case on a bare command. Craig's call: add both --output and --input as explicit flags and alias bare audio doctor to --output. The directions are named symmetrically, --input has a sibling, and nothing that scripts the bare command breaks.
</content>
</entry>
<entry>
<title>docs: spec the audio doctor's input side, one doctor per direction</title>
<updated>2026-07-10T15:42:58+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-10T15:42:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=ab22b2c935c3679296d86f740fdb09cf9e367670'/>
<id>urn:sha1:ab22b2c935c3679296d86f740fdb09cf9e367670</id>
<content type='text'>
The doctor never examines the microphone. diag collects default_source and default_source_present, the classifier reads neither, so a muted mic, a stale default source, and a mic the sound server can't see all classify as healthy. Chrome losing the mic this morning surfaced it: the stack was genuinely fine and the doctor had nothing useful to say.

The design grew past the gap in one conversation. An empty source list is normal on a mic-less desktop and a failure on a machine that should have one, and no probe can tell those apart. The missing fact comes from the user's finger: a doctor key on each of the OUTPUTS and INPUTS section headers, where pressing the input one asserts a mic should exist. That retires the DOCTOR header key I shipped hours earlier, and it dissolves the precedence question a single classifier would have faced.

A new probe tier sits below PipeWire. /proc/asound lists capture-capable cards, needs no package, spawns no process, and can't hang, so it separates "the software lost a microphone the kernel sees" from "nothing is plugged in".

Push-to-talk stays as it is. It mutes the source, the one state where the server guarantees nothing is captured. A link-based push-to-talk fails open, and a crash mid-hold is a hot mic reading as muted. The doctor reads ptt.read_state() instead of guessing.

Four decisions are open. Three are closed.
</content>
</entry>
</feed>
