diff --git a/.claude/skills/nomarchy/SKILL.md b/.claude/skills/nomarchy/SKILL.md new file mode 100644 index 0000000..48d3685 --- /dev/null +++ b/.claude/skills/nomarchy/SKILL.md @@ -0,0 +1,272 @@ +--- +name: nomarchy +description: Development and maintenance workflow for the Nomarchy NixOS-based distribution (this repository). Use this skill for ANY change to this repo — new features, bug fixes, theming or visual work (Hyprland, Waybar, rofi, wallpapers, palettes), NixOS/Home-Manager module changes, flake lock bumps, theme imports, docs updates, backlog grooming, or loop iterations. Trigger even for "small" or "obvious" changes; the whole point of this skill is that no change ships without climbing the verification ladder, and small changes are where verification gets skipped. +--- + +# Nomarchy Development Skill + +Nomarchy's promise to its user: a rock-stable, fully functional, beautiful +workstation that is reproducible, easy to recover, and never requires the +user to become a Nix expert. Every rule below exists to protect that promise. +A change that works but degrades stability, aesthetics, or user-simplicity is +a regression, not a feature. + +## 0. Read the authoritative docs first + +This skill is an enforcer, not the workflow itself. The workflow lives in the +repo and is the single source of truth: + +- `CLAUDE.md` — entry point, project conventions +- `agent/LOOP.md` — the iteration loop and the V0–V3 verification ladder +- `agent/` (remaining files) — philosophy, conventions, memory, backlog +- `docs/TESTING.md` — VM instructions, the regression checklist, known + environment gotchas + +At the start of any work session in this repo, read `CLAUDE.md` and +`agent/LOOP.md` before touching code. Read `docs/TESTING.md` before running +any VM test. If this skill and those docs ever disagree, the repo docs win — +then fix the discrepancy in the same or a follow-up commit so they can't +disagree twice. + +## 1. Preflight (once per session) + +Before starting work, establish what verification tier this environment can +reach, so you never promise verification you can't deliver: + +1. Linux x86_64 host? `/dev/kvm` present and readable? +2. Enough free disk for an image/ISO build (multi-GB)? +3. Network access for a cold Nix store? + +If the environment cannot reach V2 (no KVM, no disk, etc.): say so +immediately, do the V0/V1 work honestly, mark the change **"V2 pending"** +exactly as you would mark a hardware-blocked change "V3 pending" (see §4), +and stop short of claiming the change is done. Never simulate, guess, or +describe what a VM test "would" show. + +## 2. The verification ladder (enforcement rules) + +Climb the V0–V3 ladder as defined in `agent/LOOP.md`. This skill adds three +non-negotiable enforcement rules on top: + +1. **V2 is mandatory for anything user-visible.** If a user of the installed + system could perceive the change — behavior, layout, colors, keybinds, + timing, error messages — it must be exercised in the local VM before + commit. Docs-only, comment-only, or agent-notes changes may stop at the + tier LOOP.md assigns them; user-visible changes may not. +2. **Every "done" report names the tier reached and shows the evidence.** + Evidence means: the command run and its relevant output, the checklist + items exercised, and for visual work the screenshots viewed (§3). "It + builds" is a V1 claim, not a V2 claim. Never let a report imply a higher + tier than was actually reached. +3. **A failed or flaky test is a result, not an obstacle.** Distinguish real + failures from environment flakes using the known-gotchas section of + `docs/TESTING.md` (e.g. no-KVM slowness, missing guest GL). If you cannot + confidently classify a failure, report it as unresolved — do not retry + until green and report only the green run. +4. **VM runs are headless and unattended.** Use the repo's headless + harness — `tools/test-live-iso.sh` and `tools/test-install.sh` for + boot/install runs, `tools/vm/qmp.py` for programmatic VM control and + `tools/vm/vncshot.py` for screen capture — never a graphical VM window + or any flow that needs a human at the console. The human is not part of + the test loop: do not pause mid-run to ask them to look at the VM, click + something, or confirm what is on screen. A run must complete on its own + and leave auditable artifacts behind (logs, serial console output, exit + codes, screenshots), with every wait bounded by a timeout so a hang + becomes a recorded failure instead of a stalled session. Prefer scripted + assertions (process up, file exists, service/D-Bus state, the checks in + `tools/`) over eyeballing; where judgment is genuinely needed — visual + quality — *you* view the captured screenshots (§3), not the human. The + human reviews evidence in the final report, never the live run. + +### Regression scope after a change + +Re-running the full checklist for every change wastes VM time; running +nothing invites regressions. Default rule: + +- Always: the session-sanity items (boot to session, bar renders). +- Plus: every checklist item touching the layer you changed. +- Plus: the theming end-to-end item whenever theming plumbing changed, + even indirectly (palette generation, symlinks, reload hooks). +- Lock bumps and toolchain changes: run the full checklist — their blast + radius is unknowable by construction. + +## 3. Visual verification protocol + +Visual quality is a core feature of Nomarchy, so "it probably looks fine" is +never verification. A visual/UI change is not V2-verified until all of the +following are true: + +1. **Before/after screenshots** of the changed surface were captured + headlessly — `tools/theme-shot.nix` for reproducible theme renders, + `tools/vm/vncshot.py` (driven via `tools/vm/qmp.py`) for captures from a + running VM. No VM window, no human interaction. Capture the "before" + from the base branch or prior generation, not from memory. +2. **Scripted checks first**: run `tools/check-theme-contrast.py` and + `tools/audit-theme-design.py` against the affected theme(s) before any + eyeballing — machine-checkable legibility/design violations should never + survive to the human-judgment stage. Use `tools/vm/gap-analysis.py` + where it applies. +3. **Two themes**: repeat the "after" capture under at least two themes, one + with a generated palette and one whole-swap theme (e.g. summer-night). + These exercise different code paths in the bar/launcher theming; a change + that looks right under one can silently break the other. +4. **You actually viewed the images** — open the screenshot files and look + at them. State concretely what you inspected: alignment, spacing, + contrast/legibility against the palette, icon rendering, no clipped or + overlapping elements, and that the change looks intentional next to the + "before". +5. Keep the screenshots in the run's working area and reference their paths + in the report, so the human can audit the same evidence. + +If the VM cannot render the surface faithfully (known GL/compositor gaps in +the guest — see `docs/TESTING.md`), that specific visual aspect is +hardware-blocked: verify everything the VM *can* show, and queue the rest +per §4. + +## 4. Hardware-blocked checks + +Some checks genuinely require real hardware (GPU behavior, multi-monitor +hotplug, audio devices, power/suspend, firmware). For those: + +1. Add an entry to `agent/HARDWARE-QUEUE.md` with: what changed, **exact** + reproduction steps a human can follow verbatim, the expected observation + (what "pass" looks like), and the commit hash once known. +2. Mark the commit body **"V3 pending: "**. +3. Say it plainly in your report. A hardware-blocked check is not a failure + and not something to hide — hiding it is the failure. +4. When the human reports back, close the queue entry in the next commit and + record the outcome; if it failed on hardware, that's a new bug at the top + of the backlog. + +Do not use the hardware queue as an escape hatch: if a check *can* be done +in the VM, it must be. "The VM is slow" does not qualify. + +## 5. Maintenance work + +Maintenance is in scope for this skill and follows the same ladder: + +- **Flake lock bumps**: treat as maximum-blast-radius changes. Build, + boot the VM, run the full regression checklist, and do a visual + spot-check of the session (themes can shift with upstream package + changes). Never merge a lock bump on "it evaluates". +- **Theme imports / new themes**: import via `tools/import-palettes.py`, + then the full §3 visual protocol; additionally verify the theme-switch + round trip (into the new theme and back out). +- **Docs drift**: run `tools/check-option-docs.py` after any change that + adds or modifies options, and fix drift in the same commit as the code + change that created it. Doc-only fixes are V0 — but verify any command + you document by actually running it. +- **Backlog grooming / agent-notes**: V0; keep entries consistent with the + conventions in `agent/`. + +## 6. Guarding the philosophy + +Before committing, check the change against the distro's promises: + +- **User is not a Nix expert.** If the change requires the user to write or + read Nix to use the feature day-to-day, redesign it. Configuration the + user touches must stay in the simple, documented surface the repo defines. +- **Rock-stable and recoverable.** Prefer boring, reproducible mechanisms + over clever ones. Any change that could break boot or the session must + have an obvious rollback story (NixOS generations count, but say so). +- **Aesthetics are load-bearing.** A functionally correct but visually + regressive change fails review by definition — that's what §3 is for. + +When a requested change conflicts with these promises, stop and raise the +conflict instead of implementing it quietly. + +## 6.5 Token economy: delegate machinery, keep judgment + +Not every step needs the smartest model. Use subagents to route mechanical +work to cheap models and keep expensive reasoning where it pays. The repo +defines two in `.claude/agents/`: + +- **nomarchy-scout** (haiku, read-only): finding where things are defined, + mapping which files touch a subsystem, scanning build logs and serial + output for error lines, docs-vs-code drift sweeps. Use it for any pure + information-gathering step instead of reading files into the main + context yourself — it keeps the main context small, which matters more + than the token price on long loops. +- **nomarchy-runner** (haiku, executes the harness): builds, VM boots, + screenshot capture, the scripted `tools/` checks. It runs commands and + returns exit codes, logs, and artifact paths — nothing more. + +The dividing line is **evidence vs. judgment**. Cheap models gather +evidence; they never make verification claims. The following always stay +with the main (smart) model and are never delegated downward: + +- deciding what to test and what the regression scope is (§2) +- interpreting an ambiguous or flaky failure (§2 rule 3) +- viewing screenshots and judging visual quality (§3) — aesthetic judgment + is exactly the kind of work small models do badly, and it's load-bearing + for this distro +- writing non-trivial Nix (module structure, overlays, cross-cutting + refactors) +- the final review of the diff and the §7 report + +Practical guidance: delegation is not free — each subagent has its own +context and the tokens multiply — so delegate when the work is mechanical +*or* would pollute the main context with bulk (log files, wide file +scans), not reflexively for every small step. A one-file read is cheaper +done directly. When a scout/runner result surprises you, spot-check it +yourself before building on it: cheap models are allowed to be wrong about +hard things, which is precisely why they're not allowed to make claims. + +### Fanning out worktree agents (parallel V0/V1 work) + +When several NEXT items are independent and don't need the VM, spread them +across worktree-isolated subagents that run in parallel — but keep the +token cost down with these habits (each is a real lever, not a nicety): + +- **Match the model to the task, not the tier.** A backlog item whose spec + is already written (exact files, exact fixes) is *well-specified* → + **sonnet**, not opus. Reserve opus for genuine multi-step reasoning + (novel Nix, cross-cutting design, an ambiguous failure). Haiku for bulk + mechanical. Picking sonnet over opus for a spec'd task is the single + biggest saving. +- **Point at the spec; don't restate it.** The brief should say "the spec + is in `agent/BACKLOG.md` #NN — implement it, don't re-derive," plus only + the *constraints* (scope files, branch, no-VM, no-push). A cold agent + re-reading the whole design into its own context is the tokens you're + trying to avoid. +- **Disjoint file lanes.** Partition the items so no two agents touch the + same file (map the touched files first). Zero shared files = zero merge + conflicts at landing = no reconciliation tokens. If two items must share + a file (README, flake.nix, rofi.nix), give both to one agent or keep one + for yourself. +- **Isolation + you own landing.** Run each agent with `isolation: + worktree`; it commits to its own branch and **never pushes or touches + `main`/`v1`**. You review each diff, cherry-pick onto `main`, and do the + bookkeeping. Parallel pushers race on `main`; a single landing agent + doesn't. (Clean up: `git worktree remove --force` + `git branch -D` the + branch and its `worktree-…` sibling after landing.) +- **Lean on scriptable checks as the primary evidence.** Where a + deterministic `tools/` check or a `checks.*` guard already proves the + property (e.g. `check-theme-contrast.py` for a palette fix, + `option-docs` for a doc row), that near-free run *is* the V0/V1 + evidence — don't spend a VM render to re-confirm what the script already + asserts. +- **Batch V2 at the end, once.** Visual/behavioural items delegated at + V0/V1 come back "V2 pending." Don't boot the VM per item — collect the + landed changes and do **one** `theme-shot`/`test-install` pass covering + all of them. The VM render + screenshot review is the most expensive + token sink in the loop; amortise it. +- **Re-verify on `main`, but leanly.** After cherry-picking, confirm the + agent's V0/V1 on the merged tree — but a tiny, obviously-correct diff + needs a targeted build, not a full re-run of everything. Trust-but-spot- + check scales; blind re-running doesn't. + +The judgment that never delegates (§ above) still holds: *you* review every +diff before it lands, and *you* make the product calls (a "finish vs. +quarantine" decision is yours or Bernardo's, never a cheap agent's). + +## 7. Reporting format + +End every unit of work with a short report containing: + +1. What changed (one paragraph, plain language). +2. Verification tier reached, with evidence (commands + key output, + checklist items run, screenshot paths viewed). +3. Anything pending: "V2 pending" (environment) or "V3 pending" (hardware, + with queue entry reference). +4. Follow-ups added to the backlog, if any. diff --git a/agent/MEMORY.md b/agent/MEMORY.md index 99902ce..6def52c 100644 --- a/agent/MEMORY.md +++ b/agent/MEMORY.md @@ -110,7 +110,8 @@ iteration would otherwise rediscover. effects carry a value, matchers take `match:` (§ windowrule migration). - grub `loadfont`s every `.pf2` in a theme dir — reuse a bundled DejaVu rather than shipping fonts (§ Distro branding). -- The Claude Code harness drops machine-local files into the repo - (`.claude/skills/…`) mid-session — never `git add -A` blindly; check - `git status --short` for strangers first (they're gitignored now, but - the next surprise won't be) (§ loop hygiene). +- `.claude/skills/*/SKILL.md` are now **tracked** (the `.gitignore` + `.claude/skills/` line was un-commented→removed, 7d52d4b) — commit skill + edits like any repo doc. Still never `git add -A` blindly: check + `git status --short` for genuine strangers first (`settings.local.json`, + harness-dropped files) and commit with explicit pathspecs (§ loop hygiene).