mosaic-doctor: check the installed TOOLS-REFERENCE against the installed wrappers (host-side half of the tool-index gate) #1176

Open
opened 2026-08-12 22:04:12 +00:00 by Mos · 0 comments
Contributor

The gap that remains after the CI gate

PR #1174 adds check-tools-index.sh, which fails CI when a tools/git/ wrapper ships
without an entry in guides/TOOLS-REFERENCE.md, or when an entry names a wrapper that no
longer exists. That closes drift in the repo.

It does not close drift on a host. The index went to 23% (6 of 26 wrappers documented)
without anyone noticing, and the reason nobody noticed is that nobody reads the index
looking for absences — an agent reads it looking for a tool, finds nothing, and concludes
the tool does not exist. That failure mode is silent by construction.

A host can drift out of step in ways CI cannot see:

  • the installed ~/.config/mosaic is older than the repo, so wrappers named in a fresh
    guide are genuinely absent;
  • a partial or interrupted upgrade leaves tools/ and guides/ from different releases;
  • a wrapper is present but not executable, which reads to every [ -x ] check exactly
    like absent.

Proposal

Add the check to mosaic-doctor, which is already the host-side consistency surface — it
does check_runtime_file_copy and reports "Runtime file drift" today. The same two
directions as the CI gate, run against the installed tree rather than the repo:

  • every executable in ~/.config/mosaic/tools/<suite>/ has an entry in the installed
    guides/TOOLS-REFERENCE.md;
  • every entry names a file that exists and is executable.

Report as a warning, not a hard failure — mosaic-doctor runs on hosts mid-upgrade, and a
doctor that refuses to run is a doctor people stop running.

On "a scheduled task"

Worth stating why this should be a doctor check rather than its own timer. A timer answers
when; it does not answer what, and a scheduled consistency check that reports to
nobody is a second authority for a fact mosaic-doctor already owns. The framework
doctrine is explicit — never create a second authority for the same fact. If a periodic
run is wanted, schedule mosaic-doctor and let its output be the one place a host's
health is stated.

Scope note

check-tools-index.sh currently enforces ENFORCED_SUITES=(git). The other suites
(portainer, authentik, woodpecker, cloudflare, glpi, health) are listed but not enforced,
deliberately: enforcing them in the same change would have mixed a mechanical fix with a
large documentation backlog. Widening the enforced set is a follow-up, and the host check
should read the same list rather than hardcoding its own.

## The gap that remains after the CI gate PR #1174 adds `check-tools-index.sh`, which fails CI when a `tools/git/` wrapper ships without an entry in `guides/TOOLS-REFERENCE.md`, or when an entry names a wrapper that no longer exists. That closes drift **in the repo**. It does not close drift **on a host**. The index went to 23% (6 of 26 wrappers documented) without anyone noticing, and the reason nobody noticed is that nobody reads the index looking for absences — an agent reads it looking for a tool, finds nothing, and concludes the tool does not exist. That failure mode is silent by construction. A host can drift out of step in ways CI cannot see: - the installed `~/.config/mosaic` is older than the repo, so wrappers named in a fresh guide are genuinely absent; - a partial or interrupted upgrade leaves `tools/` and `guides/` from different releases; - a wrapper is present but not executable, which reads to every `[ -x ]` check exactly like absent. ## Proposal Add the check to `mosaic-doctor`, which is already the host-side consistency surface — it does `check_runtime_file_copy` and reports "Runtime file drift" today. The same two directions as the CI gate, run against the **installed** tree rather than the repo: - every executable in `~/.config/mosaic/tools/<suite>/` has an entry in the installed `guides/TOOLS-REFERENCE.md`; - every entry names a file that exists and is executable. Report as a warning, not a hard failure — `mosaic-doctor` runs on hosts mid-upgrade, and a doctor that refuses to run is a doctor people stop running. ## On "a scheduled task" Worth stating why this should be a doctor check rather than its own timer. A timer answers *when*; it does not answer *what*, and a scheduled consistency check that reports to nobody is a second authority for a fact `mosaic-doctor` already owns. The framework doctrine is explicit — never create a second authority for the same fact. If a periodic run is wanted, schedule `mosaic-doctor` and let its output be the one place a host's health is stated. ## Scope note `check-tools-index.sh` currently enforces `ENFORCED_SUITES=(git)`. The other suites (portainer, authentik, woodpecker, cloudflare, glpi, health) are listed but not enforced, deliberately: enforcing them in the same change would have mixed a mechanical fix with a large documentation backlog. Widening the enforced set is a follow-up, and the host check should read the same list rather than hardcoding its own.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1176