@@ -0,0 +1,472 @@
param (
[ string ] $ReturnRoot = " " ,
[ string ] $ReviewRegisterPath = " " ,
[ string ] $ArtifactRoot = " " ,
[ switch ] $FailOnBlocked
)
$ErrorActionPreference = " Stop "
$repoRoot = ( Resolve-Path ( Join-Path $PSScriptRoot " .. " ) ) . Path
$timestamp = Get-Date -Format " yyyy-MM-ddTHH-mm-ss-fff "
function Resolve-LatestArtifactDir {
param ( [ string ] $RootRelativePath )
$root = Join-Path $repoRoot $RootRelativePath
$latest = Get-ChildItem -LiteralPath $root -Directory -ErrorAction SilentlyContinue |
Sort-Object Name -Descending |
Select-Object -First 1
if ( $latest ) {
return $latest . FullName
}
return " "
}
if ( [ string ] :: IsNullOrWhiteSpace ( $ReturnRoot ) ) {
$latestKit = Resolve-LatestArtifactDir -RootRelativePath " project-docs\qa-artifacts\phase13-reviewer-kit-export "
if ( -not [ string ] :: IsNullOrWhiteSpace ( $latestKit ) ) {
$ReturnRoot = Join-Path $latestKit " reviewer-kits\return-templates "
}
}
if ( -not [ string ] :: IsNullOrWhiteSpace ( $ReturnRoot ) -and -not [ System.IO.Path ] :: IsPathRooted ( $ReturnRoot ) ) {
$ReturnRoot = Join-Path $repoRoot $ReturnRoot
}
if ( [ string ] :: IsNullOrWhiteSpace ( $ReviewRegisterPath ) ) {
$ReviewRegisterPath = Join-Path $repoRoot " project-docs\phase13-legal-knowledge-template-library\inventories\expert-review-register.csv "
}
if ( -not [ System.IO.Path ] :: IsPathRooted ( $ReviewRegisterPath ) ) {
$ReviewRegisterPath = Join-Path $repoRoot $ReviewRegisterPath
}
if ( [ string ] :: IsNullOrWhiteSpace ( $ArtifactRoot ) ) {
$ArtifactRoot = Join-Path $repoRoot " project-docs\qa-artifacts\phase13-review-return-preflight "
}
if ( -not [ System.IO.Path ] :: IsPathRooted ( $ArtifactRoot ) ) {
$ArtifactRoot = Join-Path $repoRoot $ArtifactRoot
}
$artifactDir = Join-Path $ArtifactRoot $timestamp
New-Item -ItemType Directory -Force -Path $artifactDir | Out-Null
$summaryJson = Join-Path $artifactDir " phase13-review-return-preflight-summary.json "
$summaryMd = Join-Path $artifactDir " phase13-review-return-preflight-summary.md "
$sourceManifestCsv = Join-Path $artifactDir " return-source-manifest.csv "
$validationBoardCsv = Join-Path $artifactDir " return-validation-board.csv "
$blockersCsv = Join-Path $artifactDir " return-preflight-blockers.csv "
$diffPreviewCsv = Join-Path $artifactDir " return-diff-preview.csv "
$mergePlanCsv = Join-Path $artifactDir " return-merge-plan.csv "
$gitStatusPath = Join-Path $artifactDir " git-status.txt "
$checks = New-Object System . Collections . Generic . List [ object ]
$sourceRows = New-Object System . Collections . Generic . List [ object ]
$validationRows = New-Object System . Collections . Generic . List [ object ]
$blockerRows = New-Object System . Collections . Generic . List [ object ]
$diffRows = New-Object System . Collections . Generic . List [ object ]
$mergeRows = New-Object System . Collections . Generic . List [ object ]
$reviewRequiredColumns = @ ( " review_id " , " asset_type " , " asset_id " , " asset_name " , " reviewer_role " , " reviewer " , " review_date " , " review_result " , " required_changes " , " evidence_path " , " allow_review_import " , " allow_production_release " , " notes " )
$ackRequiredColumns = @ ( " work_order_id " , " recipient_role " , " recipient " , " handoff_owner " , " acknowledged " , " ack_date " , " package_path " , " missing_materials " , " notes " )
$allowedReviewResults = @ ( " PENDING " , " CHANGES_REQUIRED " , " APPROVED_FOR_REVIEW_IMPORT " , " APPROVED_FOR_PRODUCTION " , " REJECTED " )
function Add-Check {
param (
[ string ] $Key ,
[ string ] $Label ,
[ ValidateSet ( " pass " , " fail " , " warn " , " skip " , " blocked " ) ]
[ string ] $Status ,
[ string ] $Detail ,
[ bool ] $Required = $true ,
[ hashtable ] $Meta = @ { }
)
$checks . Add ( [ ordered ] @ {
key = $Key
label = $Label
status = $Status
required = $Required
detail = $Detail
meta = $Meta
} ) | Out-Null
}
function Add-Blocker {
param ( [ string ] $Kind , [ string ] $Id , [ string ] $Severity , [ string ] $Blocker , [ string ] $Evidence )
$blockerRows . Add ( [ pscustomobject][ordered ] @ {
kind = $Kind
id = $Id
severity = $Severity
blocker = $Blocker
evidence = $Evidence
} ) | Out-Null
}
function Save-Json {
param ( [ string ] $Path , [ object ] $Value )
$Value | ConvertTo-Json -Depth 50 | Set-Content -Encoding UTF8 -Path $Path
}
function Import-CsvRows {
param ( [ string ] $Path )
if ( -not ( Test-Path -LiteralPath $Path -PathType Leaf ) ) {
return @ ( )
}
return @ ( Import-Csv -LiteralPath $Path )
}
function Get-CsvHeader {
param ( [ string ] $Path )
if ( -not ( Test-Path -LiteralPath $Path -PathType Leaf ) ) {
return @ ( )
}
$firstLine = Get-Content -LiteralPath $Path -Encoding UTF8 -TotalCount 1
if ( [ string ] :: IsNullOrWhiteSpace ( $firstLine ) ) {
return @ ( )
}
return @ ( $firstLine . Split ( " , " ) | ForEach-Object { $_ . Trim ( ) . Trim ( '"' ) } )
}
function Test-RequiredColumns {
param ( [ string ] $Path , [ string[] ] $Columns )
$header = Get-CsvHeader -Path $Path
return @ ( $Columns | Where-Object { $header -notcontains $_ } )
}
function Test-Truthy {
param ( [ string ] $Value )
if ( [ string ] :: IsNullOrWhiteSpace ( $Value ) ) {
return $false
}
return @ ( " true " , " yes " , " 1 " , " 是 " , " 已签收 " ) -contains $Value . Trim ( ) . ToLowerInvariant ( )
}
function Test-PendingName {
param ( [ string ] $Value )
if ( [ string ] :: IsNullOrWhiteSpace ( $Value ) ) {
return $true
}
return ( $Value -match " 待指定|待确认|待复核|占位|示例 " )
}
function Convert-OverallStatusText {
param ( [ string ] $Status )
switch ( $Status ) {
" PASS " { return " 通过 " }
" WARN " { return " 通过但有警告 " }
" FAIL " { return " 未通过 " }
" BLOCKED " { return " 阻塞 " }
default { return $Status }
}
}
function Convert-CheckStatusText {
param ( [ string ] $Status )
switch ( $Status ) {
" pass " { return " 通过 " }
" fail " { return " 失败 " }
" warn " { return " 警告 " }
" skip " { return " 跳过 " }
" blocked " { return " 阻塞 " }
default { return $Status }
}
}
if ( -not ( Test-Path " $HOME \.Codex\skills\gstack\bin " ) ) {
Add-Check -Key " gstack " -Label " gstack 前置检查 " -Status " fail " -Detail " gstack 缺失 "
} else {
Add-Check -Key " gstack " -Label " gstack 前置检查 " -Status " pass " -Detail " GSTACK_OK "
}
$branch = ( git -C $repoRoot rev-parse - -abbrev -ref HEAD ) . Trim ( )
$commit = ( git -C $repoRoot rev-parse HEAD ) . Trim ( )
$remoteUrl = ( git -C $repoRoot remote get-url origin ) . Trim ( )
$gitStatus = git -C $repoRoot status - -short
( $gitStatus -join [ Environment ] :: NewLine ) | Set-Content -Encoding UTF8 -Path $gitStatusPath
if ( $remoteUrl -match " 192\.168\.3\.90 " ) {
Add-Check -Key " origin_remote " -Label " origin 远端仓库 " -Status " pass " -Detail " origin 指向 192.168.3.90 " -Meta @ { branch = $branch ; commit = $commit ; remote = $remoteUrl }
} else {
Add-Check -Key " origin_remote " -Label " origin 远端仓库 " -Status " fail " -Detail " origin 未指向 192.168.3.90 " -Meta @ { branch = $branch ; commit = $commit ; remote = $remoteUrl }
}
if ( $gitStatus ) {
Add-Check -Key " working_tree " -Label " 工作区状态 " -Status " warn " -Required $false -Detail " 工作区存在未提交改动;回收预检按证据记录 " -Meta @ { artifact = $gitStatusPath }
} else {
Add-Check -Key " working_tree " -Label " 工作区状态 " -Status " pass " -Detail " 工作区干净 " -Meta @ { artifact = $gitStatusPath }
}
if ( Test-Path -LiteralPath $ReturnRoot -PathType Container ) {
Add-Check -Key " return_root " -Label " 回收文件目录 " -Status " pass " -Detail " 回收文件目录存在 " -Meta @ { path = $ReturnRoot }
} else {
Add-Check -Key " return_root " -Label " 回收文件目录 " -Status " fail " -Detail " 回收文件目录不存在 " -Meta @ { path = $ReturnRoot }
}
$registerRows = Import-CsvRows -Path $ReviewRegisterPath
$registerByReviewId = @ { }
foreach ( $registerRow in $registerRows ) {
if ( $registerRow . review_id ) {
$registerByReviewId [ $registerRow . review_id ] = $registerRow
}
}
$returnFiles = @ (
[ pscustomobject ] @ { kind = " legal " ; path = Join-Path $ReturnRoot " legal-review-result-return.csv " ; required_columns = $reviewRequiredColumns } ,
[ pscustomobject ] @ { kind = " business " ; path = Join-Path $ReturnRoot " business-review-result-return.csv " ; required_columns = $reviewRequiredColumns } ,
[ pscustomobject ] @ { kind = " ack " ; path = Join-Path $ReturnRoot " handoff-ack-return.csv " ; required_columns = $ackRequiredColumns }
)
$allReviewReturns = New-Object System . Collections . Generic . List [ object ]
$ackReturns = @ ( )
foreach ( $returnFile in $returnFiles ) {
$exists = Test-Path -LiteralPath $returnFile . path -PathType Leaf
$missing = if ( $exists ) { Test-RequiredColumns -Path $returnFile . path -Columns $returnFile . required_columns } else { $returnFile . required_columns }
$rows = if ( $exists ) { Import-CsvRows -Path $returnFile . path } else { @ ( ) }
$sourceRows . Add ( [ pscustomobject][ordered ] @ {
kind = $returnFile . kind
path = $returnFile . path
exists = $exists
rows = $rows . Count
missing_columns = ( $missing -join " ; " )
status = if ( $exists -and $missing . Count -eq 0 ) { " ready " } else { " invalid " }
} ) | Out-Null
if ( -not $exists ) {
Add-Blocker -Kind $returnFile . kind -Id $returnFile . path -Severity " P0 " -Blocker " 回收文件缺失 " -Evidence $returnFile . path
} elseif ( $missing . Count -gt 0 ) {
Add-Blocker -Kind $returnFile . kind -Id $returnFile . path -Severity " P0 " -Blocker " 回收文件字段缺失 " -Evidence ( $missing -join " , " )
}
if ( $returnFile . kind -eq " ack " ) {
$ackReturns = $rows
} else {
foreach ( $row in $rows ) {
$allReviewReturns . Add ( $row ) | Out-Null
}
}
}
$sourceRows | Export-Csv -LiteralPath $sourceManifestCsv -NoTypeInformation -Encoding UTF8
foreach ( $row in $allReviewReturns ) {
$reviewResult = if ( $row . review_result ) { $row . review_result . Trim ( ) } else { " " }
$reviewId = [ string ] $row . review_id
$inRegister = $registerByReviewId . ContainsKey ( $reviewId )
$resultAllowed = $allowedReviewResults -contains $reviewResult
$reviewerReady = -not ( Test-PendingName -Value $row . reviewer )
$dateReady = -not [ string ] :: IsNullOrWhiteSpace ( $row . review_date )
$evidenceReady = -not [ string ] :: IsNullOrWhiteSpace ( $row . evidence_path )
$completed = ( $reviewResult -ne " PENDING " -and $resultAllowed -and $reviewerReady -and $dateReady -and $evidenceReady )
$mergeAction = if ( $completed ) { " READY_FOR_DRY_RUN_APPLY " } else { " HOLD " }
if ( -not $inRegister ) {
Add-Blocker -Kind " review_return " -Id $reviewId -Severity " P0 " -Blocker " 复核编号不在专家复核登记表中 " -Evidence $reviewId
}
if ( -not $resultAllowed ) {
Add-Blocker -Kind " review_return " -Id $reviewId -Severity " P0 " -Blocker " 复核结果枚举非法 " -Evidence $reviewResult
}
if ( $reviewResult -eq " PENDING " ) {
Add-Blocker -Kind " review_return " -Id $reviewId -Severity " P0 " -Blocker " 复核结果仍为 PENDING " -Evidence $reviewId
} elseif ( -not $completed ) {
Add-Blocker -Kind " review_return " -Id $reviewId -Severity " P0 " -Blocker " 复核结果缺少复核人、日期或证据路径 " -Evidence " reviewer= $( $row . reviewer ) ; date= $( $row . review_date ) ; evidence= $( $row . evidence_path ) "
}
$validationRows . Add ( [ pscustomobject][ordered ] @ {
kind = " review_return "
review_id = $reviewId
asset_id = $row . asset_id
reviewer_role = $row . reviewer_role
reviewer = $row . reviewer
review_result = $reviewResult
in_register = $inRegister
result_allowed = $resultAllowed
reviewer_ready = $reviewerReady
date_ready = $dateReady
evidence_ready = $evidenceReady
completed = $completed
merge_action = $mergeAction
} ) | Out-Null
$current = if ( $inRegister ) { $registerByReviewId [ $reviewId ] } else { $null }
$diffRows . Add ( [ pscustomobject][ordered ] @ {
review_id = $reviewId
field = " review_result "
current_value = if ( $current ) { $current . review_result } else { " " }
returned_value = $reviewResult
merge_action = $mergeAction
} ) | Out-Null
$mergeRows . Add ( [ pscustomobject][ordered ] @ {
review_id = $reviewId
asset_type = $row . asset_type
asset_id = $row . asset_id
merge_action = $mergeAction
next_gate = " apply-phase13-review-results.ps1 "
notes = if ( $completed ) { " 可进入 DryRun 回填校验 " } else { " 等待真实复核结果齐套 " }
} ) | Out-Null
}
foreach ( $ack in $ackReturns ) {
$acknowledged = Test-Truthy -Value $ack . acknowledged
$dateReady = -not [ string ] :: IsNullOrWhiteSpace ( $ack . ack_date )
$recipientReady = -not ( Test-PendingName -Value $ack . recipient )
$completed = ( $acknowledged -and $dateReady -and $recipientReady )
if ( -not $completed ) {
Add-Blocker -Kind " ack_return " -Id $ack . work_order_id -Severity " P0 " -Blocker " 签收回收未完成 " -Evidence " acknowledged= $( $ack . acknowledged ) ; ack_date= $( $ack . ack_date ) ; recipient= $( $ack . recipient ) "
}
$validationRows . Add ( [ pscustomobject][ordered ] @ {
kind = " ack_return "
review_id = $ack . work_order_id
asset_id = " "
reviewer_role = $ack . recipient_role
reviewer = $ack . recipient
review_result = if ( $acknowledged ) { " ACKNOWLEDGED " } else { " PENDING " }
in_register = $true
result_allowed = $true
reviewer_ready = $recipientReady
date_ready = $dateReady
evidence_ready = $true
completed = $completed
merge_action = if ( $completed ) { " READY_FOR_PROGRESS_GATE " } else { " HOLD " }
} ) | Out-Null
}
$validationRows | Export-Csv -LiteralPath $validationBoardCsv -NoTypeInformation -Encoding UTF8
$blockerRows | Export-Csv -LiteralPath $blockersCsv -NoTypeInformation -Encoding UTF8
$diffRows | Export-Csv -LiteralPath $diffPreviewCsv -NoTypeInformation -Encoding UTF8
$mergeRows | Export-Csv -LiteralPath $mergePlanCsv -NoTypeInformation -Encoding UTF8
$completedReviewReturns = @ ( $validationRows | Where-Object { $_ . kind -eq " review_return " -and $_ . completed } ) . Count
$pendingReviewReturns = @ ( $validationRows | Where-Object { $_ . kind -eq " review_return " -and -not $_ . completed } ) . Count
$completedAckReturns = @ ( $validationRows | Where-Object { $_ . kind -eq " ack_return " -and $_ . completed } ) . Count
$pendingAckReturns = @ ( $validationRows | Where-Object { $_ . kind -eq " ack_return " -and -not $_ . completed } ) . Count
$mergeReadyRows = @ ( $mergeRows | Where-Object { $_ . merge_action -eq " READY_FOR_DRY_RUN_APPLY " } ) . Count
if ( $sourceRows . Count -eq 3 -and @ ( $sourceRows | Where-Object { $_ . status -eq " ready " } ) . Count -eq 3 ) {
Add-Check -Key " return_files " -Label " 回收文件结构 " -Status " pass " -Detail " 回收文件结构齐套 "
} else {
Add-Check -Key " return_files " -Label " 回收文件结构 " -Status " fail " -Detail " 回收文件结构缺失或字段不完整 "
}
if ( $validationRows . Count -gt 0 ) {
Add-Check -Key " validation_board " -Label " 回收预检看板 " -Status " pass " -Detail " 已生成 $( $validationRows . Count ) 条回收预检记录 "
} else {
Add-Check -Key " validation_board " -Label " 回收预检看板 " -Status " fail " -Detail " 未生成回收预检记录 "
}
if ( $completedReviewReturns -gt 0 -and $pendingReviewReturns -eq 0 -and $pendingAckReturns -eq 0 ) {
Add-Check -Key " return_completion " -Label " 真实回收结果齐套 " -Status " pass " -Detail " 复核与签收回收结果均已齐套 "
} else {
Add-Check -Key " return_completion " -Label " 真实回收结果齐套 " -Status " blocked " -Detail " completed_reviews= $completedReviewReturns ; pending_reviews= $pendingReviewReturns ; completed_ack= $completedAckReturns ; pending_ack= $pendingAckReturns "
}
if ( $blockerRows . Count -eq 0 ) {
Add-Check -Key " return_blockers " -Label " 回收预检阻塞项 " -Status " pass " -Detail " 无回收预检阻塞项 "
} else {
Add-Check -Key " return_blockers " -Label " 回收预检阻塞项 " -Status " blocked " -Detail " 回收预检阻塞项= $( $blockerRows . Count ) "
}
$failedRequired = @ ( $checks | Where-Object { $_ . required -and $_ . status -eq " fail " } ) . Count
$blockedRequired = @ ( $checks | Where-Object { $_ . required -and $_ . status -eq " blocked " } ) . Count
$warnings = @ ( $checks | Where-Object { $_ . status -eq " warn " } ) . Count
$overallStatus = if ( $failedRequired -gt 0 ) {
" FAIL "
} elseif ( $blockedRequired -gt 0 ) {
" BLOCKED "
} elseif ( $warnings -gt 0 ) {
" WARN "
} else {
" PASS "
}
$metrics = [ ordered ] @ {
legal_return_rows = @ ( $validationRows | Where-Object { $_ . kind -eq " review_return " -and $_ . reviewer_role -eq " 法务 " } ) . Count
business_return_rows = @ ( $validationRows | Where-Object { $_ . kind -eq " review_return " -and $_ . reviewer_role -eq " 业务 " } ) . Count
ack_return_rows = @ ( $validationRows | Where-Object { $_ . kind -eq " ack_return " } ) . Count
validation_rows = $validationRows . Count
completed_review_returns = $completedReviewReturns
pending_review_returns = $pendingReviewReturns
completed_ack_returns = $completedAckReturns
pending_ack_returns = $pendingAckReturns
merge_ready_rows = $mergeReadyRows
blocker_count = $blockerRows . Count
}
$summary = [ ordered ] @ {
name = " phase13-review-return-preflight "
status = $overallStatus
generated_at = ( Get-Date ) . ToUniversalTime ( ) . ToString ( " o " )
branch = $branch
commit = $commit
remote = $remoteUrl
return_root = $ReturnRoot
review_register_path = $ReviewRegisterPath
checks = $checks . ToArray ( )
metrics = $metrics
artifacts = [ ordered ] @ {
summary_json = $summaryJson
summary_md = $summaryMd
source_manifest = $sourceManifestCsv
validation_board = $validationBoardCsv
blockers = $blockersCsv
diff_preview = $diffPreviewCsv
merge_plan = $mergePlanCsv
git_status = $gitStatusPath
}
totals = [ ordered ] @ {
total_checks = $checks . Count
failed_required = $failedRequired
blocked_required = $blockedRequired
warnings = $warnings
}
}
Save-Json -Path $summaryJson -Value $summary
$md = New-Object System . Collections . Generic . List [ string ]
$md . Add ( " # 阶段 13 回收结果预检与合并计划门禁 " ) | Out-Null
$md . Add ( " " ) | Out-Null
$md . Add ( " - 门禁状态: $( Convert-OverallStatusText -Status $overallStatus ) ( $overallStatus ) " ) | Out-Null
$md . Add ( " - 生成时间: $( $summary . generated_at ) " ) | Out-Null
$md . Add ( " - 分支: $branch " ) | Out-Null
$md . Add ( " - 提交: $commit " ) | Out-Null
$md . Add ( " - 回收目录: $ReturnRoot " ) | Out-Null
$md . Add ( " - 产物目录: $artifactDir " ) | Out-Null
$md . Add ( " " ) | Out-Null
$md . Add ( " ## 统计 " ) | Out-Null
$md . Add ( " " ) | Out-Null
$md . Add ( " | 指标 | 数量 | " ) | Out-Null
$md . Add ( " |---|---:| " ) | Out-Null
$md . Add ( " | 法务回收记录 | $( $metrics . legal_return_rows ) | " ) | Out-Null
$md . Add ( " | 业务回收记录 | $( $metrics . business_return_rows ) | " ) | Out-Null
$md . Add ( " | 签收回收记录 | $( $metrics . ack_return_rows ) | " ) | Out-Null
$md . Add ( " | 预检记录 | $( $metrics . validation_rows ) | " ) | Out-Null
$md . Add ( " | 已完成复核回收 | $( $metrics . completed_review_returns ) | " ) | Out-Null
$md . Add ( " | 待完成复核回收 | $( $metrics . pending_review_returns ) | " ) | Out-Null
$md . Add ( " | 待完成签收回收 | $( $metrics . pending_ack_returns ) | " ) | Out-Null
$md . Add ( " | 可进入 DryRun 回填 | $( $metrics . merge_ready_rows ) | " ) | Out-Null
$md . Add ( " | 阻塞项 | $( $metrics . blocker_count ) | " ) | Out-Null
$md . Add ( " " ) | Out-Null
$md . Add ( " ## 检查项 " ) | Out-Null
$md . Add ( " " ) | Out-Null
$md . Add ( " | 检查项 | 必需 | 状态 | 说明 | " ) | Out-Null
$md . Add ( " |---|---:|---|---| " ) | Out-Null
foreach ( $check in $checks ) {
$requiredText = if ( $check . required ) { " 是 " } else { " 否 " }
$md . Add ( " | $( $check . label ) | $requiredText | $( Convert-CheckStatusText -Status $check . status ) | $( $check . detail ) | " ) | Out-Null
}
$md . Add ( " " ) | Out-Null
$md . Add ( " ## 当前结论 " ) | Out-Null
$md . Add ( " " ) | Out-Null
if ( $overallStatus -eq " BLOCKED " ) {
$md . Add ( " 回收预检和合并计划已生成,但当前回收模板仍为 PENDING,不能进入真实回填。 " ) | Out-Null
} elseif ( $overallStatus -eq " PASS " ) {
$md . Add ( " 回收结果已通过预检,可进入 DryRun 回填校验。 " ) | Out-Null
} else {
$md . Add ( " 回收预检未完全通过,请查看阻塞项和合并计划。 " ) | Out-Null
}
$md | Set-Content -Encoding UTF8 -Path $summaryMd
Write-Host " PHASE13_REVIEW_RETURN_PREFLIGHT_ $overallStatus $artifactDir "
if ( $overallStatus -eq " FAIL " ) {
throw " 阶段 13 回收结果预检门禁未通过。查看: $summaryMd "
}
if ( $overallStatus -eq " BLOCKED " -and $FailOnBlocked ) {
throw " 阶段 13 回收结果预检门禁被阻塞。查看: $summaryMd "
}