diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-25 15:01:04 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-25 15:01:04 -0500 |
| commit | 41e1507358726bcb4cee7dc2ea13b549836d78e8 (patch) | |
| tree | 24f3cdbfb7f0edba7d1b66224344f80403a8c270 /todo.org | |
| parent | 2c416f5361ed10cd73eb72eb5062261b2e73c18f (diff) | |
| download | archsetup-41e1507358726bcb4cee7dc2ea13b549836d78e8.tar.gz archsetup-41e1507358726bcb4cee7dc2ea13b549836d78e8.zip | |
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 93 |
1 files changed, 58 insertions, 35 deletions
@@ -45,6 +45,17 @@ below): input-side-spec.org (DRAFT, four decisions open). * Archsetup Open Work +** TODO [#C] Post-upgrade hooks: compositor restart reminder + font cache rebuild :feature:infra:ratio:solo: +:PROPERTIES: +:CREATED: [2026-07-25 Sat] +:LAST_REVIEWED: 2026-07-25 +:END: +Handoff from home (2026-07-25), originally combining the 2026-06-07 stale-compositor incident and 2026-06-08 fontconfig crash diagnosis. Add two reproducible pacman =PostTransaction= hooks through archsetup; do not make one-off =/etc= edits: + +1. On =Upgrade= of =hyprland=, =aquamarine=, or =mesa=, print a non-blocking reminder to log out and back in. Never restart the running compositor from the hook. This prevents a session from quietly continuing on a deleted Hyprland binary against newly installed libraries (ratio did so for 2.5 days before SIGABRT on 2026-06-04). +2. On =Upgrade= of =fontconfig=, =freetype2=, or =harfbuzz=, run =/usr/bin/fc-cache -f= after the transaction. The fontconfig 2.17→2.18 cache-format change left stale cache-9 files that crashed Qt6 apps in =FcCharSetHasChar= until the system font cache was rebuilt. + +Acceptance: hook files are source-controlled and installed by archsetup; package/operation/action fields are asserted from the generated hook text; the reminder is print-only and exits successfully; the font hook runs only after successful matching upgrades and invokes the absolute =fc-cache= path. Validate with the fast installer tests plus a disposable pacman-hook parser/install check when practical. ** TODO [#D] net-scenarios harness times out under back-to-back suite runs :test:tooling: :PROPERTIES: :LAST_REVIEWED: 2026-07-24 @@ -88,32 +99,12 @@ The unintuitive part, worth stating plainly because both sessions built habits o Craig's call: whether this becomes a durable rule in the shared rules layer (it's cross-project — any repo two sessions touch), which shape, and which session implements it. Both sessions have offered to own it. -** TODO [#B] Weather tooltip caching :feature:waybar:weather:solo: -From the roam inbox (Craig, claimed 2026-07-22): retrieve the weather tooltip data once per hour and cache it. If the network is unavailable, display the cached tooltip with explanatory text saying so. Dotfiles-side work (archsetup owns the lifecycle); touches common/.local/bin/weather. -** TODO [#B] Settings gear becomes four device toggles :feature:waybar:dotfiles:solo: -From the roam inbox (Craig, claimed 2026-07-23): the waybar gear should become four icons — touchpad, mouse, webcam, and a notification bubble. Clicking each toggles that setting directly. The first three turn red when disabled; the bubble turns red when DND is enabled. - -Today =custom/settings= (=hyprland/.config/waybar/config=) is one gear glyph () whose only job is =on-click: settings-panel=. The toggles themselves already exist and are tested — the settings package owns touchpad, mouse, and webcam (=webcam.py= is the USB-authorized kill switch from 2026-07-22), so this is a bar-side surface over existing backends rather than new capability. - -Note the state-polarity split when wiring the colors: three read "red = off" and DND reads "red = on". That asymmetry is deliberate (red means "something is disabled that normally isn't, or suppressed that normally isn't"), so encode it per-icon rather than deriving one rule. - -Decided 2026-07-23 (Craig): the gear STAYS alongside the four toggles as the panel launcher. So the bar's right side grows from 12 modules to 16 — the four toggles are net-new, the gear keeps its =on-click: settings-panel=. Open sub-question for build time, not blocking: whether the four toggles are four separate waybar modules or one custom module rendering four glyphs (fewer layout entries, one exec). Pick at build; the four-module shape is simplest and matches how mic/net already sit as individual modules. - ** TODO [#B] World face: orientation + hour-format pickers in the settings panel :feature:dotfiles: The world face (=settings/faces/world.html=, shipped 6afbe09) already supports both orientations and 12/24-hour via =?layout= and =?hour12= query params, defaulting vertical/12h. What's missing is letting Craig CHOOSE them from the desktop-settings panel. Build: (1) two new fields in the wallpaper state (world_layout, world_hour12) with the vertical/12h defaults; (2) =project.py build_uri("world")= appends =&layout=&hour12== read from state; (3) panel controls in the world channel's config section (=gui.py _conf_projected=, currently just a preview) — an orientation toggle and a 12/24 toggle; (4) TDD the URI-building and state round-trip. Solo — buildable, agent-verifiable (URI + state tests, headless render), no open design question (the two faces already exist and are approved). Requested by Craig 2026-07-23; deferred so the vertical face could ship first. ** TODO [#C] Wallpaper channel: timed transitions as an alternative to sunrise/sunset :feature:dotfiles: From the roam inbox (Craig, claimed 2026-07-23): the wallpaper channel switches on sunrise/sunset today (the sun-pair mode, =settings/src/settings/wallpaper.py=, location read live via whereami with a state.json cache). Add a timed-schedule mode as an alternative: fixed clock times drive the transitions rather than the solar calc. Not :solo: — the capture itself flags the missing inputs ("we'll need to know the transition times, and how many of them there are"). The count and the times are a design decision Craig owes: is it a two-image day/night flip at fixed hours, an N-way ring across the day, per-image dwell vs shared interval? The =set= channel already does fixed-interval cycling through a set, so the new part is specifically clock-anchored transition points, not just "a timer". Ask for the schedule shape at pickup, then build against the existing wallpaper.apply presenter vocabulary. -** TODO [#C] Wallpaper panel selection and scroll state :feature:dotfiles:solo: -:PROPERTIES: -:LAST_REVIEWED: 2026-07-25 -:END: -From the roam inbox (Craig, 2026-07-25). Screenshot: =~/pictures/screenshots/2026-07-25_013041.png=. Three related behaviors in the settings wallpaper panel (=settings/src/settings/wallpaper.py=): -1. Open at the wallpaper currently displayed, not the top of the list. -2. Highlight that wallpaper as selected in the scrollable pane while it shows in the preview. -3. Keep the scroll position when a picture is selected. Today selecting a picture snaps the scroll back to the top, which is the bug half of this. -Grade: minor scroll-reset defect x every panel selection = P3 = [#C]; the open-at-current and select-current behaviors are enhancements at the same level. One type tag, so filed =:feature:= with the scroll-reset called out as the bug. Solo: buildable in the settings GTK panel, agent-verifiable via headless capture plus the wallpaper.py tests, no design call — swww query gives the current wallpaper, and scroll-position preservation and row selection are standard GTK. ** TODO [#D] Worldclock tooltip blanks on one bad timezone row :bug:dotfiles:waybar:quick:solo: :PROPERTIES: :LAST_REVIEWED: 2026-07-25 @@ -136,12 +127,8 @@ From the roam inbox (Craig, 2026-07-25). The maintenance queue button shows the From the roam inbox (Craig, claimed 2026-07-24): the network, bt, maint, and audio waybar panels look alike, but the desktop-settings panel looks quite different. He wants them to read as one family. Deliverable: enumerate every difference (chrome, header layout, typography, spacing, control styling, color roles, close-button placement, section dividers) between the two groups and a plan to converge them on one look. Not :solo: — it needs a design pass and Craig's taste calls on which direction each group moves. When picked up, catalogue the deltas from live captures of all five, propose the shared design language (likely the Dupre instrument-console the settings panel uses, since that's the newest and most deliberate), then bring Craig the change list before touching code. ** TODO [#C] Panel text cut off — needs a few px more space :bug:dotfiles:solo: From the roam inbox (Craig, claimed 2026-07-24): panel labels look cut off; a few more pixels of space fixes it. He named the audio and bt panels, but his "before" capture is the networking panel (=~/pictures/screenshots/2026-07-23_202419.png=; "after" resizing =~/pictures/screenshots/2026-07-23_202458.png=), so the whole panel family likely shares the tight spacing. Confirm which panels clip at pickup, then add the padding/width. Grade: cosmetic × every glance at the affected panels = P3 = [#C]. Solo — buildable (CSS/size tweak) and screenshot-verifiable, no design call once the clipping panels are identified. -** TODO [#C] Net tooltip IPs and line order :feature:waybar:network:solo: -From the roam inbox (Craig, claimed 2026-07-23): in the wifi hover, add the internal IP, external IP, and gateway IP just below the Interface line; move the Signal line to just above the keyboard-shortcuts line. Design constraint: the bar's hot path does no network I/O (status.py deliberately skips _address_facts on the 2s beat) — internal IP + gateway can ride cheap local reads, but the external IP must come from a cache the connectivity probe refreshes, never a live lookup in waybar-net. ** TODO [#C] Night-watch live telemetry :feature:maint: Craig, 2026-07-21 ("mind. blown."): drive the Dupre Night Watch screensaver (docs/prototypes/2026-07-21-night-watch-screensaver-prototype-1.html, the idle-pipeline eye-candy stage in the desktop-settings spec) with real system data instead of synthetic signals — a passive status wall while the machine idles. Candidate mappings: scope = CPU load trace, drift chart = memory pressure history, spectrum = per-core utilization, VU pair = net throughput up/down, blinkenlights = disk I/O, tape counter = uptime, systems lamps / annunciator = maint status verdicts, engine-order telegraph = current power profile, VFD wire = maint status one-liner (temps, battery, pending updates). Browser prototype can poll a small local JSON endpoint; the production shape belongs to the idle-stage build. Depends on the spec's idle-pipeline implementation landing first. -** TODO [#B] Dupre Kit merge — casting additions :feature:tooling:solo: -Fold docs/prototypes/dupre-kit-additions.js back into the kit proper: detentFader (NEW — multi-detent slide attenuator with speedbump drag physics: magnet + escape hysteresis, parked tick glow) and the drumRoller redefinition (UPGRADE — 1..N channels and min/max range; stock hardcodes two drums and throws on one, defaults reproduce stock exactly) and the guardedToggle redefinition (UPGRADE — lever throws with rotateX so it flips toward the viewer instead of the stock 180° planar spin that sweeps sideways mid-transition; contract unchanged). Merge means: builders into widgets.js, the additions CSS into DUPRE_CSS, additions-scoped gradients into the shared defs plate, gallery cards for both in panel-widget-gallery.html, and POLICY entries. Origin: the desktop-settings casting sitting 2026-07-21 — Craig's direction is that components get finished by being needed ("the ones needed most will have had the most attention"), so more additions may accrue here before the merge; batch them. ** TODO [#C] Wlogout screen review :bug:hyprland:dotfiles: Craig, 2026-07-21: the wlogout window (Super+Shift+Q — lock/reboot/shutdown/logout/suspend/hibernate) "isn't great and has bugs." Review it end to end: catalogue the specific bugs, then assess the design against the Dupre instrument-console family (it predates the panel aesthetic). Config lives in dotfiles; the bind is hyprland.conf:428 (=pgrep -x wlogout || wlogout-menu=). Context: the desktop-settings panel spec withdrew lock/suspend in favor of this screen (2026-07-21 amendment), so it's now the sole owner of session-exit actions — worth being good. Grade each bug found via the severity×frequency matrix; this parent stays a [#C] review until specifics emerge. ** TODO [#B] Audit cgit-published repos for secrets and privacy :bug:security: @@ -1667,14 +1654,6 @@ while ordinary WiFi stays white. Extend auto-dim with an explicit “dim everything” setting for bright non-dark-mode contexts, with a security/usability review of its scope. -** TODO [#C] Maint live-refresh hairline replacement :feature:maint:solo: -:PROPERTIES: -:LAST_REVIEWED: 2026-07-14 -:END: -From the roam inbox (routed 2026-07-13): the memory-killer section seemed to update too often, and "it's a bit unclear what the line is doing; consider something else." Diagnosis (2026-07-14): the data cadence is already the requested 3s (gui live tier, _LIVE_SECONDS); the perceived churn is the live-refresh hairline — the 2px bar under the live sections that drains full-to-empty over each 3s window, redrawn at 150ms (gui._hair_tick, viewmodel.refresh_fraction). It exists to tell a stale board from a frozen one (2026-07-09), but it reads as constant unexplained motion. Design call for Craig: replace the draining line with something whose meaning is legible — candidates: a dot that blinks once per refresh, a "3s" age caption that only appears when refresh is overdue, slowing the drain redraw, or dropping the indicator on live tiers and keeping it only when data goes stale. Keep the stale-vs-frozen distinguishability that motivated the hairline. -*** 2026-07-21 Tue @ 08:35:00 -0500 Decided (Craig): silent-until-stale age caption -Replace the draining 2px hairline with an age caption that shows ONLY when refresh is overdue (e.g. "3s", "8s" once past the expected window) and shows nothing while the board is healthy. This keeps the stale-vs-frozen signal — a frozen board surfaces a growing age number, a live one stays clean — while removing the constant motion the hairline created. Implementation (dotfiles, archsetup-owned): drop =gui._hair_tick= / the hairline draw, add an overdue-age caption driven off =viewmodel.refresh_fraction= (or the last-refresh timestamp) rendered only past the live window. Now unblocked; needs a live visual check on the panel after. - ** TODO [#C] Net panel speedtest history :feature:dotfiles:network: :PROPERTIES: :LAST_REVIEWED: 2026-07-14 @@ -1791,9 +1770,6 @@ Grading: no behavior change; parking lot. 10 refactors remain from the sentry au In 67d0b6e: the four yes/no config-validation blocks collapse into validate_yesno (TDD), and the driver-floor literal 535 becomes NVIDIA_MIN_DRIVER. The safe, purely-testable slice; the remaining 10 (structural / system-mutation) stay parked above. *** 2026-07-21 Tue @ 08:00:00 -0500 Audit reconcile: the GRUB cmdline sed slice shipped f9da097 (2026-07-21) rewrote the boot-critical =GRUB_CMDLINE_LINUX_DEFAULT= sed into a guarded awk+mv merge with a backup and added characterization tests (tests/installer-steps/test_grub_cmdline.py). So the "GRUB sed clusters want characterization coverage before rewrite" caveat no longer covers the cmdline line — only the 4 cosmetic GRUB sed lines (timeout/default/terminal/gfxmode, which overwrite fixed values with nothing to preserve) remain in that slice. -** TODO [#D] Test-framework + prototype refactor cluster :refactor:solo: -Grading: no behavior change; parking lot. Refactors from the S5-S7 audit, distinct from the installer refactor rollup above. -scripts/testing/run-test.sh + run-test-baremetal.sh duplicate the run/poll/report skeleton and have drifted (VM uses setsid + copy helpers, baremetal uses nohup + hand-rolled sshpass scp) — extract the shared core so baremetal inherits the sturdier paths; run-maint-nspawn.sh:66 + run-maint-scenarios.sh:78 duplicate the transport-independent _scenario_var/_validate_scenario/run_scenario (a sourced lib/maint-scenario.sh); run-test.sh:251,265 uses two different mechanisms (pgrep vs ps|grep) for the same liveness check; docs/prototypes/gen_tokens.py:78 repeats the section-iteration skeleton across four emitters; gallery-widget.el:95,136 hardcodes SVG arc/hub path strings that duplicate the cx/cy/radius geometry (dial desyncs silently on a constant change); gallery-widget.el:72,84 leans on the private svg--append. See findings doc (S5, S6, S7). ** TODO [#D] Net doctor vNext :feature:dotfiles:network: Deferred from the [[file:docs/specs/2026-07-11-net-doctor-expansion-spec.org][net doctor expansion spec]] (IMPLEMENTED, v1 shipped): event-log correlation for the flaky/drops cluster (powersave, roaming stalls, USB autosuspend, no-reconnect-after-resume, firmware crashloop drop signatures — needs history a one-shot probe can't see); a DoT/DNSSEC-specific verdict distinguishing "the venue resolver mangles DNSSEC" from the generic DNS-not-resolving; per-profile autoconnect/duplicate-profile hygiene. @@ -2905,3 +2881,50 @@ Remaining work (re-graded C 2026-07-02 — the first-launch risk and the Makefil - Waypaper canonical decision (Craig): RESOLVED 2026-07-14 — dark-lion.jpg is canonical (dotfiles fea3e93), repo config.ini updated off the that-one-up-there.jpg placeholder. - Ratio check: RESOLVED 2026-07-14 — ratio's =~/.config/calibre= is a directory symlink into the repo (stow folded the dir), so the first-launch gap never existed there. - When velox is back online: run =make conflicts= / =make reset= there so its old conflict copy clears against the updated repo. (velox carries a separate boot-recovery task; check once it's reachable.) +** DONE [#B] Weather tooltip caching :feature:waybar:weather:solo: +CLOSED: [2026-07-25 Sat 10:53] +From the roam inbox (Craig, claimed 2026-07-22): retrieve the weather tooltip data once per hour and cache it. If the network is unavailable, display the cached tooltip with explanatory text saying so. Dotfiles-side work (archsetup owns the lifecycle); touches common/.local/bin/weather. +Verified complete in the 2026-07-25 batch: the weather CLI already had the hourly default TTL, fresh-cache no-fetch path, stale fallback, and explicit offline footer. Its 33-test suite and the full dotfiles suite pass. +** DONE [#B] Settings gear becomes four device toggles :feature:waybar:dotfiles:solo: +CLOSED: [2026-07-25 Sat 10:53] +From the roam inbox (Craig, claimed 2026-07-23): the waybar gear should become four icons — touchpad, mouse, webcam, and a notification bubble. Clicking each toggles that setting directly. The first three turn red when disabled; the bubble turns red when DND is enabled. + +Today =custom/settings= (=hyprland/.config/waybar/config=) is one gear glyph () whose only job is =on-click: settings-panel=. The toggles themselves already exist and are tested — the settings package owns touchpad, mouse, and webcam (=webcam.py= is the USB-authorized kill switch from 2026-07-22), so this is a bar-side surface over existing backends rather than new capability. + +Note the state-polarity split when wiring the colors: three read "red = off" and DND reads "red = on". That asymmetry is deliberate (red means "something is disabled that normally isn't, or suppressed that normally isn't"), so encode it per-icon rather than deriving one rule. + +Decided 2026-07-23 (Craig): the gear STAYS alongside the four toggles as the panel launcher. So the bar's right side grows from 12 modules to 16 — the four toggles are net-new, the gear keeps its =on-click: settings-panel=. Open sub-question for build time, not blocking: whether the four toggles are four separate waybar modules or one custom module rendering four glyphs (fewer layout entries, one exec). Pick at build; the four-module shape is simplest and matches how mic/net already sit as individual modules. +Shipped in the 2026-07-25 batch as four independent JSON modules over the existing verified settings backends. Touchpad, mouse, and webcam turn terracotta when disabled; DND uses the deliberate inverse polarity; unavailable hardware dims. The gear remains the panel launcher. The live and Dupre theme CSS copies stay byte-identical. +** DONE [#C] Wallpaper panel selection and scroll state :feature:dotfiles:solo: +CLOSED: [2026-07-25 Sat 10:53] +:PROPERTIES: +:LAST_REVIEWED: 2026-07-25 +:END: +From the roam inbox (Craig, 2026-07-25). Screenshot: =~/pictures/screenshots/2026-07-25_013041.png=. Three related behaviors in the settings wallpaper panel (=settings/src/settings/wallpaper.py=): +1. Open at the wallpaper currently displayed, not the top of the list. +2. Highlight that wallpaper as selected in the scrollable pane while it shows in the preview. +3. Keep the scroll position when a picture is selected. Today selecting a picture snaps the scroll back to the top, which is the bug half of this. +Grade: minor scroll-reset defect x every panel selection = P3 = [#C]; the open-at-current and select-current behaviors are enhancements at the same level. One type tag, so filed =:feature:= with the scroll-reset called out as the bug. Solo: buildable in the settings GTK panel, agent-verifiable via headless capture plus the wallpaper.py tests, no design call — swww query gives the current wallpaper, and scroll-position preservation and row selection are standard GTK. +Shipped in the 2026-07-25 batch. The panel queries =awww query= off the UI thread, prefers the actually displayed image over stale stored state, highlights it, scrolls it into view on first open, and remembers the horizontal adjustment across selection-triggered rebuilds. +** DONE [#C] Net tooltip IPs and line order :feature:waybar:network:solo: +CLOSED: [2026-07-25 Sat 10:53] +From the roam inbox (Craig, claimed 2026-07-23): in the wifi hover, add the internal IP, external IP, and gateway IP just below the Interface line; move the Signal line to just above the keyboard-shortcuts line. Design constraint: the bar's hot path does no network I/O (status.py deliberately skips _address_facts on the 2s beat) — internal IP + gateway can ride cheap local reads, but the external IP must come from a cache the connectivity probe refreshes, never a live lookup in waybar-net. +Shipped in the 2026-07-25 batch. The slow connectivity probe caches local addressing and a validated external IP with the network identity; the Waybar hot path only reads that valid cache. Tooltip order is Interface, internal/external/gateway IPs, connectivity detail, throughput, Signal, shortcut. +** DONE [#B] Dupre Kit merge — casting additions :feature:tooling:solo: +CLOSED: [2026-07-25 Sat 10:53] +Fold docs/prototypes/dupre-kit-additions.js back into the kit proper: detentFader (NEW — multi-detent slide attenuator with speedbump drag physics: magnet + escape hysteresis, parked tick glow) and the drumRoller redefinition (UPGRADE — 1..N channels and min/max range; stock hardcodes two drums and throws on one, defaults reproduce stock exactly) and the guardedToggle redefinition (UPGRADE — lever throws with rotateX so it flips toward the viewer instead of the stock 180° planar spin that sweeps sideways mid-transition; contract unchanged). Merge means: builders into widgets.js, the additions CSS into DUPRE_CSS, additions-scoped gradients into the shared defs plate, gallery cards for both in panel-widget-gallery.html, and POLICY entries. Origin: the desktop-settings casting sitting 2026-07-21 — Craig's direction is that components get finished by being needed ("the ones needed most will have had the most attention"), so more additions may accrue here before the merge; batch them. +Shipped in the 2026-07-25 batch. =widgets.js= now owns all three builders, shared gradients/CSS, contracts, and policy records; additions no longer redefines them when older casting pages load it. The gallery has a three-detent fader card and a three-channel 0–12 drum demonstration (112 cards total). Static ownership tests, JS syntax checks, and the complete headless interaction probe pass. +** DONE [#C] Maint live-refresh hairline replacement :feature:maint:solo: +CLOSED: [2026-07-25 Sat 10:53] +:PROPERTIES: +:LAST_REVIEWED: 2026-07-14 +:END: +From the roam inbox (routed 2026-07-13): the memory-killer section seemed to update too often, and "it's a bit unclear what the line is doing; consider something else." Diagnosis (2026-07-14): the data cadence is already the requested 3s (gui live tier, _LIVE_SECONDS); the perceived churn is the live-refresh hairline — the 2px bar under the live sections that drains full-to-empty over each 3s window, redrawn at 150ms (gui._hair_tick, viewmodel.refresh_fraction). It exists to tell a stale board from a frozen one (2026-07-09), but it reads as constant unexplained motion. Design call for Craig: replace the draining line with something whose meaning is legible — candidates: a dot that blinks once per refresh, a "3s" age caption that only appears when refresh is overdue, slowing the drain redraw, or dropping the indicator on live tiers and keeping it only when data goes stale. Keep the stale-vs-frozen distinguishability that motivated the hairline. +*** 2026-07-21 Tue @ 08:35:00 -0500 Decided (Craig): silent-until-stale age caption +Replace the draining 2px hairline with an age caption that shows ONLY when refresh is overdue (e.g. "3s", "8s" once past the expected window) and shows nothing while the board is healthy. This keeps the stale-vs-frozen signal — a frozen board surfaces a growing age number, a live one stays clean — while removing the constant motion the hairline created. Implementation (dotfiles, archsetup-owned): drop =gui._hair_tick= / the hairline draw, add an overdue-age caption driven off =viewmodel.refresh_fraction= (or the last-refresh timestamp) rendered only past the live window. Now unblocked; needs a live visual check on the panel after. +Shipped in the 2026-07-25 batch. The animated draw area and 150ms timer are gone; the memory section header stays silent through the healthy three-second window, then shows a once-per-second growing age caption. Pure boundary tests and the full maintenance suite pass. +** DONE [#D] Test-framework + prototype refactor cluster :refactor:solo: +CLOSED: [2026-07-25 Sat 10:53] +Grading: no behavior change; parking lot. Refactors from the S5-S7 audit, distinct from the installer refactor rollup above. +scripts/testing/run-test.sh + run-test-baremetal.sh duplicate the run/poll/report skeleton and have drifted (VM uses setsid + copy helpers, baremetal uses nohup + hand-rolled sshpass scp) — extract the shared core so baremetal inherits the sturdier paths; run-maint-nspawn.sh:66 + run-maint-scenarios.sh:78 duplicate the transport-independent _scenario_var/_validate_scenario/run_scenario (a sourced lib/maint-scenario.sh); run-test.sh:251,265 uses two different mechanisms (pgrep vs ps|grep) for the same liveness check; docs/prototypes/gen_tokens.py:78 repeats the section-iteration skeleton across four emitters; gallery-widget.el:95,136 hardcodes SVG arc/hub path strings that duplicate the cx/cy/radius geometry (dial desyncs silently on a constant change); gallery-widget.el:72,84 leans on the private svg--append. See findings doc (S5, S6, S7). +Completed test-first in the 2026-07-25 batch. QEMU and bare-metal runners share liveness/report helpers; maintenance transports share scenario validation/execution; token emitters share ordered section traversal; and the Emacs SVG gauge shares semicircle geometry and uses the public DOM append API. Every fast Python/ERT suite passes. |
