diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-11 01:20:56 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-11 01:20:56 -0500 |
| commit | b56d14690e69bc304ab4bb4d8ef176b67874edec (patch) | |
| tree | 84de6dc1216c1698c9695003110f59a3a5dd37aa /docs/specs/2026-07-11-bt-doctor-expansion-spec.org | |
| parent | 0f7c166e1383286ee4117d16b5810814266ca02b (diff) | |
| download | archsetup-b56d14690e69bc304ab4bb4d8ef176b67874edec.tar.gz archsetup-b56d14690e69bc304ab4bb4d8ef176b67874edec.zip | |
docs: record spec-review findings on net + bt doctor specs
Reviewed both DRAFT expansion specs against the live engines. Both stay Not ready: three open decisions apiece plus one blocking finding each.
Net: the Security dimension claims connection names are already redacted, but redact.py covers only SSID, MAC, IP, secret-keys, and portal_url, so the new keyfile-perms and rival-manager verdicts would leak a connection name into the wall and --json. Four non-blocking fixes alongside it: nm-restart's scope was overstated, is-enabled isn't used yet, some message text was listed as classifier verdicts, and the priv.py dispatch integration wants naming.
Bt: the doctor has no named-verdict layer to hang the proposed no-adapter-firmware and powered-off-persistent verdicts on. A step carries a pass/fail/warn/info status and the run an ok/warn/fail overall, nothing more. How each new verdict is represented has to be settled before Phase 1. Three non-blocking notes cover the widening sudoers surface, the real diagnostic surface, and the bounded journalctl precedent.
Both designs are sound and target verified-real gaps: neither engine reads the config or logs the specs propose to add.
Diffstat (limited to 'docs/specs/2026-07-11-bt-doctor-expansion-spec.org')
| -rw-r--r-- | docs/specs/2026-07-11-bt-doctor-expansion-spec.org | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/docs/specs/2026-07-11-bt-doctor-expansion-spec.org b/docs/specs/2026-07-11-bt-doctor-expansion-spec.org index 0775a18..bced674 100644 --- a/docs/specs/2026-07-11-bt-doctor-expansion-spec.org +++ b/docs/specs/2026-07-11-bt-doctor-expansion-spec.org @@ -8,6 +8,7 @@ :PROPERTIES: :ID: 3d4d61c4-e5df-44e9-b8e0-40b31452c3f7 :END: +- [2026-07-11 Sat @ 00:59:30 -0500] DRAFT — reviewed (spec-review). Stays DRAFT: three decisions open plus one =:blocking:= finding (the bt doctor has no named-verdict layer, so the proposed =no-adapter-firmware=/=powered-off-persistent= verdicts need their representation defined first). Design confirmed against the live engine — the two target gaps (kernel-log firmware hint, boot-persistence read) genuinely do not exist yet. Findings in =* Review findings=. - [2026-07-11 Sat @ 00:08:41 -0500] DRAFT — drafted. Extends the existing bt doctor (=~/.dotfiles/bluetooth/=, shipped) using the bluetooth half of the failure taxonomy ([[file:../design/2026-07-10-net-bt-failure-taxonomy.org][2026-07-10-net-bt-failure-taxonomy.org]]). Grounded in a read of the live engine, not memory. * Metadata @@ -128,6 +129,20 @@ Decision (proposed): defer to vNext. v1 keeps re-pair strictly user-initiated; t Consequences: no risk of the doctor offering a destructive fix for a transient condition in v1; harder — the "keeps failing to connect" case stays unnamed for now, which is the one cluster-3 gap a user might reasonably expect the doctor to catch. Owner: Craig. By: before Phase 1 (scope confirmation). +* Review findings [/] + +** TODO The bt doctor has no named-verdict layer, so "emit a verdict named X" is undefined :blocking: +The spec proposes named verdicts throughout — =no-adapter-firmware=, and =powered-off-persistent= "distinct from =powered-off=" — mirroring the net doctor's action-identifier vocabulary. But the bt doctor has no such layer. Verified: a step carries a =status= ∈ =pass/fail/warn/info= and the run has an =overall= ∈ =ok/warn/fail= (=doctor.py:182-183=); there are no verdict identifiers like =powered-off= or =power-on= as *names* — those are message text and the =power-on= auto-fix tier, not a verdict enum. So "add a =powered-off-persistent= verdict distinct from =powered-off=" has no existing mechanism to attach to, and the implementer would have to invent the representation: is the distinction a new =status= value, a field on the powered step, a message variant, an added =fix= identifier? Whatever it is, it also touches =format_doctor_human= (=cli.py:94=) and any consumer of =overall=. Define how each new "verdict" is represented in the step-status model before Phase 1 — this is the one place the spec would force the implementer to invent product/data behavior. (blocking) + +** TODO New root repairs expand the NOPASSWD sudoers surface — name it in rollout +=priv.py= today exposes a single privileged verb, =restart-bluetooth= (=priv.py:27-34=), backed by a NOPASSWD sudoers entry. The three new persistent fixes (edit =/etc/bluetooth/main.conf=, =systemctl enable bluetooth=, edit =/etc/tlp.conf=) are each a new root-capable verb and each widens the passwordless-sudo grant from "restart one service" to "edit system config files as root." That is a heavier privilege surface than the existing tier; the Rollout/compatibility dimension should name the sudoers expansion explicitly and confirm each new verb is a tightly-scoped command (not a general "run as root"), so the privilege model's Confirm floor is the *second* guard, not the only one. (non-blocking) + +** TODO The diagnostic surface is =bt doctor='s JSON, not a =bt diag= subcommand +Phase 0 says "=bt diag --json= (or the equivalent) shows the new signals." Verified: there is no =bt diag= subcommand; =diagnose()= is the report authority (=doctor.py:174=), =doctor()= wraps it (=:207=), and JSON is already the default output of the doctor subparser (=cli.py:173= — the =--json= flag is effectively redundant). Point Phase 0 at the real surface: the new signals land in =diagnose()='s report dict and render through =format_doctor_human= (=cli.py:94=). Cosmetic — the author already hedged with "(or the equivalent)." (non-blocking) + +** TODO Firmware-hint probe is new but has a bounded precedent — cite it +Phase 0's =journalctl -k= reader is genuinely new (=_adapter_step= reads nothing beyond =btctl.show=, =doctor.py:46-50=), but the engine already runs a bounded =journalctl -u bluetooth -n 1= for service-log evidence (=doctor.py:84=, timeout 5s via =cmd.run=). Cite it as the precedent so the implementer reuses the same bounded-=cmd.run= shape for the kernel-log read rather than introducing an unbounded call. Confirms feasibility; not a gap. (non-blocking) + * Implementation phases Each phase leaves the tree green and independently useful, as the existing bt phases did. @@ -182,3 +197,8 @@ The bt-audio-profile expansion (vNext) overlaps the audio taxonomy's Bluetooth-m - What: drafted the bt doctor expansion from the bluetooth half of the failure taxonomy. v1 adds the dmesg firmware-hint probe (cluster 1) and the boot-enablement probe (cluster 2); the pairing/connection/audio expansions are staged to vNext. - Why: the taxonomy showed the doctor's chain is structurally right but blind at its ends — a no-adapter verdict that won't name the firmware blob the kernel already logged, and a power-on that doesn't persist across boots. - Artifacts: [[file:../design/2026-07-10-net-bt-failure-taxonomy.org][the net/bt failure taxonomy]]; code read across =~/.dotfiles/bluetooth/src/bt/= (=doctor.py=, =repair.py=, =btctl.py=, =sysio.py=, =audio.py=, =priv.py=). + +** 2026-07-11 Sat @ 00:59:30 -0500 — Claude Code (archsetup) — Reviewer +- What: ran spec-review. Rubric =Not ready=. Recorded four findings, one =:blocking:= (no named-verdict layer to attach the proposed verdicts to) and three non-blocking (sudoers-surface expansion, the real diagnostic surface, the bounded firmware-read precedent). The three proposed decisions remain open. +- Why: the design is sound and the code read confirmed both target gaps are real — the engine reads no kernel log for firmware hints and nothing for boot persistence (=main.conf=/=is-enabled=/=tlp.conf= all grep-clean). What holds the rubric is that the spec borrows the net doctor's verdict-naming language, but the bt doctor is step-status-based (=status= pass/fail/warn/info, =overall= ok/warn/fail, =doctor.py:182-183=) with no verdict enum — so how each new "verdict" is represented is undefined. Once that representation is decided and Craig accepts the three decisions, this reaches =Ready with caveats= (shared privilege-model code being the sequencing caveat, already in Risks). +- Artifacts: engine facts verified across =doctor.py= (:25 AUTO_FIX, :46-50 no-adapter branch, :84 bounded journalctl precedent, :100-107 powered step, :174-183 diagnose/overall), =priv.py:27-34= (single =restart-bluetooth= verb), =cli.py:94/173= (formatter + json default), =redact.py:11-20=. Findings in =* Review findings=. |
