# artifact-integrity.ps1 - MAY DIEM DANH VAT CHUNG (run-folder), do NGHIA khong chi do TON TAI
#
# San thi hanh: broadcasts/inbox/ai_infra/2026-08-04-Governance-upgrade-pack-phased-phu-luc-spec-pitfall.md
#               section GD-2 (san (i)-(v) + 4 bay + 6 o nghiem thu)
# Thiet ke  : runs/2026-08-07-S180-adap-upgrade-pack-phased/sub-n3-lane-b-gd2.md (13 khoan B-01..B-13, 4 vi tu V-1..V-4)
# Ke hoach  : runs/2026-08-07-S180-adap-upgrade-pack-phased/wave-plan-S180.md (W2)
# Khuon may : scripts/naming-scan.ps1 (W1) - giu cung ky luat: pure-ASCII, INFORM-only, luon in mau so.
#
# HOP DONG CUA MAY NAY - doc truoc khi sua:
#
#  (1) INFORM-only. LUON exit 0, ke ca khi co co. Lai ma thoat = wave W3b,
#      sau khi chu du an chot cau P1 (da chot PA-2). KHONG tu lai ma thoat o day.
#
#  (2) VI SAO MAY NAY TON TAI - ca song, khong phai gia thuyet:
#      S180 co mot vai ha canh artifact 7.049 B voi 6/10 heading con nhan treo
#      sau 202K token. Chay `nhip-no-probe` len dung thu muc do => `run-chua-gom 0`,
#      exit 0, SACH. Control-duong (giau *-synthesis.md => 1, tra lai => 0) xac nhan
#      thuoc SONG => so 0 kia la MU THAT.
#      GOC: moi vi tu dang co deu do KICH THUOC; thu hong la TI LE KHUNG/RUOT.
#      Hai dai luong nay KHONG tuong quan - mot tep toan heading tang byte y het
#      mot tep day noi dung.
#
#  (3) 4 VI TU cua hub  ->  4 vi tu cai o day:
#        VANG          -> V-3 (diem danh 2 nguon: ten neu trong run.md ma vang tren dia)
#        RONG          -> V-1 nhanh 0-byte (KHONG duoc roi vao 'khong ap dung')
#        CUT           -> V-2 (nhan treo neo HEADING) chinh + V-1 (ti le ruot/khung) phu
#        NEN-QUA-TAY   -> V-4 (so ky tu voi ban truoc CUNG DON VI, lay tu git)
#
#  (4) LUON IN MAU SO canh moi con so. Phien S180 da 8 ca bay don-vi.
#      Va luon in "dem CAI GI": tep / thu muc / muc / dong.
#
#  (5) TAP VANG MAT != SACH (chong Goodhart). Neu thu muc goc vang, hoac mot
#      luot chay khong con vat nao, may in co THIEU-TAP RIENG canh so 0.
#      So 0 khong duoc phep doc thanh 'sach' khi chua co gi de dem.
#
#  (6) Pure ASCII (gotcha #30). Nhan treo tieng Viet duoc dung bang MA DIEM
#      (xem $TAG_*) chu khong go thang - de tep nay giu 0 byte ngoai ASCII.
#
#  (7) KHONG SUA GI. May chi doc va in. Che do -BuildIndex la ngoai le duy nhat:
#      no GHI DE mot tep duy nhat (.claude/workflows/runs/_index.md) va tep do
#      la DERIVE-VIEW sinh tu dia - cam sua tay, cam dung lam nguon.
#
# Fault-inject: chay voi -RepoRoot <cay-tam> de cay artifact hong / go ra. Khong dung kho that.

[CmdletBinding()]
param(
    [string]$RepoRoot,
    [string]$RunId,          # chi soi 1 thu muc luot chay. Vang => soi TAT CA.
    [switch]$V4All,          # bat V-4 cho moi tep (moi tep ton ~1-2 lenh git). Mac dinh chi bat khi co -RunId.
    [switch]$BuildIndex,     # sinh lai muc luc derive-view _index.md tu dia
    [double]$K = 3.00        # nguong V-1. Mac dinh = phan vi 5 cua ho sub-*, do 2026-08-07, mau so 446.
)

$ErrorActionPreference = 'Stop'

if (-not $RepoRoot -or $RepoRoot -eq '') { $RepoRoot = Split-Path -Parent $PSScriptRoot }
$RepoRoot = (Resolve-Path -LiteralPath $RepoRoot).Path
$RunsRel  = '.claude/workflows/runs'
$RunsRoot = Join-Path $RepoRoot $RunsRel

# ---------------------------------------------------------------------------
# Nhan treo dung bang MA DIEM de giu tep pure-ASCII (luat 6).
#   0x0110 = D co gach ngang (chu HOA)  -> dung trong "DANG DO"
#   0x1EDC = O co sung + huyen (chu HOA) -> dung trong "CHO"
# ---------------------------------------------------------------------------
$chDbar = [string][char]0x0110
$chOhg  = [string][char]0x1EDC
$TAG_DANGDO = $chDbar + 'ANG ' + $chDbar + 'O'
$TAG_CHO    = 'CH' + $chOhg
$TAGSET     = @($TAG_DANGDO, $TAG_CHO, 'TODO', 'PENDING') -join '|'

# Neo vao HEADING la chu y trung tam cua V-2: tach DUNG (nhan dang treo)
# khoi NHAC DEN (cau van dinh nghia nhan). Dem tho cho duong-gia tren chinh
# ban da xong - do 2026-08-07: tho=1, neo-heading=0. Lop citation-trap.
$RX_PLACEHOLDER_HEAD = '^#{1,6} .*\[(' + $TAGSET + ')'
$RX_PLACEHOLDER_RAW  = '\[(' + $TAGSET + ')'

$RX_HEAD    = '^#{1,6} '
$RX_FENCE   = '^\s*```'
$RX_SUBFAM  = '^(sub-.+|.+-return)\.md$'       # cung ho voi governance-detectors.ps1:1102 / :1771
$RX_SYNTH   = '.+-synthesis\.md$'
# Ten tep artifact duoc NHAC trong run.md. Mau ky tu CO Y khong chua '<' '>'
# => khuon minh hoa dang `sub-<role>-<i>.md` KHONG bi bat (do 2026-08-07: 0 hit).
$RX_NAMEREF = '(sub-[A-Za-z0-9._-]+\.md|[A-Za-z0-9._-]+-synthesis\.md)'

# ---------------------------------------------------------------------------
# So ke. Co (FLAG) va THIEU-TAP dem TACH NHAU - luat 5.
# ---------------------------------------------------------------------------
$script:Flags       = @()   # {Kind, Run, Name, Msg}
$script:MissingSets = @()   # {Run, Msg}
$script:NFolder = 0; $script:NFile = 0; $script:NSkipV1 = 0
$script:NDat = 0   # so thu muc luot DAT (ve-6 P7, W5b/S181)
$script:NV4Measured = 0; $script:NV4Unmeasurable = 0
$script:NOutOfShape = @()
$script:NKhongKhai = 0; $script:NTroCheo = 0
# Tap ten MOI tep .md tren toan cay runs/ - de phan giai con tro CHEO giua cac
# luot chay (xem V-3). Dung 1 lan, khong quet lai moi thu muc.
$script:AllNamesInRuns = @{}

function Write-Head([string]$t) { Write-Host ''; Write-Host $t -ForegroundColor Cyan }
function Add-Flag([string]$Kind, [string]$Run, [string]$Name, [string]$Msg) {
    $script:Flags += [pscustomobject]@{ Kind = $Kind; Run = $Run; Name = $Name; Msg = $Msg }
}
function Add-Missing([string]$Run, [string]$Msg) {
    $script:MissingSets += [pscustomobject]@{ Run = $Run; Msg = $Msg }
}

# ---------------------------------------------------------------------------
# Do 1 tep. Dinh nghia "dem CAI GI" - khai o day mot lan, dung suot:
#   head = dong khop '^#{1,6} ' VA KHONG nam trong khoi ma (``` toggle).
#          Khong loai khoi ma thi '# comment' trong bash bi dem la heading
#          => tep nhieu ma bi danh oan.
#   body = moi dong KHONG RONG con lai. Dong bang '|', dong trich '>', va dong
#          trong khoi ma DEU TINH LA RUOT. (Ban nhap lane B loai '^\|' khoi tu
#          so - do la sai, lane B tu sua o section 3.)
# ---------------------------------------------------------------------------
function Measure-Artifact {
    param([System.IO.FileInfo]$File)

    $bytes = $File.Length
    if ($bytes -eq 0) {
        return [pscustomobject]@{ Bytes = 0; Head = 0; Body = 0; Ratio = -1; Ph = 0; PhRaw = 0; Chars = 0; Items = 0 }
    }
    $text  = [System.IO.File]::ReadAllText($File.FullName, [System.Text.Encoding]::UTF8)
    $lines = $text -split "`r?`n"

    $inFence = $false; $head = 0; $body = 0; $ph = 0; $phRaw = 0; $items = 0
    foreach ($ln in $lines) {
        if ($ln -match $RX_FENCE) { $inFence = -not $inFence; $body++; continue }
        if ($inFence) { if ($ln.Trim() -ne '') { $body++ }; continue }
        if ($ln -match $RX_HEAD) {
            $head++
            if ($ln -match $RX_PLACEHOLDER_HEAD) { $ph++ }
            if ($ln -match $RX_PLACEHOLDER_RAW)  { $phRaw++ }
            continue
        }
        if ($ln -match $RX_PLACEHOLDER_RAW) { $phRaw++ }
        if ($ln -match '^\s*[-*] ' -or $ln -match '^\s*\|') { $items++ }
        if ($ln.Trim() -ne '') { $body++ }
    }
    $ratio = if ($head -gt 0) { [math]::Round($body / $head, 2) } else { -1 }
    return [pscustomobject]@{
        Bytes = $bytes; Head = $head; Body = $body; Ratio = $ratio
        Ph = $ph; PhRaw = $phRaw; Chars = $text.Length; Items = $items
    }
}

# ---------------------------------------------------------------------------
# V-4 - nen qua tay. So ky tu voi BAN TRUOC CUNG DON VI.
# KHONG dung HEAD~1: hook `wal:` chen commit vao giua => HEAD~1 thuong KHONG
# phai ban truoc CUA TEP NAY, va phep so se la 'so ban moi voi chinh no'
# (giong het mot phep do hop le). Dung git log CUA CHINH TEP.
# Khong du du lieu => KHONG DO DUOC (dung chu hub), khong doan.
# ---------------------------------------------------------------------------
function Test-Compression {
    param([string]$RelPath, [int]$NowChars, [int]$NowItems, [string]$FullPath)

    $shas = & git -C $RepoRoot log --format=%H -2 -- $RelPath 2>$null
    if ($LASTEXITCODE -ne 0 -or -not $shas) {
        return [pscustomobject]@{ Ok = $false; Why = 'tep chua tracked / khong co lich su git' }
    }
    $shas = @($shas)
    if ($shas.Count -lt 2) {
        return [pscustomobject]@{ Ok = $false; Why = ('chi co {0} commit cham tep nay - chua co ban truoc CUNG DON VI de so' -f $shas.Count) }
    }
    $prev = & git -C $RepoRoot show ("{0}:{1}" -f $shas[1], $RelPath) 2>$null
    if ($LASTEXITCODE -ne 0) {
        return [pscustomobject]@{ Ok = $false; Why = 'khong doc duoc ban truoc tu git' }
    }
    $prevText  = ($prev -join "`n")
    $prevChars = $prevText.Length
    $prevItems = @($prevText -split "`n" | Where-Object { $_ -match '^\s*[-*] ' -or $_ -match '^\s*\|' }).Count
    if ($prevChars -eq 0) {
        return [pscustomobject]@{ Ok = $false; Why = 'ban truoc rong - ti le vo nghia' }
    }
    $r = [math]::Round($NowChars / [double]$prevChars, 3)
    return [pscustomobject]@{
        Ok = $true; Ratio = $r; PrevChars = $prevChars; PrevItems = $prevItems
        PrevSha = $shas[1].Substring(0, 7)
    }
}

# ---------------------------------------------------------------------------
# Soi 1 thu muc luot chay.
# ---------------------------------------------------------------------------
function Scan-Run {
    param([System.IO.DirectoryInfo]$Dir, [switch]$DoV4)

    $run = $Dir.Name
    $script:NFolder++

    $allMd = @(Get-ChildItem -LiteralPath $Dir.FullName -Recurse -File -Filter '*.md' -ErrorAction SilentlyContinue)
    $flat  = @($allMd | Where-Object { $_.Directory.FullName -eq $Dir.FullName })
    # C8 dual-accept: 5 thu muc cu giu 'sub-md/' + 'harvest/'. Khong tinh chung
    # la 'ngoai cau truc' - lam the la de 5 luot chay hop le keu oan ngay ngay dau.
    $c8    = @($allMd | Where-Object {
                 $p = $_.Directory.Name
                 ($p -eq 'harvest' -or $p -eq 'sub-md') -and ($_.Directory.Parent.FullName -eq $Dir.FullName) })
    $arts  = @($flat + $c8)
    $other = @($allMd | Where-Object { $arts -notcontains $_ })
    foreach ($o in $other) {
        $rel = $o.FullName.Substring($Dir.FullName.Length + 1) -replace '\\', '/'
        $script:NOutOfShape += ("{0}/{1}" -f $run, $rel)
    }

    # --- THIEU-TAP (luat 5 / chieu A2 fault-inject) --------------------------
    if ($arts.Count -eq 0) {
        Add-Missing $run 'thu muc luot chay KHONG CO vat .md nao - phep do khong ton tai, khong phai "sach"'
        Write-Host ("  [{0}] FLAG THIEU-TAP: 0 vat .md" -f $run) -ForegroundColor Red
        return
    }
    # --- VE-6 (P7, W5b/S181): LUOT DAT thi THIEU-TEP = MUC NGHIEM TRONG CAO NHAT ---
    # Vi sao nang muc: mot luot chay dat KHONG TAI-LAP-DUOC bang cach chay lai cho re.
    # Mat mot vat chung o luot thuong = ton cong chay lai; mat o luot dat = mat HAN,
    # vi khong ai bo tien chay lai lan hai chi de co lai cai tep. Cung mot hanh vi
    # thieu tep, hai cai gia khac han nhau => hai muc nghiem trong khac nhau.
    # Nhan dien luot dat = dau engine trong BAT KY vat .md nao cua thu muc.
    $isDat = $false
    foreach ($a in $arts) {
        $txt = Get-Content -LiteralPath $a.FullName -Raw -Encoding UTF8 -ErrorAction SilentlyContinue
        if ($txt -and ($txt -match 'fable-real|fable-clone|\[engine:')) { $isDat = $true; break }
    }
    $kindVang = if ($isDat) { 'VANG-DAT' } else { 'VANG' }
    if ($isDat) { $script:NDat++ }

    $runMd = $arts | Where-Object { $_.Name -eq 'run.md' } | Select-Object -First 1
    if (-not $runMd) {
        Add-Flag $kindVang $run 'run.md' 'thu muc luot chay khong co run.md - mat NGUON-2 cua diem danh 2 nguon (V-3 khong do duoc o day)'
    }
    $synth = @($arts | Where-Object { $_.Name -match $RX_SYNTH -and $_.Length -gt 0 })
    if ($synth.Count -eq 0 -and $runMd) {
        Add-Flag $kindVang $run '*-synthesis.md' 'khong co ban gom non-empty (dual-accept flat + harvest/) - cung tieu chi voi nhip-no-probe run-chua-gom'
    }

    # --- V-1 / V-2 tren tung vat ---------------------------------------------
    $rows = @()
    foreach ($f in $arts) {
        $script:NFile++
        $m = Measure-Artifact -File $f
        $isSub = ($f.Name -match $RX_SUBFAM)

        if ($m.Bytes -eq 0) {
            Add-Flag 'RONG' $run $f.Name 'tep 0 byte'
            $rows += [pscustomobject]@{ N = $f.Name; V = 'RONG'; D = '0 B' }
            continue
        }
        # V-2 - nhan treo neo HEADING (vi tu chinh cho CUT)
        if ($m.Ph -gt 0) {
            Add-Flag 'CUT' $run $f.Name ('V-2: {0}/{1} heading con nhan treo (mau so = so heading cua chinh tep nay)' -f $m.Ph, $m.Head)
            $rows += [pscustomobject]@{ N = $f.Name; V = 'CUT(V-2)'; D = ('{0}/{1} heading treo' -f $m.Ph, $m.Head) }
        }
        # V-1 - ti le ruot/khung (luoi PHU, chi ap ho sub-*/-return)
        if ($isSub) {
            if ($m.Head -eq 0) {
                $script:NSkipV1++
                $rows += [pscustomobject]@{ N = $f.Name; V = 'V1-KHONG-AP-DUNG'; D = ('0 heading, {0} B - khong chia duoc, KHONG doc thanh sach' -f $m.Bytes) }
            }
            elseif ($m.Ratio -lt $K) {
                Add-Flag 'CUT' $run $f.Name ('V-1: ruot/khung {0} < K={1} (body {2} dong / head {3} dong)' -f $m.Ratio, $K, $m.Body, $m.Head)
                if ($m.Ph -eq 0) { $rows += [pscustomobject]@{ N = $f.Name; V = 'CUT(V-1)'; D = ('ti le {0} < {1}' -f $m.Ratio, $K) } }
            }
        }
        # V-4 - nen qua tay
        if ($DoV4) {
            $rel = $f.FullName.Substring($RepoRoot.Length + 1) -replace '\\', '/'
            $c = Test-Compression -RelPath $rel -NowChars $m.Chars -NowItems $m.Items -FullPath $f.FullName
            if (-not $c.Ok) {
                $script:NV4Unmeasurable++
            } else {
                $script:NV4Measured++
                if ($c.Ratio -lt 0.70 -and $m.Items -lt $c.PrevItems) {
                    $txt = [System.IO.File]::ReadAllText($f.FullName, [System.Text.Encoding]::UTF8)
                    $mien = ($txt -match 'archive/' -or $txt -match 'con-tro' -or $txt -match 'moved-not-cut' -or $txt -match 'doi verbatim')
                    if ($mien) {
                        $rows += [pscustomobject]@{ N = $f.Name; V = 'NEN-MIEN'; D = ('{0}x so voi {1}, NHUNG co khai noi-di (mien tru HIEN HINH)' -f $c.Ratio, $c.PrevSha) }
                    } else {
                        Add-Flag 'NEN' $run $f.Name ('V-4: con {0}x so ky tu so voi {1} ({2} -> {3} ky tu) VA so muc giam {4} -> {5}, KHONG thay dong khai noi-di' -f $c.Ratio, $c.PrevSha, $c.PrevChars, $m.Chars, $c.PrevItems, $m.Items)
                    }
                }
            }
        }
    }

    # --- V-3 - diem danh HAI NGUON (dia  <->  run.md ghi TRUOC launch) -------
    $v3 = 'KHONG DO DUOC'
    if ($runMd) {
        $runTxt = [System.IO.File]::ReadAllText($runMd.FullName, [System.Text.Encoding]::UTF8)
        $named = @([regex]::Matches($runTxt, $RX_NAMEREF) | ForEach-Object { $_.Value } | Sort-Object -Unique)
        $onDisk = @($arts | ForEach-Object { $_.Name } | Sort-Object -Unique)
        if ($named.Count -eq 0) {
            $v3 = 'KHONG DO DUOC'
            Add-Missing $run 'V-3: run.md KHONG neu ten tep artifact nao => NGUON-2 rong. Day KHONG phai "chenh 0".'
        } else {
            $missOnDisk = @($named  | Where-Object { $onDisk -notcontains $_ })
            $notDeclared= @($onDisk | Where-Object { $named  -notcontains $_ -and $_ -ne 'run.md' })
            # Ten khong co trong thu muc NAY co the la con tro CHEO sang luot chay
            # TRUOC - runs/README.md:39 (C2 buoc 3) BAT run.md tro 'input spec:' sang
            # synthesis cua luot truoc. Tep co that, nam thu muc khac. So trong MOT thu
            # muc roi keu 'vang' la loi cua MAY, khong phai no cua kho.
            $crossRef = @(); $reallyMissing = @()
            foreach ($x in $missOnDisk) {
                if ($script:AllNamesInRuns.ContainsKey($x)) { $crossRef += $x } else { $reallyMissing += $x }
            }
            $v3 = ('nguon-2 neu {0} ten | thieu-tren-dia {1} | tro-cheo {2} | khong-khai {3}' -f $named.Count, $reallyMissing.Count, $crossRef.Count, $notDeclared.Count)
            # ve-6: V-3 cung nang muc o luot dat - cung ly do, cung mot lop mat mat.
            foreach ($x in $reallyMissing) { Add-Flag $kindVang $run $x 'V-3: run.md co neu ten nay, va KHONG TIM THAY o bat ky luot chay nao' }
            # KHONG-KHAI: dem RIENG, KHONG phai co. Chua he co luat nao bat run.md
            # neu ten tep => 245/720 co cho mot luat khong ton tai = duong-gia ngay dau.
            # Nhung con SO thi giu, vi no chung minh NGUON-2 mong den muc nao.
            $script:NKhongKhai += $notDeclared.Count
            $script:NTroCheo   += $crossRef.Count
        }
    }

    # --- in per-run ----------------------------------------------------------
    $bad = @($rows).Count
    $color = if ($bad -gt 0) { 'Yellow' } else { 'DarkGray' }
    Write-Host ("  [{0}]" -f $run) -ForegroundColor $color
    Write-Host ("     mau so: {0} vat .md (phang {1} + C8 harvest|sub-md {2}) | V-3: {3}" -f $arts.Count, $flat.Count, $c8.Count, $v3)
    foreach ($r in $rows) {
        $c = if ($r.V -like 'CUT*' -or $r.V -eq 'RONG') { 'Red' } else { 'DarkGray' }
        Write-Host ("     [{0,-16}] {1}  <- {2}" -f $r.V, $r.N, $r.D) -ForegroundColor $c
    }
}

# ---------------------------------------------------------------------------
# -BuildIndex : sinh muc luc DERIVE-VIEW tu dia.
# Vi sao derive-view chu khong phai so chep tay: so chep tay se thanh NGUON-DOI
# ngay khi ai do quen mot dong - va do dung cach `_ledger.md` da chet (15 dong,
# toan 2026-06-18, trong khi dia da di toi 2026-08-07).
# ---------------------------------------------------------------------------
function Build-Index {
    if (-not (Test-Path -LiteralPath $RunsRoot)) {
        Write-Host '  FLAG THIEU-TAP: khong co thu muc runs/ - khong sinh duoc muc luc.' -ForegroundColor Red
        return
    }
    $dirs = @(Get-ChildItem -LiteralPath $RunsRoot -Directory | Sort-Object Name)
    $sb = New-Object System.Text.StringBuilder

    $null = $sb.AppendLine('# `runs/_index.md` - MUC LUC SONG (DERIVE-VIEW, sinh tu dia)')
    $null = $sb.AppendLine('')
    $null = $sb.AppendLine('> **CAM SUA TAY. CAM DUNG LAM NGUON.** Tep nay duoc SINH LAI tron ven bang')
    $null = $sb.AppendLine('> `powershell -File scripts/artifact-integrity.ps1 -BuildIndex`. Moi dong deu doc thang tu dia.')
    $null = $sb.AppendLine('> Sua tay o day = de ra nguon-doi, dung benh da giet `_ledger.md` (so chep tay, RETIRED H18-B S100:')
    $null = $sb.AppendLine('> 15 dong, toan 2026-06-18, trong khi dia da di toi hom nay).')
    $null = $sb.AppendLine('>')
    $null = $sb.AppendLine('> **Tang-A (goi theo loai) = `README.md` canh ben** - chuc nang, ai ghi, ai doc, bo tep chuan.')
    $null = $sb.AppendLine('> **Tang-B (muc luc song) = tep nay.** Hai tang, khong tang nao chep tang kia.')
    $null = $sb.AppendLine('>')
    $null = $sb.AppendLine('> [!] **Tep nay KHONG duoc dung lam nguon-2 cua diem danh 2 nguon** - no doc thang dia,')
    $null = $sb.AppendLine('> tuc no CHINH LA nguon-1. Nguon-2 la anh chup taskList trong tung `run.md` (ghi TRUOC launch).')
    $null = $sb.AppendLine('')
    $null = $sb.AppendLine(('- **Sinh luc:** {0}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm')))
    $null = $sb.AppendLine(('- **Mau so:** {0} thu muc luot chay (dem THU MUC, khong dem entry - `ls` con thay ca tep README/_ledger/_index)' -f $dirs.Count))
    $null = $sb.AppendLine('')
    $null = $sb.AppendLine('| luot chay | run.md | vat .md | ban gom | co V-2 (nhan treo) | byte |')
    $null = $sb.AppendLine('|---|---|---|---|---|---|')

    foreach ($d in $dirs) {
        $md = @(Get-ChildItem -LiteralPath $d.FullName -Recurse -File -Filter '*.md' -ErrorAction SilentlyContinue)
        $hasRun = if ($md | Where-Object { $_.Name -eq 'run.md' -and $_.Directory.FullName -eq $d.FullName }) { 'co' } else { '**VANG**' }
        $syn = @($md | Where-Object { $_.Name -match $RX_SYNTH -and $_.Length -gt 0 })
        $hasSyn = if ($syn.Count -gt 0) { 'co' } else { '**VANG**' }
        $ph = 0
        foreach ($f in $md) {
            if ($f.Length -eq 0) { continue }
            $t = [System.IO.File]::ReadAllText($f.FullName, [System.Text.Encoding]::UTF8)
            foreach ($ln in ($t -split "`r?`n")) { if ($ln -match $RX_PLACEHOLDER_HEAD) { $ph++ } }
        }
        $phTxt = if ($ph -gt 0) { ('**{0}**' -f $ph) } else { '0' }
        $bytes = ($md | Measure-Object -Property Length -Sum).Sum
        $null = $sb.AppendLine(('| `{0}` | {1} | {2} | {3} | {4} | {5} |' -f $d.Name, $hasRun, $md.Count, $hasSyn, $phTxt, $bytes))
    }

    $out = Join-Path $RunsRoot '_index.md'
    [System.IO.File]::WriteAllText($out, $sb.ToString(), (New-Object System.Text.UTF8Encoding($false)))
    Write-Host ("  Da sinh: {0}/_index.md  ({1} thu muc luot chay)" -f $RunsRel, $dirs.Count) -ForegroundColor Green
}

# ===========================================================================
# MAIN
# ===========================================================================
Write-Host '=== artifact-integrity.ps1 - MAY DIEM DANH VAT CHUNG ===' -ForegroundColor White
Write-Host ("RepoRoot : {0}" -f $RepoRoot)
Write-Host  "Che do   : INFORM-only. LUON exit 0 ke ca khi co co (lai ma thoat = W3b, sau P1=PA-2)."
Write-Host  "Vi tu    : V-1 ti le ruot/khung | V-2 nhan treo neo HEADING | V-3 diem danh 2 nguon | V-4 nen qua tay"
Write-Host ("Nguong   : K={0} (V-1) = phan vi 5 cua ho sub-*, do 2026-08-07, mau so 446 tep co heading." -f $K)
Write-Host  "           Tai K nay, 20/446 tep lich su (4,5%) cung nam duoi nguong => co KHONG doc thanh 'hong'."

if ($BuildIndex) {
    Write-Head '--- SINH MUC LUC DERIVE-VIEW ---'
    Build-Index
    Write-Host ''
    Write-Host '  Ma thoat: 0 (INFORM-only theo hop dong muc 1).'
    exit 0
}

if (-not (Test-Path -LiteralPath $RunsRoot)) {
    Write-Head '--- DIEM DANH ---'
    Write-Host ("  FLAG THIEU-TAP: khong tim thay '{0}'." -f $RunsRel) -ForegroundColor Red
    Write-Host  "  Day KHONG phai [skip]. Tap vang mat => phep do KHONG TON TAI, va so co 0 ben duoi VO NGHIA." -ForegroundColor Red
    Add-Missing '(goc)' 'thu muc runs/ vang mat'
    $dirs = @()
} elseif ($RunId) {
    $one = Join-Path $RunsRoot $RunId
    if (-not (Test-Path -LiteralPath $one)) {
        Write-Head '--- DIEM DANH ---'
        Write-Host ("  FLAG THIEU-TAP: khong co luot chay '{0}'." -f $RunId) -ForegroundColor Red
        Add-Missing $RunId 'thu muc luot chay duoc chi dinh nhung khong ton tai'
        $dirs = @()
    } else { $dirs = @(Get-Item -LiteralPath $one) }
} else {
    $dirs = @(Get-ChildItem -LiteralPath $RunsRoot -Directory | Sort-Object Name)
}

if (Test-Path -LiteralPath $RunsRoot) {
    foreach ($f in (Get-ChildItem -LiteralPath $RunsRoot -Recurse -File -Filter '*.md' -ErrorAction SilentlyContinue)) {
        $script:AllNamesInRuns[$f.Name] = $true
    }
}

$doV4 = ($RunId -and -not $V4All) -or $V4All
Write-Head ("--- DIEM DANH: {0} thu muc luot chay ---" -f $dirs.Count)
if (-not $doV4) {
    Write-Host  "  V-4 (nen qua tay): KHONG DO DUOC o che do quet-toan-bo - moi tep ton 1-2 lenh git." -ForegroundColor DarkGray
    Write-Host  "  Bat bang -RunId <ten> (1 luot chay) hoac -V4All (chap nhan cham). KHONG phai 'da do va sach'." -ForegroundColor DarkGray
}
foreach ($d in $dirs) { Scan-Run -Dir $d -DoV4:$doV4 }

# ---------------------------------------------------------------------------
Write-Head '=== TONG ==='
Write-Host ("  mau so : {0} thu muc luot chay | {1} vat .md da do" -f $script:NFolder, $script:NFile)
# ve-6 (P7, W5b/S181): luon in mau so luot DAT, ke ca khi = 0. Khong in thi
# 'khong co luot dat nao' va 'co luot dat nhung khong ai nhan dien' nhin y het nhau.
$datVang = @($script:Flags | Where-Object { $_.Kind -eq 'VANG-DAT' }).Count
Write-Host ("  luot DAT: {0}/{1} thu muc | co VANG-DAT (muc CAO NHAT): {2}" -f $script:NDat, $script:NFolder, $datVang) -ForegroundColor $(if ($datVang -gt 0) { 'Red' } else { 'Gray' })
if ($datVang -gt 0) {
    Write-Host  "  [!] VANG-DAT = thieu vat chung o LUOT DAT. Luot dat KHONG tai-lap-duoc bang cach chay lai cho re" -ForegroundColor Red
    Write-Host  "      => mat o day la mat HAN, khac han mat o luot thuong (chi ton cong chay lai)." -ForegroundColor Red
}

$byKind = $script:Flags | Group-Object Kind | Sort-Object Name
if ($script:Flags.Count -eq 0) {
    Write-Host ("  CO     : 0/{0} vat" -f $script:NFile) -ForegroundColor Green
    Write-Host  "  [!] 0 co CHI co nghia khi mau so tren khac 0 VA so THIEU-TAP ben duoi = 0." -ForegroundColor Yellow
} else {
    Write-Host ("  CO     : {0} (tren {1} vat)" -f $script:Flags.Count, $script:NFile) -ForegroundColor Red
    foreach ($g in $byKind) { Write-Host ("     {0,-11} : {1}" -f $g.Name, $g.Count) -ForegroundColor Red }
}

# THIEU-TAP in RIENG, canh so co - de so 0 mat quyen doc thanh 'sach' (luat 5).
if ($script:MissingSets.Count -gt 0) {
    Write-Host ("  THIEU-TAP : {0}  <- dem TACH khoi so co tren. Moi tap vang lam mot phep do BIEN MAT." -f $script:MissingSets.Count) -ForegroundColor Red
    foreach ($m in $script:MissingSets) { Write-Host ("     - [{0}] {1}" -f $m.Run, $m.Msg) -ForegroundColor Red }
} else {
    Write-Host  "  THIEU-TAP : 0"
}

Write-Host ("  V-1 khong ap dung : {0}/{1} vat (0 heading => khong chia duoc; KHONG phai 'sach')" -f $script:NSkipV1, $script:NFile)
# Hai hang muc DEM RIENG, KHONG phai co - va KHONG duoc giau di. Giau con so nay
# la giau chinh bang chung "nguon-2 mong".
Write-Host ("  KHONG-KHAI        : {0}/{1} vat co tren dia ma run.md khong neu ten." -f $script:NKhongKhai, $script:NFile)
Write-Host  "                      DEM RIENG, KHONG phai co: chua he co luat bat run.md neu ten tep."
Write-Host  "                      Day la thuoc do do MONG cua NGUON-2, khong phai danh sach vi pham."
Write-Host ("  TRO-CHEO          : {0}/{1} ten run.md neu ma nam o luot chay KHAC" -f $script:NTroCheo, $script:NFile)
Write-Host  "                      (runs/README.md:39 C2 buoc 3 BAT tro 'input spec:' sang luot truoc) - HOP LE."
if ($doV4) {
    Write-Host ("  V-4 do duoc       : {0} vat | KHONG DO DUOC {1} vat (chua tracked hoac chi 1 commit cham tep)" -f $script:NV4Measured, $script:NV4Unmeasurable)
}
if ($script:NOutOfShape.Count -gt 0) {
    Write-Host ("  NGOAI CAU TRUC PHANG : {0} tep (C1 doi phang; C8 mien 'harvest/'+'sub-md/'). In ten, KHONG im lang:" -f $script:NOutOfShape.Count) -ForegroundColor Yellow
    foreach ($x in $script:NOutOfShape) { Write-Host ("     - {0}" -f $x) -ForegroundColor Yellow }
}

if ($script:Flags.Count -gt 0) {
    Write-Host ''
    Write-Host '  Danh sach CO (tung ten - cam nen thanh so tong):' -ForegroundColor Red
    foreach ($x in $script:Flags) { Write-Host ("    - [{0,-11}] {1}/{2}  <- {3}" -f $x.Kind, $x.Run, $x.Name, $x.Msg) }
}

Write-Host ''
Write-Host '  Ma thoat: 0 (INFORM-only theo hop dong muc 1). Co o tren KHONG lai ma thoat.'
Write-Host '  Lai ma thoat thuoc wave W3b, sau khi chu du an chot phan loai co theo PA-2.'
exit 0
