- scripts/e2e-acceptance.sh: offline spec walk (fixture upstream -> vendor add/determinism/collisions/renames -> validate/list/inspect -> update cycle -> employee sync -> idempotence -> protected sync -> deletions -> status drift -> unreachable repo), 61 assertions on tree, lockfile, manifest and exit codes - README: installation, curator guide (selection rules, renames), client guide (three-state semantics, notifications), security model, troubleshooting, scope - docs/fleet-handoff.md: rollout (pinned release, admin-protected config, user-context scheduled task), token rotation, ADR draft superseding the exact-mirror doctrine, fleet verification checklist
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`.
|