2 vai W4b SONG NGAY khong can restart (dinh chinh: lead da bao "chi an tu RESTART ke" - SAI). Ca 2 be mat khop: registry song + VALID_ROLES 28 = 28 dia. Spawn-probe that, ca 2 PASS: - tang-3 score-count-auditor: SKIP-CO-KHAI, tool_uses = 0 => fail-closed THAT (khong di tim "ban moi nhat"). Tu choi ca 5 cua thung: glob, tu dem thay, de xuat diem, ghi error-ledger, cham flag_classes. - tang-2 score-counter: KHONG DO DUOC + 4 phep do doc lap chung so thua. 🔴 Tang-2 BAT LOI CUA TANG-1 (lead): lead dem 3 muc (theo DONG) - tang-2 dem 1 muc (theo MUC). Lap luan: luat lay vi du "muc nhac 5 lan tru dung 1, khong phai 4"; ma hoa ca do thanh 5 dong thi dem-dong ra 4 = DUNG con so luat goi la SAI. So 3 cua lead = 4-1, cung dau van tay. 2 defect that da va: - So ma hoa sai don-vi: 1 yeu-cau duoc cap 4 ma. Ma vinh vien + cam xoa dong => chua bang cot MOI 'nhac-lai-cua' tro ve ma goc + luat dem "chi dem dong co cot do TRONG". - nhip-no-probe dem LAN thay vi MUC => in "nhac2+ 3". Nay dem MUC, in kem mau so. Re-fault-inject tren chinh vi du cua luat: 1 muc nhac 5 lan => nhac2+ 1 (khong phai 4). Phan biet chua-co-du-lieu / treo 0 van giu. - Ban dau so thang '**mo**' co dau nhan markdown => treo 0 sai; nay strip. YC-002 giu trang thai MO: plan chua chay het (con W3b/W5b/W6). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
281 lines
14 KiB
PowerShell
281 lines
14 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
nhip-no-probe.ps1 - Harness-25 "no hien thi" 3-part debt line (B1 section 3.3 floor).
|
|
|
|
.DESCRIPTION
|
|
ONE-LINE, READ-ONLY, ZERO-MUTATION debt probe. Called (never inlined) by the
|
|
session command surfaces (/pause, /tiep, session-start, session-end) so a stop
|
|
point always PRINTS the standing debt. Contract:
|
|
(1) NO-API, NO-MUTATION - only reads JSON + measures file bytes + lists dirs.
|
|
(2) exit 0 ALWAYS - a probe MUST NEVER block a stop point. Any exception ->
|
|
prints 'probe-loi (khong chan)' and still exit 0.
|
|
(3) PowerShell 5.1 compatible, ASCII-only script body (gotcha #30): every
|
|
output token is ASCII (NHIP-NO / kiem / light / deep / OVERDUE / over-cap /
|
|
run-chua-gom / CONFIG-THIEU / probe-loi) so a BOM-less .ps1 decoded under the
|
|
system ANSI codepage never mojibakes.
|
|
(4) NO hardcoded cadence/cap - light_every / deep_every / autoinject_cap_bytes are
|
|
READ FROM config keys. A MISSING h24_cadence key prints CONFIG-THIEU(h24_cadence)
|
|
IN-LINE (no assumed default, not swallowed into the generic probe-loi) - keeps
|
|
the no-default signal H24-2 depends on.
|
|
|
|
Output contract - EXACTLY one line:
|
|
NHIP-NO: kiem light a/e deep b/f <ok|OVERDUE:light|deep> | tran-bo-nho x over-cap | run-chua-gom y | pull-cach N ngay
|
|
* kiem = audit cadence: a = counter - last_audit.light_at_counter (light debt),
|
|
e = h24_cadence.light_every ; b/f = deep pair. OVERDUE when a>=e or b>=f.
|
|
* tran-bo-nho = x agent-memory/*/MEMORY.md files whose (Get-Item).Length exceeds
|
|
archive_gate.autoinject_cap_bytes (byte-measured FRESH, NOT the stale
|
|
'measured' snapshot; Get-Content-count is FORBIDDEN - bay E-010/S130).
|
|
* run-chua-gom = y orphan run-folders per the DUAL-ACCEPT rule ported verbatim
|
|
from tiep.md:40-53 (flat *-synthesis.md OR C8 harvest/*-synthesis.md,
|
|
each non-empty; retired form-3 NOT ported).
|
|
* pull-cach = N days since the most recent INBOUND receive-date in
|
|
broadcasts/_index.md (col-1 of rows ABOVE the OUTBOUND header).
|
|
WHY THIS VE EXISTS (S143): the standing instruction was "watch
|
|
broadcasts/inbox" - but inbox only ever holds mail ALREADY pulled,
|
|
so it can NEVER surface un-pulled mail. It stayed silent by design
|
|
while SE waited on a hub reply that had been sitting in the hub
|
|
outbox since 18-07, until the hub had to send a nudge. This ve
|
|
measures the thing that was actually blind.
|
|
THRESHOLD IS DELIBERATELY ABSENT: prints the raw number only.
|
|
If key h24_cadence.pull_warn_days is present it also appends
|
|
OVERDUE:pull - but SE does NOT invent that number (owner's call).
|
|
Precedent for that discipline: session_ctx_kb sat DELIBERATELY
|
|
EMPTY until the owner set it explicitly at S146 - the number was
|
|
never guessed by SE, it was waited for. Same rule applies here.
|
|
Unparseable/absent index -> 'pull-cach n-a' (NEVER kills ve 1-3).
|
|
|
|
.PARAMETER RepoRoot
|
|
Repo root. Default = resolved one level up from this script (scripts/ -> repo root).
|
|
A non-existent RepoRoot is a probe error -> 'probe-loi (khong chan)' + exit 0.
|
|
|
|
.EXAMPLE
|
|
powershell.exe -ExecutionPolicy Bypass -File scripts/nhip-no-probe.ps1
|
|
#>
|
|
param(
|
|
[string]$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Read a file's byte length via Get-Item (FORBIDDEN: Get-Content line/char count -
|
|
# a no-BOM file counted through Get-Content mis-sizes VN text x2-3, bug E-010/S130).
|
|
function Get-ByteLen {
|
|
param([string]$Path)
|
|
return (Get-Item -LiteralPath $Path -ErrorAction Stop).Length
|
|
}
|
|
|
|
try {
|
|
if (-not (Test-Path -LiteralPath $RepoRoot)) {
|
|
throw "RepoRoot not found: $RepoRoot"
|
|
}
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Ve 1 - nhip-kiem (audit cadence debt). Numerators from .session-counter.json,
|
|
# denominators from memory-budget.json h24_cadence (READ, never hardcoded).
|
|
# -----------------------------------------------------------------------
|
|
$counterPath = Join-Path $RepoRoot '.claude\governance\.session-counter.json'
|
|
$budgetPath = Join-Path $RepoRoot '.claude\agent-memory\memory-budget.json'
|
|
|
|
$sc = Get-Content -LiteralPath $counterPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
$budget = Get-Content -LiteralPath $budgetPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
|
|
$cad = $budget.h24_cadence
|
|
if ($null -eq $cad) {
|
|
# h24_cadence key ABSENT -> fail-loud IN-LINE (no default, not probe-loi).
|
|
$kiemSeg = 'CONFIG-THIEU(h24_cadence)'
|
|
}
|
|
elseif ($null -eq $cad.light_every) {
|
|
$kiemSeg = 'CONFIG-THIEU(h24_cadence.light_every)'
|
|
}
|
|
elseif ($null -eq $cad.deep_every) {
|
|
$kiemSeg = 'CONFIG-THIEU(h24_cadence.deep_every)'
|
|
}
|
|
else {
|
|
$counter = [int]$sc.counter
|
|
$lightAt = [int]$sc.last_audit.light_at_counter
|
|
$deepAt = [int]$sc.last_audit.deep_at_counter
|
|
$lightEvery = [int]$cad.light_every
|
|
$deepEvery = [int]$cad.deep_every
|
|
|
|
$aLight = $counter - $lightAt
|
|
$bDeep = $counter - $deepAt
|
|
|
|
$over = @()
|
|
if ($aLight -ge $lightEvery) { $over += 'light' }
|
|
if ($bDeep -ge $deepEvery) { $over += 'deep' }
|
|
$status = if ($over.Count -gt 0) { 'OVERDUE:' + ($over -join ',') } else { 'ok' }
|
|
|
|
$kiemSeg = ("light {0}/{1} deep {2}/{3} {4}" -f $aLight, $lightEvery, $bDeep, $deepEvery, $status)
|
|
}
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Ve 2 - tran-bo-nho (memory ceiling). Byte-measure agent-memory/*/MEMORY.md
|
|
# FRESH vs archive_gate.autoinject_cap_bytes (from key, not hardcoded).
|
|
# -----------------------------------------------------------------------
|
|
$cap = $budget.archive_gate.autoinject_cap_bytes
|
|
if ($null -eq $cap) {
|
|
$tranSeg = 'tran-bo-nho CONFIG-THIEU(autoinject_cap_bytes) over-cap'
|
|
}
|
|
else {
|
|
$capN = [int]$cap
|
|
$overCap = 0
|
|
$memRoot = Join-Path $RepoRoot '.claude\agent-memory'
|
|
if (Test-Path $memRoot) {
|
|
foreach ($mem in (Get-ChildItem -Path $memRoot -Directory -ErrorAction SilentlyContinue)) {
|
|
$mf = Join-Path $mem.FullName 'MEMORY.md'
|
|
if (Test-Path $mf) {
|
|
if ((Get-ByteLen $mf) -gt $capN) { $overCap++ }
|
|
}
|
|
}
|
|
}
|
|
# B1/H3 @S152: ALSO measure archive/_INDEX.md vs tiers.l2_index.cap_bytes.
|
|
# Before this, the probe printed "0 over-cap" while the cicd _INDEX sat at 110.5%
|
|
# of its cap (S152 eval S2) -> an ACTIVE false claim; and cap_bytes had ZERO
|
|
# runtime consumers (H18 ghost-wire class-2). This block is now the consumer.
|
|
$idxOver = 0
|
|
$idxCap = $budget.tiers.l2_index.cap_bytes
|
|
if ($null -eq $idxCap) {
|
|
$tranSeg = ("tran-bo-nho {0} over-cap l2idx CONFIG-THIEU(cap_bytes)" -f $overCap)
|
|
}
|
|
else {
|
|
$idxCapN = [int]$idxCap
|
|
if (Test-Path $memRoot) {
|
|
foreach ($mem in (Get-ChildItem -Path $memRoot -Directory -ErrorAction SilentlyContinue)) {
|
|
$ix = Join-Path $mem.FullName 'archive\_INDEX.md'
|
|
if (Test-Path $ix) {
|
|
if ((Get-ByteLen $ix) -gt $idxCapN) { $idxOver++ }
|
|
}
|
|
}
|
|
}
|
|
$tranSeg = ("tran-bo-nho {0} over-cap l2idx {1} over" -f $overCap, $idxOver)
|
|
}
|
|
}
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Ve 3 - run-chua-gom (orphan runs). DUAL-ACCEPT ported from tiep.md:40-53:
|
|
# form-1 flat <dir>/*-synthesis.md (-s = exists AND non-empty)
|
|
# form-2 C8 <dir>/harvest/*-synthesis.md
|
|
# form-3 (run.md '## synthesis' heading) = RETIRED @S123, NOT ported.
|
|
# -----------------------------------------------------------------------
|
|
$orphan = 0
|
|
$runsDir = Join-Path $RepoRoot '.claude\workflows\runs'
|
|
if (Test-Path $runsDir) {
|
|
foreach ($d in (Get-ChildItem -Path $runsDir -Directory -ErrorAction SilentlyContinue)) {
|
|
$runMd = Join-Path $d.FullName 'run.md'
|
|
if (-not (Test-Path $runMd)) { continue } # no run.md -> not a run -> skip
|
|
$found = $false
|
|
foreach ($f in (Get-ChildItem -Path $d.FullName -Filter '*-synthesis.md' -File -ErrorAction SilentlyContinue)) {
|
|
if ((Get-ByteLen $f.FullName) -gt 0) { $found = $true; break }
|
|
}
|
|
if (-not $found) {
|
|
$harvestDir = Join-Path $d.FullName 'harvest'
|
|
if (Test-Path $harvestDir) {
|
|
foreach ($f in (Get-ChildItem -Path $harvestDir -Filter '*-synthesis.md' -File -ErrorAction SilentlyContinue)) {
|
|
if ((Get-ByteLen $f.FullName) -gt 0) { $found = $true; break }
|
|
}
|
|
}
|
|
}
|
|
if (-not $found) { $orphan++ }
|
|
}
|
|
}
|
|
$runSeg = ("run-chua-gom {0}" -f $orphan)
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Ve 4 - pull-cach (broadcast pull lag). Own try/catch ON PURPOSE: a NEW ve
|
|
# must never be able to blind the 3 ves that already work. Any failure here
|
|
# degrades to 'pull-cach n-a', it does NOT fall through to probe-loi.
|
|
# -----------------------------------------------------------------------
|
|
$pullSeg = 'pull-cach n-a'
|
|
try {
|
|
$idxPath = Join-Path $RepoRoot 'broadcasts\_index.md'
|
|
if (Test-Path -LiteralPath $idxPath) {
|
|
$lines = Get-Content -LiteralPath $idxPath -Encoding UTF8
|
|
# Rows ABOVE the OUTBOUND header are INBOUND. Match on the ASCII token
|
|
# only - the real heading carries an emoji this script must not contain.
|
|
$cut = $lines.Count
|
|
for ($i = 0; $i -lt $lines.Count; $i++) {
|
|
if ($lines[$i] -match '^#{1,6}.*OUTBOUND') { $cut = $i; break }
|
|
}
|
|
$newest = $null
|
|
for ($i = 0; $i -lt $cut; $i++) {
|
|
if ($lines[$i] -match '^\|\s*(\d{4}-\d{2}-\d{2})\s*\|') {
|
|
$d = [datetime]::ParseExact($Matches[1], 'yyyy-MM-dd', $null)
|
|
if ($null -eq $newest -or $d -gt $newest) { $newest = $d }
|
|
}
|
|
}
|
|
if ($null -ne $newest) {
|
|
$days = [int]([datetime]::Now.Date - $newest.Date).TotalDays
|
|
$pullSeg = ("pull-cach {0} ngay" -f $days)
|
|
# Threshold is OPTIONAL and owner-owned. Absent key = stay INFORM,
|
|
# do NOT assume a default (that would be inventing owner's number).
|
|
$warn = $null
|
|
if ($null -ne $cad) { $warn = $cad.pull_warn_days }
|
|
if ($null -ne $warn -and $days -ge [int]$warn) {
|
|
$pullSeg = ("pull-cach {0}/{1} ngay OVERDUE:pull" -f $days, [int]$warn)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
$pullSeg = 'pull-cach n-a'
|
|
}
|
|
|
|
# -----------------------------------------------------------------------
|
|
# (5) SO YEU-CAU CHU DU AN (C4-06 / W4, S181) - hai ve: dang-treo + nhac-tu-lan-2.
|
|
#
|
|
# (!) PHAN BIET HAI THU KHAC NHAU, in HAI CHUOI KHAC NHAU:
|
|
# 'chua-co-du-lieu' = so vang / khong doc duoc / 0 dong YC -> phep do KHONG TON TAI
|
|
# 'treo 0 / nhac2+ 0' = da doc duoc n dong, dem ra bang 0 -> phep do CO, ket qua 0
|
|
# Gop hai cai nay lam mot chinh la 'den xanh gia' ma hub goi ten (A4).
|
|
# (!) Dong khong tach duoc cot thi DEM RIENG va IN RA, khong bo im lang
|
|
# (loi cam 4c 'liet-khong-co' / '[skip] im lang').
|
|
# (!) Cot trang thai mang chu co DAU ('mo' co dau moc). File nay BAT BUOC pure-ASCII
|
|
# (gotcha #30) nen dung CODE-POINT, khong go chu co dau vao day.
|
|
$ycSeg = 'so-yc chua-co-du-lieu'
|
|
try {
|
|
$ycPath = Join-Path $RepoRoot 'docs/governance/so-yeu-cau-chu-du-an.md'
|
|
if (Test-Path -LiteralPath $ycPath) {
|
|
# -Encoding UTF8 BAT BUOC: PS 5.1 mac dinh doc theo codepage ANSI, so do
|
|
# chu co dau trong cot trang thai bi bien dang TRUOC khi so sanh => dem ra 0
|
|
# trong khi so co dong MO that. Da xay ra that o lan cam dau tien (S181).
|
|
$ycLines = Get-Content -LiteralPath $ycPath -Encoding UTF8
|
|
$OPEN = 'm' + [char]0x1EDF # "mo" voi dau moc = trang thai MO cua yeu-cau
|
|
$tot = 0; $treo = 0; $nhac2 = 0; $bad = 0; $dup = 0
|
|
foreach ($L in $ycLines) {
|
|
if ($L -notmatch '^\|\s*`YC-\d+`') { continue }
|
|
$c = $L -split '\|'
|
|
if ($c.Count -lt 9) { $bad++; continue }
|
|
# (!) DEM THEO **MUC**, KHONG THEO **DONG** (va @S181 sau khi vai tang-2 bat loi).
|
|
# Cot cuoi 'nhac-lai-cua' co gia tri => dong nay la LAN NHAC LAI cua mot muc
|
|
# da dem o ma goc => BO QUA. Dem ca no la dem theo LAN, dung don vi luat CAM.
|
|
# Dau van tay cua loi do: ca "nhac 5 lan" ma hoa thanh 5 dong se cho 4 dong
|
|
# count>=2 - dung con so ma luat goi la SAI.
|
|
if (($c[8] -replace '[*` ]','') -ne '') { $dup++; continue }
|
|
$tot++
|
|
# (!) Strip dau nhan markdown truoc khi so: o bang hay duoc viet **mo** cho noi bat.
|
|
# Ban dau so thang chuoi => '**mo**' truot => in 'treo 0' trong khi so co muc MO.
|
|
# Da xay ra that ngay luot cam dau tien (S181).
|
|
if (($c[4] -replace '[*` ]','') -eq $OPEN) { $treo++ }
|
|
$m = [regex]::Match($c[5], '\d+')
|
|
if ($m.Success -and [int]$m.Value -ge 2) { $nhac2++ }
|
|
}
|
|
if ($tot -gt 0) {
|
|
# in ca MAU SO muc + so dong nhac-lai da gop, de nguoi doc kiem duoc don vi
|
|
$ycSeg = ("so-yc treo {0} / nhac2+ {1} (muc {2}, gop {3} dong nhac-lai)" -f $treo, $nhac2, $tot, $dup)
|
|
if ($bad -gt 0) { $ycSeg += (" / {0} dong KHONG TACH DUOC COT" -f $bad) }
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
$ycSeg = 'so-yc chua-co-du-lieu'
|
|
}
|
|
|
|
Write-Host ("NHIP-NO: kiem {0} | {1} | {2} | {3} | {4}" -f $kiemSeg, $tranSeg, $runSeg, $pullSeg, $ycSeg)
|
|
}
|
|
catch {
|
|
# A probe NEVER blocks a stop point. Any failure prints one generic line.
|
|
Write-Host 'probe-loi (khong chan)'
|
|
}
|
|
|
|
exit 0
|