#!/usr/bin/env bash # scripts/install/s5-policy-skills.sh — S5: policy apply + skills sync # # Applies Lumina policy overlays and syncs skills into the sandbox. # Additive only: never removes existing presets. # # Platform-first: all mutations via nemohermes. # # Usage: # ./scripts/install/s5-policy-skills.sh # ./scripts/install/s5-policy-skills.sh --policy-only # ./scripts/install/s5-policy-skills.sh --skills-only # ./scripts/install/s5-policy-skills.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 ─────────────────────────────────────────────────────────────── DO_POLICY=1 DO_SKILLS=1 POLICY_ONLY_SET=0 SKILLS_ONLY_SET=0 # ── Parse args ───────────────────────────────────────────────────────────── while [[ $# -gt 0 ]]; do case "$1" in --help|-h) cat </dev/null 2>&1; then log_error "Sandbox '$SANDBOX_NAME' not found. Run S4 first." exit 1 fi # ── Policy apply ─────────────────────────────────────────────────────────── apply_policy() { log_section "S5a: Apply policy overlays" if [[ ! -d "$POLICY_DIR" ]]; then log_warn "Policy overlays directory not found: $POLICY_DIR" return 0 fi # Apply inference overlay (always apply at S5) local inference_policy="$POLICY_DIR/inference.yaml" if [[ -f "$inference_policy" ]]; then log_info "Applying inference policy overlay…" if nemohermes "$SANDBOX_NAME" policy-add --from-file "$inference_policy" --yes 2>&1; then log_info "Inference policy overlay applied." else log_warn "Inference policy overlay may already be applied (idempotent)." fi else log_warn "Inference policy overlay not found: $inference_policy" fi # List current policy for verification log_info "Current policy presets:" nemohermes "$SANDBOX_NAME" policy-list 2>&1 || log_warn "Could not list policy presets" log_info "S5a policy apply complete." } # ── Skills sync ──────────────────────────────────────────────────────────── sync_skills() { log_section "S5b: Sync skills" if [[ ! -d "$SKILLS_DIR" ]]; then log_warn "Skills directory not found: $SKILLS_DIR" return 0 fi local skill_count=0 local skill_ok=0 local skill_skip=0 local skill_fail=0 # Iterate skill directories (skip _lib and hidden dirs) for skill_dir in "$SKILLS_DIR"/*/; do # Skip if not a directory [[ -d "$skill_dir" ]] || continue local skill_name skill_name="$(basename "$skill_dir")" # Skip _lib (shared library, not a skill) if [[ "$skill_name" == "_lib" ]]; then log_info "Skipping _lib (shared library)" continue fi skill_count=$((skill_count + 1)) # Check for SKILL.md (required by nemohermes skill install) local skill_md="$skill_dir/SKILL.md" if [[ ! -f "$skill_md" ]]; then log_warn "Skipping '$skill_name': no SKILL.md found" skill_skip=$((skill_skip + 1)) continue fi log_info "Installing skill: $skill_name" if nemohermes "$SANDBOX_NAME" skill install "$skill_dir" 2>&1; then log_info " ✓ $skill_name installed" skill_ok=$((skill_ok + 1)) else log_warn " ✗ $skill_name failed (may already be installed)" skill_fail=$((skill_fail + 1)) fi done log_info "Skills sync summary: $skill_count found, $skill_ok installed, $skill_skip skipped, $skill_fail failed" if [[ $skill_count -eq 0 ]]; then log_warn "No skill directories found in $SKILLS_DIR" fi log_info "S5b skills sync complete." } # ── Execute ──────────────────────────────────────────────────────────────── if [[ $DO_POLICY -eq 1 ]]; then apply_policy fi if [[ $DO_SKILLS -eq 1 ]]; then sync_skills fi log_info "S5 complete."