Design #7282 — Pilot amux.io on lap2, alongside (not replacing) the meta-dispatcher
Issue: #7282 · Type: Plan / Design (evaluation of an opt-in pilot) · Status: plan approved via /review-plan (cycle 1)
Branch: plan/7282-amux-pilot-lap2
This document is the durable, reviewed record of the approved design. Merging it ships no amux binary and no skill — every install / security / secret step is gated behind a
sys-securityhard review and explicit human go/no-go, and is owned by roles other thandev-coder. The gated phases proceed as separately-owned follow-up work (see §Implementation phases).
0. Premise and the host discrepancy resolved at design time
amux.io is a MIT + Commons Clause-licensed (not plain MIT — the upstream
LICENSE file carries the Commons Clause v1.0 condition that forbids selling the software; free
for our internal, non-commercial self-hosted pilot), self-hosted, single Rust-binary control plane
that coordinates multiple AI coding agents (Claude Code, Codex CLI, Gemini CLI, OpenCode, Ollama).
The pilot runs parallel to, never replacing, the existing meta-dispatcher.
Host + tunnel discrepancy (raised by the plan, verified against the repo): the issue body said “dev-laptop (lap2) … autossh reverse tunnel przez vps-i1”, which conflates two distinct hosts.
| Repo source | Host | Inbound connectivity | Uptime |
|---|---|---|---|
CLAUDE.md §Server IPs | dev-laptop (Acer F5-573G), LAN 192.168.0.161 | autossh reverse tunnel through vps-i1, no public IP | ”variable” |
docs/environments/lap2.md (ADR-006) | lap2 (Dell, WSL2 Ubuntu-26.04 x86_64) | CF Tunnel lap2-ssh.zintegrowana.online (owner-only + service-token Access policies), no public IP | worker host currently DISABLED (dev_r_server_capacity id 17, enabled=false) |
The substance is identical either way (non-production, intermittent, tunnel-only, no public IP). This design targets the machine the issue calls lap2, whose real inbound is the CF Tunnel, and whose WSL2 guest is Ubuntu-26.04 x86_64 (the arch the pinned binary must target). The exact host + tunnel mechanism is pinned by sys-admin at the start of Phase 2, verified live at install time.
1. New skill — /amux-pilot, and why it structurally cannot touch production dispatch
Name: /amux-pilot (command file .claude/commands/amux-pilot.md). Deliberately unrelated to
/new-issue, /issues-review, /process-issues so no muscle-memory or fuzzy match reaches it.
The isolation contract is enforced by what the skill omits, not by a runtime guard alone:
| Production dispatch does… | /amux-pilot must NOT do… |
|---|---|
gh issue edit --milestone "Triage" → fires dispatch-to-queue.yml issues.milestoned → INSERT dev_r_worker_queue | never set ANY milestone on any issue (the milestone event is the sole prod dispatch trigger) |
POST /queue-issue to p24-meta-dispatcher.radieu.workers.dev | never call the meta-dispatcher Worker at all |
INSERT into dev_r_worker_queue / p24_queue | never write either table (no Supabase service-role key on the amux host) |
| GH Actions dispatch to bms-4/vps-i1 runners | never workflow_dispatch / gh workflow run any dispatch workflow |
What it does do: open an SSH session to lap2 over the live tunnel, confirm amux is up, and drive
amux locally on lap2 only. The skill’s frontmatter and body carry an explicit “PILOT — no queue
write, no milestone, no meta-dispatcher, no GH Actions dispatch” contract line. Phase 3 adds a
scripts/tests/ assertion that greps the shipped command file for the forbidden tokens
(dev_r_worker_queue, p24_queue, /queue-issue, --milestone, gh workflow run) and fails CI if
any appear — making the §4 isolation mechanically checkable, not just prose.
No GH Actions binding, no dispatch-to-queue.yml change, no CF Worker change, no change to any
existing skill — all explicitly out of scope per the issue.
2. Installation on lap2 (single binary, no Docker, intermittent connectivity)
- Artifact: a version-pinned amux release binary for lap2’s WSL2 guest arch (Ubuntu-26.04 x86_64), pinned by tag + SHA-256 and verified against the upstream checksum before it runs.
- Delivery over an intermittent tunnel — pull-when-up:
- sys-admin SCPs the pinned binary to lap2 over the live tunnel during a window when lap2 is up,
verifies the SHA-256, installs to a user-local, unprivileged path (
~/.local/bin/amux) — no root, no systemd unit (non-production, opt-in; must not survive as an always-on service). - If the tunnel is down at install time, the install/skill step no-ops gracefully with a clear “lap2 unreachable — retry when up” message; nothing is queued or retried against production.
- sys-admin SCPs the pinned binary to lap2 over the live tunnel during a window when lap2 is up,
verifies the SHA-256, installs to a user-local, unprivileged path (
- Run posture: amux runs as a foreground/user process under an unprivileged, dedicated local account on lap2, started manually by the operator, not on boot. It coordinates the CLI agents already present on lap2; it installs no new privileged component.
- Uptime handling: every
/amux-pilotrun begins with a tunnel-liveness probe and exits cleanly if lap2 is down — matching lap2’s documented “variable uptime” and current worker-hostDISABLEDstate (the pilot runs in the WSL2 / human-dev context regardless of the worker-host flag).
3. Security model (mandatory sys-security review BEFORE install — CLAUDE.md §Role Enforcement)
- Gating review: amux is a new process that can execute commands via coordinated agents →
sys-securitymust review it before any install, even on a non-production host. Hard Phase-1 gate; a negative finding ends the pilot (§5). - No SOPS decrypt for amux — same rule as research subagents (#5544): amux and every agent it coordinates get key NAMES only, never plaintext. The amux user account has no age key mounted or reachable.
- Least privilege: unprivileged dedicated user; no root; no Docker; no Supabase service-role key; no queue API key; no meta-dispatcher credentials. Constrain the command surface the coordinated agents may execute to the pilot working directory.
- If amux needs any secret at all (e.g. a dashboard/tunnel token): design a NEW narrow SOPS file
secrets/amux-pilot.env.sops, created bysecret-manager(NOT by a dev-coder worker), per the CLAUDE.md §SOPS file map narrow-file convention used byovh-sys.env.sops/cloudflare-workers-bms4.env.sops/wa-web-collector.env.sops: 2 recipients only (developer key + the lap2 age key), excluded fromsecrets-sync.yml(no server push, no sync job). Nothing is appended tomonitoring.env.sopsor any existing file. If the pilot can run with no secret, prefer that and create no SOPS file.
4. Isolation from production (the non-negotiable guarantee)
The pilot’s only permitted contact point with existing infra is optionally reading/creating GH Issues — and only if a feasible adapter exists (§5). Everything else is walled off:
- Cannot write
dev_r_worker_queue/p24_queue— no credential to do so, and Phase 3’s CI grep asserts the skill file contains no such write. - Cannot trigger production GH Actions dispatch — no
--milestoneset, nogh workflow run, no meta-dispatcher POST (asserted by the same grep). - Runs on lap2 (non-production) only, never bms-4/vps-i1.
- Zero edits to
secrets/monitoring.env.sops,infra-src/meta-dispatcher/,.github/workflows/dispatch-to-queue.yml, or any bms-4/vps-i1 production dispatcher code — the issue’s explicit “do not touch” set.
5. Pilot success / failure criteria (go / no-go)
Continue investing if:
- The live-steering dashboard demonstrably adds value over the current fire-and-forget queue (real-time visibility/intervention into a running agent).
- Model-switching between CLI agents (Claude Code ↔ Codex/Gemini/OpenCode/Ollama) works and is useful for a real p24-infra-style task.
- A feasible, safe adapter to the GH Issues workflow exists (read/create issues without touching the prod queue) — the bridge that would justify graduating the pilot.
End the pilot if any of:
- lap2 host instability makes runs unreliable (its documented “variable uptime” dominates).
sys-securityreturns negative findings (command-exec surface, secret exposure, sandbox escape).- No feasible GH Issues adapter — i.e. amux can’t integrate without reaching into the production queue, which §4 forbids.
Recorded outcome: a short findings note appended here (or a dedicated findings section) plus a
dev_r_priorities / session-log entry via scripts/priorities.py — no hand-edit of docs/priorities.md.
6. Cost & maintenance
- Self-hosted amux is MIT + Commons Clause — free for our non-commercial internal self-hosting (the Commons Clause only forbids selling the software, which the pilot never does), so it needs no paid amux Cloud ($20/mo) to run on lap2. The single binary + local dashboard cover the startup scope.
- A stable public dashboard tunnel is an optional Step 2, not a startup requirement. If wanted later, reuse lap2’s existing CF Tunnel + Cloudflare Access (owner-only policy) rather than paying for amux Cloud — a follow-up, gated separately.
Implementation phases (role-delegated — none shipped by merging this design doc)
| Phase | Owner role | Gate |
|---|---|---|
| 0. Verify amux’s real capabilities + security surface from upstream; pin host+tunnel (§0) | dev-coder (research) + sys-admin | feeds Phase 1 |
| 1. Security review of amux (exec surface, secret posture, sandbox) | sys-security | hard gate — negative finding = stop |
2a. Create narrow secrets/amux-pilot.env.sops iff a secret is needed | secret-manager | only after Phase 1 pass |
| 2b. Install pinned binary on lap2, unprivileged, no systemd, over the live tunnel | sys-admin | human go/no-go before install |
3. Author .claude/commands/amux-pilot.md + the CI isolation-grep test (scripts/tests/test_amux_pilot_isolation.py) (+ optional GH Issues adapter) | dev-coder | after Phase 1/2 land |
Next required step: file a sys-security review issue for Phase 1 (the hard gate). Should that
review conclude the pilot install itself is too risky to perform autonomously, that is the point at
which the follow-up work is re-labelled human-action.
Regression risks
- None to production by construction — the pilot writes no prod table, sets no milestone, calls no
dispatcher, edits no prod workflow/secret. The risk surface is confined to lap2 and is the subject of
the Phase-1
sys-securityreview. - Residual risk if the isolation contract is later weakened: the Phase-3 CI grep is the guardrail that fails the build if a forbidden token reappears in the skill file.
DB schema changes: no.
Design authored by a dev-coder worker for #7282 and approved via the /review-plan plan-iteration
workflow (cycle 1). Path convention corrected to docs/designs/ per review.