fix(mime): text/plain falls through to Text Editor on live (#119)
All checks were successful
Check / eval (push) Successful in 4m5s
All checks were successful
Check / eval (push) Successful in 4m5s
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.
This commit is contained in:
@@ -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
|
mime defaults resolve to `chromium-browser.desktop` (and the intended live-ISO
|
||||||
browser posture is explicit).
|
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
|
### 95. Live ISO/install: Ghostty does not open
|
||||||
|
|
||||||
Reproduce from the launcher and a terminal, capture its stderr/journal, and
|
Reproduce from the launcher and a terminal, capture its stderr/journal, and
|
||||||
|
|||||||
@@ -421,12 +421,11 @@ the **T14s** (webcam case).
|
|||||||
**LibreOffice** (Writer), **Text Editor**, **Amberol**, **Snapshot**.
|
**LibreOffice** (Writer), **Text Editor**, **Amberol**, **Snapshot**.
|
||||||
**Pass** = all five are *listed in the launcher* and each opens a window.
|
**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
|
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
|
a browser that is present — #94's exact bug), and a `.txt` file opens in
|
||||||
absent; its absence is correct, not a miss.
|
**Text Editor** (`text/plain` falls through to
|
||||||
**Known-not-covered:** a `.txt` file has no handler on the live ISO —
|
`org.gnome.TextEditor.desktop` after #119; vscode remains preferred on
|
||||||
`text/plain` still names vscode, which the live medium never ships
|
template installs). Firefox is deliberately absent; its absence is
|
||||||
(BACKLOG #119). Text Editor opening from the launcher is the pass here;
|
correct, not a miss.
|
||||||
double-clicking a text file is #119's problem, so don't file it twice.
|
|
||||||
|
|
||||||
## AMD dev box only
|
## AMD dev box only
|
||||||
- [ ] **#118 smartd still runs where drives DO have SMART** (this commit) — the
|
- [ ] **#118 smartd still runs where drives DO have SMART** (this commit) — the
|
||||||
|
|||||||
@@ -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)
|
## 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
|
- **Task:** BACKLOG #118 — Bernardo's live ISO showed a red Waybar health icon
|
||||||
reporting smartd.
|
reporting smartd.
|
||||||
|
|||||||
@@ -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
|
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
|
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,
|
HM user in `flake.nix` now names its own set: **Chromium, libreoffice-fresh,
|
||||||
gnome-text-editor, amberol, snapshot** (Bernardo confirmed the gap on real
|
gnome-text-editor, amberol, mpv (#119), snapshot** (Bernardo confirmed the
|
||||||
hardware 2026-07-14).
|
gap on real hardware 2026-07-14).
|
||||||
**Firefox deliberately excluded** (Bernardo's call): Chromium already owns
|
**Firefox deliberately excluded** (Bernardo's call): Chromium already owns
|
||||||
the HTTP mime default and ships in the installed template, so it is the
|
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
|
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
|
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
|
name the missing entry. **V3 pending** — that the apps *launch* needs real
|
||||||
hardware (HARDWARE-QUEUE, Acer M5-481T).
|
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
|
- ✓ **smartd self-gates on the hardware (#118):** Bernardo booted the live ISO
|
||||||
and the Waybar health icon was red. Everything downstream was working
|
and the Waybar health icon was red. Everything downstream was working
|
||||||
correctly, which is what made it worth writing down: smartd's config is
|
correctly, which is what made it worth writing down: smartd's config is
|
||||||
|
|||||||
94
flake.nix
94
flake.nix
@@ -560,23 +560,37 @@
|
|||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Live-ISO baseline apps (ROADMAP § live-ISO baseline apps, #103).
|
# Live-ISO baseline apps (ROADMAP § live-ISO baseline apps, #103)
|
||||||
# The live session shipped no
|
# plus the mime-default presence guard (#94 / #119). The live
|
||||||
# browser and no office for as long as it existed — the thing a user
|
# session shipped no browser and no office for as long as it
|
||||||
# judges the distro by before installing, and boots to rescue a dead
|
# existed — the thing a user judges the distro by before installing,
|
||||||
# machine. Nothing in a build fails when an app silently leaves the
|
# and boots to rescue a dead machine. Nothing in a build fails when
|
||||||
# live profile (it just stops being in the launcher, which is
|
# an app silently leaves the live profile (it just stops being in
|
||||||
# invisible until someone boots the ISO on real hardware and looks),
|
# the launcher), and a mime default that names a missing .desktop is
|
||||||
# so assert both halves: on PATH *and* a .desktop the launcher can
|
# silently skipped by GIO (no handler at all) — so assert both:
|
||||||
# see. Same artifacts the ISO ships, no ISO build.
|
# 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 =
|
live-baseline-apps =
|
||||||
let
|
let
|
||||||
liveHm =
|
liveHm =
|
||||||
self.nixosConfigurations.nomarchy-live.config.home-manager.users.${username};
|
self.nixosConfigurations.nomarchy-live.config.home-manager.users.${username};
|
||||||
gen = liveHm.home.activationPackage;
|
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
|
in
|
||||||
pkgs.runCommand "nomarchy-live-baseline-apps"
|
pkgs.runCommand "nomarchy-live-baseline-apps"
|
||||||
{ nativeBuildInputs = [ pkgs.gnugrep pkgs.findutils ]; }
|
{ nativeBuildInputs = [ pkgs.gnugrep pkgs.findutils pkgs.python3 ]; }
|
||||||
''
|
''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
apps=${gen}/home-path/share/applications
|
apps=${gen}/home-path/share/applications
|
||||||
@@ -590,11 +604,12 @@
|
|||||||
impress.desktop \
|
impress.desktop \
|
||||||
org.gnome.TextEditor.desktop \
|
org.gnome.TextEditor.desktop \
|
||||||
io.bassi.Amberol.desktop \
|
io.bassi.Amberol.desktop \
|
||||||
|
mpv.desktop \
|
||||||
org.gnome.Snapshot.desktop; do
|
org.gnome.Snapshot.desktop; do
|
||||||
test -f "$apps/$d" || { echo "live-baseline-apps: MISSING launcher entry $d"; exit 1; }
|
test -f "$apps/$d" || { echo "live-baseline-apps: MISSING launcher entry $d"; exit 1; }
|
||||||
done
|
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; }
|
test -x "$bins/$b" || { echo "live-baseline-apps: MISSING binary $b"; exit 1; }
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -603,16 +618,67 @@
|
|||||||
# so GIO silently skipped the entry and the live session had
|
# so GIO silently skipped the entry and the live session had
|
||||||
# no default browser at all).
|
# no default browser at all).
|
||||||
mimes=${gen}/home-files/.config/mimeapps.list
|
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"
|
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
|
# Firefox is deliberately absent — a second browser is the one
|
||||||
# item in #103's list that costs a real closure, and chromium
|
# item in #103's list that costs a real closure, and chromium
|
||||||
# owns the mime default (Bernardo 2026-07-14). If it ever
|
# owns the mime default (Bernardo 2026-07-14). If it ever
|
||||||
# ships here, that is a size decision, not a drive-by.
|
# 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; }
|
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
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@@ -1919,6 +1985,8 @@
|
|||||||
libreoffice-fresh # documents/sheets/slides off a dying disk
|
libreoffice-fresh # documents/sheets/slides off a dying disk
|
||||||
gnome-text-editor # the maintained gedit successor
|
gnome-text-editor # the maintained gedit successor
|
||||||
amberol # music player (also in the template)
|
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
|
snapshot # camera — the maintained Cheese successor
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,8 +44,12 @@ lib.mkIf config.nomarchy.mime.enable {
|
|||||||
"audio/x-m4a" = "io.bassi.Amberol.desktop";
|
"audio/x-m4a" = "io.bassi.Amberol.desktop";
|
||||||
"audio/aac" = "io.bassi.Amberol.desktop";
|
"audio/aac" = "io.bassi.Amberol.desktop";
|
||||||
|
|
||||||
# The template's active editor; degrades if you drop vscode.
|
# Prefer the template's vscode; fall through to gnome-text-editor
|
||||||
"text/plain" = "code.desktop";
|
# (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).
|
# The system-side Thunar (nomarchy.system.fileManager).
|
||||||
"inode/directory" = "thunar.desktop";
|
"inode/directory" = "thunar.desktop";
|
||||||
|
|||||||
Reference in New Issue
Block a user