scripts/commit-bug-review.ps1
|
#!/usr/bin/env pwsh param( [int]$MaxIterations = 148, [ValidateSet('claude', 'copilot')] [string]$Type = 'copilot', [string]$Model = 'gpt-5.4', [ValidateSet('low', 'medium', 'high', 'max', 'xhigh')] [string]$Effort = 'max', [switch]$DryRun ) $ErrorActionPreference = 'Stop' $RepoRoot = Split-Path $PSScriptRoot -Parent $TrackerPath = Join-Path $RepoRoot "docs\trackers\features\commit-bug-review-TRACKER.md" $PromptPath = Join-Path $RepoRoot "scripts\commit-bug-review-prompt.md" # Resolve engine binary if ($Type -eq 'copilot') { # Try common Copilot CLI locations on Windows $candidatePaths = @( "copilot", "gh copilot", "$env:LOCALAPPDATA\Programs\copilot\copilot.exe", "/home/vscode/.local/bin/copilot" ) $EngineBin = "copilot" foreach ($candidate in $candidatePaths) { if (Get-Command $candidate -ErrorAction SilentlyContinue) { $EngineBin = $candidate break } } Write-Host "Using Copilot CLI: $EngineBin" -ForegroundColor DarkGray } else { $EngineBin = "claude" } function Get-PendingCount { $tracker = Get-Content $TrackerPath -Raw return ([regex]::Matches($tracker, '\| PENDING \|')).Count } function Get-CompletedCount { $tracker = Get-Content $TrackerPath -Raw $done = ([regex]::Matches($tracker, '\| DONE \|')).Count $needsWork = ([regex]::Matches($tracker, '\| NEEDS_WORK \|')).Count $blocked = ([regex]::Matches($tracker, '\| BLOCKED \|')).Count return $done + $needsWork + $blocked } function Invoke-Iteration { param([int]$Iteration) Write-Host "" Write-Host ("=" * 50) -ForegroundColor Yellow Write-Host " Iteration $Iteration of $MaxIterations ($Type / $Model)" -ForegroundColor Yellow Write-Host ("=" * 50) -ForegroundColor Yellow $prompt = Get-Content $PromptPath -Raw if ($Type -eq 'copilot') { $copilotEffort = if ($Effort -eq 'max') { 'xhigh' } else { $Effort } $engineArgs = @( '-p', $prompt '--model', $Model '--allow-all' '--reasoning-effort', $copilotEffort ) if ($DryRun) { Write-Host " [DRY RUN] Would run: $EngineBin $($engineArgs -join ' ')" -ForegroundColor DarkGray return $true } & $EngineBin @engineArgs 2>&1 | ForEach-Object { $line = "$PSItem" if ($line -and $line -notmatch '^\s*$') { Write-Host " $line" -ForegroundColor White } } } else { $sessionId = [guid]::NewGuid().ToString() $engineArgs = @( '--dangerously-skip-permissions' '--session-id', $sessionId '--no-session-persistence' '--model', $Model '--effort', $Effort '--verbose' '--output-format', 'stream-json' '-p', $prompt ) if ($DryRun) { Write-Host " [DRY RUN] Would run: claude $($engineArgs -join ' ')" -ForegroundColor DarkGray return $true } # Stream and parse JSON - show tool use with file details & $EngineBin @engineArgs 2>&1 | ForEach-Object { $line = $PSItem try { $obj = $line | ConvertFrom-Json -ErrorAction Stop switch ($obj.type) { 'assistant' { if ($obj.message.content) { foreach ($content in $obj.message.content) { switch ($content.type) { 'tool_use' { $toolName = $content.name $detail = "" if ($content.input) { switch ($toolName) { 'Read' { $detail = Split-Path $content.input.file_path -Leaf } 'Write' { $detail = Split-Path $content.input.file_path -Leaf } 'Edit' { $detail = Split-Path $content.input.file_path -Leaf } 'Glob' { $detail = $content.input.pattern -replace '.*/',''} 'Grep' { $detail = $content.input.pattern.Substring(0, [Math]::Min(30, $content.input.pattern.Length)) } 'Bash' { $detail = ($content.input.command -split '\n')[0].Substring(0, [Math]::Min(40, ($content.input.command -split '\n')[0].Length)) } } } if ($detail) { Write-Host " 🔧 $toolName " -ForegroundColor DarkCyan -NoNewline Write-Host $detail -ForegroundColor DarkGray } else { Write-Host " 🔧 $toolName" -ForegroundColor DarkCyan } } 'text' { if ($content.text) { Write-Host $content.text -ForegroundColor White } } } } } } 'result' { $duration = [math]::Round($obj.duration_ms / 1000, 1) $cost = [math]::Round($obj.total_cost_usd, 4) Write-Host "" Write-Host "✓ Completed in ${duration}s (`$$cost)" -ForegroundColor Green } } } catch { if ($line -and $line -notmatch '^\s*$') { Write-Host $line -ForegroundColor DarkGray } } } } return $LASTEXITCODE -eq 0 } # Main loop $total = 135 # 138 commits minus 3 pre-marked version bumps Write-Host "Ralph Wiggum: commit-bug-review ($Type, $Model, effort=$Effort)" -ForegroundColor Cyan Write-Host "Tracker: $TrackerPath" -ForegroundColor DarkGray Write-Host "Prompt: $PromptPath" -ForegroundColor DarkGray Write-Host "" $iteration = 0 $stalledCount = 0 $maxStalled = 3 while ($iteration -lt $MaxIterations) { $iteration++ $pending = Get-PendingCount $completed = Get-CompletedCount $completedBefore = $completed $percent = [math]::Min(100, [math]::Round(($completed / $total) * 100)) $barFilled = [math]::Min(20, [math]::Floor($percent / 5)) $barEmpty = [math]::Max(0, 20 - $barFilled) Write-Host "[$(('=' * $barFilled))$(('-' * $barEmpty))] $percent% ($completed/$total)" -ForegroundColor Cyan if ($pending -eq 0) { Write-Host "All items completed!" -ForegroundColor Green break } if (-not (Invoke-Iteration -Iteration $iteration)) { Write-Host "Iteration failed. Stopping." -ForegroundColor Red exit 1 } # Zero-trust: verify the iteration actually progressed $completedAfter = Get-CompletedCount if ($completedAfter -le $completedBefore) { $stalledCount++ Write-Host "⚠️ No progress detected (stalled $stalledCount/$maxStalled)" -ForegroundColor Yellow Write-Host " Before: $completedBefore completed, $pending pending" -ForegroundColor Yellow Write-Host " After: $completedAfter completed" -ForegroundColor Yellow if ($stalledCount -ge $maxStalled) { Write-Host "✗ Stalled $maxStalled times in a row. AI is claiming done without finishing." -ForegroundColor Red Write-Host " Check the tracker for items marked DONE that shouldn't be." -ForegroundColor Red exit 1 } } else { $stalledCount = 0 Write-Host "✓ Progress: $completedBefore → $completedAfter completed" -ForegroundColor Green } Start-Sleep -Seconds 2 } Write-Host "Done. Completed: $(Get-CompletedCount) / $total" -ForegroundColor Green # SIG # Begin signature block # MIItZQYJKoZIhvcNAQcCoIItVjCCLVICAQMxDTALBglghkgBZQMEAgEwewYKKwYB # BAGCNwIBBKBtBGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAHUA7yk0De+ID4 # ycYISia/bWt+yBX1ULSWavKQq39r2aCCFWUwggaTMIIEe6ADAgECAhMzAABfKT87 # d5yFK2BaAAAAAF8pMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ # RCBWZXJpZmllZCBDUyBBT0MgQ0EgMDMwHhcNMjYwNDIxMDMwMjU4WhcNMjYwNDI0 # MDMwMjU4WjBXMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExDzANBgNV # BAcTBlZpZW5uYTERMA8GA1UEChMIZGJhdG9vbHMxETAPBgNVBAMTCGRiYXRvb2xz # MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAj9EnH3oz1voEI5pcaq7I # Rx46nU+UMIIVu7hr8dMxlcsjTzXd/L1GQ8Uh7HZATV7747LBTp38qGq/NfiOPFQd # Xg4D8LaestQ7ATiIoHA6ZWbC2mIw/dECVER88ErISGRIRu+cvbTsPIkD8LDZxeax # +HvwTI8kaRnjALQ7Z85asQufzX18kpNW7y+Nq6HiI++Qs/InG8HZhSeAkqh+TEZ+ # awG6oOMj+KlsyJ6z+k0WtNrXZtVU1Eb7VzWI+Eyo3shkWe0Gw6/yKyXNVL++X/B6 # MWAwEZt7tEAoiw9bA2I5j2IW4WK+kDzFNvVXc8yf/ny16aTTmOwKbc5z9nna2x+Z # 2FvPrSGA3C/fW3Q8O2hHh8X64v4aVsM5eIAxtq26Ds3wOrI6Qk9BD2vNfgCQhlsM # XPX8WJdF6Bd8xM2hhOq1qJiNX7quGpIGch7gZClKBVaiwZxx5oBf8+02YX9cCaLu # aDKGdQ6+yxflUoKopuxFmme77o+UmKGEl/6iMtnZD0b7AgMBAAGjggHTMIIBzzAM # BgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDA6BgNVHSUEMzAxBgorBgEEAYI3 # YQEABggrBgEFBQcDAwYZKwYBBAGCN2H5+cEspPS4DoOuxLIcm56wGDAdBgNVHQ4E # FgQUINW39PBdK9q49NZNttNtfG1kp9EwHwYDVR0jBBgwFoAUpEMMf3ZapYXnPo0o # DwwXokVpcMYwZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIw # QU9DJTIwQ0ElMjAwMy5jcmwwdAYIKwYBBQUHAQEEaDBmMGQGCCsGAQUFBzAChlho # dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUy # MElEJTIwVmVyaWZpZWQlMjBDUyUyMEFPQyUyMENBJTIwMDMuY3J0MFQGA1UdIARN # MEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wDQYJKoZIhvcNAQEMBQADggIB # AFf0dOq56PjSF3WnDjELVeUtIIG+qpKk4i9R18RB1DFDWbL7sbq7uuNcgbfK+NB3 # ZJ7bhwrU89iMkQV2/B03s9eN2goq/y10qARgVsm3DARwdZggtu57VSvsUAIqEMjj # huUTFF+F4D7JeanApsVXyb0l4oEdlkckO0trs0SsMqBqxoTOKAVuzN3J7+DP4fZJ # bvnQ7DxXqz+3kGod1o/XNumzBh8gawzZE1YFGentvK1JdiDQ6KHWoXlP82B2T377 # 2MleI7dS0nU5VZNfwVV0stb+52w0dK43o+zWu/rC2SjXCWFQEta/7kDnlVxQmH8f # nQxaBJidErykionoiIG/pEiaVY64GAB+p0V97sblI9Pj31Ql+jFJ8MBS3fqm8SUX # O5p7G/3jGNSadeoY4LGSInqX8OHYSuojBChM5OpnC7hTpHtAO+f050jsbho9Q1b3 # tz1ioixkALngw+Tpi6sStqwx81U5/vSiQlPXI8Hfad9JKjswwgpKsm/LdmSOZH2c # lliiNQhuCrHh8PXiJwVzNX/s3jzswC1KYXdkGqM5F2HHYDk7tOrVUED5gCxaDqzZ # DPAC/4/ZXuPm+2S/jdTybaOuKU8WzvnooxtXyr8MmN7spvp/IZECFldDnGjEB/4E # ahzxG5ySuuJE7w9galvOxHcfgOoCmc9ODbr2P/0+YhtxMIIHKDCCBRCgAwIBAgIT # MwAAABgN65FVqYoAmAAAAAAAGDANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQGEwJV # UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTQwMgYDVQQDEytNaWNy # b3NvZnQgSUQgVmVyaWZpZWQgQ29kZSBTaWduaW5nIFBDQSAyMDIxMB4XDTI2MDMy # NjE4MTEzMloXDTMxMDMyNjE4MTEzMlowWjELMAkGA1UEBhMCVVMxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiTWljcm9zb2Z0IElEIFZl # cmlmaWVkIENTIEFPQyBDQSAwMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAMiA2mA0VqKJ/ZVZ5Y/kjo+cVfEn+UHft8lHnkYK9HsYtkEyQGKNuIpXCCkE # jfEzmd/jzjOcf+qdwn44KrrLeOCdBb5Hxl3tT7suOWuZyyRqXNJDSCEzESmcFbz8 # cezZXxknNCToc/5IOxu+wvst2Uf947aXiaSeEMHCvRn9D3rpO8S2HlvyQLGPW+qJ # Xhg22EsZGplH27Z8r/IExa7zeno7i6jYR2D76AR7Dkgvu+eecoWqZKH9H288nLdY # XVhxl7ABTHyxdk1SfHdmFWDn2XYumK0+LDMToUyoiypoS9V7czO4V3Zr+5YNkfpV # sPJSJErvyYiDUNBgD3MMTLIEVw0j6fFVLOCW8vq7s9G42qBxXex/oQvHDz3KxAz9 # nhHWFEVZdGnI5YooAq18EdOTRSc2I9zGYswxizyN5SM6J19U+NMivL9RXCfDF2WQ # rzlxl8EQxhn8ME07B2iY/jn1jWfyLMqRuGxr6niXD5xBXEBMEXH2CBHv0eGvJPsc # Oak8u+Qm8FnjBbgJbfZRPZIzIN7bycg5Teb6F8eVV4pwsFBzKblWhEOMhwJUju6q # AZbY80wTRx96LzMLALLocKyywlYVLt6D9hsWGcBMlzJZ8yuQ24Bsx8w3w2mDxytL # qNVWjDIPQYbnN2CL65BVxIr/rfyYDXERgremcihCA7T264MHAgMBAAGjggHcMIIB # 2DAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFKRD # DH92WqWF5z6NKA8MF6JFaXDGMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUF # BwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3Np # dG9yeS5odG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwEgYDVR0TAQH/BAgw # BgEB/wIBADAfBgNVHSMEGDAWgBTZQSmwDw9jbO9p1/XNKZ6kSGow5jBwBgNVHR8E # aTBnMGWgY6Bhhl9odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9N # aWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0El # MjAyMDIxLmNybDB9BggrBgEFBQcBAQRxMG8wbQYIKwYBBQUHMAKGYWh0dHA6Ly93 # d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSUQlMjBW # ZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAyMS5jcnQwDQYJKoZI # hvcNAQEMBQADggIBAHHHIFb5fqaF1GJLAP08wxZwZQCfHn9BTCc29l0UYRf7gNEM # iv1YKHgLzvAe3D6WDUPe7MrXQOy09fQsUsEUALe9YxhfgiZfCguGhHTGU3yZR2is # nduCekIla4jXnfVnWsLA+5StKQHF84gYOTenYQJvcej/EeLk9FJH85Sta5AfBeJp # cxO5e7chEt7PBWRmkWY3BhEPntH03HYX/Izu3M5jQeHSEYJpgQrfz/oWtLRJdp1d # bINQJ+flc4YAJGNQKcfH4lBQbR/hIcP6JuWkAjSCX5kedWZ1dfEdNl5NrQJgIiEX # Eo/b3bazSDrMuZ6JXXctZSa239QXtOtZekyLb/RQ2eJoOgfuuc8ZFXnFVfy5fLix # mKLhqzDOo8ztjv6bNytqepnwSNmTmCMuFDcDaxlqmuU67wJpGbJ9wiJUfvNV+AC+ # bzUxZcXOIB/ubLtA6+fIQU8Z12rwxJ8+19HLD9Sre4foqmhok0h89gfp9x5lKLnd # Fq3UD2CsTGrdE6OGFKlNxyG4Ei0Aw1U/Ggo1tSb6JH9fdeQv71ZCCKePId76Fcty # Vjy8AZcUPWnjQ+owikBiyYQkEUpb11/j//U3mhAOv8Vj0gEmX+hJL3v2Lmu1Ps1n # P0q9itoI9EEazRALL6xa+BBrRygzvRAlUt5XCZLFQ7/Sh3TD1CvLttIuvEagMIIH # njCCBYagAwIBAgITMwAAAAeHozSje6WOHAAAAAAABzANBgkqhkiG9w0BAQwFADB3 # MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMUgw # RgYDVQQDEz9NaWNyb3NvZnQgSWRlbnRpdHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2Vy # dGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAwHhcNMjEwNDAxMjAwNTIwWhcNMzYwNDAx # MjAxNTIwWjBjMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMTQwMgYDVQQDEytNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ29kZSBTaWdu # aW5nIFBDQSAyMDIxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsvDA # rxmIKOLdVHpMSWxpCFUJtFL/ekr4weslKPdnF3cpTeuV8veqtmKVgok2rO0D05Bp # yvUDCg1wdsoEtuxACEGcgHfjPF/nZsOkg7c0mV8hpMT/GvB4uhDvWXMIeQPsDgCz # UGzTvoi76YDpxDOxhgf8JuXWJzBDoLrmtThX01CE1TCCvH2sZD/+Hz3RDwl2MsvD # SdX5rJDYVuR3bjaj2QfzZFmwfccTKqMAHlrz4B7ac8g9zyxlTpkTuJGtFnLBGaso # Onn5NyYlf0xF9/bjVRo4Gzg2Yc7KR7yhTVNiuTGH5h4eB9ajm1OCShIyhrKqgOkc # 4smz6obxO+HxKeJ9bYmPf6KLXVNLz8UaeARo0BatvJ82sLr2gqlFBdj1sYfqOf00 # Qm/3B4XGFPDK/H04kteZEZsBRc3VT2d/iVd7OTLpSH9yCORV3oIZQB/Qr4nD4YT/ # lWkhVtw2v2s0TnRJubL/hFMIQa86rcaGMhNsJrhysLNNMeBhiMezU1s5zpusf54q # lYu2v5sZ5zL0KvBDLHtL8F9gn6jOy3v7Jm0bbBHjrW5yQW7S36ALAt03QDpwW1JG # 1Hxu/FUXJbBO2AwwVG4Fre+ZQ5Od8ouwt59FpBxVOBGfN4vN2m3fZx1gqn52Gvai # Bz6ozorgIEjn+PhUXILhAV5Q/ZgCJ0u2+ldFGjcCAwEAAaOCAjUwggIxMA4GA1Ud # DwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU2UEpsA8PY2zv # adf1zSmepEhqMOYwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0 # bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAPBgNVHRMBAf8EBTADAQH/MB8G # A1UdIwQYMBaAFMh+0mqFKhvKGZgEByfPUBBPaKiiMIGEBgNVHR8EfTB7MHmgd6B1 # hnNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQl # MjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUy # MEF1dGhvcml0eSUyMDIwMjAuY3JsMIHDBggrBgEFBQcBAQSBtjCBszCBgQYIKwYB # BQUHMAKGdWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj # cm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlm # aWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNydDAtBggrBgEFBQcwAYYhaHR0cDov # L29uZW9jc3AubWljcm9zb2Z0LmNvbS9vY3NwMA0GCSqGSIb3DQEBDAUAA4ICAQB/ # JSqe/tSr6t1mCttXI0y6XmyQ41uGWzl9xw+WYhvOL47BV09Dgfnm/tU4ieeZ7NAR # 5bguorTCNr58HOcA1tcsHQqt0wJsdClsu8bpQD9e/al+lUgTUJEV80Xhco7xdgRr # ehbyhUf4pkeAhBEjABvIUpD2LKPho5Z4DPCT5/0TlK02nlPwUbv9URREhVYCtsDM # +31OFU3fDV8BmQXv5hT2RurVsJHZgP4y26dJDVF+3pcbtvh7R6NEDuYHYihfmE2H # dQRq5jRvLE1Eb59PYwISFCX2DaLZ+zpU4bX0I16ntKq4poGOFaaKtjIA1vRElIta # OKcwtc04CBrXSfyL2Op6mvNIxTk4OaswIkTXbFL81ZKGD+24uMCwo/pLNhn7VHLf # nxlMVzHQVL+bHa9KhTyzwdG/L6uderJQn0cGpLQMStUuNDArxW2wF16QGZ1NtBWg # KA8Kqv48M8HfFqNifN6+zt6J0GwzvU8g0rYGgTZR8zDEIJfeZxwWDHpSxB5FJ1VV # U1LIAtB7o9PXbjXzGifaIMYTzU4YKt4vMNwwBmetQDHhdAtTPplOXrnI9SI6HeTt # jDD3iUN/7ygbahmYOHk7VB7fwT4ze+ErCbMh6gHV1UuXPiLciloNxH6K4aMfZN1o # LVk6YFeIJEokuPgNPa6EnTiOL60cPqfny+Fq8UiuZzGCF1YwghdSAgEBMHEwWjEL # MAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkG # A1UEAxMiTWljcm9zb2Z0IElEIFZlcmlmaWVkIENTIEFPQyBDQSAwMwITMwAAXyk/ # O3echStgWgAAAABfKTALBglghkgBZQMEAgGgfDAQBgorBgEEAYI3AgEMMQIwADAZ # BgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYB # BAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgyXMfsEJS+90T/pNYWvbxXXCcgwksNWaR # bEWio510jHUwCwYJKoZIhvcNAQEBBIIBgCt6UG71ZQn2/GmAvehKrspEv9NLlYvd # +ODUGBDkFfNJFv89UejMIjz3HmmsI/pGpi7cysEeAqVGItLRqMlFWgMJKKFAPWsk # c8s0TVRJoWm2DuXrRutVwAkdxyCuhynH4hEUi0emDCUE1NBXQoQKS0hoWxw9NSrT # +O8Dw5+Lb/Xs+BGhiHQgFyqOyckxw6wVh6zAFE7kYkd28XQsZat7qZl2RAAjbsT4 # t/ZHjIorj74TUzR6459kCkhnfPgV7NRODBISrrVB+gUKjYI85VpymE2PWco486Dr # ah9Xu2n2K5vkNCsBjzYqI4A7faRE8PpIoTcTqxF2RCqeNT5s9BNOCr3L8P7IwfOp # Lu/cSBEZIMgmOQoZ3B1+amgMDh9SW+C2Nz5BHe0vILUZLCT5n4Mckp1kgbugGxRS # PQqndGeuqdL8LHYDihJjFa4ek9FJfNeknE1sQrGmk1zdTyrtaCWKPnsotzYYPdnT # jgrzbCa+FPS5vJs4mo3VKgQI9yhimQQgdaGCFLwwghS4BgorBgEEAYI3AwMBMYIU # qDCCFKQGCSqGSIb3DQEHAqCCFJUwghSRAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggF0 # BgsqhkiG9w0BCRABBKCCAWMEggFfMIIBWwIBAQYKKwYBBAGEWQoDATAxMA0GCWCG # SAFlAwQCAQUABCCvTqi8yAnpVwLfChm0oVGun6BeB4aseODlMvXO+umyYgIGacZo # GkmkGBMyMDI2MDQyMTE2NTYyMS45NDRaMASAAgH0AghBmX1VqxXLa6CB6aSB5jCB # 4zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk # TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5u # U2hpZWxkIFRTUyBFU046N0IxQS0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29m # dCBQdWJsaWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5oIIPKTCCB4IwggVq # oAMCAQICEzMAAAAF5c8P/2YuyYcAAAAAAAUwDQYJKoZIhvcNAQEMBQAwdzELMAkG # A1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFIMEYGA1UE # AxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENlcnRpZmlj # YXRlIEF1dGhvcml0eSAyMDIwMB4XDTIwMTExOTIwMzIzMVoXDTM1MTExOTIwNDIz # MVowYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENB # IDIwMjAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCefOdSY/3gxZ8F # fWO1BiKjHB7X55cz0RMFvWVGR3eRwV1wb3+yq0OXDEqhUhxqoNv6iYWKjkMcLhEF # xvJAeNcLAyT+XdM5i2CgGPGcb95WJLiw7HzLiBKrxmDj1EQB/mG5eEiRBEp7dDGz # xKCnTYocDOcRr9KxqHydajmEkzXHOeRGwU+7qt8Md5l4bVZrXAhK+WSk5CihNQsW # bzT1nRliVDwunuLkX1hyIWXIArCfrKM3+RHh+Sq5RZ8aYyik2r8HxT+l2hmRllBv # E2Wok6IEaAJanHr24qoqFM9WLeBUSudz+qL51HwDYyIDPSQ3SeHtKog0ZubDk4hE # LQSxnfVYXdTGncaBnB60QrEuazvcob9n4yR65pUNBCF5qeA4QwYnilBkfnmeAjRN # 3LVuLr0g0FXkqfYdUmj1fFFhH8k8YBozrEaXnsSL3kdTD01X+4LfIWOuFzTzuosl # BrBILfHNj8RfOxPgjuwNvE6YzauXi4orp4Sm6tF245DaFOSYbWFK5ZgG6cUY2/bU # q3g3bQAqZt65KcaewEJ3ZyNEobv35Nf6xN6FrA6jF9447+NHvCjeWLCQZ3M8lgeC # cnnhTFtyQX3XgCoc6IRXvFOcPVrr3D9RPHCMS6Ckg8wggTrtIVnY8yjbvGOUsAdZ # beXUIQAWMs0d3cRDv09SvwVRd61evQIDAQABo4ICGzCCAhcwDgYDVR0PAQH/BAQD # AgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRraSg6NS9IY0DPe9ivSek+ # 2T3bITBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1Ud # JQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1Ud # EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89QEE9oqKIwgYQG # A1UdHwR9MHsweaB3oHWGc2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y3JsL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUy # MENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcmwwgZQGCCsGAQUFBwEB # BIGHMIGEMIGBBggrBgEFBQcwAoZ1aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br # aW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUy # MFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3J0MA0GCSqG # SIb3DQEBDAUAA4ICAQBfiHbHfm21WhV150x4aPpO4dhEmSUVpbixNDmv6TvuIHv1 # xIs174bNGO/ilWMm+Jx5boAXrJxagRhHQtiFprSjMktTliL4sKZyt2i+SXncM23g # RezzsoOiBhv14YSd1Klnlkzvgs29XNjT+c8hIfPRe9rvVCMPiH7zPZcw5nNjthDQ # +zD563I1nUJ6y59TbXWsuyUsqw7wXZoGzZwijWT5oc6GvD3HDokJY401uhnj3ubB # hbkR83RbfMvmzdp3he2bvIUztSOuFzRqrLfEvsPkVHYnvH1wtYyrt5vShiKheGpX # a2AWpsod4OJyT4/y0dggWi8g/tgbhmQlZqDUf3UqUQsZaLdIu/XSjgoZqDjamzCP # JtOLi2hBwL+KsCh0Nbwc21f5xvPSwym0Ukr4o5sCcMUcSy6TEP7uMV8RX0eH/4JL # EpGyae6Ki8JYg5v4fsNGif1OXHJ2IWG+7zyjTDfkmQ1snFOTgyEX8qBpefQbF0fx # 6URrYiarjmBprwP6ZObwtZXJ23jK3Fg/9uqM3j0P01nzVygTppBabzxPAh/hHhhl # s6kwo3QLJ6No803jUsZcd4JQxiYHHc+Q/wAMcPUnYKv/q2O444LO1+n6j01z5mgg # CSlRwD9faBIySAcA9S8h22hIAcRQqIGEjolCK9F6nK9ZyX4lhthsGHumaABdWzCC # B58wggWHoAMCAQICEzMAAABZfNpx6Y1e9cAAAAAAAFkwDQYJKoZIhvcNAQEMBQAw # YTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy # MDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIw # MjAwHhcNMjYwMTA4MTg1OTAxWhcNMjcwMTA3MTg1OTAxWjCB4zELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IEly # ZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBF # U046N0IxQS0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNB # IFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEApi7n/jR4Rf6FP7mMVrXjpuJ3d0Dguddie2+Q/cIbDgsYBEWGe8sx # In9W2y5vMNp4WebvJvYpIzvRaYdCmt0JWqm9QfuXS4HiM3Du6sugBH2QocsTRWUy # UNK0NLFQEjerCx2uO92a9XST73+eO4MSJKXMlN/sOjB3Urds7ht5HJoWFH5jy3KY # QI6qU4B99isbbBl1UznX5BIFJ748TKSvwLo6eepKKm4Xx9m8Jvr+G6TRmbpnCxqL # FIcgBPYgQa9LtzrcibyNXdrxHQrqLbKLDQ02WdNKnDL9l+/uLCwsHCF9uMFOf5c6 # XqY/MNdBDdX5JE/3FdsYo6wFPHMaJ3tooAfDejgCGX1QZYsf2Q0/dVSiQToliSOV # +m5QZnqBDKoN7B/EPhWhgiWim3gdnTFC+pqO4nH5yvwtH8hnnqAsubDIzN17n6+2 # MGiKWvL+BJnBUbCCS+QiCko8FAcaxIHTLezOvtjvARvq/TJlqXVdS9aefPeKdNpJ # awIWss9XBWZfLedxjn93blWk6SG36br3sZY1u+w06EA4dFp+0T2P+GGSgzpGzIl8 # EueGoxwD/Bxq9/miPk17JFB0Zl4spyWz1ywpLewFTM+J3HHaKI0f0I9oOr9sskQ5 # dqxiiFcydGKe759STzWzxU7sNBIXp9+fmipIehXyV/UDHq76R1KFvwECAwEAAaOC # AcswggHHMB0GA1UdDgQWBBSPlucLXwPS+WdJGEI6I4MYa5c2djAfBgNVHSMEGDAW # gBRraSg6NS9IY0DPe9ivSek+2T3bITBsBgNVHR8EZTBjMGGgX6BdhltodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBQdWJsaWMl # MjBSU0ElMjBUaW1lc3RhbXBpbmclMjBDQSUyMDIwMjAuY3JsMHkGCCsGAQUFBwEB # BG0wazBpBggrBgEFBQcwAoZdaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w # cy9jZXJ0cy9NaWNyb3NvZnQlMjBQdWJsaWMlMjBSU0ElMjBUaW1lc3RhbXBpbmcl # MjBDQSUyMDIwMjAuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYB # BQUHAwgwDgYDVR0PAQH/BAQDAgeAMGYGA1UdIARfMF0wUQYMKwYBBAGCN0yDfQEB # MEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # RG9jcy9SZXBvc2l0b3J5Lmh0bTAIBgZngQwBBAIwDQYJKoZIhvcNAQEMBQADggIB # AEQyHML9lyOkb/NRETvPZinm+tTFSOwTldre3/ZEa8RLC9uayTdsseFIUBqOCjZd # DzGgYM/exSEoIs94gJJuRW/pXyxKnx8nwmizrKtrB/ZhWKzy1xX447tT1LokY9DO # mY+dx/NBzid7V+pnj4eIppsgMSgV111BPYSCST1/PEJj8RnnZq8nbt1J+sj8gObK # f1XXQ7eJCmDYX4L281OuTudWCgOgdr35DelivQgcadKa3mKuAZPjfrOjladc/wXE # yGzAfVqLKJJmJXOGivXQL0LnZw/cLz88SgwpRey0uOg87RMyR5b/UWvXzopcPjlB # GAGjTEiaC1ZN3NYWeUP6nv6IMEi5Ks1xFcNFi6r9phloOFZIjRJh08hZWHle9e5Y # DfVryhDRI76g9rc2TzSTTzrjCKLInUqxtKdpp5+D2+yl6CGuljyWMLDF8JS3HkdB # E2AAk4jwgoAIrh3TXgyTSGVE7SVBVEd6CoiDb0rpeqRzfrRbZkkZRyy2UqiSRWPo # oAeMbKstE/N6lh+JlQmriBfLFum8pvVcnYU3brzZpSg1ej1HJErVyHR/rqTr7KPz # yTO+4Lv68la00Oz9SkgzoeGbSRTrglQnswwRBwBzuSl+3sabth5Er6gqCpSBhcJ+ # bNtfyclclmc9rwANZWwiqy40DEIjQJleRQuh+qjkF7rPMYID1DCCA9ACAQEweDBh # MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIw # MAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAy # MAITMwAAAFl82nHpjV71wAAAAAAAWTANBglghkgBZQMEAgEFAKCCAS0wGgYJKoZI # hvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCCze/5zNywFsDjB # 8lmDuH9YmM2i6oSidiJwcnyaa+YLmTCB3QYLKoZIhvcNAQkQAi8xgc0wgcowgccw # gaAEIMtFurHbhumxxcQn4eOP3GtxRXDtHw7LIx9IHZgYrf68MHwwZaRjMGExCzAJ # BgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV # BAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwAhMz # AAAAWXzacemNXvXAAAAAAABZMCIEIC2gBNhMhMCSmMXJJ+x0jjmid6Y43rLuI811 # S22BsY6cMA0GCSqGSIb3DQEBCwUABIICAGV57xmLkxLTkW2piYP8gYOIrR45UAs9 # NLyRQZ0L8RgH/w+mrqzQO7c3DBJkr91V313ZOCSZ6Hwuqpo879snPhRSz4v/uNCO # aVBUGDmliaIEu0spcgLIKkXw6RLFgvgUXKTS3HxJcdsXamwZ5tfI4vZIZAHvUoNt # QCx4lFY6UpmlqcBLNIV/izgk/2nD+RTOIzxaZucgaGBVwMETFmTvv41HcyzV8E76 # GizKSolUi5aTKuCti9i3yiOTN7QU9XZSHXDapoeIa5TNCl4ICwouUl/nFZ43ce6O # o0ACWEwEimWB9Q82DlSRLPIOi42OOHu5OR5eUjNDOgENqAlH9ddxbvrlDbQuXvx3 # AxLGkxNHZeAFnP/0cPNO6OPMtdF0XRyIfB0zu7xtoEhTmVPHV0WylEtY4S0p8wPw # V/8xDvVggD+3f5RNapedvAmDFIZqvX45P4dENVZXgAVmOn+h57Yw7o4lLTMgqI6A # H0DAh4yKbviDKSyfdXQ6ciFT1iwGqsncuz1Zy3+Y9w2hGvlWrdlfcFkYRBX0MTfT # dlAl5ANDIHQmGHcVMo7MpMh6kvhl/Q64D7RF7QxtHT9foawQsBVugpGnanEeeafD # ewyg0MpTFBjAvCWfp8ykdimUNxiWzc21/XsY+PF/Aui1d/PvqXNgfIL3jsUdbzjG # Qg+JLYIYJCxR # SIG # End signature block |