sync-mesh.sh (3513B)
1 #!/bin/bash 2 # sync-mesh.sh — Materialize remote squad state locally 3 # 4 # Reads mesh.json, fetches remote squads into local directories. 5 # Run before agent reads. No daemon. No service. ~40 lines. 6 # 7 # Usage: ./sync-mesh.sh [path-to-mesh.json] 8 # ./sync-mesh.sh --init [path-to-mesh.json] 9 # Requires: jq (https://github.com/jqlang/jq), git, curl 10 11 set -euo pipefail 12 13 # Handle --init mode 14 if [ "${1:-}" = "--init" ]; then 15 MESH_JSON="${2:-mesh.json}" 16 17 if [ ! -f "$MESH_JSON" ]; then 18 echo "❌ $MESH_JSON not found" 19 exit 1 20 fi 21 22 echo "🚀 Initializing mesh state repository..." 23 squads=$(jq -r '.squads | keys[]' "$MESH_JSON") 24 25 # Create squad directories with placeholder SUMMARY.md 26 for squad in $squads; do 27 if [ ! -d "$squad" ]; then 28 mkdir -p "$squad" 29 echo " ✓ Created $squad/" 30 else 31 echo " • $squad/ exists (skipped)" 32 fi 33 34 if [ ! -f "$squad/SUMMARY.md" ]; then 35 echo -e "# $squad\n\n_No state published yet._" > "$squad/SUMMARY.md" 36 echo " ✓ Created $squad/SUMMARY.md" 37 else 38 echo " • $squad/SUMMARY.md exists (skipped)" 39 fi 40 done 41 42 # Generate root README.md 43 if [ ! -f "README.md" ]; then 44 { 45 echo "# Squad Mesh State Repository" 46 echo "" 47 echo "This repository tracks published state from participating squads." 48 echo "" 49 echo "## Participating Squads" 50 echo "" 51 for squad in $squads; do 52 zone=$(jq -r ".squads.\"$squad\".zone" "$MESH_JSON") 53 echo "- **$squad** (Zone: $zone)" 54 done 55 echo "" 56 echo "Each squad directory contains a \`SUMMARY.md\` with their latest published state." 57 echo "State is synchronized using \`sync-mesh.sh\` or \`sync-mesh.ps1\`." 58 } > README.md 59 echo " ✓ Created README.md" 60 else 61 echo " • README.md exists (skipped)" 62 fi 63 64 echo "" 65 echo "✅ Mesh state repository initialized" 66 exit 0 67 fi 68 69 MESH_JSON="${1:-mesh.json}" 70 71 # Zone 2: Remote-trusted — git clone/pull 72 for squad in $(jq -r '.squads | to_entries[] | select(.value.zone == "remote-trusted") | .key' "$MESH_JSON"); do 73 source=$(jq -r ".squads.\"$squad\".source" "$MESH_JSON") 74 ref=$(jq -r ".squads.\"$squad\".ref // \"main\"" "$MESH_JSON") 75 target=$(jq -r ".squads.\"$squad\".sync_to" "$MESH_JSON") 76 77 if [ -d "$target/.git" ]; then 78 git -C "$target" pull --rebase --quiet 2>/dev/null \ 79 || echo "⚠ $squad: pull failed (using stale)" 80 else 81 mkdir -p "$(dirname "$target")" 82 git clone --quiet --depth 1 --branch "$ref" "$source" "$target" 2>/dev/null \ 83 || echo "⚠ $squad: clone failed (unavailable)" 84 fi 85 done 86 87 # Zone 3: Remote-opaque — fetch published contracts 88 for squad in $(jq -r '.squads | to_entries[] | select(.value.zone == "remote-opaque") | .key' "$MESH_JSON"); do 89 source=$(jq -r ".squads.\"$squad\".source" "$MESH_JSON") 90 target=$(jq -r ".squads.\"$squad\".sync_to" "$MESH_JSON") 91 auth=$(jq -r ".squads.\"$squad\".auth // \"\"" "$MESH_JSON") 92 93 mkdir -p "$target" 94 auth_flag="" 95 if [ "$auth" = "bearer" ]; then 96 token_var="$(echo "${squad}" | tr '[:lower:]-' '[:upper:]_')_TOKEN" 97 [ -n "${!token_var:-}" ] && auth_flag="--header \"Authorization: Bearer ${!token_var}\"" 98 fi 99 100 eval curl --silent --fail $auth_flag "$source" -o "$target/SUMMARY.md" 2>/dev/null \ 101 || echo "# ${squad} — unavailable ($(date))" > "$target/SUMMARY.md" 102 done 103 104 echo "✓ Mesh sync complete"