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

No files matched your search

+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 *.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text *.jpeg filter=lfs diff=lfs merge=lfs -text
*.png 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. # how a gate gets permanently overridden.
assign_exempt='(_FILE|_PATH|_DIR|_URL|_ENDPOINT|_SOCKET)[[:space:]]*[:=]|[:=][[:space:]]*["'"'"']?(/|\.\./)' assign_exempt='(_FILE|_PATH|_DIR|_URL|_ENDPOINT|_SOCKET)[[:space:]]*[:=]|[:=][[:space:]]*["'"'"']?(/|\.\./)'
# Fail closed: a gate that cannot read the staged diff must not report success. # 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." 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 ..." echo "Override deliberately: ALLOW_SECRETS=1 git commit ..."
} >&2 } >&2
[ -n "${ALLOW_SECRETS:-}" ] && exit 0 [ -n "${ALLOW_SECRETS:-}" ] && exit 0
exit 1 exit 1
fi fi
# stderr is captured so the failure branch can quote it; on success it must not # git's stderr stays out of the name list on purpose: a `warning:` line mistaken for a path
# leak a `warning:` line into the file list and have it mistaken for a path. # becomes a file that "cannot be read", which is how a gate starts skipping the real ones.
files=$(printf '%s\n' "$files" | grep -vE '^(warning|fatal|error):' || true) [ -s "$TMPD/files" ] || exit 0
[ -z "${files//[[:space:]]/}" ] && exit 0
report="" report=""
exempt="" exempt=""
count=0 count=0
while IFS= read -r f; do while IFS= read -r -d '' f; do
[ -z "$f" ] && continue [ -z "$f" ] && continue
# Self-exemption, deliberately an exact filename list and not `tests/`: the # Self-exemption, deliberately an exact filename list and not `tests/`: the
# gate's fixtures must contain credential-shaped strings or there is nothing to # 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. # gate refused the redaction of the password it exists to catch.
added=$(printf '%s\n' "$diff" | grep -E '^\+' | grep -vE '^\+\+\+' | sed 's/^+//' || true) added=$(printf '%s\n' "$diff" | grep -E '^\+' | grep -vE '^\+\+\+' | sed 's/^+//' || true)
[ -z "$added" ] && continue [ -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 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') hits=$(printf '%s\n%s\n' "$hits" "$assigns" | sed '/^[[:space:]]*$/d')
fi fi
if [ -n "$hits" ]; then if [ -n "$hits" ]; then
n=$(printf '%s\n' "$hits" | wc -l) n=$(printf '%s\n' "$hits" | wc -l)
count=$((count + n)) 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 fi
done <<< "$files" done < "$TMPD/files"
# Say so out loud: an exemption that prints nothing is how a carve-out becomes # Say so out loud: an exemption that prints nothing is how a carve-out becomes
# invisible, and invisible is the property a secret wants. # 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 # 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 # 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 # `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>` # filename carries its wallhaven ID; `/w/<id>` answers `text/html`, so resolve the CDN URL at
# puts it back. Law: omp-docs/tools/dotfiles-deploy.md # `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/ dotfiles/noctalia/.local/share/noctalia/wallpapers/
# --- generated theme output: machine-written, never reviewable, never deployed --- # --- generated theme output: machine-written, never reviewable, never deployed ---
# noctalia/matugen rewrite these in place; a tracked copy is a stale snapshot that # 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 # deploy.sh would push back over a live palette. These patterns are the ignore half of the
# scripts/deploy.sh. Law: omp-docs/inventory/home-config-census.md, Refs #42 # 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/**/themes/noctalia*
dotfiles/**/colors/noctalia* dotfiles/**/colors/noctalia*
dotfiles/**/noctalia.* dotfiles/**/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 ### Issue tracker
Work items are Gitea issues on `dank/command-center` (Dankclaw, See [`omp-docs/skills/issue-tracker.md`](omp-docs/skills/issue-tracker.md).
`192.168.0.143:3000`) — no `gh`, no `tea`. See
[`omp-docs/skills/issue-tracker.md`](omp-docs/skills/issue-tracker.md).
### Triage labels ### Triage labels
The five canonical roles, each label string equal to its name. See See [`omp-docs/skills/triage-labels.md`](omp-docs/skills/triage-labels.md).
[`omp-docs/skills/triage-labels.md`](omp-docs/skills/triage-labels.md).
### Domain docs ### Domain docs
Single-context, inside the existing knowledge base: `omp-docs/glossary.md` and ADRs: `omp-docs/decisions/`. `omp-docs/glossary.md` is intentionally not created.
`omp-docs/decisions/`. See [`omp-docs/skills/domain-docs.md`](omp-docs/skills/domain-docs.md). See [`omp-docs/skills/domain-docs.md`](omp-docs/skills/domain-docs.md).
## Secret gate (HARD rule) ## 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 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. 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. - 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. - 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] [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 Documentation=https://github.com/swaywm/swayidle
After=graphical-session.target After=graphical-session.target
# Restart together with the session, not merely at boot: this unit is wanted by # Restart together with the session, not merely at boot: this unit is wanted by
@@ -7,10 +7,14 @@
// requires: Lenovo Group Limited 0x40A9 Unknown // requires: Lenovo Group Limited 0x40A9 Unknown
// optional: HDMI-A-1 (PM1601, dock-dependent) // optional: HDMI-A-1 (PM1601, dock-dependent)
// This panel's EDID tops out at 3440x1440@180 (read live from niri: no 240 Hz mode // The panel offers 3440x1440@239.998 as well as @180.000 (`niri msg outputs`, 2026-10-21), and
// exists). Ask for a mode the panel does not offer and niri does not fail — it logs // 180 is driven DELIBERATELY: the link trained at x8 32.0 GT/s against a max of x16 and the
// "could not be found, falling back to preferred" and drops to 60 Hz on every // display engine is throwing DMCUB errors with EINVAL page flips after s2idle, so the 240-class
// reconnect. Keep 180 here unless a re-read EDID says otherwise. // 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" { output "Sceptre Tech Inc Sceptre M34 Unknown" {
mode "3440x1440@180.000" mode "3440x1440@180.000"
scale 1 scale 1
+2 -2
View File
@@ -1,8 +1,8 @@
# Architecture decision records # Architecture decision records
Decisions this repo has made and will not silently revisit. One file per 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` decision, named `NNN-<slug>.md`, listed here — an unlisted page fails
and does not exist as far as any agent is concerned. `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 **No ADRs yet.** The first one lands the moment a decision stops being
reversible. reversible.
+2 -2
View File
@@ -57,8 +57,8 @@ search practices, open models, MCP.
## [Inventory](inventory/index.md) ## [Inventory](inventory/index.md)
Pre-pruning census of every userspace config on this box — the input for the Per-file tracked-vs-box-only census of `~/.config` on blankpad — the input for the
pruning session. dotfiles pruning/adoption session.
## [Decisions](decisions/index.md) ## [Decisions](decisions/index.md)
+4 -2
View File
@@ -1,5 +1,7 @@
# Inventory Index # 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 (`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. 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 This is the bundle's only work log; [references/okf-spec.md](references/okf-spec.md) owns the
second one in a subdirectory or under another name — `scripts/kb-lint.sh` reports any one-log rule and `scripts/kb-lint.sh` enforces it.
`log.md` that is not this one.
## 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 ## 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` 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 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. 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 The panel does offer a 240-class mode: `niri msg outputs` lists `3440x1440@239.998`. The defect
240 Hz mode to ask for. 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): Laws, now on [tools/niri/displays](tools/niri/displays.md):
- **An impossible mode does not fail, it falls back.** niri logs - **A mode string must match the advertised string verbatim.** niri does not round:
`configured mode … could not be found, falling back to preferred` and drives `3440x1440@239.999` does not select `3440x1440@239.998`. It logs
the EDID preferred mode — 60 Hz here. A config typo therefore looks like a `configured mode … could not be found, falling back to preferred` and drives the EDID
dying monitor, and every connector drop re-enacts it. 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 - **Three layers, three signatures:** config fallback, DP link drops, and
amdgpu `DMCUB` errors with `EINVAL` page flips after s2idle. Only the first 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 yields to a file edit; only the last yields to a reboot. Triage table and
probes are on the page. probes are on the page.
- **A number in a page is a claim, not a measurement.** Modes, refresh rates and - **A number in a page is a claim, not a measurement.** Mode strings, refresh rates and tool
tool availability were wrong on four pages at once — `wlr-randr` was listed as availability were wrong on several pages at once — `wlr-randr` was listed as installed while
installed while `pacman -Qs wlr` matches nothing. Read the hardware before `pacman -Qs wlr` matches nothing. Read the hardware before writing a mode into a runbook, and
writing a mode into a runbook, and destroy the stale copies. 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 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 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` ## Change Tracking with `log.md`
Every OKF bundle has a `log.md`, and it is the bundle's **only** work log: one file, Exactly one `log.md` per bundle, at the bundle root — [okf-spec.md](okf-spec.md) owns that rule
at the bundle root. A subdirectory never gets its own — not `core/log.md`, not and `scripts/kb-lint.sh` enforces it, reporting any `log.md` that is not the root's. The
`notes.md`, not a per-project, per-branch or per-run diary. Sprawl is not caution: maintenance action is collapse, never coexistence: when a second log turns up (`core/log.md`,
with fifty logs the entry is never where the next agent looks, and each copy re-dates `notes.md`, a per-run diary), move its entries into the root log under their own dates, delete
the same event on its own authority. `scripts/kb-lint.sh` reports any `log.md` that is the file, and re-run the linter.
not the root's.
**Format:** one dated section per day, newest first; a few lines per change — what **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. 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 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. 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:** **Rules:**
@@ -58,8 +57,9 @@ Details: [secret gate](../tools/index.md).
- ❌ Forgetting the entry — the change lands undocumented and the next agent rediscovers - ❌ Forgetting the entry — the change lands undocumented and the next agent rediscovers
the failure the hard way. the failure the hard way.
- ❌ Starting a second log in a subdirectory — the sprawl that makes logging useless. - ❌ 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 - ❌ Invented paths in links — the RECOMMENDED form is an absolute bundle path
linter checks them. (`/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. - ❌ 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 type: reference
title: Dotfiles deployment tier 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: tags:
- dotfiles - dotfiles
- deployment - deployment
- systemd - systemd
- noctalia - noctalia
timestamp: 2026-10-20 timestamp: 2026-10-20
verified: 2026-10-20 verified: 2026-10-21
--- ---
# Dotfiles deployment tier # 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` (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 | | `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 Two package shapes are not symlinks. `dconf/dump.txt` is loaded with `dconf load /`. The
`systemd-user` units get `daemon-reload` plus `enable`; a unit is **started** only when `systemd-user` tier gets `daemon-reload`, then **every `*.service` and `*.timer` whose start
systemd reports it as nothing-yet (`""`/`disabled`), and never when its `ExecStart` binary command resolves on this box** is enabled — a timer is the schedule that makes a oneshot service
is absent here, so a unit belonging to another box stays inert instead of crash-looping. 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 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*. 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 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 `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 whole address — but `https://wallhaven.cc/w/<id>` answers `text/html`, the web page, so
the set back. Losing it is an acceptable outcome; 80 MB per clone forever is not. 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 ## 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 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. 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 ## 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 `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. * [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. * [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. * [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. * [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. * [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. * [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 │ │ 1200x1920 │ landscape, scale 1 │ scale 1 │
│ rot 90 │ position 1581,-600 │ 5021,-240│ │ 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 | | 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 | | 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` | | 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 VRR: the M34 supports it (its connector today is `DP-1`); **left disabled by
`variable-refresh-rate` per output if that ever changes. 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 `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. 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 3. **Positions are absolute, not relational.** A disconnected panel leaves
a hole; that is exactly why positions belong to the *desk profile*, not a a hole; that is exactly why positions belong to the *desk profile*, not a
global file. global file.
4. **Ask only for modes the panel reports** (`niri msg outputs` → `Mode:` list). 4. **Ask only for modes the panel reports, and copy the string exactly.** The M34's
A mode the panel never offered does **not** leave the output dark: niri logs `Available modes` (`niri msg outputs`, 2026-10-21) are `3440x1440@239.998`,
`configured mode … could not be found, falling back to preferred` and quietly `3440x1440@180.000`, `144.001`, `120.000`, … with `59.998` marked preferred. niri
drives the panel at its EDID *preferred* mode — **60 Hz** on the M34. Nothing matches mode strings **verbatim** and does not round, so `239.999` — one digit from
looks broken except the refresh rate, and every reconnect repeats the the real mode, which is what this file and the config both carried for weeks — is not
fallback. Check Hz, not just resolution, after any "monitor is acting up". `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 ## "The monitors are broken" — three layers, three signatures
+15 -11
View File
@@ -413,17 +413,21 @@ noctalia msg templates-apply
## Dependencies ## Dependencies
| Package | Purpose | | Package | Purpose | Version on blankpad (2026-10-21) |
|---------|---------| |---------|---------|----------------------------------|
| `noctalia` (Qt) | Native desktop environment | | `noctalia` (Qt) | the shell: bar, widgets, `noctalia msg` | 5.3.0-1.1 |
| `qt6-base` | Qt6 runtime | | `qt6-base` | Qt6 runtime | 6.12.0-3.1 |
| `qt6-multimedia` | Multimedia support | | `niri` | Wayland compositor | 26.04-1.1 |
| `niri` | Wayland compositor | | `polkit` | PolicyKit integration | 128-1.1 |
| `wlr-randr` | Display information | | `imagemagick` | image processing for palette wallpapers | 7.1.2.34-2.1 |
| `brightnessctl` | Brightness control | | `ffmpeg` | media processing | 2:9.0.2-2.1 |
| `imagemagick` | Image processing |
| `ffmpeg` | Media processing | **Three rows this page used to claim are not installed**, verified with `pacman -Q` and
| `polkit` | PolicyKit integration | `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 - provisioning
- fleet - fleet
- blankpad - blankpad
verified: 2026-10-20 verified: 2026-10-21
timestamp: 2026-10-20 timestamp: 2026-10-20
--- ---
@@ -25,9 +25,13 @@ if both directions are checked.
## Manifests ## Manifests
`packages/common.pkgs` (every host) + `packages/<host>.pkgs` (this host) + `packages/aur.pkgs` `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 `#` (AUR-only, installed through `yay`). **One parser reads them for both tools**:
comments trail freely and one token per line is the whole grammar. An unknown `--host` gets the `scripts/lib/manifest.sh` — `sed 's/#.*//'` then the first field, so `#` comments trail freely and
common manifest only: a wrong-host run is a no-op, not a hazard. 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 ## 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 aur (needs a helper): <names> → belongs in packages/aur.pkgs
installer-provided, undeclared: N + names → a reinstall supplies these; do not declare installer-provided, undeclared: N + names → a reinstall supplies these; do not declare
declared, not installed: <names> → install.sh installs these 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 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 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. 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 **Known gap:** `aur.pkgs` is read for *every* host, so a desktop-only AUR package — the niri
GUI client) cannot be declared there without asking the headless servers to build it. Such a name is module `nirimod-git`, say, or a GUI client — cannot be declared there without asking the
still reported as an AUR addition; leave it undeclared until `install.sh` grows a per-host AUR 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. manifest.
## Law: orphans never reach a manifest ## Law: orphans never reach a manifest
`pacman -Qtdq` names are packages nothing depends on; emitting them would teach a fresh machine to Drift is `pacman -Qqe` — *explicitly* installed, therefore yours. `pacman -Qtdq` names packages
install the same dead weight. They are printed as `orphans ignored` and excluded from `--emit`. 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 ## 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) · - [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) [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. - Refs #51.
+19 -9
View File
@@ -8,7 +8,7 @@ tags:
- rdna4 - rdna4
- benchmarking - benchmarking
- dankserver - dankserver
verified: 2026-10-20 verified: 2026-10-21
timestamp: 2026-10-20 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 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 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 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 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 - Pinned versus pageable columns apart means pinning is load-bearing; together
means the copies are already pinned by someone else. means the copies are already pinned by someone else.
Measure one device at a time (`--device`). A run that lets the runtime pick Measure one device at a time (`--device`, a HIP ordinal). A run that lets the runtime
several devices cannot attribute bandwidth to a card at all. 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 ## The trap carried in the sources
@@ -79,14 +85,18 @@ when touching these files.
## Exit status and seams ## Exit status and seams
`0` measured · `2` usage or no sources · `3` refused, GPU busy · `4` no HIP `0` measured · `2` usage or no sources · `3` refused, GPU busy or holders unknowable ·
toolchain or build failed. A client box without the SDK exits `4` loudly rather `4` no HIP toolchain or build failed · `5` a probe ran and failed. A client box without
than reporting an empty success; the probes belong on the box with the cards. 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`, 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_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 `PCIE_PROBE_FUSER`, `PCIE_PROBE_MAX_BUSY` — the sysfs/kfd paths are what make a
a machine with no cards, which is the only honest way to test a refusal. 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 Measured campaign numbers are not kept here; they belong with the endpoint they
were taken on, in the serverAppConfigs LLM runbook vault. 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 ```bash
remote-job.sh start NAME [--] CMD... # launch detached, return at once 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 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 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 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 | | 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 | | 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 | | 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 | | Job dir missing | created on first use |
Pinned by `tests/remote-job.bats` (black-box: output, exit codes, sentinel Pinned by `tests/remote-job.bats` (black-box: output, exit codes, sentinel
+2 -2
View File
@@ -18,8 +18,8 @@ btop
# system / fleet tooling # system / fleet tooling
yay # AUR helper bootstrap: ships in the cachyos repo; aur.pkgs installs need it yay # AUR helper bootstrap: ships in the cachyos repo; aur.pkgs installs need it
git-lfs # LFS smudge/clean for tracked wallpapers (see .gitattributes) git-lfs # cloning LFS-backed upstreams (Hugging Face model/dataset repos); this repo tracks zero LFS files — .gitattributes is idle config
swayidle # idle lock + lid policy via swayidle-lock.service unit swayidle # idle lock watcher via swayidle-lock.service; suspend locking is noctalia's sleep inhibitor
# desktop apps # desktop apps
flameshot # screenshot tool; bound to CTRL+Shift+1/2/3 in niri keybinds 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 if [ "$MODE" != "check" ] && [ -d "$PKGS_DIR/systemd-user/.config/systemd/user" ]; then
systemctl --user daemon-reload || true 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 [ -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 # 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 # `%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 # 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 -un)}"
bin="${bin//%U/$(id -u)}" bin="${bin//%U/$(id -u)}"
if [ -n "$bin" ] && command -v "$bin" >/dev/null 2>&1; then 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 # 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 # 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 # 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. # mid-conversation. Only a unit nothing has installed yet gets started. Refs #44.
state="$(systemctl --user is-enabled "$name" 2>/dev/null || true)" state="$(systemctl --user is-enabled "$name" 2>/dev/null || true)"
case "$state" in if ! grep -q '^\[Install\]' "$unit"; then
"" | disabled) # systemd refuses to enable these: no [Install] section means nothing can want the unit
systemctl --user enable --now "$name" || true # at login, and live-sync.service has none on purpose — its timer pulls it in. The old
echo "ENABLE $name (ExecStart resolves here; nothing running it yet)" ;; # 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
systemctl --user enable "$name" || true # the call at all. Refs #60.
echo "ENABLE $name (already $state; not started — a live session decides what runs)" ;; echo "INERT $name (state=${state:-none}; no [Install] section — another unit arms it, enable cannot)"
esac 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 else
echo "SKIP $(basename "$unit") (ExecStart '$bin' absent on this host)" echo "SKIP $name (ExecStart '$bin' absent on this host)"
fi fi
done done
fi fi
+3 -4
View File
@@ -17,7 +17,8 @@
# otherwise sudo prompts normally. The value is never stored in this repo. # otherwise sudo prompts normally. The value is never stored in this repo.
set -euo pipefail 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}" REPO="${INSTALL_REPO:-$REPO}"
[ -n "$REPO" ] && [ -d "$REPO/packages" ] || { echo "install.sh: no packages/ under ${REPO:-<repo>}" >&2; exit 1; } [ -n "$REPO" ] && [ -d "$REPO/packages" ] || { echo "install.sh: no packages/ under ${REPO:-<repo>}" >&2; exit 1; }
@@ -36,9 +37,7 @@ SUDO() {
else sudo "$@"; fi else sudo "$@"; fi
} }
read_manifest() { # $1 = manifest path; emits package names, strips comments/blanks source "$HERE/lib/manifest.sh" # the same parser pkg-inventory.sh reads with
sed 's/#.*//' "$1" | tr -d '\r' | awk '{if ($1) print $1}'
}
# ---- desired-minus-installed delta ------------------------------------------ # ---- desired-minus-installed delta ------------------------------------------
PKGS=() PKGS=()
for m in common.pkgs "$HOST.pkgs"; do for m in common.pkgs "$HOST.pkgs"; do
+9 -2
View File
@@ -20,6 +20,10 @@ def pages():
if ".AGENTTRASH" not in p.parts: if ".AGENTTRASH" not in p.parts:
yield p 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(): for p in pages():
rel = p.relative_to(kb) rel = p.relative_to(kb)
text = p.read_text(errors="replace") text = p.read_text(errors="replace")
@@ -70,9 +74,12 @@ for p in pages():
if not Path(target).is_file(): if not Path(target).is_file():
violations.append(f"{rel}: broken relative link -> {m.group(1)}") violations.append(f"{rel}: broken relative link -> {m.group(1)}")
for m in re.finditer(r"\[\[([^\]|#]+)", text): 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] 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()}]]") violations.append(f"{rel}: broken wikilink -> [[{m.group(1).strip()}]]")
for v in violations: 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] # 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 # --device N measure HIP device ordinal N; repeat for each card. Without it the probes run
# environment's own device selection — one shared run cannot attribute bandwidth. # 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. # --build-only compile and stop; never touches the cards.
# --force measure even though the guard says the GPU is busy. # --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_SYSFS drm sysfs root (/sys/class/drm)
# PCIE_PROBE_KFD KFD device node (/dev/kfd) # PCIE_PROBE_KFD KFD device node (/dev/kfd)
# PCIE_PROBE_HIPCC compiler (hipcc) # PCIE_PROBE_HIPCC compiler (hipcc)
# PCIE_PROBE_FUSER KFD holder probe (fuser)
# PCIE_PROBE_MAX_BUSY refusal threshold, percent (5) # 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 # Exit status: 0 measured · 2 usage or missing sources · 3 REFUSED, GPU busy or unknowable ·
# build failed. # 4 no toolchain or build failed · 5 a probe ran and failed.
set -uo pipefail set -uo pipefail
@@ -39,6 +44,7 @@ BUILD="${PCIE_PROBE_BUILD:-$HOME/.cache/pcie-probe}"
SYSFS="${PCIE_PROBE_SYSFS:-/sys/class/drm}" SYSFS="${PCIE_PROBE_SYSFS:-/sys/class/drm}"
KFD="${PCIE_PROBE_KFD:-/dev/kfd}" KFD="${PCIE_PROBE_KFD:-/dev/kfd}"
HIPCC="${PCIE_PROBE_HIPCC:-hipcc}" HIPCC="${PCIE_PROBE_HIPCC:-hipcc}"
FUSER="${PCIE_PROBE_FUSER:-fuser}"
MAX_BUSY="${PCIE_PROBE_MAX_BUSY:-5}" MAX_BUSY="${PCIE_PROBE_MAX_BUSY:-5}"
force=0 force=0
@@ -63,9 +69,19 @@ fi
# ---- the guard, before anything touches the card -------------------------------- # ---- the guard, before anything touches the card --------------------------------
if (( ! force )); then if (( ! force )); then
busy="" busy=""
if [[ -e "$KFD" ]] && command -v fuser > /dev/null 2>&1; then if [[ -e "$KFD" ]]; then
holders="$(fuser "$KFD" 2>/dev/null | tr -s '[:space:]' ' ')" if command -v "$FUSER" > /dev/null 2>&1; then
[[ -n "${holders// /}" ]] && busy="KFD in use by:${holders}" 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 fi
for card in "$SYSFS"/card*; do for card in "$SYSFS"/card*; do
[[ -f "$card/device/gpu_busy_percent" ]] || continue [[ -f "$card/device/gpu_busy_percent" ]] || continue
@@ -111,7 +127,11 @@ for card in "$SYSFS"/card*; do
done done
# ---- measure, per device -------------------------------------------------------- # ---- 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) (( ${#devices[@]} > 0 )) || devices=(default)
failures=()
for d in "${devices[@]}"; do for d in "${devices[@]}"; do
if [[ $d == default ]]; then if [[ $d == default ]]; then
printf '\n########## engine device selection ##########\n' 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 for name in hip_smoke pcie_bw pcie_probe; do
bin="$BUILD/$name" bin="$BUILD/$name"
[[ -x "$bin" ]] || continue [[ -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
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) # aur (needs a helper): <names> → belongs in packages/aur.pkgs (yay)
# installer-provided, undeclared: N a reinstall supplies these; do not declare # installer-provided, undeclared: N a reinstall supplies these; do not declare
# declared, not installed: N install.sh installs these # 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 # 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 # --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. # 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 # 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 # (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 while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--emit) MODE="emit"; shift ;; --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 ;; *) echo "usage: pkg-inventory.sh [--emit]" >&2; exit 2 ;;
esac esac
done done
HERE="$(dirname "$(realpath "$0")")"
REPO="${PKGINV_REPO:-}" REPO="${PKGINV_REPO:-}"
if [[ -z "$REPO" ]]; then 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 fi
[[ -n "$REPO" && -d "$REPO/packages" ]] || { echo "pkg-inventory: no packages/ under ${REPO:-<repo>}" >&2; exit 2; } [[ -n "$REPO" && -d "$REPO/packages" ]] || { echo "pkg-inventory: no packages/ under ${REPO:-<repo>}" >&2; exit 2; }
HOST="${PKGINV_HOST:-$(hostname)}" HOST="${PKGINV_HOST:-$(hostname)}"
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
read_manifest() { # same parser install.sh uses, so a name means the same thing to both source "$HERE/lib/manifest.sh" # the same parser install.sh installs with
sed 's/#.*//' "$1" | tr -d '\r' | awk '{if ($1) print $1}'
}
# ---- installed state --------------------------------------------------------- # ---- installed state ---------------------------------------------------------
# Four queries are the tool's whole interface to pacman. -Sl is the unprivileged sync listing: # 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 # -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) 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 if [[ -n "${2:-}" ]]; then
names="$2" read -r -a names <<< "$2"
else 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 fi
if [[ ${#names[@]} -eq 0 ]]; then echo " (no jobs)"; exit 0; fi
pending=0 pending=0
for n in $names; do for n in "${names[@]}"; do
if [[ -f "$JOBS/$n.done" ]]; then if [[ -f "$JOBS/$n.done" ]]; then
printf ' %-20s DONE rc=%s %s lines\n' "$n" \ 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 ' ')" "$(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 pending=1
fi fi
done done
if [[ -z "$names" ]]; then echo " (no jobs)"; exit 0; fi
exit "$pending" exit "$pending"
;; ;;
@@ -95,8 +102,15 @@ case "${1:-}" in
tail) tail)
# Multiplexed follow: no NAME means every job at once, so one pane shows the whole harness. # 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 # Both branches check for something to follow first: an unexpanded `*.out` handed to tail
exec tail -f "$JOBS"/*.out # 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) watch)
+59 -1
View File
@@ -37,7 +37,22 @@ if [ "$2" = is-enabled ]; then
printf '%s\n' "$state" printf '%s\n' "$state"
case "$state" in disabled | "") exit 1 ;; *) exit 0 ;; esac case "$state" in disabled | "") exit 1 ;; *) exit 0 ;; esac
fi 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 STUB
chmod +x "$TEST_TMP/bin/systemctl" chmod +x "$TEST_TMP/bin/systemctl"
export PATH="$TEST_TMP/bin:$PATH" export PATH="$TEST_TMP/bin:$PATH"
@@ -57,6 +72,21 @@ systemd_unit() {
> "$REPO/dotfiles/systemd-user/.config/systemd/user/$1" > "$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" { @test "generated theme output is never adopted into a symlink" {
repo_file "ghostty/.config/ghostty/themes/noctalia" 'background = "#f43841"' repo_file "ghostty/.config/ghostty/themes/noctalia" 'background = "#f43841"'
live_file "$HOME/.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 'systemctl --user enable heartbeat.service' "$STUB_LOG"
! grep -q -- '--now' "$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)"* ]] [[ "$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" { @test "the shipped knowledge base itself is conformant" {
# The tests above exercise the linter against fixtures; nothing else in the # 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 # 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 # built or run, and the tool stops nothing and starts nothing (auto-stopping a production service is
# the thing it must not do unasked). # 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 # 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. # 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" : > "$PCIE_PROBE_BUILD/.built"
{ echo '#!/usr/bin/env bash' { echo '#!/usr/bin/env bash'
echo ': > "$PCIE_PROBE_BUILD/.ran"' 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"' echo 'echo " slab 2.344 MiB: 31.4 GB/s"'
} > "$out" } > "$out"
chmod +x "$out" chmod +x "$out"
@@ -131,6 +141,35 @@ teardown() { rm -rf "$TEST_TMP"; }
[[ "$output" == *"dev=1"* ]] [[ "$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" { @test "no probe sources is a usage-level error, not an empty success" {
rm -f "$SRC"/*.hip rm -f "$SRC"/*.hip
run "$SCRIPT" 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: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-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-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) [2026-03-06T09:00:00-0800] [ALPM] removed base (3-1)
EOF EOF
# --- installed state -------------------------------------------------------- # --- installed state --------------------------------------------------------
# ghostty/zoxide/neovim/typora declared. libfoo: explicit, arrived with the installer. # ghostty/zoxide/neovim/typora declared. libfoo: explicit, arrived with the installer.
# bun/nirimod-git: installed by hand afterwards, undeclared. python-hatchling: orphan. # bun/nirimod-git: installed by hand afterwards, undeclared. python-hatchling and libstray:
printf '%s\n' base bun filesystem ghostty libfoo neovim nirimod-git typora zoxide > "$TEST_TMP/local-all" # 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' 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 # 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. # 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" 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* ]] [[ "$(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" 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 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" { @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 [[ "$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" { @test "an unknown verb is a usage error" {
run "$SCRIPT" frobnicate run "$SCRIPT" frobnicate
[ "$status" -eq 2 ] [ "$status" -eq 2 ]
+45
View File
@@ -157,3 +157,48 @@ export API_KEY_FILE=/run/secrets/api_key'
[ "$status" -ne 0 ] [ "$status" -ne 0 ]
[[ "$output" == *"tests/other.bats"* ]] [[ "$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"* ]]
}