#!/usr/bin/env sh
# 🤖 ops — the one operator command surface for deploying and managing the
# fleet. Every verb encodes knowledge that used to live only in prose spread
# across CLAUDE.md, docs/server-releases.md, docs/multi-edge-dev-cutover.md and
# the operator runbook — prose drifts silently; a script that runs drifts
# loudly. When a verb's advice goes stale, fix it IN THE SCRIPT, not in a doc.
#
# This file is deliberately nothing but a signpost: each verb stays a readable
# standalone script beside it (the outlive-AI rule — a human can open any one
# of them and understand it in a sitting), and this dispatcher only routes.
# Add a verb = add a script + one case arm + one usage line.
set -eu

here="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"

usage() {
  cat <<'EOF'
ops — the operator command surface

  ./deploy/ops doctor  [section]        can I deploy right now? (read-only preflight)
  ./deploy/ops validate [section]       run every local check (go|web|shell|infra)
  ./deploy/ops provision <units|apex|status|operator> [args]
                                        refresh box systemd units / set the short-link apex /
                                        create an operator account on a box
  ./deploy/ops publish "notes"          build main -> release -> point edge at it
  ./deploy/ops promote <ver> <chan>     move beta/stable to a published version
  ./deploy/ops ship    [box...]         make every box's instances catch up NOW
  ./deploy/ops canary  <create|deploy|reset|destroy|list> [slug]
                                        per-session test instances (test-<slug>.11ch.at)
  ./deploy/ops dev     <plan|apply|deploy|rebuild>
                                        the two-node dev mesh (tofu / scp+stage+swap)
  ./deploy/ops ledger  "why..."         draft the public SSH-access why-entry
  ./deploy/ops mesh    seed [--prune] <peer> [box]
                                        replicate routes (+env) to a mesh peer
  ./deploy/ops pages   push [file...]   push committed web/status data files to the
                                        status box (default: carbon.json)

Start with `ops doctor` — it checks every credential and access path the other
verbs need, and prints the fix under each failure. `ops validate` is its
code-side twin: every local check (Go, web, shell, tofu) in one pass, needing
no credentials and touching no box — run it before opening a PR. Verbs that open box SSH
sessions (ship, canary, dev deploy) incur a why-entry in the public access
ledger; `ops ledger` drafts it.

Env overrides (defaults live in the verb scripts):
  LCHAT_BOXES         fleet box ssh aliases     (doctor, ship)
  LCHAT_CANARY_BOX    the box canaries live on (default: the dev mesh; prod is the deliberate exception)
  LCHAT_RELEASES_REPO the public releases repo

No verb for your task? EXTEND ops — a new verb or flag in a small PR
(deploy/README.md § The operator surface) — never a hand-run sequence
reconstructed from docs or runbooks.
EOF
}

verb="${1:-}"
[ $# -gt 0 ] && shift
case "$verb" in
  doctor)  exec "$here/doctor.sh"       "$@" ;;
  validate) exec "$here/ops-validate.sh" "$@" ;;
  provision) exec "$here/ops-provision.sh" "$@" ;;
  publish|promote|ship)
           exec "$here/ops-release.sh" "$verb" "$@" ;;
  canary)  exec "$here/ops-canary.sh"  "$@" ;;
  dev)     exec "$here/ops-dev.sh"     "$@" ;;
  ledger)  exec "$here/ops-ledger.sh"  "$@" ;;
  mesh)    exec "$here/ops-mesh.sh"    "$@" ;;
  pages)   exec "$here/ops-pages.sh"   "$@" ;;
  ""|-h|--help|help) usage ;;
  *)
    printf 'ops: unknown verb %s\n\n' "$verb" >&2
    usage >&2
    exit 2 ;;
esac
