[CLAUDE] Scripts: H25-closeout-ritual fold-per-label + batch>=3 INFORM guard (owner S137) — FP W3 tail-adjacency retired; fault-inject 12/12 PASS (9 regression + 3 fold-case); repo TOTAL 46->45, diff = dung 1 FP classified, W1/W2 window giu nguyen

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-07-17 20:34:28 +07:00
parent 467c28e046
commit 7760cdfec0

View File

@ -913,12 +913,15 @@ else {
# log is not opening this session's log. The other three books accept any touch # log is not opening this session's log. The other three books accept any touch
# (STATUS/HANDOFF/diaries are appended, not recreated). # (STATUS/HANDOFF/diaries are appended, not recreated).
# #
# HONEST LIMIT (surfaced, NOT silenced): a tail-close commit whose previous close is # FOLD-PER-LABEL (owner decision S137; was HONEST LIMIT): consecutive closes whose
# its own parent AND the same session batch yields a 1-commit window; that batch's # S-label ranges OVERLAP (batch close 'S131-S132' + tail-supplement 'S132') fold into
# real ritual lives in the excluded lower-bound commit, so the tail reads incomplete # ONE close-group, scored once over the union window that opens at the previous
# = a FALSE POSITIVE. The canonical spec baseline calls for per-session-label folding # group's newest close. This is the per-session-label folding the canonical spec
# of same-batch closes; this build is per-commit as handed. Do NOT special-case it to # baseline (phep-3 union-per-label) called for; it retires the tail-adjacency
# green a report -- classify the flag and let the owner choose the grouping. # false-positive class (W3/S132 - FP verified 3/3 on real git data in S136).
# GUARD (owner-set, same decision): folding must not become a ritual-evasion lane --
# a group spanning >= 3 sessions prints an INFORM line (not a flag) so a batch label
# that swallows many sessions stays visible to the owner.
# #
# git-based, so it honours -RepoRoot (fault-injection runs on a temp git tree). A # git-based, so it honours -RepoRoot (fault-injection runs on a temp git tree). A
# RepoRoot that is not a git work-tree SKIPs with a reason; a probe never crashes. # RepoRoot that is not a git work-tree SKIPs with a reason; a probe never crashes.
@ -941,8 +944,14 @@ if ($gitTree) {
$parts = $ln -split '\|', 2 $parts = $ln -split '\|', 2
if ($parts.Count -lt 2) { continue } if ($parts.Count -lt 2) { continue }
if ($parts[1] -match $CloseoutSubjectRx) { if ($parts[1] -match $CloseoutSubjectRx) {
$lab = if ($parts[1] -match 'S(\d+)') { 'S' + $Matches[1] } else { 'S?' } $lo = $null; $hi = $null; $lab = 'S?'
$closeouts += [pscustomobject]@{ Hash = $parts[0]; Short = $parts[0].Substring(0, 7); Label = $lab } if ($parts[1] -match 'S(\d+)(?:\s*-\s*S(\d+))?') {
$lo = [int]$Matches[1]
$hi = if ($Matches[2]) { [int]$Matches[2] } else { $lo }
if ($hi -lt $lo) { $swp = $lo; $lo = $hi; $hi = $swp }
$lab = if ($hi -ne $lo) { ('S{0}-S{1}' -f $lo, $hi) } else { ('S{0}' -f $lo) }
}
$closeouts += [pscustomobject]@{ Hash = $parts[0]; Short = $parts[0].Substring(0, 7); Label = $lab; Lo = $lo; Hi = $hi }
} }
} }
} }
@ -955,15 +964,40 @@ elseif ($closeouts.Count -eq 0) {
Write-Host ' [skip] no commit matches the closeout subject shape - nothing to score' -ForegroundColor DarkGray Write-Host ' [skip] no commit matches the closeout subject shape - nothing to score' -ForegroundColor DarkGray
} }
else { else {
$take = [Math]::Min(3, $closeouts.Count) # Fold consecutive closes with OVERLAPPING S-label ranges into close-groups
Write-Host (" closeouts found: {0} ; scoring {1} most-recent (union-window per close)" -f $closeouts.Count, $take) # (newest-first order preserved; 'S?' labels never fold). Owner decision S137.
$closeGroups = @()
foreach ($c in $closeouts) {
$joined = $false
if ($closeGroups.Count -gt 0 -and $null -ne $c.Lo) {
$g = $closeGroups[$closeGroups.Count - 1]
if ($null -ne $g.Lo -and ($c.Lo -le $g.Hi) -and ($g.Lo -le $c.Hi)) {
$g.Members += $c
if ($c.Lo -lt $g.Lo) { $g.Lo = $c.Lo }
if ($c.Hi -gt $g.Hi) { $g.Hi = $c.Hi }
$joined = $true
}
}
if (-not $joined) {
$closeGroups += [pscustomobject]@{ Tip = $c; Members = @($c); Lo = $c.Lo; Hi = $c.Hi }
}
}
$take = [Math]::Min(3, $closeGroups.Count)
Write-Host (" closeouts found: {0} in {1} close-group(s) ; scoring {2} most-recent group(s) (label-folded union-window per group)" -f $closeouts.Count, $closeGroups.Count, $take)
for ($i = 0; $i -lt $take; $i++) { for ($i = 0; $i -lt $take; $i++) {
$cur = $closeouts[$i] $gcur = $closeGroups[$i]
if ($i + 1 -ge $closeouts.Count) { $cur = $gcur.Tip
Write-Host (" [skip] {0} {1}: no earlier close to open the window (oldest close in history) - not scored, not flagged" -f $cur.Short, $cur.Label) -ForegroundColor DarkGray $glab = if ($null -eq $gcur.Lo) { 'S?' } elseif ($gcur.Hi -ne $gcur.Lo) { ('S{0}-S{1}' -f $gcur.Lo, $gcur.Hi) } else { ('S{0}' -f $gcur.Lo) }
$span = if ($null -eq $gcur.Lo) { 1 } else { $gcur.Hi - $gcur.Lo + 1 }
if ($span -ge 3) {
Write-Host (" [INFORM] batch-label guard: group {0} folds {1} sessions into one ritual window - a batch label must not become a ritual-evasion lane (threshold >=3, owner-set S137)" -f $glab, $span) -ForegroundColor Yellow
}
if ($i + 1 -ge $closeGroups.Count) {
Write-Host (" [skip] {0} {1}: no earlier close to open the window (oldest close in history) - not scored, not flagged" -f $cur.Short, $glab) -ForegroundColor DarkGray
continue continue
} }
$prev = $closeouts[$i + 1] $prev = $closeGroups[$i + 1].Tip
$range = ("{0}..{1}" -f $prev.Hash, $cur.Hash) $range = ("{0}..{1}" -f $prev.Hash, $cur.Hash)
$union = @() $union = @()
@ -981,10 +1015,10 @@ else {
if (@($union | Where-Object { $_ -match '^\.claude/agent-memory/' }).Count -eq 0) { $missing += '.claude/agent-memory/**' } if (@($union | Where-Object { $_ -match '^\.claude/agent-memory/' }).Count -eq 0) { $missing += '.claude/agent-memory/**' }
if ($missing.Count -eq 0) { if ($missing.Count -eq 0) {
Write-Host (" [ok] {0} {1}: union ({2}..{3}] has all 4 ritual books" -f $cur.Short, $cur.Label, $prev.Short, $cur.Short) -ForegroundColor DarkGray Write-Host (" [ok] {0} {1}: union ({2}..{3}] has all 4 ritual books" -f $cur.Short, $glab, $prev.Short, $cur.Short) -ForegroundColor DarkGray
} }
else { else {
Write-Flag 'MED' ("git:{0} ({1})" -f $cur.Short, $cur.Label) ` Write-Flag 'MED' ("git:{0} ({1})" -f $cur.Short, $glab) `
("closeout-ritual gap: window ({0}..{1}] missing {2} of 4 books -> {3}" -f $prev.Short, $cur.Short, $missing.Count, ($missing -join ', ')) ` ("closeout-ritual gap: window ({0}..{1}] missing {2} of 4 books -> {3}" -f $prev.Short, $cur.Short, $missing.Count, ($missing -join ', ')) `
'the session-close (or its window since the prior close) must touch STATUS + HANDOFF + a NEW session-log + an agent-memory diary' 'the session-close (or its window since the prior close) must touch STATUS + HANDOFF + a NEW session-log + an agent-memory diary'
} }