Files
box/docs/BOX-LOOP-HTTPS.md
operator 0065d11e97 feat(supervision): add choice watcher daemon, HTTPS spec docs, and test suites
- bin/muse_choice_watcher.py + systemd/muse-choices-reconcile.*: automatic choice answering and timer reconciliation
- bin/digest.py: fleet log and health summarization
- docs/BOX-*-HTTPS.md: comprehensive HTTPS execution contracts and API documentation
- docs/MUSE-CHOICES-POLICY.md & docs/SUPERVISION-SPEC.md: autonomous execution specs
- tests/test_*.py: unit test suites for HTTPS API, choice watcher, fleet heal, and swarm pruning
2026-10-07 00:25:46 +00:00

86 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Box Loop + Strategy Writes over HTTPS (No SSH)
> **Box is the main surface.** All operator work goes through Box (box.muse-dev.online). The web UI, `box` CLI, and agents share the same API endpoints. No UI-only powers.
**Date:** 2026-10-06
**Status:** implemented on bl (`exec-constrained.py` + `box-relay.sh`;
`box-ctl.py` verbs pre-existed, plus a vars-name validator fix)
**Scope:** safe loop/strategy/variable mutations. Reads (`loop-status`,
`loop-health`, `loop-breaks`, `strat-get`, `vars-get`, ...) already ride
`box.exec` or typed read ops and are unchanged here.
## 1. Why
Agents watching loop health could see breaks but needed SSH to remediate
them, resolve stale followups, tune strategy overrides, or undo variable
changes. All of this now rides the agent HTTPS path
(`https://exec.muse-dev.online/exec`, signature or bearer auth, named-op
allowlist, audit log).
## 2. New ops (all known-identities-only, none in the read-only subset)
| Op | Args | Backend |
|---|---|---|
| `loop.remediate` | `{dry_run?}` (default false) | `box-ctl.py loop-remediate [--dry-run]` |
| `loop.resolve` | `{dm_id, note?}` | `box-ctl.py loop-resolve` |
| `strat.set` | `{type!, subtype?, agent?, track?, priority?, timeout_s?, nudges?, escalate?}` | `box-ctl.py strat-set` (payload as argv JSON) |
| `strat.reset` | `{type!, subtype?, agent?}` | `box-ctl.py strat-reset` |
| `vars.reset` | `{name}` | `box-ctl.py vars-reset` (restore default) |
| `vars.rollback` | `{name, revision?}` (int step or timestamp) | `box-ctl.py vars-rollback` |
New `box-relay.sh` client commands:
```bash
box loop remediate [--dry-run]
box loop resolve <dm_id> [note...]
box strat set <type> [--subtype S] [--agent A] [--track true|false] [--priority p] [--timeout N] [--nudges N] [--escalate E]
box strat reset <type> [subtype] [--agent <agent>]
box vars reset <name>
box vars rollback <name> [revision]
```
Raw op call (signature auth, no token):
```bash
exec-sign.sh loop.remediate '{"dry_run": true}'
exec-sign.sh strat.set '{"type": "job", "priority": "important", "nudges": 3}'
```
## 3. What remediate does (non-dry)
`loop.remediate` delegates to `gravity.remediate_breaks`: resolves
followups already answered in logs, re-arms expired followups with nudges
remaining (runs the followup sweeper once), auto-allows TRUSTED (non-key)
browser approvals, and on hard breaks appends a `hard_break_alert` to
job-log plus one DM to opm. Use `{"dry_run": true}` first to preview the
`remediated` / `escalated` lists with zero side effects.
## 4. Safety notes (same posture as existing ops)
- **Fixed argv, validated values.** Strategy types are a strict enum
(`wake|job|siphon|manual|health|heartbeat`) — the backend silently maps
typos to MANUAL, so the op rejects them instead. Priorities are a
strict enum; timeouts/nudges must be integers (backend clamps);
dm ids must be 6–64 hex; variable names mirror the engine identifier
rule. All checks run before any side effect.
- **Stdin-free.** Unlike `job.put`, `strat.set` passes its JSON payload
as an argv token (`strat-set <type> [JSON]`), so no new stdin plumbing
was needed.
- **Vars-name validator fix.** `quality-validate` for all five vars
verbs used the job-name regex (`^[a-z0-9-]{1,64}$`), rejecting every
real variable name (`max_nudge_count`, ...). They now share
`qv_var_name` (`^[A-Za-z0-9_.-]{1,64}$`), mirroring the
`exec-constrained.py` rule.
- **Audited.** Every execution records identity + op + args hash;
`box-ctl.py` additionally audits each mutation with its target.
## 5. Rollout notes
- Restart `exec-constrained.py` after deploy for the new ops to appear in
`GET /ops`.
- `box-relay.sh` is served from bl (`GET /box`); agents re-fetch to get
the `loop` / `strat` groups and `vars reset|rollback`.
- Non-goals: approvals, deletes, `main-loop` enable/disable — future
expansions, same pattern. (md drive files shipped separately; see
BOX-MD-HTTPS.md.)