Initial commit: autonomous maintenance agent for semprini stack
systemd-deployed daemon that drives the semprini-core stack-support agent headless via Claude Code, monitors health via Uptime Kuma, applies safe upgrades, and escalates to the operator over Matrix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# semprini-maintainer — Claude Instructions
|
||||
|
||||
## What this is
|
||||
|
||||
A standalone, always-on **autonomous maintenance agent** for the semprini.me
|
||||
container stack, deployed as a systemd service (`semprini-maintainer`). It keeps
|
||||
the stack healthy and current and talks to the operator over Matrix
|
||||
(chat.semprini.me).
|
||||
|
||||
It is the *unattended driver* for the canonical **stack-support agent**, which
|
||||
lives in the separate **semprini-core** repo. This project does not reimplement
|
||||
that logic — it gathers state and invokes the stack-support agent headless via
|
||||
Claude Code, then relays/acts on the agent's JSON result.
|
||||
|
||||
## Relationship to other projects
|
||||
|
||||
- **semprini-core** (`../semprini-core`) — the Enterprise Landing Zone this agent
|
||||
maintains. At runtime the daemon reads, from the path in `config.json`
|
||||
`repo_dir`:
|
||||
- `agents/stack-support.agent.md` (injected as system prompt)
|
||||
- `docs/stack-support-runbook.md`
|
||||
- `core_stack/compose*.yml`
|
||||
Keep the stack-support agent definition canonical **in semprini-core** — do not
|
||||
fork a copy here.
|
||||
- **Other projects** (e.g. `../semprini-blog`) that register Uptime Kuma monitors
|
||||
are also maintained; their repos are exposed to the agent via `extra_dirs`.
|
||||
|
||||
## How it works (one screen)
|
||||
|
||||
- **Scope** = whatever **Uptime Kuma** tracks at check time, re-read every cycle
|
||||
(never hard-coded). Kuma's heartbeat is the health signal — the daemon does not
|
||||
re-probe. Kuma's root-owned `kuma.db` is read via a throwaway `keinos/sqlite3`
|
||||
container mounting the `uptime-kuma-data` volume read-only.
|
||||
- **Health loop** (5 min): down services confirmed over `down_confirmations`
|
||||
cycles → invoke stack-support agent to remediate → report to Matrix.
|
||||
- **Upgrade loop** (7 days): resolve containers behind tracked services → agent
|
||||
researches + applies safe upgrades (test, pin, rollback); escalates
|
||||
major/breaking ones to Matrix.
|
||||
- **Matrix**: bot `@maintainer:semprini.me` DMs `@paul:semprini.me`. Escalations
|
||||
are numbered questions; the reply is fed back to the agent to carry out.
|
||||
- **Autonomy** (`config.json` → `autonomy`): `full` (default) | `fix-only` |
|
||||
`notify`.
|
||||
|
||||
## Conventions / guardrails
|
||||
|
||||
- Runs as host user **`paul`** (in `docker` group), **not root** — Claude Code
|
||||
refuses `--permission-mode bypassPermissions` under root.
|
||||
- `maintainer.py` is **stdlib-only** — keep it dependency-free so it deploys
|
||||
without a venv.
|
||||
- Secrets live in `config.json` and `.bot-secrets` — **never commit** (gitignored).
|
||||
- Prefer editing existing files over adding new ones.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `maintainer.py` | The daemon (stdlib only). |
|
||||
| `config.example.json` | Template — copy to `config.json`. |
|
||||
| `register-matrix-bot.sh` | Creates `@maintainer` account + DM room; writes token to config. |
|
||||
| `install.sh` | Syntax-check, install unit, enable + start. |
|
||||
| `semprini-maintainer.service` | systemd unit (runs as `paul`). |
|
||||
| `docs/architecture.md` | Architecture decision record. |
|
||||
|
||||
## Test without the service
|
||||
|
||||
```bash
|
||||
python3 maintainer.py --config config.json --once health
|
||||
python3 maintainer.py --config config.json --once upgrade
|
||||
python3 maintainer.py --config config.json --once replies
|
||||
```
|
||||
Reference in New Issue
Block a user