From 0689d1696c92031382d91b54700890db9ee57125 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Tue, 23 Jun 2026 12:43:39 -0400 Subject: [PATCH] feat(ops): R720 WS-rollout deploy/update script (G) Idempotent attended update of the live coordinator to WS0-WS5: rsync repo + handbook, install fastapi/uvicorn, append AGENT_TEAM_API_TOKEN/SEA_HAVEN_HANDBOOK_DIR to secrev.env if absent, restart the daemon, smoke tests. HTTP API is an opt-in separate step; P3 dispatch stays inert. Snapshot-first + confirm before restart. --- agent-team/scripts/deploy-r720-ws-rollout.sh | 104 +++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100755 agent-team/scripts/deploy-r720-ws-rollout.sh diff --git a/agent-team/scripts/deploy-r720-ws-rollout.sh b/agent-team/scripts/deploy-r720-ws-rollout.sh new file mode 100755 index 0000000..811f972 --- /dev/null +++ b/agent-team/scripts/deploy-r720-ws-rollout.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# deploy-r720-ws-rollout.sh — attended UPDATE of the live R720 agent-team +# coordinator to the WS0–WS5 rollout (PRs #43–#46 + the activation wiring). +# +# This is an UPDATE, not a first-time provision: P1 is already deployed per +# agent-team/DEPLOY-R720.md (repo rsynced to ~/orchestrator, venv at +# agent-team/.venv, systemd unit agent-team-coordinator.service running). +# Run this from the MAC, after the WS branches have merged to main. It rsyncs +# the new code, installs the new deps, appends the new secrets if absent, syncs +# the engineering handbook, restarts the coordinator, and smoke-tests. +# +# It is idempotent and FAILS LOUDLY. It changes a live box, so: +# 1) SNAPSHOT FIRST (Hyper-V checkpoint of sh-secrev on the R720 host). +# 2) It prompts before the restart. +# +# What goes LIVE after this (the safe, ungated seams): +# * WS1 in-process multi-model invokers (bind_multi_invoker, already wired) +# * WS5 handbook context_provider injected into the planner prompt +# * WS2 Slack /new-task -> start a task (AUTHZ-01 owner allowlist gated) +# The HTTP API (WS1) + the /delegate hook are OPTIONAL and started separately +# (see step 6). The P3 dispatch/build-verify path stays INERT (gated). +set -euo pipefail + +# ── Config (override via env) ──────────────────────────────────────────────── +BOX="${BOX:-adam@10.10.60.120}" +SSH_KEY="${SSH_KEY:-$HOME/.ssh/r720_seahaven}" +REPO_LOCAL="${REPO_LOCAL:-$HOME/Documents/repositories/orchestrator}" +HANDBOOK_LOCAL="${HANDBOOK_LOCAL:-$HOME/Documents/repositories/engineering-handbook}" +# Where the handbook lands on the box; must match SEA_HAVEN_HANDBOOK_DIR below. +HANDBOOK_REMOTE="${HANDBOOK_REMOTE:-/home/adam/.sea-haven/engineering-handbook}" +SSH="ssh -i ${SSH_KEY} ${BOX}" + +say() { printf '\n\033[1;36m== %s\033[0m\n' "$*"; } +confirm() { read -r -p "$1 [y/N] " a; [ "$a" = "y" ] || [ "$a" = "Y" ]; } + +say "Preflight" +[ -f "${SSH_KEY}" ] || { echo "missing SSH key ${SSH_KEY}"; exit 1; } +$SSH true || { echo "cannot reach ${BOX}"; exit 1; } +echo "SNAPSHOT REMINDER: take a Hyper-V checkpoint of sh-secrev on the R720 host now." +confirm "Snapshot taken and ready to update the LIVE coordinator?" || { echo "aborted"; exit 1; } + +say "1. rsync repo (Mac -> box; same excludes as the P1 runbook)" +rsync -av --exclude .env --exclude .venv --exclude .git --exclude '__pycache__' \ + "${REPO_LOCAL}/" "${BOX}:orchestrator/" + +say "2. rsync engineering handbook -> ${HANDBOOK_REMOTE} (WS5 context_provider source)" +if [ -d "${HANDBOOK_LOCAL}" ]; then + $SSH "mkdir -p ${HANDBOOK_REMOTE}" + rsync -av --delete --exclude .git "${HANDBOOK_LOCAL}/" "${BOX}:${HANDBOOK_REMOTE}/" +else + echo "WARN: ${HANDBOOK_LOCAL} not found; context_provider will return '' (fail-safe). Skipping." +fi + +say "3. Install new venv deps (fastapi/uvicorn for the WS1 HTTP API)" +# requirements.txt now pins fastapi==0.136.1 / uvicorn==0.46.0. The coordinator +# itself does not need them, but the optional HTTP API (step 6) does. +$SSH 'cd ~/orchestrator/agent-team && . .venv/bin/activate && pip install --upgrade "fastapi==0.136.1" "uvicorn==0.46.0"' + +say "4. Append new secrets to ~/secrev.env if absent (mode 600, never committed)" +# AGENT_TEAM_API_TOKEN: required only if you run the HTTP API / /delegate hook. +# SEA_HAVEN_HANDBOOK_DIR: where load_handbook_conventions() reads from. +$SSH "bash -s" <> ~/secrev.env +if grep -q '^AGENT_TEAM_API_TOKEN=' ~/secrev.env; then + echo 'AGENT_TEAM_API_TOKEN already set; leaving as-is.' +else + echo 'AGENT_TEAM_API_TOKEN NOT set. Add it now (generated on the Mac):' + echo ' echo "AGENT_TEAM_API_TOKEN=" >> ~/secrev.env && chmod 600 ~/secrev.env' + echo '(only needed for the HTTP API / auto-delegate hook; the coordinator runs without it.)' +fi +REMOTE + +say "5. Restart the coordinator daemon" +confirm "Restart agent-team-coordinator.service now?" || { echo "skipped restart"; exit 0; } +$SSH 'sudo systemctl restart agent-team-coordinator.service && sleep 2 && systemctl is-active agent-team-coordinator.service' +$SSH 'journalctl -u agent-team-coordinator.service -n 30 --no-pager' + +say "6. (OPTIONAL) HTTP API + /delegate hook — start only if you want them" +cat <<'NOTE' +The coordinator now serves WS5 context + WS2 /new-task. The WS1 HTTP API is a +SEPARATE process (api.serve(), 127.0.0.1:8765, bearer auth). To run it: + - ensure AGENT_TEAM_API_TOKEN is set in ~/secrev.env + - run: cd ~/orchestrator/agent-team && . .venv/bin/activate && \ + python3 -c "from agent_team.api import serve; serve()" + - (for persistence, add a second systemd unit; not auto-installed here.) +Then set AGENT_TEAM_API_TOKEN + AGENT_TEAM_API_URL in the Mac Claude Code env +to enable the /delegate hook (sea-haven-claude-plugin). +NOTE + +say "7. SMOKE TESTS (manual)" +cat <<'SMOKE' + a) Coordinator up: systemctl is-active agent-team-coordinator.service -> active + b) Handbook visible: cd ~/orchestrator/agent-team && . .venv/bin/activate && \ + python3 -c "from agent_team.nodes.handbook import load_handbook_conventions as h; print(bool(h()))" -> True + c) Slack /new-task: post "/new-task add a smoke-test file" in #agent-team as an + allowlisted owner -> the bot replies with a clarifying question. + d) (if API running) auth: curl -s -o /dev/null -w '%{http_code}' \ + -H "Authorization: Bearer $AGENT_TEAM_API_TOKEN" http://127.0.0.1:8765/tasks -> 405 (GET not allowed = API up + authed) +ROLLBACK: restore the pre-update Hyper-V checkpoint (one-command revert). +SMOKE +say "Done."