main
ps1 111 lines 3.79 KB
Raw
1 # sync-mesh.ps1 — Materialize remote squad state locally
2 #
3 # Reads mesh.json, fetches remote squads into local directories.
4 # Run before agent reads. No daemon. No service. ~40 lines.
5 #
6 # Usage: .\sync-mesh.ps1 [path-to-mesh.json]
7 # .\sync-mesh.ps1 -Init [path-to-mesh.json]
8 # Requires: git
9 param(
10 [switch]$Init,
11 [string]$MeshJson = "mesh.json"
12 )
13 $ErrorActionPreference = "Stop"
14
15 # Handle -Init mode
16 if ($Init) {
17 if (-not (Test-Path $MeshJson)) {
18 Write-Host "❌ $MeshJson not found"
19 exit 1
20 }
21
22 Write-Host "🚀 Initializing mesh state repository..."
23 $config = Get-Content $MeshJson -Raw | ConvertFrom-Json
24 $squads = $config.squads.PSObject.Properties.Name
25
26 # Create squad directories with placeholder SUMMARY.md
27 foreach ($squad in $squads) {
28 if (-not (Test-Path $squad)) {
29 New-Item -ItemType Directory -Path $squad | Out-Null
30 Write-Host " ✓ Created $squad/"
31 } else {
32 Write-Host " • $squad/ exists (skipped)"
33 }
34
35 $summaryPath = "$squad/SUMMARY.md"
36 if (-not (Test-Path $summaryPath)) {
37 "# $squad`n`n_No state published yet._" | Set-Content $summaryPath
38 Write-Host " ✓ Created $summaryPath"
39 } else {
40 Write-Host " • $summaryPath exists (skipped)"
41 }
42 }
43
44 # Generate root README.md
45 if (-not (Test-Path "README.md")) {
46 $readme = @"
47 # Squad Mesh State Repository
48
49 This repository tracks published state from participating squads.
50
51 ## Participating Squads
52
53 "@
54 foreach ($squad in $squads) {
55 $zone = $config.squads.$squad.zone
56 $readme += "- **$squad** (Zone: $zone)`n"
57 }
58 $readme += @"
59
60 Each squad directory contains a ``SUMMARY.md`` with their latest published state.
61 State is synchronized using ``sync-mesh.sh`` or ``sync-mesh.ps1``.
62 "@
63 $readme | Set-Content "README.md"
64 Write-Host " ✓ Created README.md"
65 } else {
66 Write-Host " • README.md exists (skipped)"
67 }
68
69 Write-Host ""
70 Write-Host "✅ Mesh state repository initialized"
71 exit 0
72 }
73
74 $config = Get-Content $MeshJson -Raw | ConvertFrom-Json
75
76 # Zone 2: Remote-trusted — git clone/pull
77 foreach ($entry in $config.squads.PSObject.Properties | Where-Object { $_.Value.zone -eq "remote-trusted" }) {
78 $squad = $entry.Name
79 $source = $entry.Value.source
80 $ref = if ($entry.Value.ref) { $entry.Value.ref } else { "main" }
81 $target = $entry.Value.sync_to
82
83 if (Test-Path "$target/.git") {
84 git -C $target pull --rebase --quiet 2>$null
85 if ($LASTEXITCODE -ne 0) { Write-Host "⚠ ${squad}: pull failed (using stale)" }
86 } else {
87 New-Item -ItemType Directory -Force -Path (Split-Path $target -Parent) | Out-Null
88 git clone --quiet --depth 1 --branch $ref $source $target 2>$null
89 if ($LASTEXITCODE -ne 0) { Write-Host "⚠ ${squad}: clone failed (unavailable)" }
90 }
91 }
92
93 # Zone 3: Remote-opaque — fetch published contracts
94 foreach ($entry in $config.squads.PSObject.Properties | Where-Object { $_.Value.zone -eq "remote-opaque" }) {
95 $squad = $entry.Name
96 $source = $entry.Value.source
97 $target = $entry.Value.sync_to
98 $auth = $entry.Value.auth
99
100 New-Item -ItemType Directory -Force -Path $target | Out-Null
101 $params = @{ Uri = $source; OutFile = "$target/SUMMARY.md"; UseBasicParsing = $true }
102 if ($auth -eq "bearer") {
103 $tokenVar = ($squad.ToUpper() -replace '-', '_') + "_TOKEN"
104 $token = [Environment]::GetEnvironmentVariable($tokenVar)
105 if ($token) { $params.Headers = @{ Authorization = "Bearer $token" } }
106 }
107 try { Invoke-WebRequest @params -ErrorAction Stop }
108 catch { "# ${squad} — unavailable ($(Get-Date))" | Set-Content "$target/SUMMARY.md" }
109 }
110
111 Write-Host "✓ Mesh sync complete"