AI skills in use in my daily
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

161 lines
6.8 KiB

<#
.SYNOPSIS
Reconstruct the state of lights-out runs for Companion polling and Morning Review.
.DESCRIPTION
Reads the durable registry at ~\.scout\lights-out\runs.json and, for each run, re-derives
live facts from git and gnhf's own artifacts. Safe to call from a brand-new Scout session
that has no memory of the conversation that launched the run.
.EXAMPLE
.\check-run.ps1 -Latest
.EXAMPLE
.\check-run.ps1 -Since 1 -Json
#>
[CmdletBinding()]
param(
[string]$Id,
[switch]$Latest,
[switch]$Active,
[int]$Since = 0,
[int]$NotesTail = 40,
[switch]$Json
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'lib.ps1')
$runs = @(Read-LightsOutRuns)
if ($runs.Count -eq 0) {
if ($Json) { '[]' } else { Write-Host 'No lights-out runs have ever been registered.' }
return
}
$runs = $runs | Sort-Object { [datetime]::Parse($_.startedAt) } -Descending
if ($Id) { $runs = @($runs | Where-Object { $_.id -eq $Id }) }
if ($Active) { $runs = @($runs | Where-Object { $_.status -in @('running', 'launching', 'finalizing') }) }
if ($Since -gt 0) {
$cutoff = (Get-Date).AddDays(-$Since)
$runs = @($runs | Where-Object { [datetime]::Parse($_.startedAt) -ge $cutoff })
}
if ($Latest) { $runs = @($runs | Select-Object -First 1) }
$results = foreach ($run in $runs) {
$alive = $false
if ($run.PSObject.Properties['workerPid'] -and $run.workerPid) {
$alive = Test-LightsOutProcessAlive -ProcessId ([int]$run.workerPid) -StartedAtIso $run.startedAt
}
$runDir = $null
if (Test-Path -LiteralPath $run.repoPath) {
$runDir = Resolve-LightsOutRunDir -RepoPath $run.repoPath -RunId $run.id
}
$endState = $null
if ($runDir) {
$esPath = Join-Path $runDir 'end-state.json'
if (Test-Path -LiteralPath $esPath) {
try { $endState = Get-Content -LiteralPath $esPath -Raw | ConvertFrom-Json } catch { }
}
}
$commits = @()
$diffStat = ''
$branchExists = $false
if ((Test-Path -LiteralPath $run.repoPath) -and $run.baseCommit) {
$branchExists = [bool](git -C $run.repoPath rev-parse --verify --quiet $run.branch 2>$null)
$ref = if ($branchExists) { $run.branch } else { 'HEAD' }
$commits = @(git -C $run.repoPath --no-pager log --oneline "$($run.baseCommit)..$ref" 2>$null)
$diffStat = (git -C $run.repoPath --no-pager diff --shortstat "$($run.baseCommit)..$ref" 2>$null) -join ' '
}
$notesTailText = $null
if ($runDir) {
$np = Join-Path $runDir 'notes.md'
if (Test-Path -LiteralPath $np) {
$notesTailText = (Get-Content -LiteralPath $np -Tail $NotesTail -ErrorAction SilentlyContinue) -join "`n"
}
}
$elapsed = $null
try {
$end = if ($run.PSObject.Properties['endedAt'] -and $run.endedAt) { [datetime]::Parse($run.endedAt) } else { Get-Date }
$elapsed = '{0:h\hm\m}' -f ($end - [datetime]::Parse($run.startedAt))
}
catch { }
$vaultNote = $null
if ($run.PSObject.Properties['vaultNote'] -and $run.vaultNote) { $vaultNote = $run.vaultNote }
else {
$guess = Join-Path (Get-LightsOutVaultFolder -Run $run) 'summary.md'
if (Test-Path -LiteralPath $guess) { $vaultNote = $guess }
}
# A run the registry thinks is live, whose worker process is gone, died without finalizing
# (reboot, forced kill, power loss). Say so rather than reporting it as still working.
$effectiveStatus = $run.status
if ($run.status -in @('running', 'launching', 'finalizing') -and -not $alive) {
$effectiveStatus = 'orphaned'
}
[pscustomobject]@{
id = $run.id
status = $effectiveStatus
recordedStatus = $run.status
workerAlive = $alive
workerPid = if ($run.PSObject.Properties['workerPid']) { $run.workerPid } else { $null }
mode = $run.mode
agent = $run.agent
repoPath = $run.repoPath
branch = $run.branch
branchExists = $branchExists
startedAt = $run.startedAt
endedAt = if ($run.PSObject.Properties['endedAt']) { $run.endedAt } else { $null }
elapsed = $elapsed
gnhfExitCode = if ($run.PSObject.Properties['gnhfExitCode']) { $run.gnhfExitCode } else { $null }
commitCount = $commits.Count
commits = $commits
diffStat = $diffStat
stopWhen = if ($run.PSObject.Properties['stopWhen']) { $run.stopWhen } else { $null }
endState = $endState
verifyCommand = if ($run.PSObject.Properties['verifyCommand']) { $run.verifyCommand } else { $null }
verifyExitCodeBefore = if ($run.PSObject.Properties['verifyExitCodeBefore']) { $run.verifyExitCodeBefore } else { $null }
verifyExitCodeAfter = if ($run.PSObject.Properties['verifyExitCodeAfter']) { $run.verifyExitCodeAfter } else { $null }
runDir = $runDir
gnhfKind = if ($run.PSObject.Properties['gnhfKind']) { $run.gnhfKind } else { $null }
gnhfVersion = if ($run.PSObject.Properties['gnhfVersion']) { $run.gnhfVersion } else { $null }
vaultNote = $vaultNote
notesTail = $notesTailText
prompt = $run.prompt
}
}
if ($Json) {
$arr = @($results)
# NOTE: do not name this $json -- PowerShell variables are case-insensitive, so it would
# assign a string to the [switch]$Json parameter and throw at the call site.
$jsonText = $arr | ConvertTo-Json -Depth 10
if ($arr.Count -eq 1) { "[$jsonText]" } else { $jsonText }
return
}
foreach ($r in $results) {
Write-Host ''
Write-Host "=== $($r.id) ===" -ForegroundColor Cyan
Write-Host " status : $($r.status)$(if ($r.status -eq 'orphaned') { ' <- worker died without finalizing' })"
Write-Host " repo/branch : $($r.repoPath) [$($r.branch)$(if (-not $r.branchExists) { ' MISSING' })]"
Write-Host " agent/mode : $($r.agent) / $($r.mode)"
Write-Host " started : $($r.startedAt) elapsed: $($r.elapsed)"
Write-Host " commits : $($r.commitCount) $($r.diffStat)"
if ($r.stopWhen) { Write-Host " stop-when : $($r.stopWhen)" }
if ($r.endState) { Write-Host " end-state : $($r.endState.status) (iterations=$($r.endState.iterations))" }
if ($r.verifyCommand) { Write-Host " verify : '$($r.verifyCommand)' before=$($r.verifyExitCodeBefore) after=$($r.verifyExitCodeAfter)" }
if ($r.vaultNote) { Write-Host " vault note : $($r.vaultNote)" }
if ($r.runDir) { Write-Host " run dir : $($r.runDir)" }
if ($r.notesTail) {
Write-Host " --- notes tail ---"
$r.notesTail -split "`n" | ForEach-Object { Write-Host " $_" }
}
}
Write-Host ''