chore(agent): commit the machine tier and the doctrine text the checkout was already running
Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and `merge --ff-only` refuses while tracked paths are dirty. Discard is not available here (workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed. - `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new prose — the commit exists so the trunk merge can proceed. - `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat owns (AGENTS.md § Live-sync tiers). `ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the inert all-zero AWS example id — and they appear inside the two skill pages that teach that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal dies with this landing. No `--no-verify` was used: the gate ran and its verdict is recorded here. Refs #61
This commit is contained in:
1 parent
004962ffce
commit
8af40c402b
79 files changed
+2771
-332
No files matched your search
@@ -0,0 +1,88 @@
|
||||
---
|
||||
name: dotfiles-adoption-audit
|
||||
description: "Use when deciding which userspace configs on a Dank box belong in the command-center dotfiles tier — separates tracked intent from generated expansion, app state, secrets, and config owned by another repo. Not for deploying one known file."
|
||||
---
|
||||
|
||||
# Dotfiles adoption audit
|
||||
|
||||
Decides, with evidence, which files under `~/.config` (and top-level dotfiles) belong in
|
||||
`dank/command-center`'s `dotfiles/` tier. The repo law being applied: **config in, state
|
||||
out**, and **one fact, one owner**.
|
||||
|
||||
## The four gates (all four must pass)
|
||||
|
||||
1. **Installed?** `command -v <prog>` — config for software absent from the box is a prune
|
||||
candidate, never an adoption target. This eliminates most of the clutter.
|
||||
2. **Authored, or the expansion of something else?** Generated files must stay out even
|
||||
though they look like config.
|
||||
3. **Does another repo or installer already write it?** If a script or package owns the
|
||||
file, tracking it here creates a second owner that loses every argument.
|
||||
4. **Could a secret ever live in it?** If yes: template + quarantine, or leave it out.
|
||||
|
||||
## Gate 2 is the one people get wrong — prove generation from mtime
|
||||
|
||||
A generator walking the app list writes dozens of files in the same sub-second window.
|
||||
Compare timestamps across unrelated programs:
|
||||
|
||||
```bash
|
||||
cd ~/.config && stat -c '%y %n' */themes/noctalia* */noctalia.* */colors/noctalia* 2>/dev/null | sort
|
||||
```
|
||||
|
||||
Identical seconds + microsecond progression across ten different programs = generated.
|
||||
Re-check one file days later: a new mtime with no human edit proves regeneration, so the
|
||||
tracked file must be the *source* (palette/config the generator reads), never its output.
|
||||
The correct pattern is a tracked config that *imports* the generated path.
|
||||
|
||||
## Classify the whole tree per file, not per directory
|
||||
|
||||
The tracked unit is the **file symlink**, so a directory can be "real" while containing only
|
||||
tracked symlinks. Never classify by directory:
|
||||
|
||||
```bash
|
||||
cd ~/.config && for d in */; do d=${d%/}; tr=0; rl=0; rlfiles=""
|
||||
while IFS= read -r f; do
|
||||
case "$(readlink -f "$f" 2>/dev/null)" in
|
||||
*/.omp/dotfiles/*) tr=$((tr+1));;
|
||||
*) rl=$((rl+1)); rlfiles="$rlfiles ${f#./}";;
|
||||
esac
|
||||
done < <(find "$d" -maxdepth 2 \( -type f -o -type l \) 2>/dev/null \
|
||||
| grep -vE 'Cache|cache|Cookies|storage|sessions|Crashpad|Default|thumbnails|extensions')
|
||||
[ $((tr+rl)) -eq 0 ] && continue
|
||||
printf '%-22s tracked=%-3s box-only=%-3s %s\n' "$d" "$tr" "$rl" "$(echo $rlfiles | cut -c1-90)"
|
||||
done
|
||||
```
|
||||
|
||||
Then read the headers of suspicious files — installers often confess ("Installed by
|
||||
`infra/setup-dev.sh` into `~/.config/containers/systemd/`") and unit files name another
|
||||
project's `WorkingDirectory`/`ExecStart`, which means that project owns them.
|
||||
|
||||
## Ownership before adoption
|
||||
|
||||
```bash
|
||||
git -C ~/.omp ls-files dotfiles # packages deploy.sh sees
|
||||
grep -rl "<unit-or-file-name>" ~/Projects/<proj> # does a project repo own it?
|
||||
systemctl --user is-active <unit> # dead config is not load-bearing
|
||||
```
|
||||
|
||||
## Secret-gap check (do this before adopting anything env-shaped)
|
||||
|
||||
The ignore list may cover only `.env`, so `frank-job-hunt.env` / `postgres.env` fall
|
||||
through, and a token-shape secret gate (`sk-`, `ghp_`, PEM, JWT) does not match a
|
||||
low-entropy `POSTGRES_PASSWORD=…`. Test both explicitly:
|
||||
|
||||
```bash
|
||||
cd ~/.omp && git check-ignore -v --no-index 'dotfiles/x/postgres.env' || echo "NOT IGNORED"
|
||||
sed -n 's/^patterns=//p' .githooks/pre-commit
|
||||
```
|
||||
|
||||
Fix = add `*.env` to the quarantine block **and** a password-assignment pattern to the gate,
|
||||
with a red test that stages a fake `POSTGRES_PASSWORD=` file.
|
||||
|
||||
## Land it
|
||||
|
||||
Packages are home-relative trees under `dotfiles/<pkg>/`; per-host overrides go in
|
||||
`zz-$(hostname)` (stowed last). `dconf` is loaded via `dconf load /`, `systemd-user` gets
|
||||
`daemon-reload` + conditional `enable --now`. Sequence: `scripts/deploy.sh --check` (dry run,
|
||||
reports divergents) → adopt → `deploy.sh` → confirm live paths are symlinks into the repo →
|
||||
`bats tests/` (includes the real-bundle `kb-lint`/coverage gate) → branch off `origin/main`,
|
||||
PR to `main`, never merge without Frank's OK.
|
||||
Reference in new issue
Block a user