138 lines
6.2 KiB
Markdown
138 lines
6.2 KiB
Markdown
# 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": "<read-only deploy 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 <path>` 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`.
|