Set-StrictMode -Version Latest
|
$ErrorActionPreference = "Stop"
|
|
$ProjectRoot = (Resolve-Path -LiteralPath ".").Path
|
$CaseId = "ANA-ROBOT-INDUSTRY-001"
|
$RunId = "RUN-ANA-ROBOT-THREEPIECE-OUTPUT-PREPASS-EVIDENCE-REVIEW-SYNC-001"
|
$BatchId = "BATCH-ANA-ROBOT-THREEPIECE-OUTPUT-PREPASS-EVIDENCE-REVIEW-SYNC-001"
|
$ReviewMessageId = "msg_20260705115832279_c8afb307"
|
$SourceMessageId = "msg_20260705114743635_423f7cfc"
|
$AuditId = "AUDIT-ANA-ROBOT-THREEPIECE-OUTPUT-PREPASS-EVIDENCE-001"
|
$NowStamp = "2026-07-05T12:02:00+08:00"
|
|
$CaseRoot = Join-Path $ProjectRoot "ana-data/cases/机器人案例/ANA-ROBOT-INDUSTRY-001"
|
$EvidenceDir = Join-Path $CaseRoot "evidence"
|
$ManifestDir = Join-Path $CaseRoot "manifest"
|
$OutputCoreDir = Join-Path $CaseRoot "outputs/核心文档"
|
$ResultDir = Join-Path $ProjectRoot "ana-data/result/机器人案例/ANA-ROBOT-INDUSTRY-001"
|
$AuditDocDir = Join-Path $ProjectRoot "ana-doc/机器人案例"
|
$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
|
function Read-Text($Path) {
|
return [System.IO.File]::ReadAllText((Resolve-Path -LiteralPath $Path).Path, [System.Text.Encoding]::UTF8)
|
}
|
|
function Write-Text($Path, $Text) {
|
[System.IO.File]::WriteAllText((Resolve-Path -LiteralPath $Path).Path, $Text, $Utf8NoBom)
|
}
|
|
function Rel-Path($Path) {
|
$full = (Resolve-Path -LiteralPath $Path).Path
|
$root = $ProjectRoot.TrimEnd("\")
|
return $full.Substring($root.Length + 1).Replace("\", "/")
|
}
|
|
function Get-Meta($RelPath) {
|
$full = Join-Path $ProjectRoot ($RelPath -replace "/", "\")
|
if (-not (Test-Path -LiteralPath $full)) {
|
throw "Missing artifact: $RelPath"
|
}
|
$file = Get-Item -LiteralPath $full
|
[pscustomobject]@{
|
sha256 = (Get-FileHash -LiteralPath $full -Algorithm SHA256).Hash.ToLowerInvariant()
|
bytes = [string]$file.Length
|
mtime = $file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") + "+08:00"
|
}
|
}
|
|
function Csv-Text($Rows) {
|
return ($Rows | ConvertTo-Csv -NoTypeInformation) -join "`r`n"
|
}
|
|
function Add-Section-IfMissing($Text, $Header, $Body) {
|
if ($Text.Contains($Header)) {
|
return $Text
|
}
|
return $Text.TrimEnd() + "`r`n`r`n" + $Header + "`r`n`r`n" + $Body.Trim() + "`r`n"
|
}
|
|
$nextPath = Join-Path $ManifestDir "next_action_list.csv"
|
$nextRows = @(Import-Csv -LiteralPath $nextPath)
|
foreach ($row in $nextRows) {
|
if ($row.action_id -eq "NEXT-ROBOT-032B") {
|
$row.output = "threepiece_ifr_html_fact_extract_20260705.csv; threepiece_032b_source_fetch_and_extract_status_20260705.csv; threepiece_output_prepass_gap_closure_20260705.csv; threepiece_output_prepass_evidence_package_20260705.csv; threepiece_output_prepass_evidence_summary_20260705.json; review_result $ReviewMessageId / $AuditId"
|
$row.status = "CONDITIONALLY_PASSED_THREEPIECE_OUTPUT_PREPASS_EVIDENCE_READY_FOR_OUTPUT_REVIEW_PACKAGE_NOT_OUTPUT_PASS"
|
}
|
if ($row.action_id -eq "NEXT-ROBOT-032C") {
|
$row.input = "$AuditId; threepiece_output_prepass_evidence_package_20260705.csv; threepiece_output_prepass_gap_closure_20260705.csv; case_evidence_map.csv; migration_manifest.csv"
|
$row.output = "三件套输出通过审核包待准备;必须单独列出未闭环缺口和降读字段;不得自动视为输出通过"
|
$row.status = "QUEUED_AFTER_032B_CONDITIONAL_PASS_PREPARE_OUTPUT_REVIEW_PACKAGE_NOT_OUTPUT_PASS"
|
}
|
}
|
[System.IO.File]::WriteAllText($nextPath, (Csv-Text $nextRows) + "`r`n", $Utf8NoBom)
|
|
$reviewSyncPath = Join-Path $EvidenceDir "threepiece_output_prepass_evidence_review_sync_20260705.json"
|
$reviewSync = [ordered]@{
|
case_id = $CaseId
|
action_id = "NEXT-ROBOT-032B"
|
run_id = $RunId
|
source_review_message = $ReviewMessageId
|
source_submission_message = $SourceMessageId
|
source_audit_id = $AuditId
|
synced_at = $NowStamp
|
review_conclusion = "CONDITIONALLY_PASSED"
|
allowed_next = @(
|
"作为后续输出通过审核包输入",
|
"将 NEXT-ROBOT-032C 从等待复审调整为可准备输出通过审核包",
|
"后续输出包必须单独列出仍未闭环缺口和降读字段"
|
)
|
prohibited = @(
|
"输出通过",
|
"覆盖完整",
|
"对外交付",
|
"完成状态",
|
"正式扩池",
|
"正式公司池确认",
|
"强字段升级"
|
)
|
retained_gates = @(
|
"IFR PDF 后续如引用页码、表格或正文事实,必须补人工下载回执、替代官方 PDF 或其他官方可复核快照。",
|
"MIR/Omdia/智元/AMR/ASP/BOM/公司强字段缺口不得因本轮补证包升级。",
|
"NEXT-ROBOT-032C 可准备输出通过审核包,但不得自动视为输出通过。"
|
)
|
}
|
[System.IO.File]::WriteAllText($reviewSyncPath, (($reviewSync | ConvertTo-Json -Depth 8) + "`r`n"), $Utf8NoBom)
|
|
$threepieceArtifacts = @(
|
"ana-data/cases/机器人案例/ANA-ROBOT-INDUSTRY-001/outputs/核心文档/机器人报告索引.md",
|
"ana-data/cases/机器人案例/ANA-ROBOT-INDUSTRY-001/outputs/核心文档/机器人的产业链总览.md",
|
"ana-data/cases/机器人案例/ANA-ROBOT-INDUSTRY-001/outputs/核心文档/机器人的市场情况总览.md"
|
)
|
|
$evidenceMapPath = Join-Path $EvidenceDir "case_evidence_map.csv"
|
$evidenceRows = @(Import-Csv -LiteralPath $evidenceMapPath)
|
foreach ($row in $evidenceRows) {
|
if ($threepieceArtifacts -contains $row.artifact) {
|
$row.evidence_status = "THREEPIECE_OUTPUT_PREPASS_EVIDENCE_CONDITIONALLY_PASSED_READY_FOR_OUTPUT_REVIEW_PACKAGE_NOT_OUTPUT_PASS"
|
$row.evidence_entry = "threepiece_ifr_html_fact_extract_20260705.csv; threepiece_032b_source_fetch_and_extract_status_20260705.csv; threepiece_output_prepass_gap_closure_20260705.csv; threepiece_output_prepass_evidence_package_20260705.csv; threepiece_output_prepass_evidence_summary_20260705.json; threepiece_output_prepass_evidence_review_sync_20260705.json"
|
$row.review_status = "CONDITIONALLY_PASSED_NOT_OUTPUT_PASS"
|
}
|
}
|
[System.IO.File]::WriteAllText($evidenceMapPath, (Csv-Text $evidenceRows) + "`r`n", $Utf8NoBom)
|
|
$migrationPath = Join-Path $ManifestDir "migration_manifest.csv"
|
$migrationRows = @(Import-Csv -LiteralPath $migrationPath)
|
foreach ($row in $migrationRows) {
|
if ($threepieceArtifacts -contains $row.target) {
|
$row.status = "FROZEN_FORMAL_DRAFT_THREEPIECE_OUTPUT_PREPASS_EVIDENCE_CONDITIONALLY_PASSED_READY_FOR_OUTPUT_REVIEW_PACKAGE"
|
$row.conclusion_strength = "DRAFT_FOR_REVIEW_PENDING_OUTPUT_REVIEW_STRONG_FIELDS_RETAINED_AS_GAPS_NOT_OUTPUT_PASS"
|
$row.next_action = "准备 NEXT-ROBOT-032C 三件套输出通过审核包;必须列出 IFR PDF、MIR/Omdia、AMR/ASP/BOM/公司强字段等未闭环缺口;不得自动视为输出通过、覆盖完整、对外交付或强字段升级。"
|
}
|
}
|
[System.IO.File]::WriteAllText($migrationPath, (Csv-Text $migrationRows) + "`r`n", $Utf8NoBom)
|
|
$coreDocs = @(
|
(Join-Path $OutputCoreDir "机器人报告索引.md"),
|
(Join-Path $OutputCoreDir "机器人的产业链总览.md"),
|
(Join-Path $OutputCoreDir "机器人的市场情况总览.md")
|
)
|
$coreHeader = "## 0.6 NEXT-ROBOT-032B 复审承接"
|
$coreBody = @"
|
reviewer 已在 $ReviewMessageId / $AuditId 对 NEXT-ROBOT-032B 三件套输出通过前补证包给出有条件通过。该补证包可作为后续输出通过审核包输入,并允许 NEXT-ROBOT-032C 从等待复审调整为可准备输出通过审核包。
|
|
本结论不批准输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。后续如提交输出通过审核包,必须单独列出 IFR PDF 页码级抽取、MIR 原始报告、Omdia 原始报告、AMR/ASP/BOM/公司强字段等未闭环缺口,并说明仍降读的字段。
|
"@
|
foreach ($doc in $coreDocs) {
|
$text = Read-Text $doc
|
$text = $text.Replace("THREEPIECE_OUTPUT_PREPASS_EVIDENCE_PREPARED", "THREEPIECE_OUTPUT_PREPASS_EVIDENCE_CONDITIONALLY_PASSED")
|
$text = $text.Replace("NEXT_ROBOT_032B_REVIEW_REQUEST_PREPARED", "NEXT_ROBOT_032B_CONDITIONALLY_PASSED")
|
$text = Add-Section-IfMissing $text $coreHeader $coreBody
|
Write-Text $doc $text
|
}
|
|
$resultPath = Join-Path $ResultDir "result_index.md"
|
$resultText = Read-Text $resultPath
|
$resultText = $resultText.Replace("THREEPIECE_OUTPUT_PREPASS_EVIDENCE_PREPARED", "THREEPIECE_OUTPUT_PREPASS_EVIDENCE_CONDITIONALLY_PASSED")
|
$resultText = $resultText.Replace("NEXT_ROBOT_032B_REVIEW_REQUEST_PREPARED", "NEXT_ROBOT_032B_CONDITIONALLY_PASSED")
|
$resultHeader = "## 2026-07-05 三件套输出通过前补证包复审承接"
|
$resultBody = @"
|
reviewer 已在 $ReviewMessageId / $AuditId 对 NEXT-ROBOT-032B 给出有条件通过。该结论只允许将三件套输出通过前补证包作为后续输出通过审核包输入;不批准输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。
|
|
NEXT-ROBOT-032C 已调整为可准备输出通过审核包。该审核包必须单独列出仍未闭环的 IFR PDF 页码级抽取、MIR 原始报告、Omdia 原始报告、AMR/ASP/BOM/公司强字段缺口,并说明哪些字段继续降读。
|
"@
|
$resultText = Add-Section-IfMissing $resultText $resultHeader $resultBody
|
Write-Text $resultPath $resultText
|
|
$remainingPath = Join-Path $ManifestDir "remaining_work_plan_20260704.md"
|
$remainingText = Read-Text $remainingPath
|
$remainingText = $remainingText.Replace("| 6B | NEXT-ROBOT-032B | 三件套输出通过前补证包 | IFR HTML 行级抽取、PDF 完整性回执、MIR/Omdia/AMR/ASP/公司强字段补证缺口闭环 | REVIEW_REQUEST_PREPARED | 只申请补证包复审;不得申请输出通过或强字段升级 |", "| 6B | NEXT-ROBOT-032B | 三件套输出通过前补证包 | IFR HTML 行级抽取、PDF 完整性回执、MIR/Omdia/AMR/ASP/公司强字段补证缺口闭环 | CONDITIONALLY_PASSED | reviewer 已允许作为输出通过审核包输入;仍不批准输出通过或强字段升级 |")
|
if (-not $remainingText.Contains("| 6C | NEXT-ROBOT-032C |")) {
|
$remainingText = $remainingText.Replace("| 7 | NEXT-ROBOT-033 | 英搏尔 + 12 个相邻候选 | 补资料复核、继续排除/降级/候选池决策 | QUEUED | 重新进入候选池需单独复审 |", "| 6C | NEXT-ROBOT-032C | 三件套输出通过审核包准备 | 汇总 032B 证据包、仍未闭环缺口和继续降读字段 | QUEUED | 可准备但不得自动视为输出通过;完成后必须另行送审 |`r`n| 7 | NEXT-ROBOT-033 | 英搏尔 + 12 个相邻候选 | 补资料复核、继续排除/降级/候选池决策 | QUEUED | 重新进入候选池需单独复审 |")
|
}
|
$remainingText = $remainingText.Replace("- 当前状态:THREEPIECE_OUTPUT_PREPASS_EVIDENCE_PREPARED_PENDING_REVIEW_NOT_OUTPUT_PASS;不申请输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。", "- 当前状态:THREEPIECE_OUTPUT_PREPASS_EVIDENCE_CONDITIONALLY_PASSED_READY_FOR_OUTPUT_REVIEW_PACKAGE_NOT_OUTPUT_PASS;可作为后续输出通过审核包输入,但仍不批准输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。")
|
$remainingHeader = "## 19. 复审状态更新(AUDIT-ANA-ROBOT-THREEPIECE-OUTPUT-PREPASS-EVIDENCE-001)"
|
$remainingBody = @"
|
- 来源消息:$ReviewMessageId。
|
- 复审结论:NEXT-ROBOT-032B 三件套输出通过前补证包有条件通过,可作为后续输出通过审核包输入。
|
- 动作同步:NEXT-ROBOT-032B 标记为有条件通过;NEXT-ROBOT-032C 从等待复审调整为可准备输出通过审核包。
|
- 继续禁止:输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认,以及 MIR/Omdia/智元/AMR/ASP/BOM/公司强字段升级。
|
- 下一步要求:若准备 032C,必须单独列出 IFR PDF 页码级抽取、MIR 原始报告、Omdia 原始报告、AMR/ASP/BOM/公司强字段等未闭环缺口和继续降读字段。
|
"@
|
$remainingText = Add-Section-IfMissing $remainingText $remainingHeader $remainingBody
|
Write-Text $remainingPath $remainingText
|
|
$execLogPath = Join-Path $AuditDocDir "案例执行日志.md"
|
$execText = Read-Text $execLogPath
|
$execHeader = "## 2026-07-05 AUDIT-ANA-ROBOT-THREEPIECE-OUTPUT-PREPASS-EVIDENCE-001 承接"
|
$execBody = @"
|
承接 reviewer 消息 $ReviewMessageId / $AuditId:NEXT-ROBOT-032B 三件套输出通过前补证包复审结论为有条件通过。
|
|
- 已同步:next_action_list、remaining_work_plan、result_index、机器人报告索引、三件套文档、case_evidence_map 和 migration_manifest。
|
- 新增:threepiece_output_prepass_evidence_review_sync_20260705.json,记录允许事项、禁止事项和保留门禁。
|
- 后续:NEXT-ROBOT-032C 可准备输出通过审核包;仍不得自动视为输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。
|
"@
|
$execText = Add-Section-IfMissing $execText $execHeader $execBody
|
Write-Text $execLogPath $execText
|
|
$artifactManifestPath = Join-Path $ManifestDir "artifact_manifest.csv"
|
$artifactRows = @(Import-Csv -LiteralPath $artifactManifestPath)
|
$changedRel = @(
|
(Rel-Path $nextPath),
|
(Rel-Path $reviewSyncPath),
|
(Rel-Path $evidenceMapPath),
|
(Rel-Path $migrationPath),
|
(Rel-Path $coreDocs[0]),
|
(Rel-Path $coreDocs[1]),
|
(Rel-Path $coreDocs[2]),
|
(Rel-Path $resultPath),
|
(Rel-Path $remainingPath),
|
(Rel-Path $execLogPath)
|
)
|
$artifactRows = @($artifactRows | Where-Object { $_.run_id -ne $RunId })
|
foreach ($rel in $changedRel) {
|
$meta = Get-Meta $rel
|
$artifactRows += [pscustomobject]@{
|
case_id = $CaseId
|
run_id = $RunId
|
batch_id = $BatchId
|
artifact_path = $rel
|
sha256 = $meta.sha256
|
bytes = $meta.bytes
|
mtime = $meta.mtime
|
}
|
}
|
foreach ($row in $artifactRows) {
|
if ([string]::IsNullOrWhiteSpace($row.artifact_path)) { continue }
|
$full = Join-Path $ProjectRoot ($row.artifact_path -replace "/", "\")
|
if (Test-Path -LiteralPath $full) {
|
$meta = Get-Meta $row.artifact_path
|
$row.sha256 = $meta.sha256
|
$row.bytes = $meta.bytes
|
$row.mtime = $meta.mtime
|
}
|
}
|
[System.IO.File]::WriteAllText($artifactManifestPath, (Csv-Text $artifactRows) + "`r`n", $Utf8NoBom)
|
|
$manifestRows = @(Import-Csv -LiteralPath $artifactManifestPath)
|
$missing = 0
|
$emptySha = 0
|
$mismatch = 0
|
foreach ($row in $manifestRows) {
|
if ([string]::IsNullOrWhiteSpace($row.sha256)) { $emptySha++ }
|
$full = Join-Path $ProjectRoot ($row.artifact_path -replace "/", "\")
|
if (-not (Test-Path -LiteralPath $full)) {
|
$missing++
|
continue
|
}
|
$actual = (Get-FileHash -LiteralPath $full -Algorithm SHA256).Hash.ToLowerInvariant()
|
if ($actual -ne $row.sha256) { $mismatch++ }
|
}
|
$scanPatterns = '\$\(|\$extract|\$ReviewMessageId|\$AuditId|password|token|secret|123456|连接串|cookie'
|
$scanHits = 0
|
foreach ($rel in $changedRel) {
|
$full = Join-Path $ProjectRoot ($rel -replace "/", "\")
|
if (-not (Test-Path -LiteralPath $full)) { continue }
|
$txt = Read-Text $full
|
if ($txt -match $scanPatterns) { $scanHits++ }
|
}
|
[pscustomobject]@{
|
run_id = $RunId
|
next_032b_status = (@(Import-Csv -LiteralPath $nextPath) | Where-Object { $_.action_id -eq "NEXT-ROBOT-032B" }).status
|
next_032c_status = (@(Import-Csv -LiteralPath $nextPath) | Where-Object { $_.action_id -eq "NEXT-ROBOT-032C" }).status
|
manifest_rows = $manifestRows.Count
|
manifest_missing = $missing
|
manifest_empty_sha = $emptySha
|
manifest_mismatch = $mismatch
|
changed_artifacts = $changedRel.Count
|
scan_hits = $scanHits
|
}
|