Cai
2026-08-20 f046e00dff100e7510089e4e568f2165ca8a199e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
 
$ProjectRoot = (Resolve-Path -LiteralPath ".").Path
$CaseId = "ANA-ROBOT-INDUSTRY-001"
$RunId = "RUN-ANA-ROBOT-THREEPIECE-ACTUAL-SOURCE-TRACE-REVIEW-SYNC-001"
$BatchId = "BATCH-ANA-ROBOT-THREEPIECE-ACTUAL-SOURCE-TRACE-REVIEW-SYNC-001"
$ReviewMessageId = "msg_20260705111846575_e7e2c128"
$AuditId = "AUDIT-ANA-ROBOT-THREEPIECE-ACTUAL-SOURCE-TRACE-001"
$NowStamp = "2026-07-05T11:25:00+08:00"
$MtimeStamp = "2026-07-05 11:25: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-FileMeta($RelPath) {
    $full = Join-Path $ProjectRoot ($RelPath -replace "/", "\")
    if (-not (Test-Path -LiteralPath $full)) {
        throw "Missing artifact: $RelPath"
    }
    $sha = (Get-FileHash -LiteralPath $full -Algorithm SHA256).Hash.ToLowerInvariant()
    $file = Get-Item -LiteralPath $full
    [pscustomobject]@{
        sha256 = $sha
        bytes = [string]$file.Length
        mtime = $file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") + "+08:00"
    }
}
 
function ConvertTo-CsvText($Rows) {
    return ($Rows | ConvertTo-Csv -NoTypeInformation) -join "`r`n"
}
 
function Add-OrReplaceSection($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"
}
 
# 1. next_action_list.csv: close 032A review result and queue 032B.
$nextPath = Join-Path $ManifestDir "next_action_list.csv"
$nextRows = @(Import-Csv -LiteralPath $nextPath)
foreach ($row in $nextRows) {
    if ($row.action_id -eq "NEXT-ROBOT-032A") {
        $row.output = "threepiece_actual_source_trace_evidence_20260705.csv; threepiece_actual_source_gap_retained_20260705.csv; threepiece_public_source_snapshot_manifest_20260705.csv; threepiece_actual_source_trace_summary_20260705.json; review_result $ReviewMessageId / $AuditId"
        $row.status = "CONDITIONALLY_PASSED_THREEPIECE_ACTUAL_SOURCE_TRACE_READY_FOR_FOLLOWUP_EVIDENCE_NOT_OUTPUT_PASS"
    }
}
if (-not ($nextRows | Where-Object { $_.action_id -eq "NEXT-ROBOT-032B" })) {
    $nextRows += [pscustomobject]@{
        priority = "P0"
        action_id = "NEXT-ROBOT-032B"
        action = "三件套输出通过前补证包:IFR PDF 页码级抽取、MIR/Omdia/AMR/ASP/公司强字段补证缺口闭环"
        owner_role = "case_analysis.analyst.cai"
        input = "$AuditId; threepiece_actual_source_trace_evidence_20260705.csv; threepiece_actual_source_gap_retained_20260705.csv; threepiece_public_source_snapshot_manifest_20260705.csv"
        output = "输出通过前补证包待建;仍不申请输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级"
        status = "QUEUED_AFTER_THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONAL_PASS_NOT_OUTPUT_PASS"
    }
}
[System.IO.File]::WriteAllText($nextPath, (ConvertTo-CsvText $nextRows) + "`r`n", $Utf8NoBom)
 
# 2. evidence map and migration manifest shared rows.
$evidenceMapPath = Join-Path $EvidenceDir "case_evidence_map.csv"
$evidenceRows = @(Import-Csv -LiteralPath $evidenceMapPath)
$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"
)
foreach ($row in $evidenceRows) {
    if ($threepieceArtifacts -contains $row.artifact) {
        $row.evidence_status = "THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED_FOR_FOLLOWUP_EVIDENCE_NOT_OUTPUT_PASS"
        $row.evidence_entry = "threepiece_actual_source_trace_evidence_20260705.csv; threepiece_actual_source_gap_retained_20260705.csv; threepiece_public_source_snapshot_manifest_20260705.csv; threepiece_actual_source_trace_summary_20260705.json; threepiece_actual_source_trace_review_sync_20260705.json"
        $row.review_status = "CONDITIONALLY_PASSED_NOT_OUTPUT_PASS"
    }
}
[System.IO.File]::WriteAllText($evidenceMapPath, (ConvertTo-CsvText $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_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED_PENDING_FOLLOWUP_EVIDENCE"
        $row.conclusion_strength = "DRAFT_FOR_REVIEW_PENDING_OUTPUT_REVIEW_STRONG_FIELDS_RETAINED_AS_GAPS_NOT_OUTPUT_PASS"
        $row.next_action = "执行 NEXT-ROBOT-032B 输出通过前补证包准备;IFR PDF 若引用页码/表格/正文事实需页码级抽取,MIR/Omdia/AMR/ASP/公司强字段继续缺口闭环;不申请输出通过、覆盖完整、对外交付或强字段升级。"
    }
}
[System.IO.File]::WriteAllText($migrationPath, (ConvertTo-CsvText $migrationRows) + "`r`n", $Utf8NoBom)
 
# 3. review sync JSON.
$reviewSyncPath = Join-Path $EvidenceDir "threepiece_actual_source_trace_review_sync_20260705.json"
$reviewSync = [ordered]@{
    case_id = $CaseId
    action_id = "NEXT-ROBOT-032A"
    run_id = $RunId
    source_review_message = $ReviewMessageId
    source_audit_id = $AuditId
    synced_at = $NowStamp
    review_conclusion = "CONDITIONALLY_PASSED"
    allowed_next = @(
        "作为后续输出通过前补证输入",
        "准备 NEXT-ROBOT-032B 输出通过前补证包",
        "继续页码级抽取、研报来源补强、官方快照或缺口闭环"
    )
    prohibited = @(
        "输出通过",
        "覆盖完整",
        "对外交付",
        "完成状态",
        "正式扩池",
        "正式公司池确认",
        "强字段升级"
    )
    retained_gates = @(
        "IFR 官方快照只支持全球工业机器人有限市场线索;如引用 PDF 页码、表格或正文事实,必须补页码级抽取。",
        "MIR 协作机器人、Omdia 人形出货、智元引用、AMR、ASP、公司收入、客户供应、主供/独供、BOM 和利润池继续不得升级为强字段事实。",
        "NEXT-ROBOT-032A 已同步为已复审/有条件通过/可作为后续补证输入。"
    )
}
$reviewSyncJson = $reviewSync | ConvertTo-Json -Depth 8
[System.IO.File]::WriteAllText($reviewSyncPath, $reviewSyncJson + "`r`n", $Utf8NoBom)
 
# 4. Core documents and shared indexes.
$coreDocPaths = @(
    (Join-Path $OutputCoreDir "机器人报告索引.md"),
    (Join-Path $OutputCoreDir "机器人的产业链总览.md"),
    (Join-Path $OutputCoreDir "机器人的市场情况总览.md")
)
$coreReviewBlockHeader = "## 0.4 NEXT-ROBOT-032A 复审承接"
$coreReviewBlockBody = @"
reviewer 已在 `$ReviewMessageId` / `$AuditId` 对三件套实际回源核验证据包给出有条件通过。该证据包可作为后续输出通过前补证输入,并允许继续准备 `NEXT-ROBOT-032B`:IFR PDF 页码级抽取、研报原始来源补强、官方快照或缺口闭环。
 
本结论不批准输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。IFR 官方快照只支持全球工业机器人有限市场线索;MIR 协作机器人、Omdia 人形出货、智元引用、AMR、ASP、公司收入、客户供应、主供 / 独供、BOM 和利润池继续按缺口或待核验处理。
"@
foreach ($path in $coreDocPaths) {
    $text = Read-Text $path
    $text = $text.Replace("THREEPIECE_ACTUAL_SOURCE_TRACE_PREPARED", "THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED")
    $text = $text.Replace("NEXT_ROBOT_032A_REVIEW_REQUEST_PREPARED", "NEXT_ROBOT_032A_CONDITIONALLY_PASSED")
    $text = Add-OrReplaceSection $text $coreReviewBlockHeader $coreReviewBlockBody
    $text = $text.Replace('$ReviewMessageId', $ReviewMessageId).Replace('$AuditId', $AuditId)
    Write-Text $path $text
}
 
$indexPath = Join-Path $ResultDir "result_index.md"
$indexText = Read-Text $indexPath
$indexText = $indexText.Replace("THREEPIECE_ACTUAL_SOURCE_TRACE_PREPARED", "THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED")
$indexText = $indexText.Replace("NEXT_ROBOT_032A_REVIEW_REQUEST_PREPARED", "NEXT_ROBOT_032A_CONDITIONALLY_PASSED")
$indexText = $indexText.Replace("当前状态为 `THREEPIECE_ACTUAL_SOURCE_TRACE_PREPARED_PENDING_REVIEW_NOT_OUTPUT_PASS`。", "当前状态为 `THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED_FOR_FOLLOWUP_EVIDENCE_NOT_OUTPUT_PASS`。")
$indexText = $indexText.Replace("当前状态为 `THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED_PENDING_REVIEW_NOT_OUTPUT_PASS`。", "当前状态为 `THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED_FOR_FOLLOWUP_EVIDENCE_NOT_OUTPUT_PASS`。")
$indexHeader = "## 2026-07-05 三件套实际回源核验证据包复审承接"
$indexBody = @"
reviewer 已在 `$ReviewMessageId` / `$AuditId` 对 `NEXT-ROBOT-032A` 给出有条件通过。该结论只允许把实际回源核验证据包作为后续输出通过前补证输入;不批准输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。
 
下一步登记为 `NEXT-ROBOT-032B`:准备输出通过前补证包,重点是 IFR PDF 页码级抽取,以及 MIR、Omdia、AMR、ASP、公司收入、客户供应、主供 / 独供、BOM 和利润池等缺口继续闭环。
"@
$indexText = Add-OrReplaceSection $indexText $indexHeader $indexBody
$indexText = $indexText.Replace('$ReviewMessageId', $ReviewMessageId).Replace('$AuditId', $AuditId)
Write-Text $indexPath $indexText
 
# 5. remaining work plan.
$remainingPath = Join-Path $ManifestDir "remaining_work_plan_20260704.md"
$remainingText = Read-Text $remainingPath
$remainingText = $remainingText.Replace("| 6A | NEXT-ROBOT-032A | 三件套实际回源补证 | primary source、研报原始来源、页码 / 表格 / 截图 / 官方快照、缺口编号、影响范围和结论强度 | REVIEW_REQUEST_PREPARED | 仍不申请输出通过、覆盖完整、对外交付或强字段升级 |", "| 6A | NEXT-ROBOT-032A | 三件套实际回源补证 | primary source、研报原始来源、页码 / 表格 / 截图 / 官方快照、缺口编号、影响范围和结论强度 | CONDITIONALLY_PASSED | reviewer 已允许作为后续补证输入;仍不申请输出通过、覆盖完整、对外交付或强字段升级 |")
if (-not $remainingText.Contains("| 6B | NEXT-ROBOT-032B |")) {
    $remainingText = $remainingText.Replace("| 7 | NEXT-ROBOT-033 | 英搏尔 + 12 个相邻候选 | 补资料复核、继续排除/降级/候选池决策 | QUEUED | 重新进入候选池需单独复审 |", "| 6B | NEXT-ROBOT-032B | 三件套输出通过前补证包 | IFR PDF 页码级抽取、MIR/Omdia/AMR/ASP/公司强字段补证缺口闭环 | QUEUED | 只能准备补证包;不得申请输出通过或强字段升级 |`r`n| 7 | NEXT-ROBOT-033 | 英搏尔 + 12 个相邻候选 | 补资料复核、继续排除/降级/候选池决策 | QUEUED | 重新进入候选池需单独复审 |")
}
$remainingText = $remainingText.Replace("- 当前状态:THREEPIECE_ACTUAL_SOURCE_TRACE_PREPARED_PENDING_REVIEW_NOT_OUTPUT_PASS;本轮只提交实际回源核验证据包复审,不申请输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。", "- 当前状态:THREEPIECE_ACTUAL_SOURCE_TRACE_CONDITIONALLY_PASSED_FOR_FOLLOWUP_EVIDENCE_NOT_OUTPUT_PASS;reviewer 已允许作为后续输出通过前补证输入,仍不申请输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。")
$remainingHeader = "## 17. 复审状态更新(AUDIT-ANA-ROBOT-THREEPIECE-ACTUAL-SOURCE-TRACE-001)"
$remainingBody = @"
- 来源消息:$ReviewMessageId。
- 复审结论:`NEXT-ROBOT-032A` 三件套实际回源核验证据包有条件通过,可作为后续输出通过前补证输入。
- 继续允许:准备 `NEXT-ROBOT-032B`,补 IFR PDF 页码级抽取、研报原始来源、官方快照、缺口编号、影响范围和结论强度。
- 继续禁止:输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认,以及市场规模、出货、ASP、公司收入、客户供应、主供 / 独供、BOM 和利润池等强字段升级。
"@
$remainingText = Add-OrReplaceSection $remainingText $remainingHeader $remainingBody
Write-Text $remainingPath $remainingText
 
# 6. Execution log.
$execLogPath = Join-Path $AuditDocDir "案例执行日志.md"
$execLogText = Read-Text $execLogPath
$execHeader = "## 2026-07-05 RUN-ANA-ROBOT-THREEPIECE-ACTUAL-SOURCE-TRACE-REVIEW-SYNC-001"
$execBody = @"
承接 reviewer 消息 `$ReviewMessageId` / `$AuditId`:`NEXT-ROBOT-032A` 三件套实际回源核验证据包复审结论为有条件通过。
 
- 已同步:next_action_list、remaining_work_plan、result_index、机器人报告索引、三件套文档、case_evidence_map 和 migration_manifest。
- 新增:`threepiece_actual_source_trace_review_sync_20260705.json`,记录允许事项、禁止事项和保留门禁。
- 后续:新增 `NEXT-ROBOT-032B` 输出通过前补证包队列;仍不申请输出通过、覆盖完整、对外交付、完成状态、正式扩池、正式公司池确认或强字段升级。
"@
$execLogText = Add-OrReplaceSection $execLogText $execHeader $execBody
$execLogText = $execLogText.Replace('$ReviewMessageId', $ReviewMessageId).Replace('$AuditId', $AuditId)
Write-Text $execLogPath $execLogText
 
# 7. Artifact manifest: update changed shared files and record this sync run.
$artifactManifestPath = Join-Path $ManifestDir "artifact_manifest.csv"
$artifactRows = @(Import-Csv -LiteralPath $artifactManifestPath)
$changedRelPaths = @(
    (Rel-Path $nextPath),
    (Rel-Path $evidenceMapPath),
    (Rel-Path $migrationPath),
    (Rel-Path $reviewSyncPath),
    (Rel-Path $coreDocPaths[0]),
    (Rel-Path $coreDocPaths[1]),
    (Rel-Path $coreDocPaths[2]),
    (Rel-Path $indexPath),
    (Rel-Path $remainingPath),
    (Rel-Path $execLogPath)
)
$artifactRows = @($artifactRows | Where-Object { $_.run_id -ne $RunId })
foreach ($rel in $changedRelPaths) {
    $meta = Get-FileMeta $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-FileMeta $row.artifact_path
        $row.sha256 = $meta.sha256
        $row.bytes = $meta.bytes
        $row.mtime = $meta.mtime
    }
}
[System.IO.File]::WriteAllText($artifactManifestPath, (ConvertTo-CsvText $artifactRows) + "`r`n", $Utf8NoBom)
 
# 8. Self-check.
$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++
    }
}
$scanFiles = $changedRelPaths | ForEach-Object { Join-Path $ProjectRoot ($_ -replace "/", "\") }
$placeholderHits = 0
$sensitiveHits = 0
foreach ($file in $scanFiles) {
    if (-not (Test-Path -LiteralPath $file)) {
        continue
    }
    $txt = Read-Text $file
    if ($txt -match '\$\(|\$\{|\$extract') {
        $placeholderHits++
    }
    if ($txt -match '(password|token|secret|cookie|连接串|123456)') {
        $sensitiveHits++
    }
}
 
[pscustomobject]@{
    run_id = $RunId
    next_032a_status = (@(Import-Csv -LiteralPath $nextPath) | Where-Object { $_.action_id -eq "NEXT-ROBOT-032A" }).status
    next_032b_exists = [bool](@(Import-Csv -LiteralPath $nextPath) | Where-Object { $_.action_id -eq "NEXT-ROBOT-032B" })
    manifest_rows = $manifestRows.Count
    manifest_missing = $missing
    manifest_empty_sha = $emptySha
    manifest_mismatch = $mismatch
    changed_artifacts = $changedRelPaths.Count
    placeholder_hits = $placeholderHits
    sensitive_hits = $sensitiveHits
}