# kb_bootpack_acceptance_v1.1.ps1 (entries/json_entries alignment fix) # Rôle : Lecture-seule. Vérifie que le pointeur BUG_KB_JSON_POINTER réfère bien au KB courant. # Sortie : entries={json_count}|blocking={blocking_count}|ptr_exists=...|ptr_sha_match=...|ptr_entries_note=...|json_entries={json_count} # Règles : PS 5.1, ASCII-safe, UTF-8 BOM pour ce script. Aucune écriture. # Notes : On parse le JSON réél pour compter 'entries' et 'blocking' afin d'éviter toute dérive. [CmdletBinding()] param( [string]$Root = "\\DS-918\\chatgpt\\ChatGPT-Gouvernance-Projets\\_registry", [string]$BootPackPath ) function Read-All([string]$Path){ if([string]::IsNullOrWhiteSpace($Path)){ return "" } if(-not (Test-Path -LiteralPath $Path)){ return "" } $t = Get-Content -LiteralPath $Path -Raw -Encoding UTF8 $t = $t -replace "`uFEFF","" return $t } function Parse-Pointer([string]$BootPack){ $r = @{ Path=""; SHA256=""; Entries=""; Size=""; Updated="" } $txt = Read-All $BootPack if([string]::IsNullOrWhiteSpace($txt)){ return $r } $lines = $txt -split "(`r`n|`n|`r)" $n = $lines.Length $i = 0 while($i -lt $n){ $line = $lines[$i].Trim() if($line -ceq "[BUG_KB_JSON_POINTER]"){ $i = $i + 1 while($i -lt $n){ $l = $lines[$i].Trim() if($l -match "^\[.+\]\s*$"){ break } if($l -match "^Path\s*=\s*(.+)$"){ $r.Path = $matches[1].Trim() } elseif($l -match "^SHA256\s*=\s*([0-9A-Fa-f]+)$"){ $r.SHA256 = $matches[1].ToUpperInvariant() } elseif($l -match "^Entries\s*=\s*([0-9]+)$"){ $r.Entries = [int]$matches[1] } elseif($l -match "^Size\s*=\s*([0-9]+)$"){ $r.Size = [int64]$matches[1] } elseif($l -match "^Updated\s*=\s*(.+)$"){ $r.Updated = $matches[1].Trim() } $i = $i + 1 } break } $i = $i + 1 } return $r } function Trim-To-Json([string]$raw){ if([string]::IsNullOrWhiteSpace($raw)){ return "" } $raw = $raw -replace "`uFEFF","" $last = $raw.LastIndexOf('}') if($last -gt 0){ $raw = $raw.Substring(0,$last+1) } return $raw } function Load-KB([string]$KbPath){ $o = @{ Obj=$null; Count=-1; Blocking=0; Sha=""; Size=0 } if(-not (Test-Path -LiteralPath $KbPath)){ return $o } try{ $o.Sha = (Get-FileHash -LiteralPath $KbPath -Algorithm SHA256).Hash.ToUpperInvariant() }catch{ $o.Sha="ERROR" } try{ $o.Size = (Get-Item -LiteralPath $KbPath).Length }catch{ $o.Size=0 } $raw = Read-All $KbPath $raw = Trim-To-Json $raw try{ $obj = $raw | ConvertFrom-Json -ErrorAction Stop $o.Obj = $obj if($null -ne $obj -and $obj.PSObject.Properties.Match("entries").Count -gt 0 -and $null -ne $obj.entries){ $arr = @($obj.entries) $o.Count = $arr.Count $b = 0 foreach($e in $arr){ if($null -ne $e -and $e.PSObject.Properties.Match("blocking").Count -gt 0){ if($e.blocking -eq $true){ $b = $b + 1 } } } $o.Blocking = $b } else { $o.Count = -1 $o.Blocking = 0 } }catch{ $o.Count = -1 $o.Blocking = 0 } return $o } # Resolve bootpack if([string]::IsNullOrWhiteSpace($BootPackPath)){ $BootPackPath = Join-Path $Root "bootpack\\bootpack_paste.txt" } $ptr = Parse-Pointer $BootPackPath $ptrExists = $false $ptrShaMatch = $false $jsonCount = -1 $blocking = 0 if(-not [string]::IsNullOrWhiteSpace($ptr.Path)){ $ptrExists = Test-Path -LiteralPath $ptr.Path $kb = Load-KB $ptr.Path $jsonCount = $kb.Count $blocking = $kb.Blocking if(-not [string]::IsNullOrWhiteSpace($kb.Sha) -and -not [string]::IsNullOrWhiteSpace($ptr.SHA256)){ if($kb.Sha -eq $ptr.SHA256){ $ptrShaMatch = $true } } } # Sortie métriques : 'entries' = jsonCount (source de vérité), 'ptr_entries_note' = valeur notée dans le pointer $entriesVal = $jsonCount $ptrNote = $ptr.Entries if($ptrNote -is [string]){ if([int]::TryParse($ptrNote, [ref]([int]0))){ $ptrNote = [int]$ptrNote } } # ligne principale Write-Host ("entries={0}|blocking={1}|ptr_exists={2}|ptr_sha_match={3}|ptr_entries_note={4}|json_entries={5}" -f ` $entriesVal,$blocking,([string]$ptrExists).ToLower(),([string]$ptrShaMatch).ToLower(),$ptrNote,$jsonCount) # Liste des blocking ids (si disponible) if($kb -and $kb.Obj -and $kb.Obj.entries){ $ids = @() foreach($e in @($kb.Obj.entries)){ $hasId = $false $isBlock = $false $idVal = "" if($e.PSObject.Properties.Match("id").Count -gt 0){ $hasId=$true; $idVal = [string]$e.id } if($e.PSObject.Properties.Match("blocking").Count -gt 0){ if($e.blocking -eq $true){ $isBlock=$true } } if($isBlock -and $hasId -and $idVal){ $ids += $idVal } } if($ids.Count -gt 0){ $joined = [string]::Join(",", $ids) Write-Host ("[GATE-BLOCK] blocking ids: {0}" -f $joined) } }