diff --git a/README.md b/README.md index e590a0c..8a1218e 100644 --- a/README.md +++ b/README.md @@ -519,6 +519,17 @@ reload # exec zsh (reload the shell) line to slim the machine, uncomment an extra (a browser, email, full TeX Live), or add your own. No `nomarchy.apps.*` toggles — a package list is already its own opt-out, so the distro doesn't impose these or wrap them. +- **A newer individual app (unstable channel, #134):** Nomarchy carries a + second, newer nixpkgs channel and exposes it as `unstable` through its + overlay, so any package can be taken from it by prefixing `unstable.` in + `home.packages` — e.g. `unstable.lmstudio` — with no second flake input of + your own to manage. Three costs, stated plainly: (a) **you own this + combination** — nothing upstream tests a pinned Nomarchy plus an unstable + app together; (b) an unstable package brings its own second toolchain into + your closure (measured: `unstable.lmstudio` shares only ~690 of ~4k store + paths with the pinned set); (c) it moves whenever the flake lock moves + (`nomarchy-pull`), not on its own schedule. Home packages only — that's + the supported surface, not `system.nix` or the module set. ## Roadmap & known issues diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index f19f2d2..7510456 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -89,29 +89,6 @@ rofi#2317, and take the fix when a release carries it. If it is still open at the next lock bump, that is fine — nothing here rots meanwhile. *Last checked 2026-07-17: open, no maintainer response, no linked PR.* -### 134. `unstable.` in the downstream — decided, build it - -**Decided 2026-07-17 (Bernardo): Nomarchy carries the channel.** Add a -`nixpkgs-unstable` input to the distro flake and expose it through -`overlays.default` as an `unstable` attrset, so -`home.packages = [ unstable.lmstudio ];` just works — downstream stays one -locked input and `nomarchy-pull` still moves it. Scope is **home packages -only**; no `unstable.*` surface in system.nix, no `stable.` synonym for now. -The input rides in the eval unconditionally (an unused input still locks + -fetches — accepted). Original diagnosis stands: `mkFlake` has no overlay -seam and `homeConfigurations` uses mkFlake's own `pkgs`, so nothing short of -the distro carrying the channel keeps the user out of `fetchTarball` pinning. - -Costs accepted with the ruling, to be stated in docs, not hidden: lock bumps -now move two channels (VERIFICATION §5 full-checklist applies to both); a -user who reaches for `unstable.` pays a second stdenv/glibc in their closure -(measured: lmstudio shares only ~690 of ~3.7–4k paths); and nothing upstream -tests pinned-Nomarchy + unstable-app together — the README needs an explicit -"you own this combination" paragraph. Ship with a commented example in -`templates/downstream/home.nix` (opt-in convention) and a README table note. -Pass = flake check green + a V1 build of the template HM closure with one -`unstable.` package enabled. Related: #133. - ## LATER - **Wallpapers artifact split** (ROADMAP § Faster switches — decided, @@ -312,7 +289,7 @@ decide. **Resolved** entries stay for history; agents treat them as closed. is promoted, a public binary cache (cachix) is the likely first step. - **#134 unstable packages** — build it: Nomarchy carries the `nixpkgs-unstable` input, `unstable.*` via the overlay, home-scope only. - Moved to NEXT with the full decided shape. + Shipped the same day (ROADMAP § `unstable.` in the downstream). - **#114 greeter layouts** — document only: a VT has one keymap by design, so tuigreet cannot honour per-device layouts. Shipped as the README "Greeter keyboard layout" note + a RECOVERY.md pointer; entry deleted. diff --git a/agent/CONVENTIONS.md b/agent/CONVENTIONS.md index 00e3362..ac43422 100644 --- a/agent/CONVENTIONS.md +++ b/agent/CONVENTIONS.md @@ -68,5 +68,7 @@ those, it probably shouldn't exist. - Commit style: `feat|fix|test|docs|chore(scope): summary`, body with what/why + verification tier + what remains. Bookkeeping (`agent/` updates) rides in the same commit as the change. -- `flake.lock` moves only when the task *is* a lock bump, and only within - the pinned release branches. +- `flake.lock` moves only when the task *is* a lock bump. The release + inputs stay within their pinned release branches; the `nixpkgs-unstable` + input (#134, feeds `unstable.*`) tracks `nixos-unstable` and bumps + together with the rest — never alone, never `nix flake update`. diff --git a/agent/JOURNAL.md b/agent/JOURNAL.md index bea3a73..00f3f2a 100644 --- a/agent/JOURNAL.md +++ b/agent/JOURNAL.md @@ -19,6 +19,25 @@ Template: --- +## 2026-07-17 — #134: `unstable.` seam shipped +- **Task:** BACKLOG #134 (NEXT, decided shape from this morning's triage). +- **Did:** `nixpkgs-unstable` input + `unstable` attrset in + `overlays.default` (plain lazy import, allowUnfree mirrored); + `lib.nix` untouched by design — mkFlake's pkgs already applies the + overlay. Template opt-in comment (`unstable.lmstudio`), README costs + paragraph, `checks.unstable-seam` (eval-only), VERIFICATION §5 + + CONVENTIONS two-channel lock rules. Lock gained exactly one node + (nixos-unstable @ 753cc8a, 2026-07-15). Sonnet implemented; design + + review here. +- **Verified:** V1 — flake check green; unstable-seam check green + (26.05pre vs 26.11pre lib.version); template HM activation built with + `unstable.hello` and its closure carries the unstable store path + (pg2zfr… vs pinned nm7p8w…). +- **Pending:** nothing; Bernardo's real-world case is him adding + `unstable.lmstudio` to ~/.nomarchy/home.nix whenever he likes. +- **Next suggestion:** queue is NEXT-empty save watches (#143/#146/#149); + NOW holds only the install-findings stub awaiting Bernardo's call. + ## 2026-07-17 — #127 CLOSED: the brick was hypridle eating its own resume path - **Task:** BACKLOG #127 (NOW). Two Sonnet forensics passes over the machine's journal; interpretation, verdict and close-out here. Bernardo ruled: close + diff --git a/agent/VERIFICATION.md b/agent/VERIFICATION.md index 14c0f56..6658a17 100644 --- a/agent/VERIFICATION.md +++ b/agent/VERIFICATION.md @@ -137,7 +137,10 @@ Maintenance 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". + changes). Never merge a lock bump on "it evaluates". Since #134 the + lock carries **two channels** (the release pin and the + `nixos-unstable` pin feeding `unstable.*`) — a bump moves both, and + this checklist applies to both. - **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). diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index f31def0..371e326 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -493,6 +493,23 @@ Design/decision records and a running log of shipped work (items marked V2 by render, both heads + the password dialog, via the new `tools/plymouth-preview.sh`. V3 (a real docked boot/shutdown) is queued: the fake heads exist from the start, so the rig cannot resize a canvas. +- ✓ **`unstable.` in the downstream (#134, 2026-07-17):** Nomarchy now + carries a `nixpkgs-unstable` input and exposes it through + `overlays.default` as an `unstable` attrset — in the template's + `home.packages = with pkgs; [ … ]` a user writes `unstable.lmstudio` and + is done: one downstream input, still locked, still moved by + `nomarchy-pull`. `lib.nix` needed zero changes (mkFlake's pkgs already + applies the overlay). A plain non-recursive `import` keeps it lazy — + configs that never write `unstable.` pay nothing beyond the input fetch; + `allowUnfree` mirrors the base set so the motivating lmstudio resolves. + Home packages are the supported surface (documented convention — the + overlay is technically visible system-side, deliberately undocumented). + Costs stated in the README, not hidden: you own the combination, second + toolchain in the closure (~690 of ~4k paths shared), moves with the lock. + Lock bumps now move two channels — VERIFICATION §5 + CONVENTIONS updated. + V1: template HM activation built with `unstable.hello`, closure carries + the unstable store path; `checks.unstable-seam` (eval-only) guards the + seam permanently; lock diff added exactly the one node. - ✓ **The idle brick's CAUSE found (#127 closed, 2026-07-17):** the incident was misdated — it did not happen "before 12:51:34 Jul 15" (that boot was healthy all day and ended in a routine clean reboot); it ended the diff --git a/flake.lock b/flake.lock index 3818b8d..b520855 100644 --- a/flake.lock +++ b/flake.lock @@ -196,6 +196,22 @@ "type": "github" } }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1784120854, + "narHash": "sha256-KesHgItiZPgGX740axSiQLcIQ8D24MDqNpkKYWIek8k=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "753cc8a3a87467296ddd1fa93f0cc3e81120ee46", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nur": { "inputs": { "flake-parts": [ @@ -226,6 +242,7 @@ "home-manager": "home-manager", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable", "stylix": "stylix" } }, diff --git a/flake.nix b/flake.nix index a032bf9..413d6e6 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,11 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; + # Second, newer channel — exists solely to feed the `unstable.*` overlay + # seam (#134), so downstream can pick individual newer apps without a + # second flake input of their own. + nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; + home-manager = { url = "github:nix-community/home-manager/release-26.05"; inputs.nixpkgs.follows = "nixpkgs"; @@ -27,7 +32,7 @@ }; }; - outputs = { self, nixpkgs, home-manager, stylix, nixos-hardware, ... }: + outputs = { self, nixpkgs, nixpkgs-unstable, home-manager, stylix, nixos-hardware, ... }: let system = "x86_64-linux"; username = "nomarchy"; # reference host only; downstream picks its own @@ -79,6 +84,17 @@ # the `nomarchy.stateFile` option — reading it stays pure. overlays.default = final: prev: { + # A second, newer channel for individual apps (#134) — e.g. lmstudio, + # whose fast-moving upstream a pinned nixpkgs lags. Plain `import`, + # deliberately NOT final-recursive: it evaluates only when a config + # actually references `unstable.something`, so checkouts that never + # write `unstable.` pay nothing for it. allowUnfree mirrors the base + # set (lib.nix) so unfree apps — lmstudio is the motivating case — + # resolve here too. + unstable = import nixpkgs-unstable { + inherit (prev.stdenv.hostPlatform) system; + config.allowUnfree = true; + }; nomarchy-state-sync = final.callPackage ./pkgs/nomarchy-state-sync { # Presets baked into the package, so `nomarchy-state-sync list` # works on machines that don't check out this repo. @@ -2268,6 +2284,22 @@ ) ''; }; + + # #134: proves the `unstable.*` overlay seam exists and is really a + # second channel, without building anything from it — evaluation-only, + # so this stays cheap even though nixpkgs-unstable is a whole extra + # input. `pkgs` here already carries overlays.default (line ~35). + unstable-seam = + let + expect = cond: msg: nixpkgs.lib.assertMsg cond "unstable-seam: ${msg}"; + ok = + expect (pkgs.unstable ? hello) + "pkgs.unstable has no `hello` — the overlay attr is missing or broken" + && expect (pkgs.unstable.lib.version != pkgs.lib.version) + ("pkgs.unstable.lib.version == pkgs.lib.version — this is the same " + + "channel as the pinned nixpkgs, not a second one"); + in + assert ok; pkgs.runCommand "nomarchy-unstable-seam" { } "touch $out"; }; # ─── Reference host ──────────────────────────────────────────── diff --git a/templates/downstream/home.nix b/templates/downstream/home.nix index bda69d8..99abc2f 100644 --- a/templates/downstream/home.nix +++ b/templates/downstream/home.nix @@ -201,6 +201,8 @@ # Local AI (Ollama is a service toggle in system.nix) # lmstudio # (unfree; large closure) + # unstable.lmstudio # newer lmstudio from the unstable channel — + # # you own this combination (see README) # alpaca # GTK Ollama UI ]; }