关于 audit-reproducibility
用于复现性审计的技能,可将论文中的数值主张与分析输出及其他声明展示位置进行核对。它按记录的容差判定各项结果,并定位不一致之处,而不预设论文或代码哪一方正确。
主要功能
- 01提取论文中的数值主张
- 02将主张匹配至分析输出
- 03按记录的容差核对数值
- 04比较各声明展示位置的数值
- 05逐项报告审计结论
- 06保存主张清单与审计报告
适用场景
- 01投稿前检查论文数值
- 02查找幻灯片或补充材料中的旧数值
- 03核验复现包中的结果
- 04重大修订后审计分析结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pedrohcgs/ claude-code-my-workflow --skill audit-reproducibility安装后在 Claude Code 中输入/audit-reproducibility确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/marker.txtevals/cases/manuscript-not-oracle.mdtolerance-before-comparison.md详细介绍
审计可复现性
将稿件中的数值声明(点估计、标准误、p 值、计数)与分析流水线实际生成的输出进行比较。根据 .claude/rules/replication-protocol.md 中定义的容差阈值,逐项报告 PASS / FAIL。
核心原则:如果论文写着 ATT = -1.632 (0.584),而代码生成的结果是 -1.628 (0.591),我们会通过数值验证差异是否在文档规定的容差范围内。不再凭感觉判断“看起来差不多”。
两个方向,而非一个。 纵向检查每项声明是否与生成该声明的输出一致。横向检查它是否与展示相同数字的所有其他产物一致——补充材料表格、幻灯片、海报。纵向检查可能顺利通过,但幻灯片引用的却是上个月的数值;只有横向检查能发现这一点。已声明的展示位置列在 passport 的 appears_in 列表中——参见 replication-protocol.md → 横向检查。
适用时机
- **提交前。**发现“我更新了分析,却忘了更新表 2”这类问题。
- **使用同一组数字进行展示或教学前。**发现最后一次重新运行后从未重新生成的幻灯片、海报或补充材料。
- **发布复现包前。**验证代码确实能复现论文结果。
- **重大修订后。**确保论文仍与最新代码一致。
- **
/commit的质量门禁。**在更改稿件和分析内容前,配合提交前调用使用。
输入
$0— 稿件路径(.tex、.qmd、.md、.pdf)。必填。$1— 输出目录路径。默认为output/,所有语言的流水线都会将结果写入此目录(R、通过/stata-replication使用的 Stata、Python)。已识别的其他目录:_targets/objects/(Rtargets工作流),以及用户指定输出所在的任何目录。如果output/不存在,但存在 v2.6 之前的scripts/<lang>/_outputs/,则使用该目录,并在报告中说明。
工作流
阶段 0:预检
- 阅读
replication-protocol.md,了解当前生效的容差阈值。 - 确认输出目录存在且非空。如果目录为空或已过期(比稿件更早),提示用户重新运行流水线(例如
Rscript scripts/R/00_run_all.R),然后再进行审计。 - 确保输出目录中存在
sessionInfo.txt或同等的环境记录文件。
阶段 1:从稿件中提取声明
解析稿件中的数值声明。匹配模式包括:
- 点估计 + SE:
ATT = -1.632 (0.584)、$\beta = 0.342$ (0.091)、带星号表示显著性的hat{\tau} = 1.28** - 表格单元格:LaTeX 表格环境中的
& -1.632$^{***}$ & 0.584 & - 计数:
our sample of 2,847 firms、$N = 2{,}847$ - 汇总统计量:
mean = 0.423、SD = 0.087 - P 值:
p < 0.01、$p = 0.003$
将每项声明记录为一个元组:
{
claim_id: "Table2_col3_ATT",
location: "Table 2, Column 3, row 'Treatment'",
kind: "point_estimate" | "standard_error" | "p_value" | "count" | "percentage",
reported_value: -1.632,
uncertainty: 0.584, # only for point estimates
significance_stars: 3, # 0-3 or None
raw_context: "the ATT estimate of -1.632 (0.584) indicates..."
}
将提取出的声明写入 quality_reports/reproducibility_claims_[manuscript-name].json,以便用户在审计前检查提取结果。
阶段 2:从输出中提取结果
在 $1 中扫描对应的数值。优先顺序:
.rds文件 — 使用readRDS(path)$coef[["treatment"]]形式的查找。可使用Rscript -e "saveRDS(summary(readRDS(...)), '/tmp/audit.rds')"进行提取。.tex表格 — 直接解析 LaTeX 表格单元格;根据列标题 + 行标签进行匹配。.csv汇总文件 — 使用 pandas/readr 解析,并按键值查找。.out/.log文件(Stata、回归输出)— 使用正则表达式提取。.json— 直接按键查找。
记录每项提取出的结果:
{
source: "output/results.rds",
lookup_key: "fit_main$coefficients['treated']",
value: -1.628,
uncertainty: 0.591,
p_value: 0.005
}
阶段 2b:收集每个声明的展示位置(护照模式)
对于每项护照声明,读取其 appears_in 列表,并提取各条目中实际显示的值:
{
claim_id: "C3",
displays: [
{ path: "manuscript.tex", locator: "Table 1, Col 2", display_precision: 3, shown: 0.342 },
{ path: "Slides/Lecture04_Results.tex", locator: "frame 'Main result'", display_precision: 2, shown: 0.34 }
]
}
本轮规则:
- 主要的
location:也是展示位置之一,并非独立的一项——如果appears_in中重复出现它,那就算一个展示位置,而不是两个。 - 无法解析的已声明展示位置——文件缺失,或
locator处没有值——记录为shown: NOT_FOUND。 在阶段 4c 中,它将判定为 FAIL。绝不可跳过:悄然停止匹配的 locator,正是隐藏过时数字的地方。 - 没有
appears_in列表的声明,表示横向未核查,而非横向无误。应如实报告(见阶段 5),不要默默判定为通过。
阶段 3:将声明与结果匹配
精确标签不匹配时,使用模糊启发式方法:
- 名称相似度(
"treatment effect"~"ATT"~"treated") - 数值相似度(如果两个候选值与报告值相差不超过 10%,优先选择 SE 更接近的候选值)
- 声明
raw_context字段中的上下文提示(表格编号、行标签、描述)
为每项声明生成一个匹配候选项,并给出置信度评分。置信度低于 0.7 的声明应标记为“UNMATCHED — 需要人工审核”,而不是默默判定为通过。
阶段 4:容差检查
对于每项匹配的声明,应用 replication-protocol.md 中的阈值:
| 类型 | 容差 | 示例 |
|---|---|---|
| 整数(N、计数) | 精确相等 | 2,847 必须等于 2,847 |
| 点估计 | abs(reported - computed) < 0.01 | -1.632 与 -1.628 → 差值 = 0.004 → PASS |
| 标准误 | abs(reported - computed) < 0.05 | 0.584 与 0.591 → 差值 = 0.007 → PASS |
| P 值 | 显著性水平相同 | p<0.01 且 p<0.01 → PASS;p<0.01 且 p=0.03 → FAIL |
| 百分比 | ±0.1 个百分点 | 42.3% 与 42.35% → PASS |
遵循用户在其 replication-protocol.md 分支中写明的任何容差覆盖设置(他们可能因 MC 噪声而放宽容差,也可能针对行政数据而收紧容差)。
阶段 4b:处置结果——PASS / FAIL / EXPLAINED / UNMATCHED
容差检查会得出以下四种处置结果之一:
- PASS — 在容差范围内。
- FAIL — 超出容差,且没有记录站得住脚的替代方案。会阻止通过(退出代码为 1)。
- EXPLAINED — 超出容差,但作者已记录一个具体且具名的替代规格来解释差异(见降级规则)。会在报告中列出并纳入给审稿人的回复;不会阻止通过。
- UNMATCHED — 找不到计算结果作为对应项(阶段 3 的置信度 < 0.7)。绝不可自动降级。
不匹配并不自动意味着失败。 在应用研究中,最常见的超出容差结果是站得住脚的替代规格,而非错误——例如 reghdfe 与 feols 的聚类 df、不同的带宽选择规则、不同的 MC 种子或重复次数,或展示时的舍入。该技能的职责是为人工审核者整理分歧,而不是断言代码正确、论文错误。(下文“Stata 专项说明”中的 df 调整说明,是具名替代方案的典型示例。)
稿件并非裁判标准。 当计算值与稿件不符时,不要想当然地认为代码正确而论文过时,也不要反过来。重构可能破坏了此前正确的表格(磁盘上的输出才是有问题的),也可能是论文沿用了旧数字。计算值是一个挑战者,而非事实标准。报告不匹配时,应写成“{论文,代码} 中必有一方需要修改——查明是哪一方”,绝不要写成“回退代码以匹配论文”。这样可以避免为了让论文“复现”而回退真正的错误修复。
降级规则:FAIL → EXPLAINED
只有当针对该确切主张,在通行证条目的 notes: 字段(通行证模式)或审计报告的作者备注列(默认模式)中记录了明确点名的替代方案时,才可以将 FAIL 降级为 EXPLAINED。有效备注示例:
"reghdfe 与 feols 的聚类自由度调整不同;采用 reghdfe 的小样本校正后,已发布的值为 −1.19,与脚本的 −1.187 在舍入误差范围内。待修正代码。"
作者是审计员:该技能会安排双向比较(同时显示报告值和计算值);人工撰写一行点名替代方案的备注;该技能记录此备注,并在之后遵循它。将处理结果标记为 PAPER-CORRECTED、CODE-CORRECTED 或 DEFENSIBLE-ALTERNATIVE。
不可逾越的底线——绝不能降级为 EXPLAINED:
- 空白备注、“不清楚”、“看起来没问题”,或任何未点名具体替代规格的备注。
- UNMATCHED 主张(没有可供比较的计算结果)。
- 没有提供替代方案的直接数值矛盾。
(引文/存在性主张不在此范围内——由 /verify-claims 负责,并在其范围内采用同样的点名替代方案宽免规则。)
重复出现 EXPLAINED 是一种信号(两次规则)
沿用 review-paper --adversarial 和 summary-parity.md 中的两次规则:如果同一条主张在连续两次审计中被降级为 EXPLAINED,却从未被修正为 PASS(作者不断援引替代方案,却从未更新论文或代码),就不要再把它当作已悄然解决的问题。在 Phase 5 中醒目指出——"这一存在争议的数字已两次被标记为 EXPLAINED,却从未得到修正"——这样,未解决的分歧就不能无限期地藏在已记录的备注后面。在通行证模式下,通过将当前的 status/notes 与上次审计进行比较来检测。
Phase 4c:横向检查——各处展示的内容必须彼此一致
Phase 4 将主张与代码进行比较。本阶段对 Phase 2b 收集的 displays 进行两两比较,检查该主张在各处的展示是否彼此一致:
- 按较低的精度对双方进行舍入。 两处展示值在都舍入到两者
display_precision中较小值所对应的精度后相等,即视为一致。幻灯片中的0.34与论文中的0.342在 2 位小数精度下相符;0.29与0.342则不符。 - 不适用容差。
tolerance:块用于纵向比较,即比较两个测量值。同一个数值的两处展示是两个副本——按步骤 1 舍入后,它们要么匹配,要么不匹配。 - 按 Phase 4b 的术语给出处置结果:
- PASS — 每一对展示都一致。
- FAIL — 任一对展示不一致,或任一处展示为
NOT_FOUND。绝不能降级为 EXPLAINED:点名替代规格可以解释代码与论文为何不同,却无法解释同一个数值的两个副本为何不同。如果某处展示的确采用了不同规格,那就是另一条主张,应单独建立通行证条目。 - UNCHECKED — 该主张未声明
appears_in列表。报告此情况,但不阻止流程;修复方法是声明这些展示位置。
- 报告哪一处发生了变化,而不是哪一处正确。 指出其值与其他位置不同的产物,以及它最后一次修改的时间;由作者决定是幻灯片过时还是论文过时。不要手动编辑某处展示值来匹配对应展示——应根据该主张所指向的输出重新推导两者(
replication-protocol.md→ 反模式)。
Phase 5:报告
撰写 quality_reports/reproducibility_audit_[manuscript-name].md:
# Reproducibility Audit: [Manuscript Title]
**Date:** [YYYY-MM-DD]
**Manuscript:** [path]
**Outputs directory:** [path]
**Tolerance source:** .claude/rules/replication-protocol.md
## Summary
| Status | Count |
|---|---|
| PASS (vertical and horizontal) | N |
| FAIL (diff > tolerance, no named alternative) | M |
| EXPLAINED (out of tolerance, named alternative recorded) | E |
| UNMATCHED (manual review) | K |
| HORIZONTAL DRIFT (declared displays disagree, or a display not found) | H |
| HORIZONTALLY UNCHECKED (claim declares no `appears_in`) | U |
| **Overall verdict** | **PASS / FAIL** (FAIL iff M > 0 or H > 0; EXPLAINED does not fail the audit) |
## PASS (all within tolerance)
| Claim | Reported | Computed | Diff | Tolerance |
|---|---|---|---|---|
| Table2_col3_ATT | -1.632 (0.584) | -1.628 (0.591) | 0.004 / 0.007 | 0.01 / 0.05 |
## FAIL (outside tolerance — BLOCKER)
| Claim | Reported | Computed | Diff | Tolerance | Location in paper | Author note (name a concrete alternative to downgrade → EXPLAINED) |
|---|---|---|---|---|---|---|
## EXPLAINED (out of tolerance; defensible named alternative recorded — non-blocking, carry into response-to-referees)
| Claim | Reported | Computed | Named alternative (why the gap is defensible) | Resolution |
|---|---|---|---|---|
| Table3_col2_ATT | -1.187 | -1.19 | reghdfe vs feols clustering-df adjustment | DEFENSIBLE-ALTERNATIVE |
## UNMATCHED (manual review)
| Claim | Raw context | Candidate sources |
|---|---|---|
## HORIZONTAL DRIFT (one number, two values — BLOCKER)
| Claim | Display A | Display B | Compared at | Values | Which side moved |
|---|---|---|---|---|---|
| C3 | manuscript.tex — Table 1, Col 2 | Slides/Lecture04_Results.tex — frame 'Main result' | 2 decimals | 0.34 vs 0.29 | deck older than the claim's output_file |
## HORIZONTALLY UNCHECKED (no `appears_in` declared)
| Claim | Primary display | Other artifacts to declare |
|---|---|---|
## Environment
[sessionInfo excerpt]
## Next steps
1. Resolve each FAIL row — either correct the manuscript, rerun the analysis, or (if the gap is a defensible alternative spec) record a concrete named alternative to downgrade it to EXPLAINED.
2. Resolve each HORIZONTAL DRIFT row — regenerate the lagging display from the claim's output, never by retyping the other display's value. A `NOT_FOUND` display is fixed by correcting the `locator`, not by dropping the entry.
3. Review UNMATCHED rows — add explicit lookup keys or widen the search scope.
4. Declare `appears_in` for the HORIZONTALLY UNCHECKED rows — every artifact a reader sees the number in.
5. Review EXPLAINED rows before submission — each should map to a sentence in the response-to-referees.
6. After zero FAILs and zero HORIZONTAL DRIFT (EXPLAINED rows allowed), the paper is replication-ready.
阶段 5b:追加到复现日志
每次运行都会重写上面的报告和护照,因此两者都不会保留历史记录。日志会保留。每次运行后——无论是默认模式还是护照模式——都要向 quality_reports/replication-log.md 追加一个区块。日志会提交到仓库,因此合作者或数据编辑者无需阅读代码,就能看到检查了什么、依据哪个提交,以及每个数字是如何得出的。
- 仅追加。 使用
>>写入;绝不编辑或重新排序过去的区块。需要更正时,应重新运行,而不是编辑。仓库卫生检查会拒绝编辑或删除已提交行的提交——提交前钩子会对照上一个提交检查,CI 会对照此次工作合并到的分支检查。它能证明没有条目被编辑,但不能证明每次运行都已记录。披露内容脱敏是唯一例外:使用ALLOW_LOG_REWRITE=1提交,并在提交消息中说明原因。 - 标注修订版本。 记录短提交哈希;如果
quality_reports/以外的任何内容尚未提交(包括未跟踪文件),则在哈希后加上-dirty——这样未提交代码的评估结果会明确标示出来,而审计自身的报告文件不会触发此标记。在 Git 仓库之外,或首次提交之前,标记为no-commit。 - “计算方式”必须是阶段 2 使用的确切访问器或命令——信息应足够让他人重新计算该数字。
- 受限数据: 日志包含与报告相同的数字,因此只有在通过披露审查后才能提交,其他输出也遵循相同规则(
confidential-data.md)。
LOG=quality_reports/replication-log.md
[ -f "$LOG" ] || printf '%s\n' "# Replication log" "" \
"Append-only record of /audit-reproducibility runs: what was checked, against which commit, and how each number was computed. Never edit a past entry; a correction is a new run." "" > "$LOG"
# -dirty = anything uncommitted outside quality_reports/, untracked files included (the audit writes its own files in quality_reports/)
if REV=$(git rev-parse --short HEAD 2>/dev/null); then
[ -n "$(git status --porcelain -- . ':(exclude)quality_reports' 2>/dev/null)" ] && REV="$REV-dirty"
else
REV="no-commit" # not a git repository, or nothing committed yet
fi
printf '## %s — %s @ %s\n\n' "$(date +%F)" "<manuscript path>" "$REV" >> "$LOG"
# Quoted heredoc: nothing below is expanded, so an accessor's `$` or backtick is written as-is.
cat >> "$LOG" <<'EOF'
Outputs: `<outputs dir>` · Verdict: **<PASS|FAIL>** (<M> FAIL, <H> horizontal drift, <E> EXPLAINED, <K> unmatched)
| Claim | Location | Reported | Computed | How computed | Tolerance | Verdict |
|---|---|---|---|---|---|---|
| Table2_col3_ATT | main.tex: Table 2, col 3 | -1.632 | -1.628 | `readRDS("output/results.rds")$coef[["treatment"]]` | 0.01 | PASS |
EOF
每个经审计的主张占一行,顺序与报告一致。
退出行为
- 全部为 PASS(或 PASS + EXPLAINED): 退出码为 0,并打印摘要。
- 任何 HORIZONTAL DRIFT: 退出码为 1,与 FAIL 同等处理——两个产物对同一数字显示不同值,无论哪一个正确,都是缺陷。HORIZONTALLY UNCHECKED 行会发出警告(退出码为 0)并列出。
- 任何 FAIL: 退出码为 1,并将摘要打印到 stderr。这使该技能可用作
/commit的提交前检查——执行模式见replication-protocol.md。EXPLAINED 行不计为 FAIL,也不会触发退出码 1——它们会显示出来,但不会阻止提交。对于真正的 FAIL(没有注明替代方案)以及伪造或 UNMATCHED 的主张,检查仍会严格把关。 - UNMATCHED > 0(且 FAIL 为 0): 退出码为 0,但会发出警告——用户必须手动审查。
源语言覆盖范围
该技能会将稿件中的主张与三种源语言生态系统的输出进行比较。三者都写入同一个 output/ 目录:
| 源语言 | 默认输出目录 | 通过以下方式读取输出 | 常见主张来源 |
|---|---|---|---|
| R(默认) | output/ | readRDS()、arrow::read_parquet()、vroom::vroom() | .rds / .parquet / .csv / tinytable .tex |
| Stata(v1.9.0) | output/ | 从 R 调用 haven::read_dta(),或从 Python 调用 pyreadstat.read_dta() | .dta / esttab .tex / .smcl 日志值 |
| Python | output/(或 _targets/) | pandas.read_parquet、pickle.load | .parquet / .pickle / .csv |
Stata 专属说明(v1.9.0):
.dta输出可通过haven::read_dta()(R)、pyreadstat.read_dta()(Python)读取;如果稿件引用的是表格单元格中的值,也可以解析对应的esttab.tex。- 稿件单元格
\input{output/tab_main.tex}是最有力的溯源信号——该单元格的值由 .do 文件机械生成。将.tex中的位置与03_analyze.do中的回归调用匹配。 reghdfe和基础命令reg, cluster()的聚类 df 调整可能不同。如果标准误在小数点后第 2 位不匹配,replication-protocol.md中的容差规则适用;如果在小数点后第 1 位不匹配,则应调查 df 调整。
护照模式(v1.9.0)
当 quality_reports/passports/<paper-slug>.yaml 存在时,该技能会以 护照模式 运行:不再一次性生成报告,而是读取、更新并原地重写护照文件。
- 对护照中的每个
claims:条目,执行与默认模式相同的数值审计(从稿件的location提取报告值,在source_file:source_line/output_file:output_field处定位计算值,并与tolerance:比较),然后对该条目的appears_in列表执行 Phases 2b 和 4c 的横向检查。 - 审计每项声明后,原地更新其
status:- PASS → 声明在容差范围内,并且每个已声明的展示值都与更粗精度下的结果一致。
- FAIL → 声明超出容差,且条目的
notes未注明具体的替代规范;或两个已声明的展示值不一致;或无法在文件中定位某个appears_in条目。在notes中记录差异——纵向 FAIL 记录报告值与计算值,横向 FAIL 记录两个展示值及其路径。阻止通过(退出码为 1)。 - EXPLAINED → 声明超出容差,但条目的
notes已记录具体命名的替代规范(非空,也不是“unclear”)。技能在下次运行时会读取notes,并将同一项超出容差的声明判定为 EXPLAINED,而不是 FAIL——会显示,但不阻止通过。仍适用硬性底线:UNMATCHED 声明或未注明替代规范的备注仍判定为 FAIL。 - STALE → 如果
source_file、output_file或任何appears_in路径的修改时间晚于last_verified_on,则标记为 STALE 并重新运行审计逻辑(重新审计后,状态将变为 PASS / FAIL / EXPLAINED——STALE 是临时状态)。
- 按声明更新
last_verified_on和last_verified_by: "/audit-reproducibility"。 - 更新顶层的
paper.last_audit。
如果检测到稿件中有声明没有匹配的护照条目,则发出 UNVERIFIED 警告——作者应添加该条目(护照范围由作者维护,而非自动填充,以避免错误推断)。
护照模式不会删除护照条目。如果某项声明从稿件中消失,其护照条目仍会保留,并标记为 STALE——由作者决定是删除该条目(声明已撤回),还是更新其 location(声明已移动)。
它也不会自行添加 appears_in 条目。如果横向检查恰好发现某个展示——护照未声明、但在演示文稿或补充材料中出现相同值——则会在 HORIZONTALLY UNCHECKED 表中将其报告为建议,由作者决定是否声明。理由与上述不自动填充规则相同:推断出的展示实际上可能是另一种量值,导致横向检查一直失败。
有关完整架构和集成点(/commit、/review-paper),请参阅 .claude/rules/replication-protocol.md 中的“声明溯源:passport.yaml”。
交叉引用
.claude/rules/replication-protocol.md— 容差约定 + 护照架构。templates/passport-template.yaml— 新论文的起始文件;复制后使用,其中的appears_in列表用于声明图表。.claude/hooks/claim-reconcile.py— 事件驱动的提示:编写受跟踪的脚本、输出或已声明的图表名称时,会指出需要重新审核的论断。它负责统计声明;此技能负责比较。.claude/skills/review-r/SKILL.md— 检查代码风格问题;此技能检查数值可复现性。.claude/skills/diagnose/SKILL.md— 当某项论断判定为 FAIL,且需要定位流水线中哪一步产生了超出容差的值时,转交给/diagnose(针对单项论断的根因分析:复现 → 精简 → 二分)。.claude/skills/review-paper/SKILL.md— 内容审查;与此技能配合,进行完整的投稿前审计。.claude/skills/replication-package/SKILL.md— 在组装 AEA DCAS 存档前,必须通过此技能的检查。.claude/skills/capture-environment/SKILL.md·.claude/skills/disclosure-check/SKILL.md— 下游的环境捕获 + 受限数据筛查。
此技能不做什么
- 不重新运行分析。 此技能将当前输出与手稿中的论断进行比较。如果输出已过时,请先重新运行流水线(预检阶段会发出警告)。
- 不检查错误的设定。 一个能顺利编译并生成可复现
-1.632的回归结果,就是可复现的。-1.632是否代表正确的估计对象,则属于review-paper/ 领域审稿人的审查范畴。 - 不检查外部软件包版本。
sessionInfo.txt捕获结果可供审稿人查看环境;版本固定由用户负责(通过renv.lock或DESCRIPTION文件)。
长时间批量重跑:使用 Monitor 工具(2026 年 4 月)
当要求 /audit-reproducibility 验证论文中的所有数值论断时,最稳妥的做法是重新运行完整流水线(00_run_all.R 或同等程序),并将重新生成的输出与手稿中的数值进行比较。对于运行时间超过几分钟的流水线,可在后台启动重跑,并使用 Anthropic 的 Monitor 工具(2026 年 4 月第 15 周)流式查看 stdout。这样,审计过程可在运行期间及时响应错误,而不必等到整个流水线完成后才发现某一步骤失败。