From 355d8cb1a40e49c5939e2cb11077842d10d3eb11 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Wed, 15 Jul 2026 09:24:48 +0100 Subject: [PATCH] fix(mime): text/plain falls through to Text Editor on live (#119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A singleton default naming code.desktop left the live ISO with no text handler — GIO skips missing .desktop files and offers nothing. Prefer vscode when present, then org.gnome.TextEditor.desktop. Live also gains mpv (video defaults had the same hole; free via the template pin). checks.live-baseline-apps now requires every Default Applications key to resolve to a present .desktop on live (HM + system path) and on the default template install. Proved to fail on a vscode-only text/plain. Verified: V2 (live-baseline-apps green + prove-to-fail); V0 flake check. --- agent/BACKLOG.md | 25 ----------- agent/HARDWARE-QUEUE.md | 11 +++-- agent/JOURNAL.md | 20 +++++++++ docs/ROADMAP.md | 15 ++++++- flake.nix | 94 +++++++++++++++++++++++++++++++++++------ modules/home/mime.nix | 8 +++- 6 files changed, 125 insertions(+), 48 deletions(-) diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index 9586882..4fc9cba 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -55,31 +55,6 @@ 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 diff --git a/agent/HARDWARE-QUEUE.md b/agent/HARDWARE-QUEUE.md index cf48ced..8d6b7dd 100644 --- a/agent/HARDWARE-QUEUE.md +++ b/agent/HARDWARE-QUEUE.md @@ -421,12 +421,11 @@ the **T14s** (webcam case). **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. + a browser that is present — #94's exact bug), and a `.txt` file opens in + **Text Editor** (`text/plain` falls through to + `org.gnome.TextEditor.desktop` after #119; vscode remains preferred on + template installs). Firefox is deliberately absent; its absence is + correct, not a miss. ## AMD dev box only - [ ] **#118 smartd still runs where drives DO have SMART** (this commit) — the diff --git a/agent/JOURNAL.md b/agent/JOURNAL.md index a46a255..ba9bfd9 100644 --- a/agent/JOURNAL.md +++ b/agent/JOURNAL.md @@ -19,6 +19,26 @@ Template: --- +## 2026-07-15 — #119: mime defaults must name a present .desktop (this commit) +- **Task:** BACKLOG #119 — `text/plain` named vscode, which the live ISO never + ships (same GIO-skip trap as #94, one key over). +- **Did:** `text/plain` is now an ordered fallback + `code.desktop` → `org.gnome.TextEditor.desktop` (HM tries the next when the + preferred is missing). Live profile gains `mpv` too — video mime defaults + had the same hole and the package is free via the template pin. Extended + `checks.live-baseline-apps` so every `[Default Applications]` key has at + least one listed `.desktop` on **live** (HM path + system path for thunar) + and on the **default template install**. +- **Verified:** **V2** — check green; mimeapps.list renders + `text/plain=code.desktop;org.gnome.TextEditor.desktop`; **proved to fail** + when `text/plain` is a vscode-only singleton. V0 flake check green. +- **Pending:** V3 launch of a `.txt` on the Acer is covered by the existing + #103 HARDWARE-QUEUE entry (now expects Text Editor for text files). Opting + out of *both* vscode and Text Editor still leaves no handler — that is the + delete-the-line convention, not a silent live-ISO bug. +- **Next suggestion:** #95 (Ghostty does not open) or #94 residual + (test-install chromium launch). + ## 2026-07-14 — #118: smartd self-gates; the doctor was right all along (this commit) - **Task:** BACKLOG #118 — Bernardo's live ISO showed a red Waybar health icon reporting smartd. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 7ae1332..90f988e 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -380,8 +380,8 @@ Design/decision records and a running log of shipped work (items marked 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). + gnome-text-editor, amberol, mpv (#119), 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 @@ -404,6 +404,17 @@ Design/decision records and a running log of shipped work (items marked 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). +- ✓ **Mime defaults must name a present .desktop (#119):** same bug class as + #94, one key over. `text/plain` pointed at `code.desktop` (vscode), which + the live ISO never ships — GIO skips the missing entry and leaves no + handler, so a double-clicked `.txt` did nothing. Fix: ordered fallback + `code.desktop` → `org.gnome.TextEditor.desktop` (HM/GIO try the next when + preferred is missing); live gains `mpv` too (video defaults had the same + hole, free via the template pin). Guard extended: every + `[Default Applications]` key must have *at least one* listed `.desktop` in + the live HM path **or** system path (thunar is system-side) *and* on the + default template install — proved to fail when `text/plain` is a vscode + singleton. Template still prefers vscode when present. - ✓ **smartd self-gates on the hardware (#118):** Bernardo booted the live ISO and the Waybar health icon was red. Everything downstream was working correctly, which is what made it worth writing down: smartd's config is diff --git a/flake.nix b/flake.nix index cc67120..85f377d 100644 --- a/flake.nix +++ b/flake.nix @@ -560,23 +560,37 @@ touch $out ''; - # 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-ISO baseline apps (ROADMAP § live-ISO baseline apps, #103) + # plus the mime-default presence guard (#94 / #119). 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), and a mime default that names a missing .desktop is + # silently skipped by GIO (no handler at all) — so assert both: + # binaries + launcher entries for the baseline suite, and that + # every Default Applications key has at least one listed .desktop + # present in the live profile or system path (thunar is system-side). + # 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; + # system.path carries NixOS-side apps (thunar); HM-only + # home-path does not. A mime default that only names a + # system desktop must still resolve. + sysPath = + self.nixosConfigurations.nomarchy-live.config.system.path; + # Template install path: same mime defaults, different package + # set (vscode present, gnome-text-editor not). Guard both so + # a live-only fix cannot re-break the installed machine. + templateGen = downstream.homeConfigurations.me.activationPackage; + templateSys = + downstream.nixosConfigurations.default.config.system.path; in pkgs.runCommand "nomarchy-live-baseline-apps" - { nativeBuildInputs = [ pkgs.gnugrep pkgs.findutils ]; } + { nativeBuildInputs = [ pkgs.gnugrep pkgs.findutils pkgs.python3 ]; } '' set -euo pipefail apps=${gen}/home-path/share/applications @@ -590,11 +604,12 @@ impress.desktop \ org.gnome.TextEditor.desktop \ io.bassi.Amberol.desktop \ + mpv.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 + for b in chromium libreoffice gnome-text-editor amberol mpv snapshot; do test -x "$bins/$b" || { echo "live-baseline-apps: MISSING binary $b"; exit 1; } done @@ -603,16 +618,67 @@ # 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" + grep -q '^x-scheme-handler/https=chromium-browser.desktop' "$mimes" \ + || { echo "live-baseline-apps: https mime must name chromium-browser.desktop (#94)"; exit 1; } test -f "$apps/chromium-browser.desktop" + # text/plain must prefer vscode but fall through to the live + # editor (#119) — never a singleton that only names code. + grep -qE '^text/plain=.*org\.gnome\.TextEditor\.desktop' "$mimes" \ + || { echo "live-baseline-apps: text/plain must fall through to org.gnome.TextEditor.desktop (#119)"; exit 1; } + test -f "$apps/org.gnome.TextEditor.desktop" + + # Every Default Applications key: at least one listed + # .desktop must exist in home-path OR system path. A key + # whose every entry is missing is the #94/#119 bug class. + # Covers live *and* the default template install. + python3 - "$mimes" "$apps" "${sysPath}/share/applications" \ + "${templateGen}/home-files/.config/mimeapps.list" \ + "${templateGen}/home-path/share/applications" \ + "${templateSys}/share/applications" <<'PY' + import sys + from pathlib import Path + + def check(label, mimes, *app_dirs): + text = Path(mimes).read_text() + in_defaults = False + bad = [] + for line in text.splitlines(): + if line.startswith("["): + in_defaults = line.strip() == "[Default Applications]" + continue + if not in_defaults or not line.strip() or line.startswith("#"): + continue + if "=" not in line: + continue + key, val = line.split("=", 1) + desktops = [d for d in val.split(";") if d.strip()] + if not desktops: + bad.append(f"{key}= (empty)") + continue + if not any( + any((Path(d) / desk).is_file() for d in app_dirs) + for desk in desktops + ): + bad.append(f"{key}={';'.join(desktops)} (none present)") + if bad: + print(f"live-baseline-apps: mime defaults missing on {label}:") + for b in bad: + print(f" {b}") + sys.exit(1) + print(f"live-baseline-apps: mime defaults ok on {label}") + + check("live", sys.argv[1], sys.argv[2], sys.argv[3]) + check("template", sys.argv[4], sys.argv[5], sys.argv[6]) + PY + # 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" + echo "live-baseline-apps: ok — browser, office, editor, music, video, camera + mime defaults resolve" touch $out ''; @@ -1919,6 +1985,8 @@ libreoffice-fresh # documents/sheets/slides off a dying disk gnome-text-editor # the maintained gedit successor amberol # music player (also in the template) + mpv # video (mime defaults → mpv.desktop; also + # template — free on the ISO via the pin) snapshot # camera — the maintained Cheese successor ]; }; diff --git a/modules/home/mime.nix b/modules/home/mime.nix index 3e2d4b9..e2ac8aa 100644 --- a/modules/home/mime.nix +++ b/modules/home/mime.nix @@ -44,8 +44,12 @@ lib.mkIf config.nomarchy.mime.enable { "audio/x-m4a" = "io.bassi.Amberol.desktop"; "audio/aac" = "io.bassi.Amberol.desktop"; - # The template's active editor; degrades if you drop vscode. - "text/plain" = "code.desktop"; + # Prefer the template's vscode; fall through to gnome-text-editor + # (ships on the live ISO after #103, and is the only editor there). + # A singleton that names an absent .desktop is silently skipped by + # GIO and leaves no handler at all — the #94 / #119 trap. HM tries + # the next entry when the preferred one is missing. + "text/plain" = [ "code.desktop" "org.gnome.TextEditor.desktop" ]; # The system-side Thunar (nomarchy.system.fileManager). "inode/directory" = "thunar.desktop";