#!/usr/bin/env bash # ═══════════════════════════════════════════════════════════════════════ # Video Pipeline Setup — {{TITLE}} # # Generated by video-orchestrator skill. # # Slug: {{SLUG}} # Workspace: {{WORKSPACE}} # Tenant: {{TENANT}} # ═══════════════════════════════════════════════════════════════════════ set -euo pipefail PROJECT_SLUG="{{SLUG}}" WORKSPACE="$HOME/projects/video-pipeline/${PROJECT_SLUG}" TENANT="{{TENANT}}" # ───────────────────────────────────────────────────────────────────── # 1. Verify required API keys # ───────────────────────────────────────────────────────────────────── echo "═══ Checking required API keys ═══" check_key() { local var="$1" local kc_account="${2:-hermes}" local kc_service="${3:-$1}" if grep -q "^${var}=" "$HOME/.hermes/.env" 2>/dev/null && \ [ -n "$(grep "^${var}=" "$HOME/.hermes/.env" | cut -d= -f2-)" ]; then echo " ✓ ${var} (env)" return 0 fi if command -v security >/dev/null 2>&1 && \ security find-generic-password -a "${kc_account}" -s "${kc_service}" -w >/dev/null 2>&1; then echo " ✓ ${var} (Keychain ${kc_account}/${kc_service})" return 0 fi echo " ✗ ${var} not set in ~/.hermes/.env or Keychain (${kc_account}/${kc_service})" return 1 } # Customize this list per project — only check keys actually used: {{KEY_CHECKS}} # ───────────────────────────────────────────────────────────────────── # 2. Create project workspace # ───────────────────────────────────────────────────────────────────── echo "═══ Creating project workspace ═══" mkdir -p "$WORKSPACE"/{taste,audio/{voiceover,sfx},assets,scenes,checkpoints,tools,output} {{SCENE_DIRS}} echo " ✓ $WORKSPACE" # ───────────────────────────────────────────────────────────────────── # 3. Create Hermes profiles # ───────────────────────────────────────────────────────────────────── echo "═══ Creating Hermes profiles ═══" {{PROFILE_CREATE_COMMANDS}} # ───────────────────────────────────────────────────────────────────── # 4. Configure profiles (toolsets, skills, cwd) # ───────────────────────────────────────────────────────────────────── echo "═══ Configuring profiles ═══" configure_profile() { local profile="$1" local toolsets_json="$2" # JSON array string, e.g. '["kanban","terminal","file"]' local skills_json="$3" # JSON array string, e.g. '["kanban-worker","ascii-video"]' python3 - "$profile" "$toolsets_json" "$skills_json" "$WORKSPACE" <<'PY' """Patch a Hermes profile config.yaml using PyYAML so we don't depend on the exact default-config string format. Validates the patch took effect and exits non-zero if anything's off.""" import json import os import sys try: import yaml except ImportError: print("ERROR: PyYAML required. pip install pyyaml", file=sys.stderr) sys.exit(1) profile, toolsets_json, skills_json, workspace = sys.argv[1:5] toolsets = json.loads(toolsets_json) skills = json.loads(skills_json) p = os.path.expanduser(f"~/.hermes/profiles/{profile}/config.yaml") if not os.path.exists(p): print(f" ✗ profile config not found: {p}", file=sys.stderr) sys.exit(1) with open(p) as f: cfg = yaml.safe_load(f) or {} # Apply our changes — only the keys we actually want to set. cfg["toolsets"] = toolsets cfg.setdefault("skills", {}) cfg["skills"]["always_load"] = skills # Note: we do NOT touch cfg["approvals"] — that's a security-sensitive # setting (manual confirmation of tool calls). Workspace cwd is overridden # per-task by `--workspace dir:` on `hermes kanban create`, so we # don't need to mutate cfg["terminal"]["cwd"] either. with open(p, "w") as f: yaml.safe_dump(cfg, f, sort_keys=False) # Validate with open(p) as f: after = yaml.safe_load(f) errors = [] if after.get("toolsets") != toolsets: errors.append(f"toolsets mismatch: {after.get('toolsets')!r}") if after.get("skills", {}).get("always_load") != skills: errors.append(f"skills.always_load mismatch: {after.get('skills', {}).get('always_load')!r}") if errors: print(f" ✗ {profile}: " + "; ".join(errors), file=sys.stderr) sys.exit(1) PY if [ $? -ne 0 ]; then echo " ✗ failed to configure ${profile}" >&2 exit 1 fi echo " ✓ ${profile}" } {{PROFILE_CONFIG_COMMANDS}} # ───────────────────────────────────────────────────────────────────── # 5. Write SOUL.md per profile # ───────────────────────────────────────────────────────────────────── echo "═══ Writing profile personalities ═══" {{SOUL_WRITES}} # ───────────────────────────────────────────────────────────────────── # 6. Copy brief, TEAM.md, and any provided assets # ───────────────────────────────────────────────────────────────────── echo "═══ Writing brief + taste ═══" cat > "$WORKSPACE/brief.md" <<'BRIEF_EOF' {{BRIEF_CONTENTS}} BRIEF_EOF cat > "$WORKSPACE/TEAM.md" <<'TEAM_EOF' {{TEAM_CONTENTS}} TEAM_EOF {{TASTE_WRITES}} {{ASSET_COPIES}} # ───────────────────────────────────────────────────────────────────── # 7. Fire the initial kanban task # ───────────────────────────────────────────────────────────────────── echo "═══ Firing initial kanban task ═══" hermes kanban create "Direct production of {{TITLE}}" \ --assignee director \ --workspace dir:"$WORKSPACE" \ --tenant "$TENANT" \ --priority 2 \ --max-runtime 4h \ --body "$(cat <