Payload/scripts/kaden/harness/harness-stop-gate.ps1

<#
.SYNOPSIS
    Cursor stop-hook gate: strict validate only for a review_ready slice whose own turn is open.

.DESCRIPTION
    Silent (exit 0) while no slice is both review_ready and in an open turn of its own.
    A closed turn stays out even when that slice is the feature current_slice.
    When in scope, runs validate-review-loop -RequireReviewReady -Strict and blocks
    (exit 1) on FAIL. On fail, creates harness-gate-failure.json when it is absent,
    or replaces it only when its slice name is a slice this run validated. On pass,
    deletes that file only when its slice name is a slice this run validated and no
    in-scope slice on that feature failed. Any other existing file stays in place.
    Does not rewrite an unchanged failure set. Historical idle review_ready slices
    are skipped.

    Install: .\scripts\kaden\harness\setup-harness-hooks.ps1

.EXAMPLE
    pwsh -NoProfile -File scripts/kaden/harness/harness-stop-gate.ps1 -RepoRoot .
#>

#Requires -Version 5.1
[CmdletBinding()]
param(
    [string]$RepoRoot = ''
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$modulePath = Join-Path $PSScriptRoot 'lib\HarnessContract.psm1'
Import-Module $modulePath -Force
# Review-ready validation reads journal/events.jsonl. validate-review-loop imports
# this module at entry. This script is a separate process, so it must too.
Import-Module (Join-Path $PSScriptRoot 'lib\HarnessJournal.psm1') -Force

if ([string]::IsNullOrWhiteSpace($RepoRoot)) {
    $RepoRoot = Get-HarnessRepoRoot -StartPath $PSScriptRoot
}

$gate = Invoke-HarnessReviewReadyGate -RepoRoot $RepoRoot
if ($gate.verdict -eq 'PASS') {
    exit 0
}

foreach ($failure in $gate.failures) {
    Write-Output "[harness-stop-gate] BLOCKED $($failure.feature)/$($failure.slice) - see $($failure.path)"
    foreach ($finding in $failure.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
    }
}

exit 1