100 lines
3.8 KiB
PowerShell
100 lines
3.8 KiB
PowerShell
#requires -version 5.1
|
|
<#
|
|
run-parallel-100.ps1 - orchestrate 100-article SEO restoration with parallel Sonnet /goal agents.
|
|
Run from the odoo-expertos repo root.
|
|
Phases:
|
|
setup -> SETUP.txt on fix/seo-all (brand, persona, flow, strategy, clusters, z-image probe). Serial.
|
|
batches -> B01..B10.txt in parallel git worktrees, each on its own fix/seo-batch-bNN branch.
|
|
final -> FINAL.txt on fix/seo-all (merge all batches, W5b, clusters exec, REVIEW gate, deploy, re-audit).
|
|
all -> setup -> batches -> final.
|
|
|
|
Examples:
|
|
.\seo-audit-2026-05-27\run-parallel-100.ps1 # all phases, max 10 concurrent
|
|
.\seo-audit-2026-05-27\run-parallel-100.ps1 -Phase setup # just setup
|
|
.\seo-audit-2026-05-27\run-parallel-100.ps1 -Phase batches -MaxConcurrent 5
|
|
.\seo-audit-2026-05-27\run-parallel-100.ps1 -Phase final
|
|
#>
|
|
param(
|
|
[ValidateSet('setup','batches','final','all')][string]$Phase = 'all',
|
|
[int]$MaxConcurrent = 10,
|
|
[string]$Model = "sonnet"
|
|
)
|
|
$ErrorActionPreference = "Stop"
|
|
$Repo = (Resolve-Path ".").Path
|
|
$Goals = Join-Path $Repo "seo-audit-2026-05-27\goals"
|
|
if(-not (Test-Path (Join-Path $Repo ".git"))){ throw "Run from the odoo-expertos repo root (no .git here: $Repo)" }
|
|
if(-not (Get-Command claude -ErrorAction SilentlyContinue)){ throw "claude CLI not on PATH" }
|
|
function ReadGoal($name){ Get-Content -Raw (Join-Path $Goals "$name.txt") }
|
|
|
|
function Run-Setup {
|
|
Write-Host "=== SETUP (serial) ===" -ForegroundColor Cyan
|
|
git checkout -B fix/seo-all
|
|
$g = ReadGoal 'SETUP'
|
|
claude --model $Model -p "/goal $g"
|
|
Write-Host "--- SETUP done. Verify BRAND.md + personas + cluster plans + z-image probe exist." -ForegroundColor Green
|
|
}
|
|
|
|
function Run-Batches {
|
|
Write-Host "=== BATCHES (parallel, MaxConcurrent=$MaxConcurrent) ===" -ForegroundColor Cyan
|
|
$ids = 1..10 | ForEach-Object { "B{0:00}" -f $_ }
|
|
$wt = @{}
|
|
$parent = Split-Path $Repo -Parent
|
|
foreach($id in $ids){
|
|
$wtDir = Join-Path $parent ("odoo-wt-" + $id.ToLower())
|
|
$branch = "fix/seo-batch-" + $id.ToLower()
|
|
if(-not (Test-Path $wtDir)){
|
|
Write-Host "creating worktree $wtDir on $branch (from fix/seo-all)"
|
|
git worktree add -b $branch $wtDir fix/seo-all
|
|
} else {
|
|
Write-Host "worktree exists: $wtDir"
|
|
}
|
|
$wt[$id] = $wtDir
|
|
}
|
|
|
|
$queue = New-Object System.Collections.Queue
|
|
foreach($id in $ids){ $queue.Enqueue($id) }
|
|
$running = @{}
|
|
while($queue.Count -gt 0 -or $running.Count -gt 0){
|
|
while($running.Count -lt $MaxConcurrent -and $queue.Count -gt 0){
|
|
$id = $queue.Dequeue()
|
|
$g = ReadGoal $id
|
|
$wtDir = $wt[$id]
|
|
Write-Host "--> launching $id in $wtDir" -ForegroundColor Yellow
|
|
$j = Start-Job -ScriptBlock {
|
|
param($wtDir, $model, $goal, $id)
|
|
Set-Location $wtDir
|
|
$log = Join-Path $wtDir "$id.log"
|
|
& claude --model $model -p "/goal $goal" *> $log
|
|
return @{Id=$id; ExitCode=$LASTEXITCODE; Log=$log}
|
|
} -ArgumentList $wtDir, $Model, $g, $id
|
|
$running[$id] = $j
|
|
}
|
|
Start-Sleep -Seconds 30
|
|
foreach($id in @($running.Keys)){
|
|
$j = $running[$id]
|
|
if($j.State -ne 'Running'){
|
|
$r = Receive-Job $j -ErrorAction SilentlyContinue
|
|
Remove-Job $j -Force
|
|
Write-Host "<-- $id finished (exit $($r.ExitCode); log: $($r.Log))" -ForegroundColor Green
|
|
$running.Remove($id)
|
|
}
|
|
}
|
|
}
|
|
Write-Host "--- ALL BATCHES finished. Inspect each fix/seo-batch-bNN branch + its log before FINAL." -ForegroundColor Green
|
|
}
|
|
|
|
function Run-Final {
|
|
Write-Host "=== FINAL (serial) ===" -ForegroundColor Cyan
|
|
git checkout fix/seo-all
|
|
$g = ReadGoal 'FINAL'
|
|
claude --model $Model -p "/goal $g"
|
|
Write-Host "--- FINAL done. Check the live re-audit score." -ForegroundColor Green
|
|
}
|
|
|
|
switch($Phase){
|
|
'setup' { Run-Setup }
|
|
'batches' { Run-Batches }
|
|
'final' { Run-Final }
|
|
'all' { Run-Setup; Run-Batches; Run-Final }
|
|
}
|