The agent-team venv was missing langchain-anthropic/-openai/-google-genai/ -community, so models.py failed to import and the in-process GPT-4.1 review / Gemini scan / DeepSeek build silently fail-closed to REQUEST_CHANGES (the non-Claude models never ran on the box). Step 3 now installs the full pinned requirements.txt into the venv instead of just fastapi/uvicorn. Installed + verified live on the box: all three model factories construct.
109 lines
6.1 KiB
Bash
Executable file
109 lines
6.1 KiB
Bash
Executable file
#!/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 venv deps from the pinned requirements.txt"
|
||
# Install the FULL pinned set into the agent-team venv. This includes the
|
||
# non-Claude model stack (langchain-anthropic/-openai/-google-genai/-community)
|
||
# that the in-process invokers (WS1: GPT-4.1 review, Gemini scan, DeepSeek build)
|
||
# import via models.py — WITHOUT these, models.py fails to import and the review
|
||
# loop silently fail-closes to REQUEST_CHANGES (the non-Claude models never run).
|
||
# Also brings fastapi/uvicorn (WS1 HTTP API). Leaves the venv-only deps that are
|
||
# NOT in requirements.txt (claude-agent-sdk, slack_sdk, slack_bolt) untouched.
|
||
$SSH 'cd ~/orchestrator/agent-team && . .venv/bin/activate && pip install --upgrade -r ~/orchestrator/requirements.txt'
|
||
|
||
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" <<REMOTE
|
||
set -euo pipefail
|
||
touch ~/secrev.env && chmod 600 ~/secrev.env
|
||
grep -q '^SEA_HAVEN_HANDBOOK_DIR=' ~/secrev.env || \
|
||
echo 'SEA_HAVEN_HANDBOOK_DIR=${HANDBOOK_REMOTE}' >> ~/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=<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."
|