diff --git a/README.md b/README.md index 16a3b7b..e096709 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,13 @@ the locked inputs into the ISO store — so theme switching (including the `home-manager switch` it triggers) works **offline**, exactly like on an installed system. Verification checklist: [docs/TESTING.md](docs/TESTING.md). +It's a working desktop, not a demo shell: Chromium, LibreOffice, Text Editor, +Amberol and Snapshot are in the launcher alongside the terminal tooling — so +you can read these docs in a browser while you try it, or boot the stick to +rescue a machine that won't start and get a document off it. Installed +machines get their app list from the template's `home.packages` instead, which +is yours to edit. + Like what you see? **`nomarchy-install`** (in a terminal) walks you through installing to disk: pick a disk, LUKS2 full-disk encryption **by default** (in exchange the desktop logs in passwordless — the passphrase already diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index 2ec3759..d42c313 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -78,11 +78,17 @@ tested directly against a stubbed `smartctl`). generation the ISO pins for offline installs contains the chromium binary, `chromium-browser.desktop`, and all three HTTP/HTML handlers (mime.nix sets them; template ships the package). The Acer sighting is the -LIVE session, which ships NO browser by design (mime defaults name chromium, -GIO skips it while absent) — #103 adds live baseline apps. Live posture is -now explicit in the flake comment. Remains: a test-install VM run proving -chromium launches post-install (chain #97's Bluetooth-click V2 into the -same run). +LIVE session, which shipped NO browser by design (mime defaults name chromium, +GIO skips it while absent). + +**Update 2026-07-14:** the live half is **gone** — #103 shipped, so the live +session now carries chromium (plus office/editor/music/camera) on PATH and in +the launcher, and `checks.live-baseline-apps` asserts HTTPS still resolves to +`chromium-browser.desktop` *and* that the entry it names is actually present — +the exact "mime names a package nothing ships" trap this item found. What +remains here is only the **installed** path: a test-install VM run proving +chromium launches post-install (chain #97's Bluetooth-click V2 into the same +run). Chromium is the resolved default-browser decision and is present in the downstream template, but this hardware pass found no usable default browser. @@ -91,6 +97,31 @@ template source. Pass = Chromium launches after installation and HTTP/HTTPS mime defaults resolve to `chromium-browser.desktop` (and the intended live-ISO browser posture is explicit). +### 119. `text/plain` names vscode, which the live ISO does not ship + +Found while shipping #103 (2026-07-14), deliberately not fixed there — same +bug class as #94, one mime key over. `modules/home/mime.nix:48` assigns +`text/plain = code.desktop`, and vscode ships only in the **template**, never +on the live ISO. GIO silently skips an entry whose desktop file is absent, so +opening a text file in the live session finds no handler at all — the exact +shape of the no-default-browser bug, and now the only one left of its kind +since #103 put chromium on the live medium. + +Two ways it bites, and a fix should settle both: (1) the live session, which +now ships `gnome-text-editor` (`org.gnome.TextEditor.desktop`) — the obvious +live handler; (2) any installed machine where the user takes the template at +its word and deletes the `vscode` line (opt-out = delete the line, per the +option-surface convention), which silently breaks `text/plain` with no warning. + +The general trap is worth fixing once rather than per-key: a mime default +naming a package the profile does not carry is invisible until a user +double-clicks a file. `checks.live-baseline-apps` now guards exactly this for +HTTPS (asserts the named .desktop is present, not merely named) — the cheap +version of this item is extending that assertion to every key in +`defaultApplications`, which would have caught both #94 and this. Pass = no +mime default names a desktop entry the profile lacks, on the live ISO and on +a template install, and a guard fails on a regression. + ### 95. Live ISO/install: Ghostty does not open Reproduce from the launcher and a terminal, capture its stderr/journal, and @@ -137,6 +168,79 @@ pre-existing ISO-pinning gap. ## NEXT +### 120. A netinstall ISO, next to the fat offline one + +Bernardo 2026-07-14, after seeing the measured size: **keep the current ISO +exactly as it is** — the guaranteed offline install is the feature it buys — +and ship a **much lighter netinstall variant alongside it**. Two products, one +distro: "works on a plane" and "8 GiB is absurd to download" are both true, and +a second target settles them without compromising either. + +**Measured facts (2026-07-14), so this starts from numbers, not vibes:** +- Current ISO **8.078 GiB** compressed; **18.03 GiB** of store uncompressed + (`zstd -19`, 2.23:1 — compression is already near-max, not the lever). +- The offline pin (`system.extraDependencies`, 60 roots: a representative + installed system + the template HM closure + all flake inputs) is **4.02 GiB + uncompressed of that — only ~22%**. Dropping it entirely still leaves a + **14.01 GiB** desktop → roughly **6.3 GiB** compressed at the same ratio. + **So "no pin" alone is NOT the lighter ISO** — this is the trap to avoid. +- The 14 GiB desktop's own top weights: libreoffice 1457 MiB, initrd 1369, + linux-firmware 770, chromium ×2 (1391 combined — see #121), llvm-lib 540, + bibata-cursors 322, mesa 264, mbrola-voices 259, nerd-fonts ~420 combined. + +**So the real decision is what a netinstall ISO IS**, and it should be settled +first (`[human]`): (a) the full try-before-install desktop minus the pin +(~6.3 GiB — barely lighter, probably not worth a second target); (b) a **TUI +installer only, no desktop** (~1 GiB, the actual "netinstall" in the Debian +sense) which drops "try before install" from that medium — the fat ISO still +offers it; (c) a middle desktop (no libreoffice/chromium — but note #103 just +put those there deliberately, and a *demo* desktop that can't browse is the +bug #103 fixed). + +**The gotcha that decides feasibility:** without the pin, a netinstall target +fetches from `cache.nixos.org` for stock nixpkgs paths — but **Nomarchy's own +derivations are in no binary cache**, so they would build *from source on the +user's machine* during install. That is the same failure `tools/vm/gap-analysis.py` +exists to diagnose (and #113 is a live instance of). So this item probably +depends on a public binary cache (cachix) for the flake's own outputs, or it +trades an 8 GiB download for a 40-minute install. Establish that before +building the target. + +Pass = a second, documented ISO target that is *substantially* smaller (state +the measured number, both ISOs built from one tree), installs successfully with +a network in a QEMU run, says clearly at boot that it needs one, and leaves the +offline ISO's behaviour untouched (`checks.*` for the offline path stay green). + +### 121. The Widevine chromium wrapper drags a second 687 MiB chromium along + +Found while measuring #103 (2026-07-14). **Pre-existing and not live-only** — +it is in the template HM closure, so it is on **every installed Nomarchy +machine** and in the ISO, and predates #103 by however long chromium has been +the default browser. + +`templates/downstream/home.nix` ships `chromium.override { enableWideVine = +true; }` (correctly — DRM for Netflix/Spotify). The resulting wrapper depends on +**two** unwrapped builds: + + 704 MiB chromium-unwrapped-150.0.7871.114-wv ← the browser it runs + 687 MiB chromium-unwrapped-150.0.7871.114 ← plain build, pulled in for + `share/applications` ONLY + +`nix why-depends --precise` on the live closure shows the wrapped +`chromium-…/share/applications` symlinking into the *plain* unwrapped output, +which retains the whole 687 MiB derivation for a directory of `.desktop` files. +Nothing runs it. + +Investigate whether this is a nixpkgs wrapper bug (the wrapper should take its +desktop entry from the same variant it wraps) — fix upstream and/or work around +it locally, but **verify the fix by closure diff, not by reading the +expression**: `nix path-info -r | grep chromium-unwrapped` +should list one full build plus the small sandbox. Do **not** "fix" it by +dropping `enableWideVine` — that silently removes DRM playback, which is a +feature decision (ROADMAP § Default application suite), not a size cleanup. +Pass = one full chromium in the closure, DRM still works (V3: a Widevine page +plays on hardware), and the measured install/ISO delta is recorded. + ### 115. Suspend-then-hibernate, with a way to set it up Bernardo, 2026-07-14: a suspended laptop should be able to fall through to @@ -183,41 +287,6 @@ existing downstream checkout both work, every in-repo reference (modules, tools, template, docs) uses the new name, and the shim is documented with the release it can be dropped in. -### 103. Live ISO baseline desktop applications - -**Confirmed again on hardware, Bernardo 2026-07-14** (live ISO): still no -browser, and no office/utility apps — *"that makes a live iso useful"*. This -is the item's **why**, and it is worth more than the app list: a live ISO is -what someone judges the distro by before installing, and what a user boots to -rescue a machine that will not start — reading a wiki page, saving a document -off a dying disk, checking a webmail. Nomarchy's live session currently cannot -do any of those. - -**Verified inventory 2026-07-14** (eval of `nomarchy-live`'s HM packages + -`environment.systemPackages`): `chromium=no firefox=no libreoffice=no -amberol=no snapshot=no text-editor=no`. What the live session *does* carry is -terminal tooling (yazi, btop, bat, fd, ripgrep, ghostty) plus zathura (PDF) -and imv (images) — so the gap is exactly the GUI apps a non-Nix user would -reach for. #94 established this is *by design* (the live profile never named -them) and pointed here for the fix; #94's own remaining V2 (chromium launches -post-install) is a different path and stays separate. - -Make Chromium and Firefox, `libreoffice-fresh`, GNOME Text Editor, Amberol, and -GNOME Snapshot explicitly available in the live profile and application -launcher. Text Editor and Snapshot are the maintained gedit/Cheese successors; -HTTP remains assigned to Chromium. Pass = all six launch in the live session -and the resulting ISO-size delta is recorded. - -**Settle before starting (`[human]`, and the reason this is not just a package -list):** the ISO-size delta is the whole trade — Firefox *and* Chromium *and* -libreoffice-fresh is plausibly +2 GB on an image people download, and the -squashfs cannot be trimmed after the fact. Options are (a) ship both browsers, -(b) one browser (Chromium, since it already owns the HTTP mime default and the -installed template), (c) a lighter office story than libreoffice-fresh for the -live medium only. Record the measured delta per option rather than guessing; -`nomarchy-live` and the installed `nomarchy` profile need not carry the same -set, and the live medium is the one with a size ceiling. - ### 104. Runtime Airplane mode Add Airplane mode under System connectivity controls. It must disable Wi-Fi diff --git a/agent/HARDWARE-QUEUE.md b/agent/HARDWARE-QUEUE.md index effaf53..a71d44d 100644 --- a/agent/HARDWARE-QUEUE.md +++ b/agent/HARDWARE-QUEUE.md @@ -410,6 +410,23 @@ the **T14s** (webcam case). survives relogin (the ExecCondition gate on the swapped unit — the eval check proves the wiring, not the runtime gate). **Pass** = warm shift at the location's night + toggle/persistence intact. +- [ ] **#103 live-ISO baseline apps actually launch** (this commit) — the + half no headless check can reach: `checks.live-baseline-apps` proves the + binaries and `.desktop` entries are in the exact HM generation the ISO + ships, but not that a GUI app opens on real hardware (the agent may not + drive a graphical VM, and the live ISO has no SSH to script one). On the + **Acer M5-481T** (the machine that found this — its GPU is the oldest + shipped, so it is the honest test), boot the new live ISO and, from the + launcher only — no terminal, that's the point: open **Chromium**, + **LibreOffice** (Writer), **Text Editor**, **Amberol**, **Snapshot**. + **Pass** = all five are *listed in the launcher* and each opens a window. + Also: a `.html` file opens in Chromium (the HTTPS mime default now names + a browser that is present — #94's exact bug). Firefox is deliberately + absent; its absence is correct, not a miss. + **Known-not-covered:** a `.txt` file has no handler on the live ISO — + `text/plain` still names vscode, which the live medium never ships + (BACKLOG #119). Text Editor opening from the launcher is the pass here; + double-clicking a text file is #119's problem, so don't file it twice. ## AMD dev box only - [ ] **AMD runtime bits** — VA-API (`vainfo` → radeonsi), amd-pstate EPP diff --git a/agent/JOURNAL.md b/agent/JOURNAL.md index ff176c6..48c3230 100644 --- a/agent/JOURNAL.md +++ b/agent/JOURNAL.md @@ -19,6 +19,48 @@ Template: --- +## 2026-07-14 — #103: the live ISO gets a desktop, for +41 MiB (this commit) +- **Task:** BACKLOG #103 — Bernardo, live ISO 2026-07-14: still no browser, + no office. *"That makes a live iso useful."* +- **Did:** the live HM user in `flake.nix` now names its own set — chromium, + libreoffice-fresh, gnome-text-editor, amberol, snapshot. Firefox dropped + (Bernardo's call): chromium owns the HTTP mime default and ships in the + installed template, and it was the one item that would cost a real closure. +- **The finding that inverted the trade:** I asked Bernardo to choose on a + ~+2 GB premise. Wrong premise — `system.extraDependencies` *already* pins + the template's HM closure into the ISO for offline installs, so chromium/ + libreoffice/amberol were **already in the image's store**, just absent from + the live user's profile. Verified, not assumed: the live and template + chromium resolve to the *same store path*, so reusing the template's exact + `chromium.override { enableWideVine = true; }` costs zero — a plain + `chromium` would have been a second 2.5 GiB closure. Only text-editor and + snapshot are new: 9 paths, 133 MiB uncompressed (99 MiB is gst-plugins-rs). + His Firefox call still held for the right reason — it was genuinely unpinned. +- **Verified:** **V2** — measured ISO delta (the item's pass condition), both + built from the same tree: **8.038 → 8.078 GiB = +41.2 MiB (+0.50%)**. + New `checks.live-baseline-apps` asserts each app is on PATH *and* has a + .desktop the launcher can see (a bin without one is invisible), that HTTPS + resolves to a chromium entry that is actually **present** (#94's trap), and + that Firefox has not crept back. **Proved to fail:** dropping snapshot makes + it name the missing entry. flake check + live-install-entry + option-docs + + template-sot green. +- **Pending:** **V3** — that the apps *launch* needs hardware (HARDWARE-QUEUE, + Acer M5-481T: from the launcher only, no terminal). New **#119**: `text/plain` + names vscode, which the live ISO never ships — #94's bug one mime key over, + and now the last of its kind. +- **Where the 8 GiB actually goes** (Bernardo asked how Debian fits one in 4 GB; + I first blamed the offline-install pin and **that was wrong** — measured, the + pin is 4.02 of 18.03 GiB uncompressed, ~22%). The live *desktop itself* is + **14.01 GiB**: libreoffice 1457 MiB, initrd 1369, linux-firmware 770, mesa, + fonts, two chromiums (see #121). Debian fits ~4 GB by installing *by copying + the live filesystem* (no second closure) and by sharing one library version + archive-wide, where Nix pins exact deps per package. Compression is not the + gap — we already use `zstd -19` (2.23:1). Bernardo's call: **keep the offline + ISO as is**, add a netinstall variant → **#120** (NEXT). Filed **#121**: the + Widevine chromium wrapper drags a *second* 687 MiB unwrapped chromium in for + its `share/applications` alone — pre-existing, on every installed machine. +- **Next suggestion:** #118 (smartd self-gate) — Bernardo's stated order. + ## 2026-07-14 — triage: #117 is not work, it's an input to #110 (this commit) - **Task:** Bernardo's call on #117 (filed by the previous entry, which suggested it as the next item — it is not; that suggestion is stale). diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 8cd828b..60dd021 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -367,10 +367,43 @@ Design/decision records and a running log of shipped work (items marked just reinholds what a package list already gives, and the honest opt-out for a package is *deleting the line*. So the suite is the user's own curated list (extending the existing `# firefox` convention), not a distro-module feature — - which also keeps the apps out of the live ISO automatically (it never starts - from the template) and respects that editor/office/graphics are personal-taste - choices, not defaults to impose. Unfree `vscode` evaluates fine — `mkFlake` - and the system both set `allowUnfree = true`. + and it respects that editor/office/graphics are personal-taste choices, not + defaults to impose. Unfree `vscode` evaluates fine — `mkFlake` and the system + both set `allowUnfree = true`. **Amended 2026-07-14 (#103):** this design + also kept the apps off the live ISO automatically (it never starts from the + template) — which was read as a feature here, and was in fact the bug: the + live session had no browser and no office at all. The live medium now names + its own baseline set explicitly (see below); "the template is the app list" + still holds for *installed* machines. +- ✓ **Live-ISO baseline apps (#103):** the live session shipped the distro + modules only — no browser, no office — for as long as it existed. That is + the thing a user judges the distro by *before* installing, and what they + boot to rescue a machine that will not start; it could do neither. The live + HM user in `flake.nix` now names its own set: **Chromium, libreoffice-fresh, + gnome-text-editor, amberol, snapshot** (Bernardo confirmed the gap on real + hardware 2026-07-14). + **Firefox deliberately excluded** (Bernardo's call): Chromium already owns + the HTTP mime default and ships in the installed template, so it is the + browser that matches what a user gets after installing — and it was the one + item on #103's original list that would have cost a real closure. + **The size finding, which inverted the trade:** `system.extraDependencies` + already pins the template's HM closure into the ISO for offline installs, so + chromium/libreoffice/amberol were *already in the image's store* — merely + absent from the live user's profile, so nothing put them on PATH or in the + launcher. Reusing the template's **exact** derivations (including + `chromium.override { enableWideVine = true; }` — a plain `chromium` would be + a second full browser build) makes those three cost **zero**. Only + gnome-text-editor and snapshot are new: 9 store paths, 133 MiB uncompressed + (99 MiB of it gst-plugins-rs, Snapshot's media stack). **Measured ISO delta: + 8.038 → 8.078 GiB = +41.2 MiB (+0.50%)**, both built from the same tree. + Guard: `checks.live-baseline-apps` asserts each app is on PATH *and* has a + `.desktop` the launcher can see (a binary without one is invisible, which is + the failure that matters), that HTTPS resolves to a chromium entry which is + actually **present** — #94's exact trap, a mime default naming a package + nothing ships — and that Firefox has not reappeared, since that is a size + decision rather than a drive-by. Proved to fail: dropping snapshot makes it + name the missing entry. **V3 pending** — that the apps *launch* needs real + hardware (HARDWARE-QUEUE, Acer M5-481T). - ✓ **Plymouth logo contrast:** the shipped art was a fixed navy that vanished on dark bases. `modules/nixos/plymouth.nix` now recolors every element from the palette at build time (flat fill, alpha kept): diff --git a/flake.nix b/flake.nix index f3dc084..1ae80e0 100644 --- a/flake.nix +++ b/flake.nix @@ -559,6 +559,62 @@ # sheet to ✖/exit-1 and names the unit; with the failure # cleared it reports healthy/exit-0. Minimal node (just the # package) — the disk/flake/snapper checks self-skip in a VM. + # Live-ISO baseline apps (ROADMAP § live-ISO baseline apps, #103). + # The live session shipped no + # browser and no office for as long as it existed — the thing a user + # judges the distro by before installing, and boots to rescue a dead + # machine. Nothing in a build fails when an app silently leaves the + # live profile (it just stops being in the launcher, which is + # invisible until someone boots the ISO on real hardware and looks), + # so assert both halves: on PATH *and* a .desktop the launcher can + # see. Same artifacts the ISO ships, no ISO build. + live-baseline-apps = + let + liveHm = + self.nixosConfigurations.nomarchy-live.config.home-manager.users.${username}; + gen = liveHm.home.activationPackage; + in + pkgs.runCommand "nomarchy-live-baseline-apps" + { nativeBuildInputs = [ pkgs.gnugrep pkgs.findutils ]; } + '' + set -euo pipefail + apps=${gen}/home-path/share/applications + bins=${gen}/home-path/bin + + # Binary + launcher entry for each baseline app. The .desktop + # is what makes it discoverable — VISION's "discoverable + # without reading the README" — so a bin without one fails. + for d in chromium-browser.desktop \ + startcenter.desktop writer.desktop calc.desktop \ + impress.desktop \ + org.gnome.TextEditor.desktop \ + io.bassi.Amberol.desktop \ + org.gnome.Snapshot.desktop; do + test -f "$apps/$d" || { echo "live-baseline-apps: MISSING launcher entry $d"; exit 1; } + done + + for b in chromium libreoffice gnome-text-editor amberol snapshot; do + test -x "$bins/$b" || { echo "live-baseline-apps: MISSING binary $b"; exit 1; } + done + + # HTTP must still resolve to the browser that is actually + # present (#94: mime named chromium while nothing shipped it, + # so GIO silently skipped the entry and the live session had + # no default browser at all). + mimes=${gen}/home-files/.config/mimeapps.list + grep -q '^x-scheme-handler/https=chromium-browser.desktop' "$mimes" + test -f "$apps/chromium-browser.desktop" + + # Firefox is deliberately absent — a second browser is the one + # item in #103's list that costs a real closure, and chromium + # owns the mime default (Bernardo 2026-07-14). If it ever + # ships here, that is a size decision, not a drive-by. + test ! -f "$apps/firefox.desktop" || { echo "live-baseline-apps: firefox reappeared — size decision, see #103"; exit 1; } + + echo "live-baseline-apps: ok — browser, office, editor, music, camera on PATH + in the launcher" + touch $out + ''; + # Live-ISO install affordance (BACKLOG #57): desktop entry baked # into the live host's HM generation + installer on PATH + Tools # menu gate in nomarchy-menu. Builds the real nomarchy-live HM @@ -1758,16 +1814,44 @@ home-manager = { useGlobalPkgs = true; useUserPackages = true; - users.${username} = { + users.${username} = { pkgs, ... }: { imports = [ self.homeModules.nomarchy ]; nomarchy.stateFile = ./theme-state.json; - # Deliberate live-session posture (BACKLOG #94): the live - # desktop ships the distro modules only — NO browser or - # template app suite (mime defaults still name chromium, - # which GIO skips while absent). The template's Chromium + - # apps arrive with installation (the ISO pins that HM - # closure for offline installs); #103 adds a baseline app - # set to the live session itself. + + # Live-session baseline apps (ROADMAP § live-ISO baseline + # apps, #103). Until now the + # live desktop shipped the distro modules only — no browser, + # no office — which is what a user judges the distro by before + # installing, and what they boot to rescue a machine that + # won't start. Terminal tooling (yazi, btop) plus zathura/imv + # already ride along with the modules; this adds the GUI apps + # a non-Nix user reaches for. + # + # These cost almost NOTHING on the ISO: system.extraDependencies + # below already pins the template's HM closure for offline + # installs, so chromium/libreoffice-fresh/amberol are in the + # image's store either way — they were merely absent from the + # live user's profile, so nothing put them on PATH or in the + # launcher. Reuse the template's EXACT derivations and the + # store paths are shared; a plain `chromium` (no override) + # would be a second full browser build instead. + # + # Firefox is deliberately NOT here (Bernardo 2026-07-14): + # Chromium already owns the HTTP mime default and ships in the + # installed template, so it is the browser that matches what a + # user gets after installing — and a second browser is the one + # item in #103's list that would cost a real closure. It stays + # a template opt-in for installed machines. + home.packages = with pkgs; [ + # Same override as templates/downstream/home.nix — must + # match exactly to share the store path (Widevine DRM; + # unfree CDM, allowUnfree is on for this system). + (chromium.override { enableWideVine = true; }) + libreoffice-fresh # documents/sheets/slides off a dying disk + gnome-text-editor # the maintained gedit successor + amberol # music player (also in the template) + snapshot # camera — the maintained Cheese successor + ]; }; }; diff --git a/modules/home/mime.nix b/modules/home/mime.nix index 47db7c7..3e2d4b9 100644 --- a/modules/home/mime.nix +++ b/modules/home/mime.nix @@ -50,9 +50,12 @@ lib.mkIf config.nomarchy.mime.enable { # The system-side Thunar (nomarchy.system.fileManager). "inode/directory" = "thunar.desktop"; - # Template ships chromium (chromium-browser.desktop). Entry is - # skipped by GIO if the package is deleted; install another browser - # and/or override these keys to retarget. + # Template ships chromium (chromium-browser.desktop), and since #103 + # so does the live ISO — an entry naming a package nothing installs is + # silently skipped by GIO, which is exactly how the live session ended + # up with no default browser at all (#94). Delete the package and the + # entry goes quiet again; install another browser and/or override these + # keys to retarget. "text/html" = "chromium-browser.desktop"; "x-scheme-handler/http" = "chromium-browser.desktop"; "x-scheme-handler/https" = "chromium-browser.desktop";