# Fleet handoff — agent-lib v2 rollout What az-fleet must roll out, and why. This document is written so the fleet team can implement their role from this file alone. ## What the binary does (and does not do) `agent-lib` is one static Go binary with two roles: - **Curator** (maintainer machine): `vendor add/update/diff/remove/list/inspect` plus `validate` — manages external content inside the company work repository. Publication = `git commit && git push` by the maintainer. - **Client** (employee machine): `sync` + `status` — pulls the work repository and deploys skills/commands/agents into the OpenCode paths. Deploys with three-state protection: user-modified managed items are skipped with a warning (never steamrolled), self-created items are never touched, unmodified items update/remove silently. The binary handles all content transport itself. It never deploys or merges MCP fragments — `mcp/` and `external/*/mcp/` stay under controller-side merge and vault substitution (clone the work repository as before, now including the external areas). ## Rollout components ### 1. Binary via pinned GitHub release - Source of truth: GitHub releases of `m3tam3re/agent-lib`. - Artifacts: `agent-lib_{windows_amd64,linux_amd64,linux_arm64,darwin_amd64,darwin_arm64}` plus `checksums.txt` (tar.gz archives; windows is a zip). - Fleet pins an exact release tag (installer-pin pattern already used for other tools). **No self-update exists in the binary** — binary updates are exclusively fleet rollouts. Content updates are pulled by the binary itself. - Verify the checksum during rollout; install to a fixed path (e.g. `C:\Program Files\agent-lib\agent-lib.exe` / `/usr/local/bin/agent-lib`). ### 2. Admin-protected client config Path: `C:\ProgramData\agent-lib\config.json` (Windows, ACL restricted to Administrators + read for Users) or `/etc/agent-lib/config.json` (Linux, root-owned, mode 0644). ```json { "repo_url": "https://git.example.com/company/agent-content.git", "ref": "main", "token": "", "token_user": "oauth2" } ``` - The token is a **shared read-only** deploy token scoped to the work repository. It is used for HTTP basic auth only and never appears in the lockfile, the manifest, logs, or error output. - Employees must be able to read the config (sync runs in their context) but must not be able to alter it. - Per-run overrides for testing: `--config ` or `AGENT_LIB_CONFIG`. Local state (manifest, cached bare repo, sync log) lives per-user: `%LocalAppData%\agent-lib` on Windows, `~/.local/state/agent-lib` on Linux (override with `AGENT_LIB_STATE_DIR`). ### 3. Scheduled task — logged-in user context (required) - Schedule `agent-lib sync` per user, **running as the logged-in user, not SYSTEM**. Two reasons: 1. Deployment targets (`~/.agents/skills`, `~/.config/opencode/...`) resolve against the user's profile. 2. Windows toast notifications require an interactive user session. A task running as SYSTEM produces no visible toasts. - Suggested cadence: every 1–4 hours plus/except at logon. Sync is idempotent and cheap when unchanged. - Optional companion: a drift check running `agent-lib status --json` headless; its non-zero exit (`problematic_drift: true`) means a user's local modifications are blocking company updates — feed it into monitoring. ## Token rotation procedure 1. Create/rotate the read-only deploy token on the git host. 2. Update `token` in the admin-protected config via the fleet (single run; config is fleet-managed, so this is one playbook task). 3. No client-side action: the next scheduled sync picks up the new token (config is read on every run). The old token can be revoked once the fleet run completed. 4. A failed sync never damages local state — a revoked token mid-rotation only means "no updates until the config arrives". ## ADR draft — superseding the "exact mirror" doctrine > # ADR-000X: agent-lib three-state sync supersedes exact-mirror deletion > > ## Status > Proposed (supersedes ADR-0006 "exact mirror including deletion") > > ## Context > The previous fleet doctrine required employee machines to be an exact > mirror of the company content repository, including deletions. This > steamrolled legitimate local work: employees' own skills and their local > adjustments to company skills were destroyed by routine syncs. > > agent-lib v2 replaces the mirror sync with a **manifest-based three-state > sync**: a local manifest records every item agent-lib deployed (name, type, > origin, revision, content hash), and the planner compares repository, > manifest and on-disk content per item. > > ## Decision > 1. Managed items that the user modified locally are **skipped** — the local > version wins, a warning is logged and (on Windows) toasted. > 2. Items on disk that agent-lib never deployed are **unmanaged** — left > untouched, reported by `status` as unrecognized. > 3. Upstream deletions remove only the **unmodified** managed copies; > modified copies are kept and warned about. > 4. Everything else (new, changed-unmodified) updates silently; sync is > idempotent and safe to schedule. > > ## Consequences > - Employee machines are no longer exact mirrors by design; drift is > visible (`status`, exit code) instead of silently destroyed. > - "What's in the repo is what I have" holds for everything the user never > touched. > - Remediation for blocked updates is a human decision (restore the company > version by deleting the local copy and re-syncing), not a forced > overwrite. > - The controller-side MCP merge is unaffected: it clones the work > repository (now including `external/*/mcp/`) and continues to own > activation, merging and vault substitution. ## Verification checklist for the fleet team - [ ] Pinned binary installed, `agent-lib version` prints the release version. - [ ] Config at the admin-protected path, readable by users, writable only by admins; token present. - [ ] Scheduled task runs as the logged-in user; toast appears when a modified item is skipped (manual visual check on a Windows client). - [ ] `agent-lib status` exits 0 on a clean machine, non-zero after editing a deployed file (self-test). - [ ] Drift monitoring consumes `status --json` → `problematic_drift`.