feat(flake): #134 — unstable.<pkg> in the downstream, one input, no hand pins
All checks were successful
Check / eval (push) Successful in 4m16s
All checks were successful
Check / eval (push) Successful in 4m16s
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. Downstream stays one locked input; nomarchy-pull moves it. lib.nix needed zero changes — mkFlake's pkgs already applies the overlay. The import is plain and non-recursive, so configs that never reference 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). Costs stated in the README, not hidden: you own the pinned+unstable combination; a second toolchain lands in your closure (~690 of ~4k paths shared, measured on lmstudio); it moves when the lock moves. Lock bumps now move two channels — VERIFICATION §5 and CONVENTIONS updated accordingly. flake.lock gained exactly one node (nixos-unstable @ 753cc8a); nothing else moved. Verification: V1 — nix flake check --no-build green; new eval-only checks.unstable-seam green (26.05pre vs 26.11pre lib.version, no builds); template HM activation built via mkFlake with unstable.hello enabled and its closure carries the unstable store path (pg2zfr… vs pinned nm7p8w…). Implementation by a Sonnet subagent; design and review on Fable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
11
README.md
11
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
|
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
|
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.
|
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
|
## Roadmap & known issues
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
the next lock bump, that is fine — nothing here rots meanwhile.
|
||||||
*Last checked 2026-07-17: open, no maintainer response, no linked PR.*
|
*Last checked 2026-07-17: open, no maintainer response, no linked PR.*
|
||||||
|
|
||||||
### 134. `unstable.<pkg>` 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
|
## LATER
|
||||||
|
|
||||||
- **Wallpapers artifact split** (ROADMAP § Faster switches — decided,
|
- **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.
|
is promoted, a public binary cache (cachix) is the likely first step.
|
||||||
- **#134 unstable packages** — build it: Nomarchy carries the
|
- **#134 unstable packages** — build it: Nomarchy carries the
|
||||||
`nixpkgs-unstable` input, `unstable.*` via the overlay, home-scope only.
|
`nixpkgs-unstable` input, `unstable.*` via the overlay, home-scope only.
|
||||||
Moved to NEXT with the full decided shape.
|
Shipped the same day (ROADMAP § `unstable.<pkg>` in the downstream).
|
||||||
- **#114 greeter layouts** — document only: a VT has one keymap by design,
|
- **#114 greeter layouts** — document only: a VT has one keymap by design,
|
||||||
so tuigreet cannot honour per-device layouts. Shipped as the README
|
so tuigreet cannot honour per-device layouts. Shipped as the README
|
||||||
"Greeter keyboard layout" note + a RECOVERY.md pointer; entry deleted.
|
"Greeter keyboard layout" note + a RECOVERY.md pointer; entry deleted.
|
||||||
|
|||||||
@@ -68,5 +68,7 @@ those, it probably shouldn't exist.
|
|||||||
- Commit style: `feat|fix|test|docs|chore(scope): summary`, body with
|
- Commit style: `feat|fix|test|docs|chore(scope): summary`, body with
|
||||||
what/why + verification tier + what remains. Bookkeeping (`agent/`
|
what/why + verification tier + what remains. Bookkeeping (`agent/`
|
||||||
updates) rides in the same commit as the change.
|
updates) rides in the same commit as the change.
|
||||||
- `flake.lock` moves only when the task *is* a lock bump, and only within
|
- `flake.lock` moves only when the task *is* a lock bump. The release
|
||||||
the pinned release branches.
|
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`.
|
||||||
|
|||||||
@@ -19,6 +19,25 @@ Template:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-07-17 — #134: `unstable.<pkg>` 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
|
## 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
|
- **Task:** BACKLOG #127 (NOW). Two Sonnet forensics passes over the machine's
|
||||||
journal; interpretation, verdict and close-out here. Bernardo ruled: close +
|
journal; interpretation, verdict and close-out here. Bernardo ruled: close +
|
||||||
|
|||||||
@@ -137,7 +137,10 @@ Maintenance follows the same ladder:
|
|||||||
- **Flake lock bumps**: treat as maximum-blast-radius changes. Build,
|
- **Flake lock bumps**: treat as maximum-blast-radius changes. Build,
|
||||||
boot the VM, run the full regression checklist, and do a visual
|
boot the VM, run the full regression checklist, and do a visual
|
||||||
spot-check of the session (themes can shift with upstream package
|
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`,
|
- **Theme imports / new themes**: import via `tools/import-palettes.py`,
|
||||||
then the full §3 visual protocol; additionally verify the theme-switch
|
then the full §3 visual protocol; additionally verify the theme-switch
|
||||||
round trip (into the new theme and back out).
|
round trip (into the new theme and back out).
|
||||||
|
|||||||
@@ -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
|
V2 by render, both heads + the password dialog, via the new
|
||||||
`tools/plymouth-preview.sh`. V3 (a real docked boot/shutdown) is queued: the
|
`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.
|
fake heads exist from the start, so the rig cannot resize a canvas.
|
||||||
|
- ✓ **`unstable.<pkg>` 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
|
- ✓ **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
|
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
|
healthy all day and ended in a routine clean reboot); it ended the
|
||||||
|
|||||||
17
flake.lock
generated
17
flake.lock
generated
@@ -196,6 +196,22 @@
|
|||||||
"type": "github"
|
"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": {
|
"nur": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": [
|
"flake-parts": [
|
||||||
@@ -226,6 +242,7 @@
|
|||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"nixos-hardware": "nixos-hardware",
|
"nixos-hardware": "nixos-hardware",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||||
"stylix": "stylix"
|
"stylix": "stylix"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
34
flake.nix
34
flake.nix
@@ -4,6 +4,11 @@
|
|||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
|
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 = {
|
home-manager = {
|
||||||
url = "github:nix-community/home-manager/release-26.05";
|
url = "github:nix-community/home-manager/release-26.05";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
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
|
let
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
username = "nomarchy"; # reference host only; downstream picks its own
|
username = "nomarchy"; # reference host only; downstream picks its own
|
||||||
@@ -79,6 +84,17 @@
|
|||||||
# the `nomarchy.stateFile` option — reading it stays pure.
|
# the `nomarchy.stateFile` option — reading it stays pure.
|
||||||
|
|
||||||
overlays.default = final: prev: {
|
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 {
|
nomarchy-state-sync = final.callPackage ./pkgs/nomarchy-state-sync {
|
||||||
# Presets baked into the package, so `nomarchy-state-sync list`
|
# Presets baked into the package, so `nomarchy-state-sync list`
|
||||||
# works on machines that don't check out this repo.
|
# 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 ────────────────────────────────────────────
|
# ─── Reference host ────────────────────────────────────────────
|
||||||
|
|||||||
@@ -201,6 +201,8 @@
|
|||||||
|
|
||||||
# Local AI (Ollama is a service toggle in system.nix)
|
# Local AI (Ollama is a service toggle in system.nix)
|
||||||
# lmstudio # (unfree; large closure)
|
# lmstudio # (unfree; large closure)
|
||||||
|
# unstable.lmstudio # newer lmstudio from the unstable channel —
|
||||||
|
# # you own this combination (see README)
|
||||||
# alpaca # GTK Ollama UI
|
# alpaca # GTK Ollama UI
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user