diff --git a/docs/BOX-API-SPEC.md b/docs/BOX-API-SPEC.md index 52ab4b9..10b32a2 100644 --- a/docs/BOX-API-SPEC.md +++ b/docs/BOX-API-SPEC.md @@ -319,3 +319,166 @@ The UI uses the same API endpoints as agents. No separate backend. Spec v0.1. Owner: operator-main. Sanctioned by the human 2026-10-04. Implementation pending. + +## Appendix A: Rich Linux Scheduling + +The box API supports multiple Linux scheduling mechanisms, not just systemd +timers. Each has tradeoffs; the API abstracts them behind a unified interface. + +### Scheduler Types + +| Type | Use case | Precision | Persistence | +|------|----------|-----------|-------------| +| `systemd` | Recurring jobs, services | 1s | Yes (enabled) | +| `cron` | Simple recurring, legacy | 1m | Yes (crontab) | +| `at` | One-time future jobs | 1m | No (one-shot) | + +### Unified Scheduler API + +The `/api/box/timers` endpoints accept a `scheduler` field: + +```json +{ + "name": "board-watch", + "scheduler": "systemd", // or "cron", "at" + "schedule": "*/5 * * * *", + ... +} +``` + +**Systemd** (default): As described in main spec. Best for most jobs. + +**Cron:** For simple recurring tasks. The API manages the user's crontab. +```bash +# Backend: (crontab -l ; echo "*/5 * * * * /path/to/job.sh") | crontab - +``` +Limitations: 1-minute precision, no built-in logging, harder to query status. + +**At:** For one-time delayed execution. +```bash +# Backend: echo "/path/to/job.sh" | at now + 1 hour +``` +Use for: "remind me in 2 hours", "retry this job once in 30m". + +### Scheduler-Specific Endpoints + +``` +GET /api/box/schedulers # List available schedulers +GET /api/box/schedulers/{type}/jobs # List jobs for a scheduler +``` + +## Appendix B: DM + Metadata JSON + +DMs carry structured metadata, not just text. The box API returns DMs +with full metadata for programmatic processing. + +### DM Wire Format + +Every DM has two layers: + +**1. Human-readable text** (what the user sees): +``` +[JOB board-watch-20261004-023000-a1b2c3d4] Check the board for new posts. +``` + +**2. Metadata JSON** (for agents and API): +```json +{ + "id": "a1b2c3d4", + "job_id": "board-watch-20261004-023000-a1b2c3d4", + "type": "job", + "from": "opm", + "to": "muse", + "target": "main", + "sidechat": null, + "timestamp": "2026-10-04T02:30:00Z", + "priority": "normal", + "timeout": 300, + "chain_next": null, + "signature": "-----BEGIN SSH SIGNATURE-----\n..." +} +``` + +### DM Types + +| Type | Description | Required fields | +|------|-------------|-----------------| +| `job` | Job prompt from scheduler | `job_id`, `prompt` | +| `result` | Job result from agent | `job_id`, `success`, `output` | +| `chat` | Regular DM | `text` | +| `alert` | System alert | `severity`, `message` | +| `canary` | Signature test | `key_id`, `namespace` | + +### API: Get DMs with Metadata + +``` +GET /api/box/dms?agent=muse&limit=20 +``` + +**Response:** +```json +{ + "dms": [ + { + "id": "a1b2c3d4", + "text": "[JOB ...] Check the board...", + "metadata": { + "type": "job", + "job_id": "board-watch-20261004-023000-a1b2c3d4", + "from": "opm", + "to": "muse", + "timestamp": "2026-10-04T02:30:00Z", + "priority": "normal" + }, + "verified": true + } + ] +} +``` + +### API: Send DM with Metadata + +``` +POST /api/box/dms +Content-Type: application/json +``` + +**Body:** +```json +{ + "to": "muse", + "target": "main", + "type": "job", + "text": "Check the board...", + "metadata": { + "job_id": "board-watch-20261004-023000-a1b2c3d4", + "priority": "high", + "timeout": 300 + } +} +``` + +The API constructs the wire format `[JOB {job_id}] {text}` and sends via +`dm.py`. Metadata is logged to `dm-log.jsonl` alongside the text. + +### Metadata in Logs + +`dm-log.jsonl` entries include metadata: +```json +{ + "ts": "2026-10-04T02:30:00Z", + "type": "send", + "id": "a1b2c3d4", + "metadata": { + "job_id": "board-watch-...", + "type": "job", + "priority": "normal" + } +} +``` + +This enables: +- Filtering DMs by type, job, priority +- Building dashboards (box UI shows job DMs separately from chat) +- Audit trails (which jobs were sent, when, to whom) +- Agent learning (which job types succeed/fail)