Collector milestone 6: packaging — install.sh, systemd unit, docs

systemd/agent-watcher.service: --user unit with on-failure restart,
ProtectSystem=strict, ProtectHome=read-write, NoNewPrivileges=yes,
PrivateTmp=yes. JSON logs to journald. Survives reboot via
'loginctl enable-linger'.

examples/collector.yaml: working starter config for both sources with
inline comments, per-route examples, and the spec §3.1.2 schema for
drop files.

install.sh: idempotent installer following the agent-ping pattern.
Builds the binary, installs it + the unit, drops the example config if
absent, reloads systemd, enables, and (unless --no-start) starts the
service. Adds drop-folder lifecycle artifacts (*.tmp, .dead-letter/)
to workspace .stignore so they don't replicate during processing.
Skips Syncthing-related steps gracefully when ~/Nyx/workspace is not
present.

INSTALL.md: prerequisites, install, configure, verify (drop-file +
webhook end-to-end probes), survive-logout, uninstall, troubleshooting
table.

README.md: rewritten to reflect actual status — v0 working with 43
tests, packaging ready, Layer 2 in progress on Bob's side.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
bob-boat 2026-05-06 16:26:16 -04:00
parent e7d4ea036a
commit 4ff8c3f78d
5 changed files with 324 additions and 6 deletions

95
INSTALL.md Normal file
View file

@ -0,0 +1,95 @@
# INSTALL — agent-watcher Collector (Layer 1)
The MCP Watcher (Layer 2) has its own install path; this file covers Layer 1 only.
## Prerequisites
- Linux with systemd
- Go 1.22+ (`sudo apt install golang-go` on Ubuntu/Mint)
- An existing agent-ping install on this host (the Collector writes to its inbox dir)
## Install
Per CLAUDE.md rule #2, **Angus runs the install commands** — agents do not modify their own configuration.
```sh
git clone https://git.botbought.ai/foreman/agent-watcher ~/agent-watcher
cd ~/agent-watcher
./install.sh
```
The script builds, installs to `~/.local/bin/agent-watcher`, drops the systemd unit into `~/.config/systemd/user/`, copies the example config to `~/.config/agent-watcher/collector.yaml` (if absent), reloads systemd, and starts the service.
To install without auto-starting (so you can edit the config first):
```sh
./install.sh --no-start
```
## Configure
Edit `~/.config/agent-watcher/collector.yaml`. The example has both sources configured for `agent: foreman` with placeholder routes — adapt to this host. At least one of `webhook:` or `drop_folder:` must be configured.
After editing:
```sh
systemctl --user restart agent-watcher
```
## Verify
```sh
# logs
journalctl --user -u agent-watcher -f
# health
curl http://127.0.0.1:18790/health
# end-to-end via drop folder
echo '{"recipient":"bob","type":"INFO","payload":"hello from drop"}' \
> ~/Nyx/workspace/incoming/test.json
# end-to-end via webhook
curl -X POST http://127.0.0.1:18790/forgejo/push \
-H 'Content-Type: application/json' \
-d '{"repo":"agent-ping","actor":"angus"}'
# the lines should appear in the recipient's inbox
tail -2 ~/Nyx/workspace/pings/bob.inbox
```
## Survive logout
`systemctl --user` units stop when the user logs out. To keep the Collector running across logouts:
```sh
sudo loginctl enable-linger $USER
```
## Uninstall
```sh
systemctl --user disable --now agent-watcher
rm ~/.local/bin/agent-watcher
rm ~/.config/systemd/user/agent-watcher.service
systemctl --user daemon-reload
# config and example left behind; remove if desired:
# rm -rf ~/.config/agent-watcher
```
## Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| `journalctl` shows `config: ... is required` | YAML field missing | Match the example, save, restart. |
| `systemctl --user status` shows `address already in use` | port 18790 taken by something else | Edit `webhook.listen` to a free port. |
| Drop file disappears but no inbox line | check `.dead-letter/` for the file + `.reason` sidecar | Schema validation failed — fix the producer. |
| Webhook returns 404 | path doesn't match a configured route | Routes must match exactly; check trailing slashes. |
| Service won't start across reboot | `linger` not enabled | `sudo loginctl enable-linger $USER` |
| Drop file syncs back from another host before processing | drop folder is in Syncthing scope | This is intended (lets producers on other hosts deliver). Lifecycle artifacts (`.tmp`, `.dead-letter/`) are excluded by `install.sh`. |
## What this does NOT install
- The agent-ping system. Install that first (`~/agent-ping/install.sh <name>`).
- Layer 2 (MCP Watcher). Different binary, different runtime, different unit — separate install when it lands.
- Caddy / reverse-proxy webhook auth. v1 is loopback-only; v2 will document the upgrade path.