#!/usr/bin/env bash # scripts/install/s4-sandbox.sh — S4: sandbox verification / onboard # # Two modes: # attach (default) — verify existing sandbox is healthy; no destructive ops # onboard — create new sandbox from agent package (clean host only) # # Platform-first: all mutations via nemohermes. Never hand-edit in-sandbox config. # # Usage: # ./scripts/install/s4-sandbox.sh # attach mode (default) # ./scripts/install/s4-sandbox.sh --mode attach # ./scripts/install/s4-sandbox.sh --mode onboard # ./scripts/install/s4-sandbox.sh --mode onboard --dry-run # ./scripts/install/s4-sandbox.sh --help set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Source shared helpers # shellcheck source=../lib/common.sh source "$SCRIPT_DIR/../lib/common.sh" # shellcheck source=../lib/env.sh source "$SCRIPT_DIR/../lib/env.sh" # ── Defaults ─────────────────────────────────────────────────────────────── MODE="${LUMINA_INSTALL_MODE:-attach}" DRY_RUN=0 # ── Parse args ───────────────────────────────────────────────────────────── while [[ $# -gt 0 ]]; do case "$1" in --help|-h) cat < Install mode (default: attach) --dry-run Preview onboard without executing --help Show this help Modes: attach Verify existing sandbox is healthy (UAT default) onboard Create new sandbox from agent package (clean host) Examples: $(basename "$0") # attach mode $(basename "$0") --mode onboard # onboard mode $(basename "$0") --mode onboard --dry-run # onboard dry-run EOF exit 0 ;; --mode) shift MODE="${1:-}" if [[ -z "$MODE" ]]; then log_error "--mode requires a value (attach or onboard)" exit 1 fi shift ;; --dry-run) DRY_RUN=1 shift ;; *) log_error "Unknown argument: $1" exit 1 ;; esac done # ── Validate mode ────────────────────────────────────────────────────────── if [[ "$MODE" != "attach" && "$MODE" != "onboard" ]]; then log_error "Invalid mode: $MODE (must be 'attach' or 'onboard')" exit 1 fi log_section "S4: Sandbox ($MODE mode)" # ── Load .env ────────────────────────────────────────────────────────────── load_env # ── Validate required keys ───────────────────────────────────────────────── validate_env || exit 1 # ── Check CLI prerequisites ──────────────────────────────────────────────── require_cmd nemohermes "Install nemohermes CLI (part of NemoClaw platform)" SANDBOX_NAME="$(get_sandbox_name)" AGENT_PKG_DIR="$REPO_ROOT/agents/hermes" # ── Attach mode ──────────────────────────────────────────────────────────── do_attach() { log_info "Attach mode: verifying sandbox '$SANDBOX_NAME'" # Check sandbox exists and report status if ! nemohermes "$SANDBOX_NAME" status &>/dev/null; then log_error "Sandbox '$SANDBOX_NAME' not found or not reachable." log_error "If this is a clean host, re-run with --mode onboard" log_error "Or create the sandbox manually: nemohermes onboard" return 1 fi log_info "Sandbox '$SANDBOX_NAME' is healthy." # Verify agent package exists (reference only in attach mode) if [[ -d "$AGENT_PKG_DIR" ]]; then log_info "Agent package found at $AGENT_PKG_DIR" if [[ -f "$AGENT_PKG_DIR/skills-manifest/manifest.yaml" ]]; then log_info "Skills manifest present — S5 will sync skills" else log_warn "Skills manifest not found — skills sync (S5) may be incomplete" fi else log_warn "Agent package directory not found at $AGENT_PKG_DIR" fi log_info "S4 attach complete." } # ── Onboard mode ─────────────────────────────────────────────────────────── do_onboard() { log_info "Onboard mode: preparing sandbox '$SANDBOX_NAME' from agent package" # Verify agent package exists if [[ ! -d "$AGENT_PKG_DIR" ]]; then log_error "Agent package not found at $AGENT_PKG_DIR" return 1 fi # Check if sandbox already exists — do not destroy it if nemohermes "$SANDBOX_NAME" status &>/dev/null; then log_warn "Sandbox '$SANDBOX_NAME' already exists." log_warn "Onboard mode does not destroy existing sandboxes." log_warn "Switching to attach behavior for safety." do_attach return 0 fi if [[ $DRY_RUN -eq 1 ]]; then log_info "DRY-RUN: Would execute:" log_info " nemohermes onboard --from-dir $AGENT_PKG_DIR" log_info " (with inference from .env: $LUMINA_INFERENCE_BASE_URL)" log_info "S4 onboard dry-run complete." return 0 fi # Onboard with agent package log_info "Running nemohermes onboard with agent package…" if nemohermes onboard --from-dir "$AGENT_PKG_DIR"; then log_info "Sandbox '$SANDBOX_NAME' onboarded successfully." else log_error "Onboard failed. Check nemohermes logs for details." log_error "You may need to run nemohermes onboard manually first." return 1 fi log_info "S4 onboard complete." } # ── Execute ──────────────────────────────────────────────────────────────── case "$MODE" in attach) do_attach ;; onboard) do_onboard ;; esac