<# .SYNOPSIS Verify / repair code-review report file naming compliance. .DESCRIPTION Enforces the archive convention defined in project-review/SKILL.md: every review report must live under /docs/reviews/ and be named -review-YYYY-MM-DD-HHMMSS.{md,html} (exact timestamp suffix). Two modes: (default) verify - scan and report non-compliance; exit 0 = clean, 1 = violations. -Fix - move stray root-level code-review-report.* files into docs/reviews/ with a timestamp suffix, then verify. Violations (blocking, exit 1): stray root-level code-review-report.* files. Warnings (non-blocking): docs/reviews/ files not carrying a -YYYY-MM-DD-HHMMSS suffix. Historic files are only reported, never renamed automatically. .PARAMETER Repo Repository root. Defaults to the current directory. .PARAMETER Fix Repair blocking violations automatically (archive stray root reports). .EXAMPLE powershell -File verify-report.ps1 -Repo D:\AuraSpace powershell -File verify-report.ps1 -Repo D:\AuraSpace -Fix #> param( [string]$Repo = "", [switch]$Fix ) $ErrorActionPreference = "Stop" function Write-Step([string]$msg) { Write-Host " $msg" -ForegroundColor DarkGray } function Write-Ok([string]$msg) { Write-Host " [OK] $msg" -ForegroundColor Green } function Write-Bad([string]$msg) { Write-Host " [!!] $msg" -ForegroundColor Red } function Write-Warn([string]$msg) { Write-Host " [!] $msg" -ForegroundColor Yellow } # Resolve repo root --------------------------------------------------------- if ([string]::IsNullOrWhiteSpace($Repo)) { $Repo = (Get-Location).Path } $root = (Resolve-Path -LiteralPath $Repo).Path $reviewsDir = Join-Path $root "docs\reviews" $timestampRe = '^(.+?-review)-\d{4}-\d{2}-\d{2}-\d{6}\.(md|html)$' Write-Host "verify-report: repo = $root" Write-Host "" # Phase 0 - optional repair ------------------------------------------------- if ($Fix) { Write-Host "Fix mode: archiving stray root-level code-review-report.*" $stray = Get-ChildItem -LiteralPath $root -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '^code-review-report\.(md|html)$' } if ($stray) { New-Item -ItemType Directory -Path $reviewsDir -Force | Out-Null foreach ($f in $stray) { $ts = $f.LastWriteTime.ToString("yyyy-MM-dd-HHmmss") $target = Join-Path $reviewsDir "report-review-$ts$($f.Extension)" if (Test-Path -LiteralPath $target) { $ts2 = $f.LastWriteTime.ToString("yyyy-MM-dd-HHmmss-fff") $target = Join-Path $reviewsDir "report-review-$ts2$($f.Extension)" } Move-Item -LiteralPath $f.FullName -Destination $target -Force Write-Ok "archived $($f.Name) -> $target" } } else { Write-Ok "no stray root-level reports to archive" } Write-Host "" } # Phase 1 - verify root has no stray reports (BLOCKING) --------------------- $violations = @() $warnings = @() Write-Host "1. Root-level report files (blocking):" $rootStray = Get-ChildItem -LiteralPath $root -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '^code-review-report\.(md|html)$' } if ($rootStray) { foreach ($f in $rootStray) { Write-Bad "stray root report: $($f.FullName)" $violations += $f.FullName } } else { Write-Ok "no stray root-level code-review-report.* files" } Write-Host "" # Phase 2 - verify docs/reviews naming (WARNING only) ----------------------- Write-Host "2. docs/reviews/*.{md,html} naming (should carry -YYYY-MM-DD-HHMMSS):" if (-not (Test-Path -LiteralPath $reviewsDir)) { Write-Ok "docs/reviews/ does not exist yet - nothing to verify" } else { $reports = Get-ChildItem -LiteralPath $reviewsDir -File | Where-Object { $_.Extension -in @(".md", ".html") } if (-not $reports) { Write-Ok "no report files present" } else { foreach ($f in $reports) { if ($f.Name -match $timestampRe) { Write-Ok $f.Name } else { Write-Warn "non-conforming name (historic, not auto-fixed): $($f.Name)" $warnings += $f.FullName } } } } Write-Host "" # Verdict ------------------------------------------------------------------- if ($violations.Count -gt 0) { Write-Host "RESULT: FAIL ($($violations.Count) blocking violation(s))" -ForegroundColor Red exit 1 } else { if ($warnings.Count -gt 0) { Write-Host "RESULT: PASS ($($warnings.Count) non-blocking historic naming warning(s) - rename manually if desired)" -ForegroundColor Green } else { Write-Host "RESULT: PASS - all review reports are archived under docs/reviews/ with timestamp suffixes" -ForegroundColor Green } exit 0 }