# Fleet drift report — 2026-08-15 12:47 (+07)

Real `fleet/check.sh` run (`--check --diff`) against laptop + debian1/2/3, all
reachable per `~/.claude/buildbox-hosts.json`. Raw ansible output per role:
`check-20260815-124720-<role>.txt` in this directory. Nothing on any host was
changed by this run — check mode only.

## path_bins

| host    | result |
|---------|--------|
| laptop  | 0 drift — all 6 declared symlinks already correct |
| debian1 | not asserted (see gap below); observed: `buildbox-scratch-bind` and `cdx` absent, `pi` → mise shim (not the workstation formula), `~/.claude/{bin,lib,hooks}` are real directories |
| debian2 | same pattern as debian1 |
| debian3 | same pattern as debian1 |

Applied: `fleet/apply.sh path_bins --limit laptop` — real apply, 0 changes
(already converged). Post-apply re-check: `postapply-20260815-124720-
path_bins-laptop.txt`, 0 changed — receipt confirms empty diff.
Buildboxes: **not applied**. The workstation symlink formula does not match
how buildboxes actually get these bins (mise shims / bootstrap-installed real
files, not deploy-clone symlinks) — see `fleet/README.md` gap list.

## settings_template

| host    | result |
|---------|--------|
| laptop  | 1 changed — large diff: model (`fable` live vs `opus` in repo template), several hook entries differ both ways |
| debian1 | 1 changed — same shape of diff |
| debian2 | 1 changed — same shape of diff |
| debian3 | 1 changed — same shape of diff |

**Not applied anywhere.** The diff is far bigger than the three named
2026-08-15 fixes (retention, security-guidance, its env flag — those three
are now correctly reflected in the repo template after cherry-picking
`082b4a478`, and no longer show as reverting anything). What remains is
substantial pre-existing live customization not yet captured in the repo
template. Applying a full-file copy would silently overwrite it. This is a
named, deliberate STOP under the fold-forward rule — reconciling it is its
own task, not a same-day blind apply.

## systemd_units

| host    | result |
|---------|--------|
| laptop  | 1 changed (agent.slice + 7 other slice files) |
| debian1/2/3 | not run (role scoped to `workstations` group only — buildboxes have no `agent.slice` deployed today) |

Source fix landed this pass (fold-forward, not a host apply): repo
`modules/monitor/systemd/user/agent.slice` had `CPUQuota=150%` +
`CPUWeight=1` — the exact hard-quota shape that starved every agent shell on
2026-08-15 — while the live laptop already ran a hand-applied override
(`agent.slice.d/50-no-starvation.conf`: `CPUWeight=50`, no quota). Folded the
correct values into the base file. **Not applied to the live laptop this
pass** — a `daemon-reload` of the very slice this agent session runs under,
mid-session, was judged unnecessary risk for a same-day change; the live
drop-in already carries the same effective values, so there is no live
regression from leaving this unapplied today. `fleet/roles/systemd_units/
files/policy_lint.py` now enforces the doctrine (no `CPUQuota=`, no
`MemoryHigh=`/`MemoryMax=` on agent slices, `TasksMax=` required) against the
source files — passes today, blocks a regression tomorrow.

## What this run did NOT verify

- Whether the buildboxes' `pi`/`cdx`/bin-symlink layout (mise shims,
  bootstrap-installed real files) is itself drift-free against
  `devtools.json` — this pass only observed and reported it, did not check
  version pins.
- Any config home other than the one `~/.claude/settings.json` per host —
  the plan's "13 config homes" figure is not fully enumerated by this
  inventory yet.
- `ssh`/`sshd` config anywhere — explicitly out of scope per the plan.
- Credentials/tokens — explicitly out of scope (`seat-creds.mjs` owns that
  plane).
