fix(#60): checks that lied, and claims the machine stopped honouring #61

Merged
dank merged 13 commits from fix/60-review-findings into main 2026-10-21 01:44:07 -07:00
34 changed files with 699 additions and 157 deletions
+10
View File
@@ -1,3 +1,13 @@
# LFS routing for image types. Measured 2026-10-21: this repo tracks ZERO LFS files
# (`git lfs ls-files` = 0) — the wallpaper library became live theme state and is gitignored
# (omp-docs/tools/dotfiles-deploy.md), so these four rules match nothing today. They are kept
# because tracked media is a plausible future and idle filters cost nothing; deleting the file
# is a pruning call for a session with Frank, not a cleanup an agent runs alone.
#
# Do not cite this file as the reason `git-lfs` is installed on a box. The manifest carries its
# own justification (packages/common.pkgs), and a tool justified by dead config is a tool nobody
# can defend when the config goes.
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
+54 -11
View File
@@ -34,24 +34,36 @@ placeholders='changeme|change[-_]|placeholder|redacted|example|sample|dummy|noke
# how a gate gets permanently overridden.
assign_exempt='(_FILE|_PATH|_DIR|_URL|_ENDPOINT|_SOCKET)[[:space:]]*[:=]|[:=][[:space:]]*["'"'"']?(/|\.\./)'
# Fail closed: a gate that cannot read the staged diff must not report success.
if ! files=$(git diff --cached --diff-filter=ACM --name-only 2>&1); then
#
# `-z`, and the list lives in a file. Two traps decide this: git quotes any path it cannot print
# as UTF-8 (core.quotePath is on by default), and a quoted name handed back to
# `git diff -- <path>` matches nothing — the file is skipped, and a skipped file used to be a
# silent pass. Command substitution cannot hold the list either, because $() deletes NUL bytes,
# so the names go to a temp file and the loop reads them with a NUL delimiter.
TMPD=$(mktemp -d) || TMPD=""
if [ -z "$TMPD" ]; then
echo "SECRET GATE: cannot create a temp dir — refusing to commit." >&2
[ -n "${ALLOW_SECRETS:-}" ] && exit 0
exit 1
fi
trap 'rm -rf "$TMPD"' EXIT
if ! git diff --cached --diff-filter=ACM --name-only -z > "$TMPD/files" 2> "$TMPD/err"; then
{
echo "SECRET GATE: cannot read the staged diff — refusing to commit."
printf ' %s\n' "$files"
sed 's/^/ /' "$TMPD/err"
echo "Override deliberately: ALLOW_SECRETS=1 git commit ..."
} >&2
[ -n "${ALLOW_SECRETS:-}" ] && exit 0
exit 1
fi
# stderr is captured so the failure branch can quote it; on success it must not
# leak a `warning:` line into the file list and have it mistaken for a path.
files=$(printf '%s\n' "$files" | grep -vE '^(warning|fatal|error):' || true)
[ -z "${files//[[:space:]]/}" ] && exit 0
# git's stderr stays out of the name list on purpose: a `warning:` line mistaken for a path
# becomes a file that "cannot be read", which is how a gate starts skipping the real ones.
[ -s "$TMPD/files" ] || exit 0
report=""
exempt=""
count=0
while IFS= read -r f; do
while IFS= read -r -d '' f; do
[ -z "$f" ] && continue
# Self-exemption, deliberately an exact filename list and not `tests/`: the
# gate's fixtures must contain credential-shaped strings or there is nothing to
@@ -67,17 +79,48 @@ while IFS= read -r f; do
# gate refused the redaction of the password it exists to catch.
added=$(printf '%s\n' "$diff" | grep -E '^\+' | grep -vE '^\+\+\+' | sed 's/^+//' || true)
[ -z "$added" ] && continue
hits=$(printf '%s\n' "$added" | grep -Ei "$shapes" || true)
# Shape hits are judged on the MATCHED TOKEN, not on the whole line. Documentation about
# credentials quotes vendor placeholders — AWS publishes an all-zeros access-key id that ends
# in EXAMPLE for exactly this purpose — and
# a gate that blocks prose over an inert example gets worked around until it means nothing:
# the live-sync heartbeat failed three ticks on 2026-10-21 because a managed skill page quotes
# exactly that id. A line is exempted only when EVERY shape on it is inert, so one live token
# sharing the file with a documented fake still blocks.
hits=$(printf '%s\n' "$added" | while IFS= read -r line; do
live=0
while IFS= read -r m; do
# The shape regexes carry fixed quantifiers, so the match they return is TRUNCATED:
# `AKIA` + exactly 16 characters stops inside the word EXAMPLE and the placeholder
# disappears from what is judged. Judge the match plus what follows it instead.
ctx=$(printf '%s' "$line" | awk -v m="$m" '{ i = index($0, m); print (i > 0 ? substr($0, i, length(m) + 8) : m) }')
printf '%s' "$ctx" | grep -Eiq 'EXAMPLE|X{4,}|Y{4,}|Z{4,}|_{4,}|REDACTED|CHANGEME|PLACEHOLDER' || live=1
done < <(printf '%s\n' "$line" | grep -Eio "$shapes" || true)
[ "$live" = 1 ] && printf '%s\n' "$line"
done)
if [ "${f##*.}" != "md" ]; then
assigns=$(printf '%s\n' "$added" | grep -Ei "$assign" | grep -Ev "$assign_exempt" | grep -Eiv "$placeholders" || true)
# The placeholder filter reads the VALUE, never the whole line. A trailing comment that
# says `# example` says nothing about the token the same line assigns; scoping the filter
# to what follows the separator is what keeps `API_TOKEN=<real> # placeholder` a block.
assigns=$(printf '%s\n' "$added" | grep -Ei "$assign" | grep -Ev "$assign_exempt" \
| while IFS= read -r line; do
# The judged value is the assigned token alone: it ends at whitespace or `#`, so a
# trailing comment cannot vouch for it. Truncating a quoted value early only ever errs
# toward blocking, which is the safe direction for a gate that can be overridden.
value=${line#*[:=]}
value=${value#"${value%%[![:space:]]*}"}
value=${value%%[[:space:]]*}
value=${value%%#*}
printf '%s\n' "$value" | grep -Eiq "$placeholders" && continue
printf '%s\n' "$line"
done)
hits=$(printf '%s\n%s\n' "$hits" "$assigns" | sed '/^[[:space:]]*$/d')
fi
if [ -n "$hits" ]; then
n=$(printf '%s\n' "$hits" | wc -l)
count=$((count + n))
report+=" $f"$'\n'"$(printf '%s\n' "$hits" | cut -c1-100 | sed 's/^/ /')"
report+=" $f"$'\n'"$(printf '%s\n' "$hits" | cut -c1-100 | sed 's/^/ /')"$'\n'
fi
done <<< "$files"
done < "$TMPD/files"
# Say so out loud: an exemption that prints nothing is how a carve-out becomes
# invisible, and invisible is the property a secret wants.
+16 -4
View File
@@ -86,15 +86,27 @@ agent/memories/--home-blank-.omp-wt-*
# 2026-10-20), so this path in the repo was a duplicate of it, not its source — and
# note that untracking deletes the copy in every other checkout regardless of
# `git rm --cached` on the branch. A fresh box starts with an empty library; every
# filename carries its wallhaven ID, so `curl -L -o <name> https://wallhaven.cc/w/<id>`
# puts it back. Law: omp-docs/tools/dotfiles-deploy.md
# filename carries its wallhaven ID; `/w/<id>` answers `text/html`, so resolve the CDN URL at
# `https://wallhaven.cc/api/v1/w/<id>` and download `data.path` — the recipe, with the reason it
# is not a plain `curl -L`, is on omp-docs/tools/dotfiles-deploy.md
dotfiles/noctalia/.local/share/noctalia/wallpapers/
# --- generated theme output: machine-written, never reviewable, never deployed ---
# noctalia/matugen rewrite these in place; a tracked copy is a stale snapshot that
# deploy.sh would push back over a live palette. Patterns match the exclusion list in
# scripts/deploy.sh. Law: omp-docs/inventory/home-config-census.md, Refs #42
# deploy.sh would push back over a live palette. These patterns are the ignore half of the
# exclusion list in `deploy_file` (scripts/deploy.sh): change one, change the other, or a
# generated file becomes tracked-but-never-deployed — the fiction class #41 removed. The
# capital-N rule is noctalia's own palette-directory naming, and it was in deploy.sh only.
# Law: omp-docs/inventory/home-config-census.md, Refs #42, #60
dotfiles/**/themes/noctalia*
dotfiles/**/colors/noctalia*
dotfiles/**/noctalia.*
dotfiles/**/noctalia-*
dotfiles/**/Noctalia*
# --- harness natives: unpacked runtime payloads, never configuration ----------
# 2.4 MB of tree-sitter grammars the harness unpacks into the repo root on first use (measured
# on blankpad 2026-10-21). Regenerable, unreviewable, not config — every clause of AGENTS.md's
# runtime-state doctrine applies, and it sat unnamed in the root, one `git add -A` away from
# being committed as if it were configuration.
natives/
+4 -7
View File
@@ -94,19 +94,16 @@ knowledge base. Those pages own their facts; this is only the pointer.
### Issue tracker
Work items are Gitea issues on `dank/command-center` (Dankclaw,
`192.168.0.143:3000`) — no `gh`, no `tea`. See
[`omp-docs/skills/issue-tracker.md`](omp-docs/skills/issue-tracker.md).
See [`omp-docs/skills/issue-tracker.md`](omp-docs/skills/issue-tracker.md).
### Triage labels
The five canonical roles, each label string equal to its name. See
[`omp-docs/skills/triage-labels.md`](omp-docs/skills/triage-labels.md).
See [`omp-docs/skills/triage-labels.md`](omp-docs/skills/triage-labels.md).
### Domain docs
Single-context, inside the existing knowledge base: `omp-docs/glossary.md` and
`omp-docs/decisions/`. See [`omp-docs/skills/domain-docs.md`](omp-docs/skills/domain-docs.md).
ADRs: `omp-docs/decisions/`. `omp-docs/glossary.md` is intentionally not created.
See [`omp-docs/skills/domain-docs.md`](omp-docs/skills/domain-docs.md).
## Secret gate (HARD rule)
+1 -1
View File
@@ -72,7 +72,7 @@ Documentation exists for ONE reason: **point of use**. A page earns its bytes on
#### THE WORK LOG IS ONE FILE.
The work log is a single page in the knowledge base: `omp-docs/log.md` in this repo, or whichever change-log page the repo's docs index names. Write the entry when the change lands — in the same commit as the change — and read that page to recover where things stand before starting. It follows its own entry law: a dated entry is what changed plus the durable lesson, a few lines.
- NEVER create a second log: not per directory, not per project, feature, branch or run, not `NOTES.md` / `PROGRESS.md` / `STATUS.md` / `worklog/`, not a dated diary. Logging in fifty places is not logging — the entry is never where the next reader looks, and each copy re-dates the same event on its own authority. In `dank/command-center` the KB linter reports any `log.md` that is not the bundle root's.
- NEVER create a second log: not per directory, not per project, feature, branch or run, not `NOTES.md` / `PROGRESS.md` / `STATUS.md` / `worklog/`, not a dated diary. In `dank/command-center` the KB linter reports any `log.md` that is not the bundle root's; the rule and its reasoning are owned by `omp-docs/references/okf-spec.md`.
- A log holds laws and incidents, never bookkeeping: no per-file inventories, no run-by-run numbers, no transcripts. A number in a log still has to pass the purpose test above.
- If a knowledge base has no log page, add one at its root and list it in the index. That is the fix — never a log somewhere else.
@@ -1,5 +1,5 @@
[Unit]
Description=swayidle idle lock (locks via noctalia-shell IPC, suspends on lid)
Description=swayidle idle lock watcher (arms the idle lock via noctalia-shell IPC; suspend is covered by noctalia's sleep inhibitor)
Documentation=https://github.com/swaywm/swayidle
After=graphical-session.target
# Restart together with the session, not merely at boot: this unit is wanted by
@@ -7,10 +7,14 @@
// requires: Lenovo Group Limited 0x40A9 Unknown
// optional: HDMI-A-1 (PM1601, dock-dependent)
// This panel's EDID tops out at 3440x1440@180 (read live from niri: no 240 Hz mode
// exists). Ask for a mode the panel does not offer and niri does not fail — it logs
// "could not be found, falling back to preferred" and drops to 60 Hz on every
// reconnect. Keep 180 here unless a re-read EDID says otherwise.
// The panel offers 3440x1440@239.998 as well as @180.000 (`niri msg outputs`, 2026-10-21), and
// 180 is driven DELIBERATELY: the link trained at x8 32.0 GT/s against a max of x16 and the
// display engine is throwing DMCUB errors with EINVAL page flips after s2idle, so the 240-class
// mode stays undriven until a reboot clears that state. niri matches mode strings VERBATIM and
// does not round: "@239.999" is not "@239.998", and a mode it cannot find does not fail — it
// logs "could not be found, falling back to preferred" and drops the panel to 60 Hz on every
// reconnect, which is how this desk ran for weeks. Copy the string from `niri msg outputs`.
// Reasoning and triage: omp-docs/tools/niri/displays.md ("The config pattern", rules 4 and 5).
output "Sceptre Tech Inc Sceptre M34 Unknown" {
mode "3440x1440@180.000"
scale 1
+2 -2
View File
@@ -1,8 +1,8 @@
# Architecture decision records
Decisions this repo has made and will not silently revisit. One file per
decision, named `NNN-<slug>.md`, listed here — an unlisted page fails `kb-lint`
and does not exist as far as any agent is concerned.
decision, named `NNN-<slug>.md`, listed here — an unlisted page fails
`scripts/kb-coverage.py` and does not exist as far as any agent is concerned.
**No ADRs yet.** The first one lands the moment a decision stops being
reversible.
+2 -2
View File
@@ -57,8 +57,8 @@ search practices, open models, MCP.
## [Inventory](inventory/index.md)
Pre-pruning census of every userspace config on this box — the input for the
pruning session.
Per-file tracked-vs-box-only census of `~/.config` on blankpad — the input for the
dotfiles pruning/adoption session.
## [Decisions](decisions/index.md)
+4 -2
View File
@@ -1,5 +1,7 @@
# Inventory Index
Census of all userspace program configuration on the workstation.
Tracked-vs-box-only census of userspace configuration on blankpad. Read the scope before
trusting coverage: these pages measure `~/.config`, not `~/.local/share`, not system package
state, not the servers.
- [home-config-census.md](home-config-census.md) — Complete inventory of top-level dotfiles, ~/.config, ~/.local/share state, and special directories (~/.pi, ~/.omp)
- [home-config-census.md](home-config-census.md) — Per-file tracked-vs-box-only census of ~/.config on blankpad — the input for the dotfiles pruning/adoption session.
+59 -13
View File
@@ -16,32 +16,78 @@ lesson, a few lines. Full incident narratives are recoverable from git
(`git log --follow omp-docs/log.md`); knowledge that outlives an entry lives
on its concept page, linked here. Never re-expand an entry in place.
This page is the bundle's **only** work log: one file, at the root. Never start a
second one in a subdirectory or under another name — `scripts/kb-lint.sh` reports any
`log.md` that is not this one.
This is the bundle's only work log; [references/okf-spec.md](references/okf-spec.md) owns the
one-log rule and `scripts/kb-lint.sh` enforces it.
## 2026-10-21 — reviewing a day of work, and finding checks that lie
Two-axis review (Standards / Spec) of everything landed 2026-10-20 → 2026-10-21: 51 commits,
30 findings, worked on `fix/60-review-findings` (issue #60). Three findings were the same shape —
a check that reports confidence it did not earn:
- **A guard that cannot see must refuse.** `pcie-probe.sh` dropped the `/dev/kfd` half of its
busy check when `fuser` was absent, and `gpu_busy_percent` reads `0` for a resident-but-idle
service: the tool measured beside a live endpoint while its own LAW said not to. Missing
visibility is now a refusal (exit `3`), not a narrower check.
- **A swallowed status is a false report.** `deploy.sh` printed `ENABLE` for units systemd
refuses to enable (`live-sync.service` has no `[Install]` section; its timer arms it), and the
loop walked `*.service` only, so a rebuilt box deployed the heartbeat and never armed its
timer. Every outcome now reports what actually happened.
- **A gate that reads a quoted path reads nothing.** git quotes non-ASCII paths in
`--name-only` output; the quoted name came back as an empty diff and the secret gate
`continue`d past it. Fail closed means `-z`, and it means the placeholder filter reads the
assigned value — a comment saying `# example` cannot vouch for the token beside it.
The law that cost the most, from the probe: **a test that observes the tool's environment instead
of what the tool passed on cannot see the bug.** The stub probe echoed `$HIP_VISIBLE_DEVICES`
rather than its argument, so the suite asserted the mask was set and per-card bandwidth was
unobtainable on the 2×R9700 box. Model the platform rule in the stub and the existing test goes
red against the old code — that is the red-proof worth having.
Same shape in `remote-job.sh status`: it globbed its arguments, so a job named `x*` was reported
as whatever happened to match in the caller's directory. A name is data — split it (`read -a`),
never let the shell expand it — and a multiplexed `tail` with no jobs says "no jobs" instead of
handing `*.out` to tail and reporting a missing file.
Incident, found while verifying the gate: the live-sync heartbeat had failed three hourly ticks,
because a managed skill that documents how to write a secret gate quotes the vendor's all-zeros
placeholder id and the gate's shape rule fired on the documentation. Prose about credentials is
what the machine tier is made of; a gate that blocks it is worked around, and the workaround is
the hole. Placeholder judgement reads the matched token — plus what follows it, because a fixed
quantifier truncates `EXAMPLE` to `EXA` — never the whole line. `ALLOW_SECRETS` stays the only
override, and the heartbeat's own payload was replayed through the fixed hook to prove it lands.
The rest of #60 was claims about the machine that the machine had stopped honouring:
`.gitignore` and `deploy.sh`'s exclusion list had drifted apart (`Noctalia*` was excluded, never
ignored), `.gitattributes` was the stated reason `git-lfs` was installed — for wallpapers that
same week's diff untracked, and the one-log rule was restated in four owners. A coverage claim
names what was measured; a tool justified by dead config is a tool nobody can defend when the
config goes.
## 2026-10-21 — a documented mode the panel never had
The home ultrawide had been running at 60 Hz for weeks while `desk-1-home.kdl`
asked for `3440x1440@239.999`. The page that owns that file documented the same
phantom mode, so every reader — including tonight's inspection — trusted it.
`niri msg outputs` says the Sceptre M34's EDID tops out at 180 Hz; there is no
240 Hz mode to ask for.
The panel does offer a 240-class mode: `niri msg outputs` lists `3440x1440@239.998`. The defect
was one character — niri matches mode strings verbatim, and `239.999` is not `239.998`.
Laws, now on [tools/niri/displays](tools/niri/displays.md):
- **An impossible mode does not fail, it falls back.** niri logs
`configured mode … could not be found, falling back to preferred` and drives
the EDID preferred mode — 60 Hz here. A config typo therefore looks like a
dying monitor, and every connector drop re-enacts it.
- **A mode string must match the advertised string verbatim.** niri does not round:
`3440x1440@239.999` does not select `3440x1440@239.998`. It logs
`configured mode … could not be found, falling back to preferred` and drives the EDID
preferred mode — 60 Hz here. A one-character typo therefore looks like a dying monitor, and
every connector drop re-enacts it.
- **Three layers, three signatures:** config fallback, DP link drops, and
amdgpu `DMCUB` errors with `EINVAL` page flips after s2idle. Only the first
yields to a file edit; only the last yields to a reboot. Triage table and
probes are on the page.
- **A number in a page is a claim, not a measurement.** Modes, refresh rates and
tool availability were wrong on four pages at once — `wlr-randr` was listed as
installed while `pacman -Qs wlr` matches nothing. Read the hardware before
writing a mode into a runbook, and destroy the stale copies.
- **A number in a page is a claim, not a measurement.** Mode strings, refresh rates and tool
availability were wrong on several pages at once — `wlr-randr` was listed as installed while
`pacman -Qs wlr` matches nothing. Read the hardware before writing a mode into a runbook, and
destroy the stale copies. A correction is itself a measurement: the first pass at this entry
published a second wrong hardware fact, with a `verified:` date stamped on it.
Fix: `desk-1-home.kdl` 239.999 → 180.000 on the identity block and both legacy
connector blocks, applied live with `niri msg output <panel> mode <mode>` — the
+9 -9
View File
@@ -21,12 +21,11 @@ Knowledge bundles rot. It is the nature of knowledge to attract cobwebs, much li
## Change Tracking with `log.md`
Every OKF bundle has a `log.md`, and it is the bundle's **only** work log: one file,
at the bundle root. A subdirectory never gets its own — not `core/log.md`, not
`notes.md`, not a per-project, per-branch or per-run diary. Sprawl is not caution:
with fifty logs the entry is never where the next agent looks, and each copy re-dates
the same event on its own authority. `scripts/kb-lint.sh` reports any `log.md` that is
not the root's.
Exactly one `log.md` per bundle, at the bundle root — [okf-spec.md](okf-spec.md) owns that rule
and `scripts/kb-lint.sh` enforces it, reporting any `log.md` that is not the root's. The
maintenance action is collapse, never coexistence: when a second log turns up (`core/log.md`,
`notes.md`, a per-run diary), move its entries into the root log under their own dates, delete
the file, and re-run the linter.
**Format:** one dated section per day, newest first; a few lines per change — what
happened, and the durable lesson. It is not a file manifest.
@@ -38,7 +37,7 @@ happened, and the durable lesson. It is not a file manifest.
A gate that gets an empty file list reports success. Law: a check MUST fail closed;
a silently-passing gate is worse than none, because it buys the belief of safety.
Details: [secret gate](../tools/index.md).
Details: [secret gate](/tools/index.md).
```
**Rules:**
@@ -58,8 +57,9 @@ Details: [secret gate](../tools/index.md).
- ❌ Forgetting the entry — the change lands undocumented and the next agent rediscovers
the failure the hard way.
- ❌ Starting a second log in a subdirectory — the sprawl that makes logging useless.
- ❌ Invented absolute paths in links — links resolve relative to the page, and the
linter checks them.
- ❌ Invented paths in links — the RECOMMENDED form is an absolute bundle path
(`/tools/index.md`), resolved against the bundle root; the mistake is a path that
names no file there, and that is what the linter reports.
- ❌ Re-expanding an old entry in place — the entry is a pointer; git is the transcript.
---
+31 -8
View File
@@ -1,14 +1,14 @@
---
type: reference
title: Dotfiles deployment tier
description: How dotfiles/ packages become live configuration — stow-equivalent symlinks, host override packages, and the two laws about theme media and systemd enable symlinks.
description: How dotfiles/ packages become live configuration — deploy.sh modes, host override packages, and the tier's hard-won laws, from media and generated theme output to systemd enable/start semantics, dconf dumps, and idle-lock watcher triage.
tags:
- dotfiles
- deployment
- systemd
- noctalia
timestamp: 2026-10-20
verified: 2026-10-20
verified: 2026-10-21
---
# Dotfiles deployment tier
@@ -25,10 +25,15 @@ is stowed last and its files replace symlinks coming from base packages.
| `deploy.sh` (sync) | adopt identicals, link new, quarantine divergents into `.quarantine/` and replace them |
| `deploy.sh --adopt` | like sync, but divergents are reported and skipped rather than quarantined |
Two package shapes are not symlinks. `dconf/dump.txt` is loaded with `dconf load /`, and
`systemd-user` units get `daemon-reload` plus `enable`; a unit is **started** only when
systemd reports it as nothing-yet (`""`/`disabled`), and never when its `ExecStart` binary
is absent here, so a unit belonging to another box stays inert instead of crash-looping.
Two package shapes are not symlinks. `dconf/dump.txt` is loaded with `dconf load /`. The
`systemd-user` tier gets `daemon-reload`, then **every `*.service` and `*.timer` whose start
command resolves on this box** is enabled — a timer is the schedule that makes a oneshot service
run at all, and it carries no `ExecStart` of its own, so the belonging test is applied to the
service it activates. A unit is **started** (`--now`) only when systemd reports it as nothing-yet
(`""`/`disabled`), and never when its binary is absent here, so a unit belonging to another box
stays inert instead of crash-looping. Three outcomes are printed, and each says what actually
happened: `ENABLE` only when `systemctl enable` returned success, `INERT` when it could not or did
not, `SKIP` when the unit is foreign. Refs #44, #60.
Starting something already installed is what makes `deploy.sh` unsafe to run beside a live
session — see *Never start a unit a session may already be running*.
@@ -54,8 +59,17 @@ checkout, `git rm --cached` on the branch notwithstanding.
Restore on a fresh box: the library lives in `~/.local/share/noctalia/wallpapers/`, a path
`deploy.sh` does not manage. Every filename is `wallhaven_<id>.<ext>` and the ID is the
whole address — `curl -L -o <name> "https://wallhaven.cc/w/<id>"` into that directory puts
the set back. Losing it is an acceptable outcome; 80 MB per clone forever is not.
whole address — but `https://wallhaven.cc/w/<id>` answers `text/html`, the web page, so
resolve the direct CDN URL through the API and download that:
```bash
id=73g8xo # the wallhaven_<id> stem of any file in the set
url=$(curl -s "https://wallhaven.cc/api/v1/w/$id" | grep -o '"path":"[^"]*' | cut -d'"' -f4)
curl -L -o ~/.local/share/noctalia/wallpapers/"${url##*/}" "$url"
```
`data.path` already ends in `wallhaven_<id>.<ext>`, so the filename keeps itself. Losing it
is an acceptable outcome; 80 MB per clone forever is not.
## Law: never `systemctl --user enable` a unit from a worktree
@@ -158,6 +172,15 @@ fresh box — where everything reports `disabled` — still gets its units up. B
are pinned in `tests/deploy.bats` over a stub `systemctl`, because the real one on this box
is exactly what must not be invoked from a test. Refs #44.
**A third state exists, and it is not an error.** A unit file with no `[Install]` section cannot be
enabled at all — `systemctl --user enable` answers with a non-zero exit and a paragraph about
missing `WantedBy`. `live-sync.service` is one on purpose: `live-sync.timer` pulls it in, which is
also why systemd reports it as `linked`. Until 2026-10-21 the deploy swallowed that failure and
printed `ENABLE` anyway, so the line an operator reads to learn what a rebuild armed was false on
every box, on the repo's own heartbeat. The section is readable from the file being deployed, so
the tool checks it and prints `INERT …(no [Install] section — another unit arms it, enable cannot)`
without making the call. Refs #60.
## Law: expand systemd specifiers before calling a unit foreign
`ExecStart=%h/.omp/scripts/live-sync.sh` is valid systemd and meaningless to a shell. The
+1 -1
View File
@@ -9,7 +9,7 @@ Configuration guides and reference material for installed software. Each tool ha
* [applications](applications.md) — Default userspace applications on CachyOS with Niri — browsers, editor, terminal, file manager, audio, screenshots, gaming.
* [cachyos](cachyos.md) — Arch-based rolling release with performance-optimized kernels, repositories, and gaming stack. Running on the workstation.
* [comfyui](comfyui/index.md) — Node-based AI image generation engine on dankclaw. FLUX.2 klein 4B, CPU backend, systemd managed.
* [dotfiles-deploy](dotfiles-deploy.md) — How `dotfiles/` packages become live config: `deploy.sh` modes, host override packages, and why theme media and worktree-enabled units are traps.
* [dotfiles-deploy](dotfiles-deploy.md) — How `dotfiles/` packages become live config: `deploy.sh` modes, host override packages, and the tier's hard-won laws, from media and generated theme output to systemd enable/start semantics, dconf dumps, and idle-lock watcher triage.
* [ghostty](ghostty/index.md) — GPU-accelerated terminal emulator with extensive configuration, keybindings, and shaders.
* [gitea](gitea/index.md) — Private Git hosting on dankclaw. Quadlet-managed containers: Gitea, PostgreSQL, Caddy.
* [handy](handy.md) — Offline speech-to-text transcription with WebKitGTK backend and Tauri v2 UI.
+22 -10
View File
@@ -41,17 +41,19 @@ list it as an installed tool are stale.
│ 1200x1920 │ landscape, scale 1 │ scale 1 │
│ rot 90 │ position 1581,-600 │ 5021,-240│
└──────────────┴──────────────────────────────┴──────────┘
HDMI-A-1 DP-2 (focus-at-startup) eDP-1 (fallback focus)
HDMI-A-1 DP-1 (focus-at-startup) eDP-1 (fallback focus)
Connector names are today's (`niri msg outputs`, 2026-10-21). They reshuffle with
the dock and the cable, which is why the config keys on the EDID long name instead.
```
| Panel | EDID long name | Keyed by | Notes |
|-------|----------------|----------|-------|
| Sceptre M34 ultrawide | `Sceptre Tech Inc Sceptre M34 Unknown` | identity | `mode "3440x1440@180.000"` — the EDID maximum; no 240 Hz mode exists — `focus-at-startup` |
| Sceptre M34 ultrawide | `Sceptre Tech Inc Sceptre M34 Unknown` | identity | `mode "3440x1440@180.000"`, **deliberate** — the panel also offers `3440x1440@239.998`, `144.001` and `120.000`; 180 is driven while the link is degraded (see the law below) — `focus-at-startup` |
| PM1601 portrait | *not captured* | connector `HDMI-A-1` | dock-dependent; run `desk.sh capture` when plugged in, then re-key |
| eDP-1 laptop panel | `Lenovo Group Limited 0x40A9 Unknown` | identity | scale **1.0** (deliberate; Ghostty grid at 1.25 rejected 2026-10-09), second `focus-at-startup` |
VRR: DP-2 supports it; **left disabled by decision** (2026-10-09). Add
`variable-refresh-rate` per output if that ever changes.
VRR: the M34 supports it (its connector today is `DP-1`); **left disabled by
decision** (2026-10-09). Add `variable-refresh-rate` per output if that ever changes.
`focus-at-startup` on both M34 and eDP-1: niri focuses in config order, so
the ultrawide wins when present and the laptop panel is the fallback.
@@ -113,12 +115,22 @@ Four rules learned the hard way:
3. **Positions are absolute, not relational.** A disconnected panel leaves
a hole; that is exactly why positions belong to the *desk profile*, not a
global file.
4. **Ask only for modes the panel reports** (`niri msg outputs` → `Mode:` list).
A mode the panel never offered does **not** leave the output dark: niri logs
`configured mode … could not be found, falling back to preferred` and quietly
drives the panel at its EDID *preferred* mode — **60 Hz** on the M34. Nothing
looks broken except the refresh rate, and every reconnect repeats the
fallback. Check Hz, not just resolution, after any "monitor is acting up".
4. **Ask only for modes the panel reports, and copy the string exactly.** The M34's
`Available modes` (`niri msg outputs`, 2026-10-21) are `3440x1440@239.998`,
`3440x1440@180.000`, `144.001`, `120.000`, … with `59.998` marked preferred. niri
matches mode strings **verbatim** and does not round, so `239.999` — one digit from
the real mode, which is what this file and the config both carried for weeks — is not
`239.998`. A mode it cannot find does **not** leave the output dark: niri logs
`configured mode … could not be found, falling back to preferred` and quietly drives
the panel at its EDID *preferred* mode — **60 Hz**. Nothing looks broken except the
refresh rate, and every reconnect repeats the fallback. Check Hz, not just
resolution, after any "monitor is acting up".
5. **180 Hz here is a decision, not a ceiling.** The panel offers 239.998 and is driven
at 180.000 deliberately: the link trained at `x8 32.0 GT/s` against a max of `x16`,
and the display engine is throwing `DMCUB` errors with `EINVAL` page flips after
s2idle, so the 240-class mode is not driven until a reboot clears that state. Before
changing the mode, re-read `niri msg outputs` **and** the link sysfs; treat "restore
240" as a change to verify on a healthy link, never as the obvious fix. Refs #60.
## "The monitors are broken" — three layers, three signatures
+15 -11
View File
@@ -413,17 +413,21 @@ noctalia msg templates-apply
## Dependencies
| Package | Purpose |
|---------|---------|
| `noctalia` (Qt) | Native desktop environment |
| `qt6-base` | Qt6 runtime |
| `qt6-multimedia` | Multimedia support |
| `niri` | Wayland compositor |
| `wlr-randr` | Display information |
| `brightnessctl` | Brightness control |
| `imagemagick` | Image processing |
| `ffmpeg` | Media processing |
| `polkit` | PolicyKit integration |
| Package | Purpose | Version on blankpad (2026-10-21) |
|---------|---------|----------------------------------|
| `noctalia` (Qt) | the shell: bar, widgets, `noctalia msg` | 5.3.0-1.1 |
| `qt6-base` | Qt6 runtime | 6.12.0-3.1 |
| `niri` | Wayland compositor | 26.04-1.1 |
| `polkit` | PolicyKit integration | 128-1.1 |
| `imagemagick` | image processing for palette wallpapers | 7.1.2.34-2.1 |
| `ffmpeg` | media processing | 2:9.0.2-2.1 |
**Three rows this page used to claim are not installed**, verified with `pacman -Q` and
`command -v`: `wlr-randr` (display information is `niri msg outputs` — no package needed, and
[displays](niri/displays.md) owns that procedure), `qt6-multimedia` (audio reaches PipeWire
through noctalia's own dependency), and `brightnessctl` (`/sys/class/backlight/amdgpu_bl1`
exists and nothing on this box drives it — laptop brightness is a gap to close, not a feature
to document). A dependency table is a claim about the machine: check it before writing it.
---
+24 -11
View File
@@ -8,7 +8,7 @@ tags:
- provisioning
- fleet
- blankpad
verified: 2026-10-20
verified: 2026-10-21
timestamp: 2026-10-20
---
@@ -25,9 +25,13 @@ if both directions are checked.
## Manifests
`packages/common.pkgs` (every host) + `packages/<host>.pkgs` (this host) + `packages/aur.pkgs`
(AUR-only, installed through `yay`). The parser is `sed 's/#.*//'` then the first field, so `#`
comments trail freely and one token per line is the whole grammar. An unknown `--host` gets the
common manifest only: a wrong-host run is a no-op, not a hazard.
(AUR-only, installed through `yay`). **One parser reads them for both tools**:
`scripts/lib/manifest.sh` — `sed 's/#.*//'` then the first field, so `#` comments trail freely and
one token per line is the whole grammar; an unreadable manifest is a loud failure rather than an
empty desired list. `tests/manifest-parser.bats` owns that contract. The two scripts carried
verbatim copies of the body until 2026-10-21, which is exactly how a manifest line can come to mean
two things to the two halves of the same check. An unknown `--host` gets the common manifest only:
a wrong-host run is a no-op, not a hazard.
## Rebuild a workstation
@@ -48,7 +52,7 @@ undeclared additions (declare these): N ← exit 1 when N > 0
aur (needs a helper): <names> → belongs in packages/aur.pkgs
installer-provided, undeclared: N + names → a reinstall supplies these; do not declare
declared, not installed: <names> → install.sh installs these
orphans ignored: <names> → pacman -Qtdq
orphans ignored: <names> → pacman -Qtdq, never drift (see the law below)
flatpak: <app ids> → reported only, install.sh installs no flatpaks
```
@@ -78,15 +82,23 @@ how a manifest becomes a pile of source builds.
Classify with `pacman -Sl` (world-readable). **`pacman -Sqq` requires root** — a tool that only
reads the machine must not need sudo to answer a question about it.
**Known gap:** `aur.pkgs` is read for *every* host, so a desktop-only AUR package (a niri module, a
GUI client) cannot be declared there without asking the headless servers to build it. Such a name is
still reported as an AUR addition; leave it undeclared until `install.sh` grows a per-host AUR
**Known gap:** `aur.pkgs` is read for *every* host, so a desktop-only AUR package — the niri
module `nirimod-git`, say, or a GUI client — cannot be declared there without asking the
headless servers to build it. Such a name is still reported as an AUR addition and stays
undeclared (see the note in `packages/blankpad.pkgs`) until `install.sh` grows a per-host AUR
manifest.
## Law: orphans never reach a manifest
`pacman -Qtdq` names are packages nothing depends on; emitting them would teach a fresh machine to
install the same dead weight. They are printed as `orphans ignored` and excluded from `--emit`.
Drift is `pacman -Qqe` — *explicitly* installed, therefore yours. `pacman -Qtdq` names packages
installed **as a dependency** that nothing requires any more, and a package carries exactly one
install reason, so the two sets cannot overlap (blankpad 2026-10-21: 206 explicit, 3 orphans, none
in common). That is why nothing in `pkg-inventory.sh` subtracts the orphan list from the additions:
the query is already the guard. Do not add such a subtraction — it cannot fire, and it would bury
the invariant that matters, *an implicit install is never drift no matter when it arrived*, which
`tests/pkg-inventory.bats` pins with a dependency installed after the baseline. What the
`orphans ignored` line is for is the other half: dead weight on the machine that a manifest must
never teach a fresh box to install.
## Two traps that produced this tool
@@ -102,5 +114,6 @@ install the same dead weight. They are printed as `orphans ignored` and excluded
- [tools/index](index.md) · [dotfiles-deploy](dotfiles-deploy.md) (the config tier that follows) ·
[live-sync](live-sync.md) (the heartbeat that commits machine state)
- Tests: `tests/pkg-inventory.bats` (fixtures + stubbed `pacman`, no real package database touched).
- Tests: `tests/pkg-inventory.bats` (fixtures + stubbed `pacman`, no real package database touched)
and `tests/manifest-parser.bats` (the grammar above, observed as names in / names out).
- Refs #51.
+19 -9
View File
@@ -8,7 +8,7 @@ tags:
- rdna4
- benchmarking
- dankserver
verified: 2026-10-20
verified: 2026-10-21
timestamp: 2026-10-20
---
@@ -40,7 +40,10 @@ scripts/pcie-probe.sh --build-only # compile, never touch the cards
The guard runs **before anything is built or run** and refuses when the GPU is
occupied — `gpu_busy_percent` above `PCIE_PROBE_MAX_BUSY` (default 5 %) or any
process holding `/dev/kfd`. Refusal is exit `3`, and it stops nothing.
process holding `/dev/kfd`. Refusal is exit `3`, and it stops nothing. If the holder
probe is missing the guard refuses too rather than assuming idle — see
[seams](#exit-status-and-seams); `gpu_busy_percent` reads `0` for a service that is
resident and idle, so a silent fallback is exactly the benchmark this law forbids.
Auto-stopping a production endpoint is not this tool's decision to make, and a
measurement taken as noise beside serving traffic is worthless anyway: it is
@@ -65,8 +68,11 @@ throughput at *that* size is what matters, not the big-transfer figure:
- Pinned versus pageable columns apart means pinning is load-bearing; together
means the copies are already pinned by someone else.
Measure one device at a time (`--device`). A run that lets the runtime pick
several devices cannot attribute bandwidth to a card at all.
Measure one device at a time (`--device`, a HIP ordinal). A run that lets the runtime
pick several devices cannot attribute bandwidth to a card at all. The ordinal goes to
the probe as an argument and **the driver never sets `HIP_VISIBLE_DEVICES`**: masking
the device *and* passing its real ordinal asks `hipSetDevice` for a card the runtime
has hidden, so every card but ordinal 0 fails to measure at all. One selector only.
## The trap carried in the sources
@@ -79,14 +85,18 @@ when touching these files.
## Exit status and seams
`0` measured · `2` usage or no sources · `3` refused, GPU busy · `4` no HIP
toolchain or build failed. A client box without the SDK exits `4` loudly rather
than reporting an empty success; the probes belong on the box with the cards.
`0` measured · `2` usage or no sources · `3` refused, GPU busy or holders unknowable ·
`4` no HIP toolchain or build failed · `5` a probe ran and failed. A client box without
the SDK exits `4` loudly rather than reporting an empty success; the probes belong on
the box with the cards. A probe that dies (the segfault above, an unfundable
allocation) exits `5` and names which probe on which device — a sweep that quietly
swallowed the failure would report success with half its rows missing.
Test seams (all documented in the script header): `PCIE_PROBE_SRC`,
`PCIE_PROBE_BUILD`, `PCIE_PROBE_SYSFS`, `PCIE_PROBE_KFD`, `PCIE_PROBE_HIPCC`,
`PCIE_PROBE_MAX_BUSY` — the sysfs/kfd paths are what make a refusal testable on
a machine with no cards, which is the only honest way to test a refusal.
`PCIE_PROBE_FUSER`, `PCIE_PROBE_MAX_BUSY` — the sysfs/kfd paths are what make a
refusal testable on a machine with no cards, which is the only honest way to test a
refusal.
Measured campaign numbers are not kept here; they belong with the endpoint they
were taken on, in the serverAppConfigs LLM runbook vault.
+3 -2
View File
@@ -38,10 +38,10 @@ read afterwards by a short-lived connection. That is what this is.
```bash
remote-job.sh start NAME [--] CMD... # launch detached, return at once
remote-job.sh status [NAME] # one line per job; exit 0 only if all DONE
remote-job.sh status [NAME] # one line per job; names literal, never globs
remote-job.sh wait NAME [SEC] [N] # block until DONE or timeout, then tail N lines
remote-job.sh out NAME [N] # tail a job's output
remote-job.sh tail [NAME] # follow one job, or every job at once
remote-job.sh tail [NAME] # follow one job, or all; exit 1 if nothing to follow
remote-job.sh watch # refreshing status, for a spare pane
```
@@ -77,6 +77,7 @@ can be made from a fresh session on a machine that rebooted underneath it.
| Command name is wrong | `PENDING (no output yet)`, exit 1 — never a false DONE |
| Job exits non-zero | `DONE rc=N`; the code is data, not the report's status |
| Two jobs, same NAME | the second replaces the first's state files |
| `tail` with no job, or a name that is a glob | exit 1 saying there is nothing to follow; names are matched literally, never expanded |
| Job dir missing | created on first use |
Pinned by `tests/remote-job.bats` (black-box: output, exit codes, sentinel
+2 -2
View File
@@ -18,8 +18,8 @@ btop
# system / fleet tooling
yay # AUR helper bootstrap: ships in the cachyos repo; aur.pkgs installs need it
git-lfs # LFS smudge/clean for tracked wallpapers (see .gitattributes)
swayidle # idle lock + lid policy via swayidle-lock.service unit
git-lfs # cloning LFS-backed upstreams (Hugging Face model/dataset repos); this repo tracks zero LFS files — .gitattributes is idle config
swayidle # idle lock watcher via swayidle-lock.service; suspend locking is noctalia's sleep inhibitor
# desktop apps
flameshot # screenshot tool; bound to CTRL+Shift+1/2/3 in niri keybinds
+32 -12
View File
@@ -120,9 +120,20 @@ done
if [ "$MODE" != "check" ] && [ -d "$PKGS_DIR/systemd-user/.config/systemd/user" ]; then
systemctl --user daemon-reload || true
for unit in "$PKGS_DIR"/systemd-user/.config/systemd/user/*.service; do
UNITS_DIR="$PKGS_DIR/systemd-user/.config/systemd/user"
# Services AND timers. A timer is the schedule that makes a oneshot service run at all, and it
# carries no ExecStart of its own — the binary that decides whether the unit belongs on this
# box lives in the service it activates. Walking *.service only deployed live-sync.service on
# every rebuild and never armed live-sync.timer: the heartbeat was present and never ticked.
for unit in "$UNITS_DIR"/*.service "$UNITS_DIR"/*.timer; do
[ -e "$unit" ] || continue
bin="$(sed -n 's/^ExecStart=\([^ ]*\).*/\1/p' "$unit" | head -1)"
name="$(basename "$unit")"
probe="$unit"
if [ "${name##*.}" = timer ]; then
act="$(sed -n 's/^Unit=\(.*\)$/\1/p' "$unit" | head -1)"
probe="$UNITS_DIR/${act:-"${name%.timer}.service"}"
fi
bin="$(sed -n 's/^ExecStart=\([^ ]*\).*/\1/p' "$probe" 2>/dev/null | head -1)"
# systemd expands specifiers inside ExecStart; this shell does not. Matching the literal
# `%h/…` makes a unit of THIS box look foreign and skips it in silence — which is exactly
# how live-sync.service, the repo's own heartbeat, has been reported "absent on this
@@ -132,22 +143,31 @@ if [ "$MODE" != "check" ] && [ -d "$PKGS_DIR/systemd-user/.config/systemd/user"
bin="${bin//%u/$(id -un)}"
bin="${bin//%U/$(id -u)}"
if [ -n "$bin" ] && command -v "$bin" >/dev/null 2>&1; then
name="$(basename "$unit")"
# Read the state, not the exit status: `is-enabled` exits 1 for a `linked` unit exactly
# as for a `disabled` one. Starting something already installed is how a deploy locks a
# live session — swayidle-lock sits enabled/inactive on blankpad and `--now` arms it
# mid-conversation. Only a unit nothing has installed yet gets started. Refs #44.
state="$(systemctl --user is-enabled "$name" 2>/dev/null || true)"
case "$state" in
"" | disabled)
systemctl --user enable --now "$name" || true
echo "ENABLE $name (ExecStart resolves here; nothing running it yet)" ;;
*)
systemctl --user enable "$name" || true
echo "ENABLE $name (already $state; not started — a live session decides what runs)" ;;
esac
if ! grep -q '^\[Install\]' "$unit"; then
# systemd refuses to enable these: no [Install] section means nothing can want the unit
# at login, and live-sync.service has none on purpose — its timer pulls it in. The old
# branch swallowed that failure and printed ENABLE anyway, so the one line a rebuild is
# checked by was false on every box. The section is readable right here, so do not make
# the call at all. Refs #60.
echo "INERT $name (state=${state:-none}; no [Install] section — another unit arms it, enable cannot)"
elif [ -z "$state" ] || [ "$state" = disabled ]; then
if systemctl --user enable --now "$name"; then
echo "ENABLE $name (ExecStart resolves here; nothing running it yet)"
else
echo "INERT $name (enable --now failed — systemd's message above says why)"
fi
elif systemctl --user enable "$name"; then
echo "ENABLE $name (already $state; not started — a live session decides what runs)"
else
echo "INERT $name (already $state; enable failed — systemd's message above says why)"
fi
else
echo "SKIP $(basename "$unit") (ExecStart '$bin' absent on this host)"
echo "SKIP $name (ExecStart '$bin' absent on this host)"
fi
done
fi
+3 -4
View File
@@ -17,7 +17,8 @@
# otherwise sudo prompts normally. The value is never stored in this repo.
set -euo pipefail
REPO="$(git -C "$(dirname "$(realpath "$0")")" rev-parse --show-toplevel 2>/dev/null || true)"
HERE="$(dirname "$(realpath "$0")")"
REPO="$(git -C "$HERE" rev-parse --show-toplevel 2>/dev/null || true)"
REPO="${INSTALL_REPO:-$REPO}"
[ -n "$REPO" ] && [ -d "$REPO/packages" ] || { echo "install.sh: no packages/ under ${REPO:-<repo>}" >&2; exit 1; }
@@ -36,9 +37,7 @@ SUDO() {
else sudo "$@"; fi
}
read_manifest() { # $1 = manifest path; emits package names, strips comments/blanks
sed 's/#.*//' "$1" | tr -d '\r' | awk '{if ($1) print $1}'
}
source "$HERE/lib/manifest.sh" # the same parser pkg-inventory.sh reads with
# ---- desired-minus-installed delta ------------------------------------------
PKGS=()
for m in common.pkgs "$HOST.pkgs"; do
+9 -2
View File
@@ -20,6 +20,10 @@ def pages():
if ".AGENTTRASH" not in p.parts:
yield p
# Names that a wikilink may point at: exactly the pages pages() reports. Deriving this
# once keeps linting and link resolution from disagreeing about what exists.
live = {p.stem for p in pages()}
for p in pages():
rel = p.relative_to(kb)
text = p.read_text(errors="replace")
@@ -70,9 +74,12 @@ for p in pages():
if not Path(target).is_file():
violations.append(f"{rel}: broken relative link -> {m.group(1)}")
for m in re.finditer(r"\[\[([^\]|#]+)", text):
# wikilinks resolve by filename anywhere in the KB (Obsidian semantics)
# wikilinks resolve by filename anywhere in the KB (Obsidian semantics) — but only
# among pages that BELONG to the bundle. A raw rglob also walked .AGENTTRASH/, so a
# link to a quarantined page stayed "valid" here while pointing at nothing on every
# other machine (the trash is gitignored). Same exclusion as pages(), one source.
name = m.group(1).strip().rsplit("/", 1)[-1]
if not list(kb.rglob(name + ".md")):
if name not in live:
violations.append(f"{rel}: broken wikilink -> [[{m.group(1).strip()}]]")
for v in violations:
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# scripts/lib/manifest.sh — the one parser for packages/*.pkgs
#
# install.sh walks desired → installed; pkg-inventory.sh walks installed → declared. Both read the
# same hand-written manifests, so both must agree on what a line MEANS: if one forgives an inline
# comment and the other does not, the same name is simultaneously "desired" and "drift", and the
# pair stops being a check on the machine. Source it — do not paste the body into a caller again
# (Refs #60: it was pasted twice, in install.sh and in pkg-inventory.sh).
#
# Contract, and tests/manifest-parser.bats is that contract:
# name first field of a line, emitted as one bare token — callers hand it to pacman
# comment `#` and everything after it is dropped, whole-line or trailing
# CRLF stripped (the manifests are edited on more than one box)
# blank empty and whitespace-only rows vanish
# unreadable non-zero exit, no names: a silent empty list reads as "nothing desired", and a
# rebuild would then install nothing while reporting success
#
# Sourced, never executed; callers own `set -euo pipefail`.
read_manifest() { # $1 = manifest path; prints one package name per line
[[ -r "$1" ]] || { printf 'read_manifest: cannot read %s\n' "$1" >&2; return 2; }
sed 's/#.*//' "$1" | tr -d '\r' | awk '{if ($1) print $1}'
}
+37 -8
View File
@@ -15,8 +15,12 @@
#
# usage: pcie-probe.sh [--device N]... [--build-only] [--force]
#
# --device N measure this device; repeat for each card. Without it the probes run once with the
# environment's own device selection — one shared run cannot attribute bandwidth.
# --device N measure HIP device ordinal N; repeat for each card. Without it the probes run
# once with the environment's own device selection — one shared run cannot
# attribute bandwidth. The ordinal is passed to the probes as argv, which is the
# only selector that survives contact with HIP: HIP_VISIBLE_DEVICES=1 makes
# ordinal 0 the sole visible card, so masking AND passing N asks the probe for a
# device that no longer exists. The mask is deliberately not set here.
# --build-only compile and stop; never touches the cards.
# --force measure even though the guard says the GPU is busy.
#
@@ -27,10 +31,11 @@
# PCIE_PROBE_SYSFS drm sysfs root (/sys/class/drm)
# PCIE_PROBE_KFD KFD device node (/dev/kfd)
# PCIE_PROBE_HIPCC compiler (hipcc)
# PCIE_PROBE_FUSER KFD holder probe (fuser)
# PCIE_PROBE_MAX_BUSY refusal threshold, percent (5)
#
# Exit status: 0 measured · 2 usage or missing sources · 3 REFUSED, GPU busy · 4 no toolchain or
# build failed.
# Exit status: 0 measured · 2 usage or missing sources · 3 REFUSED, GPU busy or unknowable ·
# 4 no toolchain or build failed · 5 a probe ran and failed.
set -uo pipefail
@@ -39,6 +44,7 @@ BUILD="${PCIE_PROBE_BUILD:-$HOME/.cache/pcie-probe}"
SYSFS="${PCIE_PROBE_SYSFS:-/sys/class/drm}"
KFD="${PCIE_PROBE_KFD:-/dev/kfd}"
HIPCC="${PCIE_PROBE_HIPCC:-hipcc}"
FUSER="${PCIE_PROBE_FUSER:-fuser}"
MAX_BUSY="${PCIE_PROBE_MAX_BUSY:-5}"
force=0
@@ -63,9 +69,19 @@ fi
# ---- the guard, before anything touches the card --------------------------------
if (( ! force )); then
busy=""
if [[ -e "$KFD" ]] && command -v fuser > /dev/null 2>&1; then
holders="$(fuser "$KFD" 2>/dev/null | tr -s '[:space:]' ' ')"
[[ -n "${holders// /}" ]] && busy="KFD in use by:${holders}"
if [[ -e "$KFD" ]]; then
if command -v "$FUSER" > /dev/null 2>&1; then
holders="$("$FUSER" "$KFD" 2>/dev/null | tr -s '[:space:]' ' ')"
[[ -n "${holders// /}" ]] && busy="KFD in use by:${holders}"
else
# No fuser (psmisc) means the KFD holders are unknowable — and gpu_busy_percent reads 0
# for a service that is resident but idle. Guessing "idle" here is how you end up
# benchmarking beside a live endpoint, so the guard fails closed instead.
printf 'pcie-probe: REFUSED — cannot see who holds %s: `%s` not found (psmisc)\n' "$KFD" "$FUSER" >&2
printf ' install psmisc, or pass --force if you have decided the contention is\n' >&2
printf ' acceptable and read gpu_busy_percent yourself first.\n' >&2
exit 3
fi
fi
for card in "$SYSFS"/card*; do
[[ -f "$card/device/gpu_busy_percent" ]] || continue
@@ -111,7 +127,11 @@ for card in "$SYSFS"/card*; do
done
# ---- measure, per device --------------------------------------------------------
# One selector only (see --device above), and every probe's exit status is honoured: a probe
# that dies must not let the sweep report success. Failures are collected so the remaining
# cards are still measured — losing the second card's numbers is how a campaign lies.
(( ${#devices[@]} > 0 )) || devices=(default)
failures=()
for d in "${devices[@]}"; do
if [[ $d == default ]]; then
printf '\n########## engine device selection ##########\n'
@@ -121,6 +141,15 @@ for d in "${devices[@]}"; do
for name in hip_smoke pcie_bw pcie_probe; do
bin="$BUILD/$name"
[[ -x "$bin" ]] || continue
if [[ $d == default ]]; then "$bin"; else HIP_VISIBLE_DEVICES="$d" "$bin" "$d"; fi
if [[ $d == default ]]; then
"$bin" || failures+=("$name (engine selection)")
else
"$bin" "$d" || failures+=("$name (device $d)")
fi
done
done
if (( ${#failures[@]} > 0 )); then
printf 'pcie-probe: %d probe(s) failed:\n' "${#failures[@]}" >&2
printf ' %s\n' "${failures[@]}" >&2
exit 5
fi
+13 -6
View File
@@ -19,11 +19,19 @@
# aur (needs a helper): <names> → belongs in packages/aur.pkgs (yay)
# installer-provided, undeclared: N a reinstall supplies these; do not declare
# declared, not installed: N install.sh installs these
# orphans ignored: <names> pacman -Qtdq — never emitted
# orphans ignored: <names> pacman -Qtdq — never drift, never emitted
# flatpak: <app ids> reported only, install.sh installs no flatpaks
#
# --emit prints the additions as manifest lines, ready to fold into packages/. Names are bare
# tokens so install.sh's `sed 's/#.*//'` + first-field parser reads them unchanged.
# Drift is `pacman -Qqe`: explicitly installed, therefore something you asked for and a rebuild
# must declare. `pacman -Qtdq` orphans are packages installed AS A DEPENDENCY and no longer
# required, and a package carries exactly one install reason, so the two sets are disjoint by
# construction (blankpad, 2026-10-21: 206 explicit, 3 orphans, none in common). Nothing here
# subtracts the orphan list from the additions and nothing should — the query is the guard. Do not
# add such a subtraction: it cannot fire, and it would hide the real invariant (implicit installs
# are never drift, whenever they arrived) behind a line that looks like protection.
#
# Exit status: 0 clean · 1 drift (undeclared additions exist) · 2 usage · 3 cannot classify
# (pacman log unreadable or sync databases unavailable — worse to guess than to say so, because
@@ -42,23 +50,22 @@ MODE="report"
while [[ $# -gt 0 ]]; do
case "$1" in
--emit) MODE="emit"; shift ;;
-h | --help) sed -n '2,40p' "$0"; exit 0 ;;
-h | --help) awk '/^set /{exit} NR>1' "$0"; exit 0 ;;
*) echo "usage: pkg-inventory.sh [--emit]" >&2; exit 2 ;;
esac
done
HERE="$(dirname "$(realpath "$0")")"
REPO="${PKGINV_REPO:-}"
if [[ -z "$REPO" ]]; then
REPO="$(git -C "$(dirname "$(realpath "$0")")" rev-parse --show-toplevel 2>/dev/null || true)"
REPO="$(git -C "$HERE" rev-parse --show-toplevel 2>/dev/null || true)"
fi
[[ -n "$REPO" && -d "$REPO/packages" ]] || { echo "pkg-inventory: no packages/ under ${REPO:-<repo>}" >&2; exit 2; }
HOST="${PKGINV_HOST:-$(hostname)}"
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
read_manifest() { # same parser install.sh uses, so a name means the same thing to both
sed 's/#.*//' "$1" | tr -d '\r' | awk '{if ($1) print $1}'
}
source "$HERE/lib/manifest.sh" # the same parser install.sh installs with
# ---- installed state ---------------------------------------------------------
# Four queries are the tool's whole interface to pacman. -Sl is the unprivileged sync listing:
# -Sqq asks for root, and a read of the machine must not need sudo. Field 2 of -Sl is the package
+20 -6
View File
@@ -51,13 +51,21 @@ case "${1:-}" in
;;
status)
# Job names are data, never patterns. `for n in $names` word-split AND globbed: a job named
# `x*` was expanded against the caller's working directory, so the report described unrelated
# files there as jobs and never mentioned the one that ran. Splitting stays (several names in
# one argument is the documented call shape); expansion does not.
names=()
if [[ -n "${2:-}" ]]; then
names="$2"
read -r -a names <<< "$2"
else
names=$(cd "$JOBS" && ls *.out 2>/dev/null | sed 's/\.out$//' | sort)
while IFS= read -r -d '' f; do
names+=("$(basename "$f" .out)")
done < <(find "$JOBS" -maxdepth 1 -name '*.out' -print0 2>/dev/null | sort -z)
fi
if [[ ${#names[@]} -eq 0 ]]; then echo " (no jobs)"; exit 0; fi
pending=0
for n in $names; do
for n in "${names[@]}"; do
if [[ -f "$JOBS/$n.done" ]]; then
printf ' %-20s DONE rc=%s %s lines\n' "$n" \
"$(cat "$JOBS/$n.rc" 2>/dev/null)" "$(wc -l < "$JOBS/$n.out" 2>/dev/null | tr -d ' ')"
@@ -69,7 +77,6 @@ case "${1:-}" in
pending=1
fi
done
if [[ -z "$names" ]]; then echo " (no jobs)"; exit 0; fi
exit "$pending"
;;
@@ -95,8 +102,15 @@ case "${1:-}" in
tail)
# Multiplexed follow: no NAME means every job at once, so one pane shows the whole harness.
if [[ -n "${2:-}" ]]; then exec tail -f "$JOBS/$2.out"; fi
exec tail -f "$JOBS"/*.out
# Both branches check for something to follow first: an unexpanded `*.out` handed to tail
# reports a missing *file*, which reads as a broken tool instead of an empty harness.
if [[ -n "${2:-}" ]]; then
[[ -f "$JOBS/$2.out" ]] || { echo "remote-job: no job '$2' (no $JOBS/$2.out)" >&2; exit 1; }
exec tail -f "$JOBS/$2.out"
fi
mapfile -d '' -t follow < <(find "$JOBS" -maxdepth 1 -name '*.out' -print0 2>/dev/null | sort -z)
(( ${#follow[@]} )) || { echo "remote-job: no jobs in $JOBS yet" >&2; exit 1; }
exec tail -f "${follow[@]}"
;;
watch)
+59 -1
View File
@@ -37,7 +37,22 @@ if [ "$2" = is-enabled ]; then
printf '%s\n' "$state"
case "$state" in disabled | "") exit 1 ;; *) exit 0 ;; esac
fi
exit 0
if [ "$2" = enable ]; then
# Modelled, not stubbed flat: systemd refuses to enable a unit whose file has no [Install]
# section, and the deployed file is what it reads. A stub that always says yes hides the
# one case this repo actually ships (live-sync.service is driven by its timer).
target=""
for a in "$@"; do
case "$a" in
*.service | *.timer | *.socket) target="$a" ;;
esac
done
file="$HOME/.config/systemd/user/${target##*/}"
if [ -e "$file" ] && ! grep -q '^\[Install\]' "$file"; then
printf 'The unit files have no installation config (WantedBy=, RequiredBy=, Also= settings in the [Install] section). This means they are not meant to be enabled using this command.\n' >&2
exit 1
fi
fi
STUB
chmod +x "$TEST_TMP/bin/systemctl"
export PATH="$TEST_TMP/bin:$PATH"
@@ -57,6 +72,21 @@ systemd_unit() {
> "$REPO/dotfiles/systemd-user/.config/systemd/user/$1"
}
# systemd_unit_no_install <name> <ExecStart> — a unit nothing can enable (live-sync.service:
# it is pulled in by live-sync.timer, so it carries no [Install] section on purpose).
systemd_unit_no_install() {
mkdir -p "$REPO/dotfiles/systemd-user/.config/systemd/user"
printf '[Unit]\nDescription=%s\n[Service]\nType=oneshot\nExecStart=%s\n' "$1" "$2" \
> "$REPO/dotfiles/systemd-user/.config/systemd/user/$1"
}
# systemd_timer <name> <service-name> — a schedule; it has no ExecStart of its own.
systemd_timer() {
mkdir -p "$REPO/dotfiles/systemd-user/.config/systemd/user"
printf '[Unit]\nDescription=%s\n[Timer]\nOnCalendar=hourly\nPersistent=true\n[Install]\nWantedBy=timers.target\n' "$1" \
> "$REPO/dotfiles/systemd-user/.config/systemd/user/$1"
}
@test "generated theme output is never adopted into a symlink" {
repo_file "ghostty/.config/ghostty/themes/noctalia" 'background = "#f43841"'
live_file "$HOME/.config/ghostty/themes/noctalia" 'background = "#f43841"'
@@ -152,3 +182,31 @@ systemd_unit() {
grep -q 'systemctl --user enable heartbeat.service' "$STUB_LOG"
! grep -q -- '--now' "$STUB_LOG"
}
@test "a unit nothing can enable is reported as what it is, never as ENABLE" {
# `systemctl --user enable live-sync.service` fails on every deploy: the file has no
# [Install] section (its timer arms it), and systemd says so with a non-zero exit. The
# deploy swallowed that and printed ENABLE, so the one line the operator reads to learn
# what a rebuild armed was false on every box, on the repo's own heartbeat.
systemd_unit_no_install heartbeat.service /bin/sh
printf 'linked\n' > "$UNIT_STATE"
run "$REPO/scripts/deploy.sh"
[ "$status" -eq 0 ]
[[ "$output" == *"heartbeat.service"*"[Install]"* ]]
[[ "$output" != *"ENABLE heartbeat.service"* ]]
# No futile call: the section is readable from the file being deployed.
! grep -q 'systemctl --user enable heartbeat.service' "$STUB_LOG"
}
@test "a timer in the tier is armed, because a service on its own has no schedule" {
# The loop walked *.service only. On a rebuilt box live-sync.service is deployed and the
# timer is never enabled, so the heartbeat that commits machine state simply does not run
# — and the deploy report says nothing about it.
systemd_unit heartbeat.service /bin/sh
systemd_timer heartbeat.timer heartbeat.service
printf 'disabled\n' > "$UNIT_STATE"
run "$REPO/scripts/deploy.sh"
[ "$status" -eq 0 ]
[[ "$output" != *"SKIP heartbeat.timer"* ]]
grep -q 'systemctl --user enable --now heartbeat.timer' "$STUB_LOG"
}
+22
View File
@@ -120,6 +120,28 @@ EOF
[[ "$output" == *"0 violation(s)"* ]]
}
@test "a wikilink must not resolve into the quarantine" {
# Obsidian resolves [[name]] by filename anywhere under the vault, and the resolver copied
# that with a raw rglob — so [[log]] stayed "valid" by landing on the copy waiting in
# .AGENTTRASH/. That is #57's failure wearing a green check: the page is out of circulation
# until a pruning session with Frank, and it is not even tracked, so on another machine the
# link points at nothing while the gate here says it is fine.
mkdir -p "$KB/.AGENTTRASH"
printf 'no frontmatter, quarantined\n' > "$KB/.AGENTTRASH/log.md"
printf -- '---\ntype: reference\n---\nSee [[log]] for the history.\n' > "$KB/good.md"
run bash "$LINT" "$KB"
[ "$status" -ne 0 ]
[[ "$output" == *"broken wikilink -> [[log]]"* ]]
}
@test "a wikilink to a live page still resolves, in any directory" {
# The narrowing above must cost nothing: filename-anywhere semantics is the point.
printf -- '---\ntype: reference\n---\nSee [[good]].\n' > "$KB/sub/other.md"
run bash "$LINT" "$KB"
[ "$status" -eq 0 ]
[[ "$output" == *"0 violation(s)"* ]]
}
@test "the shipped knowledge base itself is conformant" {
# The tests above exercise the linter against fixtures; nothing else in the
# suite ever points it at the real bundle, so a page added without frontmatter
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bats
# tests/manifest-parser.bats — the one manifest parser, shared by install.sh and pkg-inventory.sh
#
# `packages/*.pkgs` is hand-written, so the parser's whole job is to forgive the ways a hand-edited
# list is wrong. The same function decides what install.sh tries to install and what pkg-inventory
# calls drift, so a manifest line must mean the same thing to both — which is why it lives in one
# file instead of being pasted into each caller (Refs #60: it was pasted twice).
#
# Observed through the function's exit status and stdout only:
# names first field of a line, one bare token; `#` and everything after it is a comment
# CRLF tolerated (the manifests get edited on more than one box)
# blank lines vanish
# unreadable non-zero with no names — an empty desired list must never be a silent success,
# because "nothing desired" is exactly what a rebuild would install
setup() {
TEST_TMP="$(mktemp -d)"
LIB="$BATS_TEST_DIRNAME/../scripts/lib/manifest.sh"
}
teardown() { rm -rf "$TEST_TMP"; }
parse() { # $1 = manifest contents, verbatim
printf '%s' "$1" > "$TEST_TMP/m.pkgs"
run bash -c 'source "$1"; read_manifest "$2"' _ "$LIB" "$TEST_TMP/m.pkgs"
}
@test "inline notes, full-line comments, blank rows and CRLF come out as bare names" {
parse $'# desired state\r\nghostty # terminal\r\n\r\n \r\nzoxide\r\n'
[ "$status" -eq 0 ]
[ "$(printf '%s\n' "$output" | tr '\n' ' ')" = "ghostty zoxide " ]
}
@test "only the first field of a line is a package" {
# install.sh hands every emitted token straight to pacman, so a stray second token on a line
# must never become an install target; whatever it is, the manifest did not declare it.
parse $'neovim extra tokens here\n'
[ "$output" = "neovim" ]
}
@test "a comment that names a package is not a package" {
parse $'# vlc\n#typora\nbun\n'
[ "$output" = "bun" ]
}
@test "an unreadable manifest fails loudly instead of yielding an empty desired list" {
run --separate-stderr bash -c 'source "$1"; read_manifest "$2"' _ "$LIB" "$TEST_TMP/nope.pkgs"
[ "$status" -ne 0 ]
[ -z "$output" ]
[[ "$stderr" == *nope.pkgs* ]]
}
+41 -2
View File
@@ -6,7 +6,8 @@
# built or run, and the tool stops nothing and starts nothing (auto-stopping a production service is
# the thing it must not do unasked).
#
# Exit status: 0 measured · 2 usage · 3 refused (GPU busy) · 4 no toolchain / build failed.
# Exit status: 0 measured · 2 usage · 3 refused (GPU busy) · 4 no toolchain / build failed ·
# 5 a probe ran and failed.
#
# hipcc and the compiled probes are stubbed: this box has no HIP SDK (it is a client laptop) and a
# real measurement belongs on a machine with the cards, beside no running model.
@@ -46,7 +47,16 @@ while [ $# -gt 0 ]; do [ "$1" = "-o" ] && out="$2"; shift; done
: > "$PCIE_PROBE_BUILD/.built"
{ echo '#!/usr/bin/env bash'
echo ': > "$PCIE_PROBE_BUILD/.ran"'
echo 'echo "PROBE RAN dev=${HIP_VISIBLE_DEVICES:-none} bin=$(basename "$0")"'
# HIP rule, modelled because it is the trap: with HIP_VISIBLE_DEVICES set, the ONLY
# valid ordinal is 0. A driver that masks the device and still passes its real ordinal
# asks for a card the runtime cannot see — which is why the stub used to report the
# env var instead of the argument, and could not see the collision.
echo 'dev="${1:-0}"'
echo 'if [ -n "${HIP_VISIBLE_DEVICES:-}" ] && [ "$dev" != 0 ]; then'
echo ' printf "setDevice(%s) failed\n" "$dev" >&2; exit 1'
echo 'fi'
echo '[ "${STUB_PROBE_FAILS:-0}" = 1 ] && { echo "stub probe died mid-measurement" >&2; exit 1; }'
echo 'echo "PROBE RAN dev=$dev bin=$(basename "$0")"'
echo 'echo " slab 2.344 MiB: 31.4 GB/s"'
} > "$out"
chmod +x "$out"
@@ -131,6 +141,35 @@ teardown() { rm -rf "$TEST_TMP"; }
[[ "$output" == *"dev=1"* ]]
}
@test "a device ordinal the environment mask would hide is still measured" {
# Reproduction, not preference: HIP_VISIBLE_DEVICES=1 leaves ordinal 0 as the only
# selectable card, so masking AND passing the ordinal asks hipSetDevice(1) for a
# device the runtime cannot see. Per-card bandwidth was unobtainable that way.
run "$SCRIPT" --device 0 --device 1
[ "$status" -eq 0 ]
[[ "$output" == *"PROBE RAN dev=1"* ]]
[[ "$output" != *"setDevice"* ]]
}
@test "a probe that dies is reported as a failed run, not a green one" {
# The header promises "0 measured". A probe that segfaults (the documented hazard on
# this ROCm build) must not let the sweep exit 0.
run env STUB_PROBE_FAILS=1 "$SCRIPT"
[ "$status" -eq 5 ]
[[ "$output" == *"failed"* ]]
[[ "$output" == *"hip_smoke"* ]]
}
@test "the guard refuses when it cannot see who holds the KFD, instead of assuming idle" {
# Without fuser the /dev/kfd half of the guard cannot run, and gpu_busy_percent reads
# 0 for a service that is resident but idle — a silent fallback would benchmark beside
# a live endpoint, which is the one thing this tool's LAW forbids.
run env PCIE_PROBE_FUSER="$TEST_TMP/nope-fuser" "$SCRIPT"
[ "$status" -eq 3 ]
[[ "$output" == *"fuser"* ]]
[ ! -e "$BUILD/.built" ]
}
@test "no probe sources is a usage-level error, not an empty success" {
rm -f "$SRC"/*.hip
run "$SCRIPT"
+32 -6
View File
@@ -39,15 +39,18 @@ EOF
[2026-03-04T09:00:00-0800] [ALPM] installed bun (1.2-1)
[2026-03-04T09:30:00-0800] [ALPM] upgraded filesystem (2026.01.01-1 -> 2026.03.01-1)
[2026-03-05T09:00:00-0800] [ALPM] installed nirimod-git (r7-1)
[2026-03-07T09:00:00-0800] [ALPM] installed libstray (1.0-1)
[2026-03-06T09:00:00-0800] [ALPM] removed base (3-1)
EOF
# --- installed state --------------------------------------------------------
# ghostty/zoxide/neovim/typora declared. libfoo: explicit, arrived with the installer.
# bun/nirimod-git: installed by hand afterwards, undeclared. python-hatchling: orphan.
printf '%s\n' base bun filesystem ghostty libfoo neovim nirimod-git typora zoxide > "$TEST_TMP/local-all"
# bun/nirimod-git: installed by hand afterwards, undeclared. python-hatchling and libstray:
# installed as dependencies and now unrequired (pacman -Qtdq). libstray arrived AFTER the
# baseline, so the date filter alone cannot keep it out of drift — only the explicit query can.
printf '%s\n' base bun filesystem ghostty libfoo libstray neovim nirimod-git typora zoxide > "$TEST_TMP/local-all"
printf '%s\n' bun ghostty libfoo neovim nirimod-git typora zoxide > "$TEST_TMP/local-explicit"
printf '%s\n' python-hatchling > "$TEST_TMP/orphans"
printf '%s\n' python-hatchling libstray > "$TEST_TMP/orphans"
# nirimod-git is deliberately ABSENT here: no sync db can serve it, which is the fact that
# routes it to aur.pkgs in the test below.
printf '%s\n' bun ghostty neovim typora zoxide libfoo vlc python-hatchling base filesystem > "$TEST_TMP/sync-all"
@@ -131,11 +134,34 @@ ADDITIONS() { section "^undeclared additions" "^installer-provided"; }
[[ "$(section "^declared," "^orphans")" == *vlc* ]]
}
@test "orphans are reported as ignored and never emitted" {
@test "orphans are named on their own line, not mixed into the drift answer" {
run "$SCRIPT"
[[ "$output" == *orphans*python-hatchling* ]]
[[ "$(section "^orphans" "^flatpak")" == *python-hatchling* ]]
[[ "$(ADDITIONS)" != *python-hatchling* ]]
}
@test "a dependency installed after the baseline is never drift, orphan or not" {
# Drift means `pacman -Qqe` — you asked for this one. libstray arrived as a dependency
# after install day and is now unrequired, so the baseline filter does not exclude it:
# only the explicit query does. Swap -Qqe for -Qq and every dependency on the machine,
# dead ones included, becomes a manifest line install.sh will reinstall on a rebuild.
run "$SCRIPT"
[[ "$(ADDITIONS)" != *libstray* ]]
[[ "$output" == *"undeclared additions (declare these): 2"* ]]
[[ "$(section "^orphans" "^flatpak")" == *libstray* ]]
run "$SCRIPT" --emit
[[ "$output" != *python-hatchling* ]]
[[ "$output" != *libstray* ]]
}
@test "--help prints the header and stops before the shell" {
# The header IS the contract (report shape, exit status, seams). A hardcoded line range
# that runs past the comment block hands the reader `set -euo pipefail` as if it were
# documentation.
run "$SCRIPT" --help
[ "$status" -eq 0 ]
[[ "$output" == *"Exit status"* ]]
[[ "$output" != *"pipefail"* ]]
[[ "$output" != *"LC_ALL"* ]]
}
@test "--baseline moves packages installed on that date into the installer set" {
+25
View File
@@ -122,6 +122,31 @@ until_done() {
[[ "$output" == *38* ]] # the tail, not the head
}
@test "status treats a job name as a name, not a pattern" {
"$SCRIPT" start 'x*' -- bash -c 'echo star'
until_done 'x*'
touch "$TEST_TMP/anchor"
# The report is read from a directory full of unrelated files on purpose: a name that is
# expanded as a glob resolves against the CALLER's cwd, so the tool would describe `anchor`
# as a job and never mention the one that really ran.
run bash -c 'cd "$1" && "$2" status "$3"' _ "$TEST_TMP" "$SCRIPT" 'x*'
[[ "$output" == " x*"*"DONE rc=0"* ]]
[[ "$output" != *anchor* ]]
}
@test "tail on an empty harness and on a missing job both say so" {
# An unexpanded `*.out` reaching tail is reported as a missing FILE, which reads as a broken
# script; the honest answer is that there is nothing to follow yet.
run timeout 5 "$SCRIPT" tail
[ "$status" -ne 0 ]
[[ "$output" == *"no jobs"* ]]
[[ "$output" != *".out"* ]]
run timeout 5 "$SCRIPT" tail nosuchjob
[ "$status" -ne 0 ]
[[ "$output" == *"nosuchjob"* ]]
[[ "$output" != *"No such file"* ]]
}
@test "an unknown verb is a usage error" {
run "$SCRIPT" frobnicate
[ "$status" -eq 2 ]
+45
View File
@@ -157,3 +157,48 @@ export API_KEY_FILE=/run/secrets/api_key'
[ "$status" -ne 0 ]
[[ "$output" == *"tests/other.bats"* ]]
}
@test "a credential under a path git quotes is still read" {
# core.quotePath is on by default, so `git diff --name-only` prints "caf\303\251/…" for a
# non-ASCII directory. Feed that quoted string back to `git diff -- <path>` and the diff is
# empty — and a gate that skips an unreadable file reports success. This is the fail-closed
# promise breaking on its own terms, not a cosmetic quoting complaint.
try_commit "café/postgres.env" 'POSTGRES_PASSWORD=hunter2corp2026'
[ "$status" -ne 0 ]
[[ "$output" == *"postgres.env"* ]]
}
@test "a placeholder word elsewhere on the line does not exempt a live value" {
# The rule is about the VALUE. `# example` in a comment says nothing about the token the
# line assigns, but a whole-line placeholder filter lets the comment vouch for the secret.
try_commit "app.env" 'API_TOKEN=hunter2corp2026 # example, placeholder, changeme'
[ "$status" -ne 0 ]
[[ "$output" == *"app.env"* ]]
}
@test "each hit is attributed to the file it came from" {
# The report is how the next agent finds the leak. If one file's last hit line runs into the
# next file's name, the audit starts at a clean file and the leaker keeps its name.
mkdir -p "$REPO/a" "$REPO/b"
printf 'A_PASSWORD=hunter2corp2026\n' > "$REPO/a/one.env"
printf 'B_PASSWORD=hunter2corp2026\n' > "$REPO/b/two.env"
run git -C "$REPO" add -A
run git -C "$REPO" commit -q -m "two leakers"
[ "$status" -ne 0 ]
printf '%s\n' "$output" | grep -qx ' a/one.env'
printf '%s\n' "$output" | grep -qx ' b/two.env'
! printf '%s\n' "$output" | grep -qE 'hunter2corp2026 +b/two\.env'
}
@test "a documented fake id in prose is committable; a live-shaped id in the same file is not" {
# Measured on blankpad 2026-10-21: the live-sync heartbeat failed three ticks in a row
# because a managed-skill page documents how to write a secret gate and quotes AWS's own
# placeholder id. A gate that blocks the machine tier over an inert example gets worked
# around, and a workaround is the hole. The exemption reads the matched token, so a real
# id in the same file still blocks.
try_commit "docs.md" 'Inert fixtures look like AKIAIOSFODNN7EXAMPLE or AKIA0000000000000EXAMPLE.'
[ "$status" -eq 0 ]
try_commit "docs.md" 'Inert fixture AKIAIOSFODNN7EXAMPLE and a live one AKIAQZR4W7DBPCFG7V3Q.'
[ "$status" -ne 0 ]
[[ "$output" == *"docs.md"* ]]
}