aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/design/2026-07-02-bluetooth-panel-spec.org25
-rw-r--r--scripts/testing/tests/test_desktop.py29
-rw-r--r--todo.org13
3 files changed, 59 insertions, 8 deletions
diff --git a/docs/design/2026-07-02-bluetooth-panel-spec.org b/docs/design/2026-07-02-bluetooth-panel-spec.org
index 89872f5..121197a 100644
--- a/docs/design/2026-07-02-bluetooth-panel-spec.org
+++ b/docs/design/2026-07-02-bluetooth-panel-spec.org
@@ -4,10 +4,16 @@
#+TODO: TODO | DONE
#+TODO: DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED
-* DOING Status
+* IMPLEMENTED Status
:PROPERTIES:
:ID: 1271a845-4463-4831-9902-990eda6b2265
:END:
+- [2026-07-02 Thu] IMPLEMENTED — all five phases shipped the same day
+ (dotfiles eb2230f / 76b2c05 / e372de3 / 2a026b1; archsetup d8d8c53):
+ engine, panel, bar module + blueman retirement, bt-priv + package swap,
+ install wiring proven by VM assertions. 43 dotfiles suites green, both
+ AT-SPI smokes green, panels verified live; the phase 4-5 VM assertions
+ run on the next VM pass.
- [2026-07-02 Thu] DOING — spec-response decomposed the five phases into
build sub-tasks under the todo.org parent (:SPEC_ID: bound); build
started same day per Craig ("4 first, then 1" — bugs then bluetooth).
@@ -23,7 +29,7 @@
| Field | Value |
|--------+---------------------------------------------------------------------------------|
-| Status | doing |
+| Status | implemented |
|--------+---------------------------------------------------------------------------------|
| Owner | Craig Jennings |
|--------+---------------------------------------------------------------------------------|
@@ -363,6 +369,21 @@ Non-blocking; it's the donor default made explicit.
* Review and iteration history
+** 2026-07-02 Thu @ 15:19:58 -0400 — Claude Code (archsetup) — phase 5 builder, spec closed
+- *What changed or was recommended:* Phase 5 shipped and the spec flipped
+ to IMPLEMENTED. No new install code was needed — the waybar module, the
+ =Super+Shift+B= bind, and the shared panel css all ride the dotfiles
+ hyprland tier that a fresh install already clones and stows, and sudoers
+ is covered by the blanket grant. The phase's substance is proof:
+ =test_desktop.py= gained hyprland-gated assertions for the four stowed
+ bt bins, the =custom/bluetooth= waybar entry, the =bt-panel= keybind,
+ and the stowed =panel.css=.
+- *Why:* Final phase of the DOING decomposition; with it the todo parent
+ closed and the lifecycle keyword flipped with a history line.
+- *Artifacts:* archsetup =scripts/testing/tests/test_desktop.py=; todo.org
+ parent DONE + dated phase 5 / test-surface entries; this spec's Status
+ heading.
+
** 2026-07-02 Thu @ 15:16:51 -0400 — Claude Code (archsetup) — phase 4 builder
- *What changed or was recommended:* Phase 4 shipped. Dotfiles =2a026b1=:
the stowed =bt-priv= shim (one verb, verified against the fake-systemctl)
diff --git a/scripts/testing/tests/test_desktop.py b/scripts/testing/tests/test_desktop.py
index c02d2b6..6f79bfd 100644
--- a/scripts/testing/tests/test_desktop.py
+++ b/scripts/testing/tests/test_desktop.py
@@ -109,3 +109,32 @@ def test_autologin_configured(host):
if not conf.exists:
pytest.skip("autologin not configured (AUTOLOGIN=no, may be intentional)")
assert conf.exists
+
+
+BT_PANEL_BINS = ["bt", "bt-panel", "bt-priv", "waybar-bt"]
+
+
+@pytest.mark.attribution("archsetup")
+@pytest.mark.parametrize("name", BT_PANEL_BINS)
+def test_bt_panel_bin_stowed(host, hyprland_installed, home, name):
+ # Executable via either stow shape (per-file symlink or folded dir).
+ if not hyprland_installed:
+ pytest.skip("Hyprland not installed (DESKTOP_ENV != hyprland)")
+ path = "%s/.local/bin/%s" % (home, name)
+ assert host.file(path).exists, "%s missing from ~/.local/bin" % name
+ assert host.run("test -x %s" % path).rc == 0, "%s not executable" % name
+
+
+@pytest.mark.attribution("archsetup")
+def test_bt_panel_wired(host, hyprland_installed, home):
+ # A fresh install lands the panel reachable: bar module, keybind, css.
+ if not hyprland_installed:
+ pytest.skip("Hyprland not installed (DESKTOP_ENV != hyprland)")
+ waybar = host.file("%s/.config/waybar/config" % home)
+ assert "custom/bluetooth" in waybar.content_string, \
+ "waybar config lacks the custom/bluetooth module"
+ hyprconf = host.file("%s/.config/hypr/hyprland.conf" % home)
+ assert "bt-panel" in hyprconf.content_string, \
+ "hyprland.conf lacks the bt-panel keybind"
+ assert host.file("%s/.config/themes/dupre/panel.css" % home).exists, \
+ "shared panel css missing from the stowed theme"
diff --git a/todo.org b/todo.org
index d25aa5c..30f2024 100644
--- a/todo.org
+++ b/todo.org
@@ -537,11 +537,12 @@ Design / open questions (propose before building):
Implementation notes: a small GTK layer-shell app (mirror pocketbook's structure: src-layout Python package, pytest, Makefile) talking to brightnessctl / hyprctl / the touchpad + airplane helpers. Lives in the dotfiles repo or in-tree like pocketbook. TDD the backing toggle/slider logic. Sizable — worth a design doc first.
-** DOING [#B] Bluetooth panel + bar module :feature:waybar:bluetooth:
+** DONE [#B] Bluetooth panel + bar module :feature:waybar:bluetooth:
+CLOSED: [2026-07-02 Thu]
:PROPERTIES:
:SPEC_ID: 1271a845-4463-4831-9902-990eda6b2265
:END:
-Spec: [[file:docs/design/2026-07-02-bluetooth-panel-spec.org]] (DOING — reviewed READY and decomposed 2026-07-02; all four decisions resolved, two non-blocking findings dispositioned in the fused review pass).
+Spec: [[file:docs/design/2026-07-02-bluetooth-panel-spec.org]] (IMPLEMENTED 2026-07-02 — all five phases shipped same day: engine eb2230f, panel 76b2c05, bar module e372de3, bt-priv + blueman retirement 2a026b1/d8d8c53, install wiring proven by VM assertions). Residual: the phase 4-5 VM assertions run on the next VM pass; ratio picks up the package removal + hand-links on its trip list.
A bluetooth panel driving a CLI underneath (bluetoothctl one-shot verbs), consistent in look and feel with the net panel (GTK4 + layer-shell + Blueprint, humble-object presenter, verify-everything). Minimalistic interface, full functionality, plus a diagnostics/troubleshooting section mirroring the net panel's Diagnostics tab. Bar module glyph opens it. Craig's ask (2026-07-02): follow UX/UI best practices; where the net panel's patterns conflict with best practices, file a net-panel bug task rather than clone the flaw.
@@ -557,11 +558,11 @@ Cloned the net panel's shape over the phase 1 engine: GTK-free PanelModel + view
*** 2026-07-02 Thu @ 15:16:51 -0400 Shipped phase 4 — bt-priv shim, blueman out, VM assertions
Dotfiles =2a026b1=: the stowed =bt-priv= shim over the phase-2 =bt.priv= module (one verb, =restart-bluetooth=; verified end-to-end against the symlinked fake-systemctl — rc 0 with =BT_SUDO= empty, rc 2 on bad verb/usage; hand-linked into =~/.local/bin=), and the sxhkd =Super+Shift+B= bind repointed from the retired blueman-manager to =st -e bluetoothctl= (the decided terminal fallback — the GTK panel is Wayland-only, and the bt CLI is hyprland-tier so dwm never gets it). 43 dotfiles suites green. archsetup: blueman dropped from the =desktop_environment= bluetooth loop (bluez + bluez-utils stay, solaar untouched); VM assertions added to =test_packages.py= (bluez/bluez-utils installed, blueman NOT installed as the retirement regression guard — collected 15, exercised on the next VM run since VM tests run committed code); =bash -n= + =py_compile= + =make test-unit= green. SUDOERS: no new rule needed, same conclusion as net-priv (2026-07-01 entry) — archsetup:1089 grants the primary user blanket =NOPASSWD: ALL=, which covers =systemctl restart bluetooth=; a narrow bt-priv rule would be dead config under the blanket grant, so phase 5's "sudoers placed" item is satisfied by the existing grant. LIVE: blueman package removed from velox (=pacman -Rns=, decision "drop it outright, both machines"); ratio needs the same + the bt-priv hand-link on its trip list.
-*** TODO Phase 5 — install defaults (archsetup) :feature:
-Keybind/config defaults so a fresh install lands the panel wired: waybar module present, bind set, sudoers placed.
+*** 2026-07-02 Thu @ 15:19:58 -0400 Shipped phase 5 — install-default wiring proven by VM assertions
+No new install code was needed: the waybar =custom/bluetooth= module, the =Super+Shift+B= → =bt-panel= bind (hyprland.conf), and the shared =themes/dupre/panel.css= all live in the dotfiles hyprland tier, so the existing clone + =make stow hyprland= step lands them on a fresh install; sudoers is covered by the blanket grant (phase 4 conclusion). The phase's substance is the proof: =test_desktop.py= gained hyprland-gated assertions that the four bt bins (=bt=, =bt-panel=, =bt-priv=, =waybar-bt=) are stowed executable in =~/.local/bin= (either stow shape — per-file symlink or folded dir), the waybar config carries =custom/bluetooth=, hyprland.conf carries the =bt-panel= bind, and the stowed theme has =panel.css=. Collected 30 in =test_desktop.py=; exercised on the next VM run (VM tests run committed code).
-*** TODO Test surface :test:
-Engine suites over fake binaries (bluetoothctl show/devices/info/scan parse, doctor chain verdicts, A2DP repair verify), PanelModel presenter suite, pairing state-machine suite (passkey confirm / NoInputNoOutput / timeout), bar-module suite, gated AT-SPI smoke, VM assertions for phases 4-5.
+*** 2026-07-02 Thu @ 15:19:58 -0400 Test surface complete across all phases
+Everything the surface named exists and is green: engine suites over fake binaries (phase 1, 101 tests — btctl parse, doctor chain, A2DP repair verify), PanelModel presenter suite (phase 2, 69 tests), pairing state-machine suite (passkey confirm / NoInputNoOutput / timeout, over the fake's interactive mode), bar-module suite (phase 3), gated AT-SPI smoke (=make test-panel-bt=, run green live), and the phase 4-5 VM assertions (=test_packages.py= bluetooth stack + blueman-absent guard; =test_desktop.py= panel wiring). 43 dotfiles suites green; VM assertions await the next VM run.
** TODO [#B] Local offline LLM runtime + per-host model cache :tooling:llm:
:PROPERTIES: