Payload/scripts/kaden/harness/validate-review-loop.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Gate oracle: validate the review-loop projection against profile requirements. .DESCRIPTION Reads docs/harness/features/<slug>/.review-loop.json (schema 1.2 gate projection) plus on-disk artifacts (.reviews, sensors, handoffs). Does NOT treat journal prose as proof of completeness - that is intentional (ADR 0003 / docs/kaden/harness-journal.md). Checks phases, reviewer cycles, sensor evidence, quality-gates / slice-review ordering, and Phase 1-2 verdict shapes (rejects bare APPROVE stubs). Exit codes: 0 = PASS; with -Strict, 1 = FAIL; without -Strict, 2 = FAIL (soft). With -RequireReviewReady, journal/events.jsonl must exist and be non-empty. Invoke-HarnessOwnershipSessionEval (PROCESS_* discretionary codes) is opt-in Pester only - RequireReviewReady does not call it (discretionary process-eval only). Honesty is enforced by recorder throws and journal validator checks, not the process-eval scorer. With -Mode preflight -Next <hop>, runs a subset of checks before expensive gate work. .PARAMETER Feature Feature slug. .PARAMETER Slice Optional slice id to scope validation. .PARAMETER FeatureRoot Override feature directory (test fixtures). .PARAMETER RequireReviewReady Enforce review_ready obligations (reviewer cycles, sensors, handoff, feature phases). .PARAMETER Mode full (default) or preflight. .PARAMETER Next When Mode is preflight: quality-gates | slice-review | review_ready. .PARAMETER Strict Exit 1 on FAIL (agent / stop-hook gates). .PARAMETER Json Emit JSON report to stdout. .EXAMPLE .\scripts\validate-review-loop.ps1 -Feature saved-search-queries -Slice mo-save-list -RequireReviewReady -Strict .EXAMPLE .\scripts\validate-review-loop.ps1 -Feature saved-search-queries -Slice mo-save-list -Mode preflight -Next quality-gates -Strict #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Feature, [string]$Slice = '', [string]$FeatureRoot = '', [string]$RepoRoot = '', [switch]$RequireReviewReady, [ValidateSet('full', 'preflight')] [string]$Mode = 'full', [ValidateSet('quality-gates', 'slice-review', 'review_ready', '')] [string]$Next = '', [switch]$Strict, [switch]$Json, [switch]$AllowArbitraryFeatureRoot ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $modulePath = Join-Path $PSScriptRoot 'lib\HarnessContract.psm1' Import-Module $modulePath -Force # Slice-review recorder validation reads journal/events.jsonl via Get-HarnessJournalEvents. # HarnessContract.psm1 does not import HarnessJournal.psm1 - this is a second module, not a duplicate import. Import-Module (Join-Path $PSScriptRoot 'lib\HarnessJournal.psm1') -Force Test-HarnessContractModuleReady # Explicit journal dependency for model-provenance cross-checks (SR-QAP-002 / CS-QAP-06). if (-not (Get-Command Get-HarnessJournalEvents -ErrorAction SilentlyContinue)) { throw 'validate-review-loop requires Get-HarnessJournalEvents after importing HarnessJournal.psm1.' } if ([string]::IsNullOrWhiteSpace($RepoRoot)) { $RepoRoot = Get-HarnessRepoRoot -StartPath $PSScriptRoot } if ($Mode -eq 'preflight' -and [string]::IsNullOrWhiteSpace($Next)) { throw 'validate-review-loop: -Next is required when -Mode is preflight (quality-gates | slice-review | review_ready).' } $featureRootPath = Get-HarnessFeatureRoot -RepoRoot $RepoRoot -Feature $Feature -FeatureRootOverride $FeatureRoot -AllowArbitraryFeatureRoot:$AllowArbitraryFeatureRoot Write-Verbose "validate-review-loop featureRoot=$featureRootPath slice=$Slice mode=$Mode next=$Next requireReviewReady=$RequireReviewReady" $report = Invoke-HarnessReviewLoopValidation -RepoRoot $RepoRoot -FeatureRoot $featureRootPath -SliceId $Slice ` -RequireReviewReady:$RequireReviewReady -Mode $Mode -PreflightNext $Next if ($Json) { $report | ConvertTo-Json -Depth 10 } else { $modeLabel = [string](Get-HarnessProperty -Object $report -Name 'mode') if ([string]::IsNullOrWhiteSpace($modeLabel)) { $modeLabel = $Mode } $nextLabel = [string](Get-HarnessProperty -Object $report -Name 'preflight_next') if ([string]::IsNullOrWhiteSpace($nextLabel)) { $nextLabel = $Next } Write-Output "validate-review-loop: $($report.verdict) (profile=$($report.profile) feature=$($report.feature) slice=$($report.slice) mode=$modeLabel next=$nextLabel)" foreach ($finding in $report.findings) { $line = " [$($finding.code)] $($finding.message)" $nextCmd = [string](Get-HarnessProperty -Object $finding -Name 'next_command') if (-not [string]::IsNullOrWhiteSpace($nextCmd)) { $line += " -> $nextCmd" } Write-Output $line } } if ($Strict -and $report.verdict -ne 'PASS') { exit 1 } if ($report.verdict -ne 'PASS') { exit 2 } exit 0 |