All checks were successful
Check / eval (push) Successful in 3m4s
nomarchy.displayProfiles: named layouts for the same outputs, each a list of nomarchy.monitors-style entries. The active profile lives in the in-flake state (settings.displayProfile) on the night-light pattern: nomarchy-display-profile apply <name> fires the baked hyprctl rules instantly and writes the state with --no-switch; the next rebuild bakes the profile's entries over nomarchy.monitors whole-by-name. Monitor-rule composition is extracted to pure monitor-rules.nix (renderer + 3-layer resolve, incl. a disable-guard so a stale menu resolution pick can't resurrect a profile-disabled panel, and junk state degrading to base config instead of an eval error) — because a writeText/toFile state fixture is unreadable at flake-check eval time, the new checks.display-profiles unit-tests the pure function directly. Menu: System › Display gains a self-gated "Profiles ›" row (●/○ active mark, Base layout to clear); commented template example + README row. Verified: V0 (flake check, forcing the new check's asserts); V1 — a scratch downstream through lib.mkFlake builds: the generated tool passes bash -n with correct rules (disable/vrr/float scale), the baked hyprland.conf shows the exact expected overlay, the menu renders, and list/usage smoke-test clean. Remains: V3 live switching on a dock (HARDWARE-QUEUE). Slices b (hotplug auto-switch) + c (workspace binding) stay in item 15. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
188 lines
9.9 KiB
Markdown
188 lines
9.9 KiB
Markdown
# Backlog — the prioritized task queue
|
||
|
||
The forward-looking half of the old docs/ROADMAP.md, reworked as a queue
|
||
agents can execute. Detailed design notes and decision records stay in
|
||
`docs/ROADMAP.md` (referenced as "ROADMAP § <item>"); this file is *what's
|
||
next, in what order*.
|
||
|
||
**Rules:**
|
||
- Agents take the topmost actionable item (see LOOP.md). Finished items
|
||
are **deleted** here — the journal + git log are the record; durable
|
||
design notes get a ✓-entry in docs/ROADMAP.md if worth keeping.
|
||
- Item numbers are **stable IDs** — never renumbered or reused. A gap in
|
||
the sequence means shipped (or dropped) work; new items take the next
|
||
free number regardless of tier.
|
||
- Tags: `[blocked:hw]` needs real hardware (see HARDWARE-QUEUE.md) ·
|
||
`[human]` needs Bernardo · `[stuck]` two failed attempts, needs help ·
|
||
`[big]` must be split before starting.
|
||
- Agents may append to **PROPOSED** and **Decisions** freely; only
|
||
Bernardo moves items *out* of PROPOSED into the tiers.
|
||
|
||
---
|
||
|
||
## NOW
|
||
|
||
*(empty — NEXT's top item is the queue head)*
|
||
|
||
## NEXT
|
||
|
||
### 14. Automated lock bumps — confirm the first real run
|
||
Slices b+c shipped 2026-07-05 (`.gitea/workflows/bump.yml`): weekly
|
||
schedule (Mon 05:17 UTC) + `workflow_dispatch` as the security
|
||
fast-lane; `nix flake update` → eval gate → pathspec-limited lock
|
||
commit pushed to `main` on green (that push triggers check.yml as the
|
||
second net). Update/commit/push logic simulated locally end-to-end in
|
||
a scratch clone, incl. a real update; today's bumped lock evals green.
|
||
Remaining (not confirmable from a session): the first scheduled or
|
||
dispatched run must land — watch that the runner picks up the cron and
|
||
that the Actions token can push. Then delete this item. Item 20's KVM
|
||
runner later upgrades the gate from eval-only to the VM suite.
|
||
|
||
### 20. KVM runner → VM suite in CI `[human]`
|
||
The remaining stretch of the CI item — checks-on-push is live and
|
||
**green** (run #58; runner = gitea/act_runner docker, eval tier).
|
||
Register a second runner on a host with `/dev/kvm` + nix (host-mode
|
||
label `nix-kvm`), then an agent uncomments the workflow's `vm-checks`
|
||
job: the `checks.*` VM suite + real toplevel/HM builds on every push
|
||
(also upgrades item 14's bump gate from eval-only to the full suite).
|
||
|
||
### 15. Display profiles — docked/undocked switching
|
||
ROADMAP § Display / monitor management, remaining: profile switching of
|
||
the *same* outputs. **Plan (designed 2026-07-05, iteration #27):**
|
||
- **Option:** `nomarchy.displayProfiles` (HM) = `attrsOf (listOf
|
||
monitorType)` — each profile is a named list reusing the existing
|
||
monitor submodule verbatim (no second schema). Example: `docked =
|
||
[ { name="eDP-1"; resolution="disable"; } { name="DP-3"; … } ]`.
|
||
- **State:** `settings.displayProfile = "<name>"` (absent = base
|
||
config), menu-written with `--no-switch` — the night-light pattern:
|
||
instant now, baked at the next rebuild. Add the key to
|
||
nomarchy-theme-sync's known-settings list (item 11's validator warns
|
||
on unknowns).
|
||
- **Rebuild overlay** (hyprland.nix): active profile's entries replace
|
||
base `nomarchy.monitors` entries whole, by name; the existing
|
||
`settings.monitors` resolution overlay then applies field-level on
|
||
top, EXCEPT onto entries whose profile resolution = "disable" (a
|
||
stale resolution pick must not resurrect a disabled panel).
|
||
- **Instant apply** (menu): System › Display gains a self-gated
|
||
"Profile: <active>" row (only when profiles are declared) → pick →
|
||
`hyprctl keyword monitor <rule>` per entry (rules baked into the
|
||
dispatcher at build, like everything else in rofi.nix) + state write
|
||
+ toast. Outputs the profile doesn't name keep their base rules.
|
||
- **Slices:** (a) ✓ shipped 2026-07-05 (iteration #28): option +
|
||
overlay (pure `modules/home/monitor-rules.nix`, unit-tested by
|
||
checks.display-profiles) + `nomarchy-display-profile` applier + menu
|
||
Profiles row + template example — V3 (real dock) queued; (b)
|
||
opt-in hotplug auto-switch: a socket2 watcher on monitoradded/
|
||
removed picks the profile whose named-output set matches connected
|
||
outputs (exact match, else largest subset, ties = no switch) —
|
||
decide the flag shape (`settings.displayProfile = "auto"` vs a
|
||
separate boolean) at implementation; (c) optional per-profile
|
||
`workspaces = { "1" = "DP-3"; }` → Hyprland `workspace` keywords.
|
||
- **Non-goals:** no kanshi (fights Hyprland's output management —
|
||
decided in ROADMAP), nwg-displays stays a find-the-values helper.
|
||
|
||
### 16. Greeter theming from the JSON
|
||
ROADMAP § Greeter. tuigreet themed from theme-state.json at system
|
||
rebuild (same model as Plymouth's tint). Scope: tuigreet only (no SDDM).
|
||
|
||
### 17. Launch-or-focus UX scripts
|
||
ROADMAP § launch-or-focus. Hyprland dispatch scripts: a bind launches an
|
||
app or focuses its existing window. Curate which apps get binds;
|
||
cheatsheet entries via keybinds.nix.
|
||
|
||
### 18. "nomarchy" control center + first-boot welcome `[big]`
|
||
ROADMAP § control center. A single front-end over the common toggles on
|
||
the same `nomarchy-theme-sync` surface, + a first-boot guided
|
||
"pick your theme / essentials" flow. Needs a design pass (TUI vs GUI)
|
||
→ write options into Decisions before implementing. Note: items 9–11
|
||
(rollback menu, doctor, validation) are natural panels of it — design
|
||
them as composable commands, not dead ends.
|
||
|
||
### 19. Look & Feel menu category
|
||
ROADMAP § Menu system, remaining: group Theme + night-light (+ wallpaper
|
||
cycle, future appearance toggles) under a Look & Feel submenu once it
|
||
earns ≥3 entries — keep the root at six.
|
||
|
||
## LATER
|
||
|
||
- **Wallpapers artifact split** (ROADMAP § Faster switches — decided,
|
||
deferred): pinned `Nomarchy-wallpapers` input so a state write stops
|
||
re-copying 86 MB. Follow-on: pre-built theme variants if switches are
|
||
still slow after.
|
||
- **Installer round 2** (ROADMAP § Installer): multi-disk BTRFS RAID,
|
||
impermanence, BIOS/legacy boot.
|
||
- **Boot-from-snapshot**: a systemd-boot equivalent of grub-btrfs.
|
||
- **Night-light geo mode**: lat/long auto sunset/sunrise (means wlsunset).
|
||
- **Per-theme icon overrides** / more icon packs (ROADMAP § Icon themes).
|
||
- **MIPI/IPU software-ISP camera** support (no-UVC machines).
|
||
- **OCR screenshot-to-text**: a Capture › entry (grim region → tesseract
|
||
→ clipboard) — recording (#12, shipped 2026-07-04) already reshaped
|
||
the submenu, so this is now a two-row addition.
|
||
- **Doctor Waybar warning**: a self-gating bar indicator fed by
|
||
`nomarchy-doctor` (shipped 2026-07-04) — appears only when the sheet
|
||
has a ✖; click opens the sheet.
|
||
- **Auto-timezone Waybar tooltip** showing the detected zone (optional).
|
||
- **VPN exit-node richer display** (country/city) (optional).
|
||
- **NixOS release bump → v2** `[human]`: deliberate, hand-edited, never
|
||
automated; the previous attempt was discarded (2026-06-22) over a
|
||
Hyprland OOM blocker — see MEMORY.md before retrying (NOW#3 should
|
||
also soften that blocker class).
|
||
|
||
## PROPOSED (agent suggestions — await human triage)
|
||
|
||
*Agents: append here with a one-paragraph pitch (what/why/cost). Do not
|
||
implement. Bernardo moves accepted items into a tier.*
|
||
|
||
- **Menu parity for downstream-flake options** (raised by Bernardo,
|
||
2026-07-04, from the hardware sweep): anything the docs or the
|
||
hardware queue ask a user to *hand-edit into the downstream flake*
|
||
(`keyboard.layout` multi-layout, `power.batteryChargeLimit`,
|
||
`updates.enable`, `services.printing`, …) should have a menu toggle
|
||
instead — the in-flake-state philosophy already gives the menu a
|
||
write-into-the-flake path, and night-light / auto-timezone /
|
||
auto-commit prove the pattern (incl. rebuild-on-first-enable).
|
||
Pitch: (a) an audit listing every user-facing `nomarchy.*` option vs
|
||
its menu surface; (b) menu writers for the gaps, respecting the
|
||
toggle-vs-package discipline (bare template packages stay hand-edits)
|
||
and menu-placement convention (right submenu, root stays short).
|
||
Values beyond booleans (layout lists, charge thresholds) need a small
|
||
input UI per option. Cost: audit is one iteration; the writers a few
|
||
more, sliceable per option.
|
||
|
||
- **Portal/Flatpak camera picker still lists the internal IR sensor**
|
||
(ROADMAP § Webcam follow-up). The shipped IR-hide is a *WirePlumber
|
||
v4l2* rule, but Flatpak/portal apps consume cameras via the
|
||
**libcamera** path, where both sensors remain visible — a Flatpak
|
||
Zoom user can still pick the black IR "camera". Options, roughly
|
||
ascending cost: (a) do nothing — document it (portal camera support
|
||
is still rare in practice); (b) a WirePlumber *libcamera* monitor
|
||
rule disabling GREY-only nodes — needs verifying that libcamera
|
||
monitor rules can match early enough (the v4l2 investigation found
|
||
only `device.api` binds pre-rule, which is why surgical scoping
|
||
failed before — same wall likely applies); (c) a libcamera
|
||
configuration/udev quirk hiding the IR sensor at the libcamera layer
|
||
itself. Cost: (b)/(c) need a T14s-style RGB+IR machine to verify →
|
||
pairs with a hardware-queue session. Recommend (a) now, (b)
|
||
investigated when the T14s is next available.
|
||
|
||
## Decisions `[human]`
|
||
|
||
Open calls only Bernardo can make; agents add options/evidence but never
|
||
decide.
|
||
|
||
- **Formatter adoption:** repo deliberately has none; `nixfmt-rfc-style`
|
||
would flatten the aligned hand-formatting of ~33 files. Adopt or
|
||
declare never?
|
||
- **Docs site vs Markdown-in-repo** (from the docs-review item).
|
||
- **Control center form factor:** TUI (gum/ratatui-style) vs GUI vs
|
||
"the rofi menu *is* the control center, just add a first-boot flow".
|
||
- **zram swap:** faster under pressure and pairs with NOW#3, but it
|
||
interacts with the hibernation-swapfile story (resume device/priority
|
||
ordering) — adopt, adopt-with-hibernation-guard, or skip?
|
||
- **Default browser:** the template comments Firefox out. The shipped
|
||
mime defaults (item 8, done) point `text/html`/http(s) at
|
||
`firefox.desktop` as *inert* entries — they activate the moment
|
||
Firefox is installed and are skipped otherwise, so the remaining call
|
||
is only: ship a browser active in the suite, or stay
|
||
browserless-by-default?
|