From 4a99b64532616be3a9c1b631db25f1d8b73a52aa Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Thu, 9 Jul 2026 19:35:01 +0100 Subject: [PATCH] docs(skill): fan-out token-economy guidance + track nomarchy skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "Fanning out worktree agents" subsection to §6.5: match model to task (sonnet for spec'd work, opus for judgment), point briefs at the backlog spec, disjoint file lanes, worktree isolation with the parent owning landing, lean on scriptable checks as evidence, batch V2 in one VM pass. First commit of the tracked skill (skills were un-ignored in 7d52d4b). MEMORY note updated: skills are now tracked. Co-Authored-By: Claude Opus 4.8 --- .claude/skills/nomarchy/SKILL.md | 272 +++++++++++++++++++++++++++++++ agent/MEMORY.md | 9 +- 2 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 .claude/skills/nomarchy/SKILL.md 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).