agents/preflight.ps1
|
# preflight.ps1 — Discover specs, constitution check # Usage: .\preflight.ps1 -SpecsDir <path> -ProjectDir <path> -RunDir <path> # Outputs: spec-discovery.json (spec list) in RunDir param( [Parameter(Mandatory)] [string]$SpecsDir, [Parameter(Mandatory)] [string]$ProjectDir, [Parameter(Mandatory)] [string]$RunDir, [Parameter(Mandatory)] [string]$LogFile, [string]$Model ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8 # Work from the target project directory Push-Location $ProjectDir try { # ── Logging ─────────────────────────────────────────────────────── function Log { param([string]$Message, [string]$Color = 'White') Write-Host $Message -ForegroundColor $Color "$(Get-Date -Format 'HH:mm:ss') $Message" | Out-File -FilePath $LogFile -Append } Log "========== PRE-FLIGHT CHECK ==========" Blue # ── 1. Discover specs ───────────────────────────────────────────── Log "--- Spec Discovery ---" Blue Log "Specs directory : $SpecsDir" DarkGray $specFiles = Get-ChildItem -Path $SpecsDir -Filter '*.md' | Where-Object { $_.Name -match '^\d{2}-' } | Sort-Object Name if ($specFiles.Count -eq 0) { Log "No numbered spec files (NN-*.md) found in $SpecsDir — nothing to do." Yellow Log "Are you using spec-kit style specs? See https://github.com/github/spec-kit" Yellow exit 1 } Log "Found $($specFiles.Count) spec(s):" DarkGray $specs = @() foreach ($sf in $specFiles) { Log " - $($sf.Name)" DarkGray $specs += @{ name = $sf.BaseName file = $sf.FullName } } $discoveryFile = Join-Path $RunDir 'spec-discovery.json' $specs | ConvertTo-Json -Depth 2 | Set-Content -Path $discoveryFile -Encoding UTF8 Log "Discovery written to: $discoveryFile" Green # ── 2. Constitution check ──────────────────────────────────────── Log "--- Constitution Check ---" Blue $constitutionPath = Join-Path $SpecsDir 'CONSTITUTION.md' if (-not (Test-Path $constitutionPath)) { Log "No CONSTITUTION.md found at $constitutionPath — skipping constitution check." Yellow Log "Are you using spec-kit style specs? See https://github.com/github/spec-kit" Yellow Log "Pre-flight complete (no constitution)." Green exit 0 } $findingsFile = Join-Path $RunDir 'preflight-findings.md' & copilot -p @" You are a pre-flight reviewer. Your job is to review a project constitution and make sure it does not interfere with how the dev-loop operates. A constitution can say ANYTHING about the product itself — constraints, architecture, naming conventions, quality gates, implementation preferences, whatever the author wants. That's all fair game. The ONE thing a constitution must NOT do is dictate dev-loop process: - **Spec inventory or cross-references** — lists of spec files, dependency graphs, build orders. An agent reading the constitution should not discover what other specs exist or what order to build them. - **Process instructions** — how specs are structured, how amendments work, how the build loop operates, how to iterate. The dev-loop owns its own process. - **Spec templates or layouts** — what sections a spec should have, what format specs follow. That's dev-loop tooling, not a product concern. If the constitution talks about the product, leave it alone — even if it's very specific. Only flag things that step on the dev-loop's process. Review the constitution at: $constitutionPath For each finding, report: - **Severity: HIGH or LOW** - The specific text that violates the above rules - Which category it falls into (spec inventory, process instruction, or spec template) - Why it's a problem (how it could interfere with dev-loop operation) SEVERITY GUIDELINES: - **HIGH** — The text will actively mislead an autonomous agent, cause it to refuse valid approaches, or inject scope/structure it should not know about. These are blocking problems. - **LOW** — The text is suboptimal or slightly out of lane, but an autonomous agent would still produce correct output. These are advisory only. SCOPE CONSTRAINT: Only read the constitution file. Do not read any other files. OUTPUT RULES: - If you find ZERO issues, or only LOW-severity issues: print exactly "PREFLIGHT: PASS" to stdout. Do NOT create any files. - If you find any HIGH-severity issues: write ALL findings (both HIGH and LOW) to $findingsFile and print "PREFLIGHT: FINDINGS" as the first line of that file, followed by each finding. Also print the findings to stdout. "@ --yolo $(if ($Model) { "--model $Model" }) 2>&1 | ForEach-Object { Write-Host $_; $_ | Out-File -FilePath $LogFile -Append } if (Test-Path $findingsFile) { Log "Pre-flight findings saved to: $findingsFile" Yellow Log "Review the findings and update CONSTITUTION.md before running the dev-loop." Yellow exit 1 } Log "Pre-flight complete." Green exit 0 } catch { $errMsg = "FATAL [preflight]: $_" Write-Host $errMsg -ForegroundColor Red "$(Get-Date -Format 'HH:mm:ss') $errMsg" | Out-File -FilePath $LogFile -Append throw } finally { Pop-Location } |