mcpField
S
sync-submission

sync-submission

github.com/aperivue文档处理353106 次安装1 天前更新
代码仓库

关于 sync-submission

sync-submission 是用于同步规范稿件与期刊投稿包的技能,面向管理多期刊稿件的研究团队。它通过哈希审计、构建、预检和冻结记录追踪差异与状态,但冻结不代表审批或内容保真已验证。

主要功能

  1. 01审计投稿包与规范稿件的差异
  2. 02按声明文件构建投稿包并记录元数据
  3. 03冻结字节快照及可用检查上下文
  4. 04运行可配置的投稿前检查门
  5. 05扫描双盲投稿材料中的作者标识
  6. 06生成同步审计和质量检查报告

适用场景

  1. 01检查期刊投稿包是否与规范稿件同步
  2. 02在投稿前构建并登记最终材料
  3. 03运行门禁检查后冻结提交版本
  4. 04查找双盲材料中的作者身份信息

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/aperivue/medsci-skills --skill sync-submission

安装后在 Claude Code 中输入/sync-submission确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
build_synthetic_bundle.py
references/
bundle_workflow.md
journal_availability_policy.json
marked_manuscript.md
springer_em_packaging.md
scripts/
_quote_match.py
_yaml_frontmatter.py
assemble_supplement.py
author_registry_example.yaml
blind_sweep.py
build_marked_manuscript.py
check_asset_anonymization.py
check_checklist_dump_leak.py
check_credit_integrity.py
check_cross_artifact_stale.py
check_disclosure_availability.py
check_marked_manuscript.py
check_portal_field_residue.py
check_portal_mirror.py
check_wordcount_cap.py
cover_letter_drift_check.py
scripts/check_portal_field_residue_challenge/
problem.md
verify.sh
scripts/check_portal_field_residue_challenge/fixture/negative/
abstract.txt
keywords.txt
scripts/check_portal_field_residue_challenge/fixture/positive/
abstract.txt
take_home.txt
scripts/credit_integrity_challenge/
verify.sh
scripts/credit_integrity_challenge/fixture/
manuscript_bad.md
manuscript_good.md

详细介绍

同步投稿包

确保规范稿件与期刊专用投稿包保持一致。 将 submission/{journal}/ 视为派生输出,并记录其状态是最新、过期还是已冻结。

输入

  1. 包含 project.yaml 的项目根目录,或规范稿件的直接路径。
  2. 期刊简称,例如 chest、ryai、academic_radiology。
  3. 可选模式:
    • audit:将现有投稿包与规范源文件进行比较。
    • build:复制规范源文件和可选的已声明最终制品,保留文件字节,并写入元数据。
    • freeze:冻结所选字节快照及其现有检查上下文(不代表投稿已获批准)。

确定性脚本

python "${CLAUDE_SKILL_DIR}/scripts/sync_submission.py" audit --project-root . --journal chest
python "${CLAUDE_SKILL_DIR}/scripts/sync_submission.py" build --project-root . --journal chest
python "${CLAUDE_SKILL_DIR}/scripts/sync_submission.py" freeze --project-root . --journal chest --status submitted

对于双盲期刊,请扫描所有上传制品中的作者标识符:

python "${CLAUDE_SKILL_DIR}/scripts/blind_sweep.py" \
  --registry _shared/authors/author_registry.yaml \
  --files submission/{journal}/supplementary/*.md submission/{journal}/cover_letter.md \
  --backup-dir .cache/blind_sweep_backup

注册表是项目本地的 YAML 映射,将作者标识符(全名、原文姓名、姓名首字母缩写〔带句点或不带句点〕、电子邮件、ORCID)映射到角色标签(例如“审稿人 1”);架构见 scripts/author_registry_example.yaml。切勿将填有实际内容的注册表提交到公开仓库,因为其中列有作者身份信息——请将其保存在稿件旁。

输出约定

制品路径用途
投稿元数据submission/{journal}/.journal_meta.json源哈希、状态、规范路径
同步审计qc/submission_sync_{journal}.json由编排器使用的差异结果
清单更新artifact_manifest.json投稿包注册表
预检门禁qc/preflight_gate_report.json汇总式失败即停止清单(见下文“预检门禁”)
补充材料结构qc/supplement_structure.json门禁 14:索引↔文件一一对应、子章节缺漏、文中引用覆盖情况

要生成完整包,请先运行现有渲染器,然后运行 build --bundle-spec bundle.json。 该声明会添加最终 Word/PDF、补充材料、投稿信、表格/图件和声明文件,并附带固定的渲染输入哈希及复用权记录。复制会保留文件字节;内容和视觉保真度在单独审核前均标记为 not_assessed。Build 会拒绝已编辑或已冻结的输出,以及具有破坏性的路径冲突。有关架构、可运行的合成示例以及每项已记录检查的局限,请参阅 投稿包工作流。

预检门禁(单条命令——冻结前的最后一步)

在 freeze/提交之前,立即运行一次:

python "${CLAUDE_SKILL_DIR}/scripts/preflight_gate.py" --project-root . --journal chest
# add --strict to also halt on the heuristic/conditional (P1) checks
# add --online to make fabricated / author-mismatched references halt (PubMed/CrossRef)
# add --double-blind to make the asset-anonymization scan halt

该命令会调用各项检查脚本(不重新实现其功能),写入 qc/preflight_gate_report.json,并以 0 表示通过、1 表示停止(≥1 个阻断项)、2 表示门禁配置错误 (例如,无法运行 --require 指定的检查项)。非零退出状态会阻止冻结。

  • P0 — 默认停止(明确、确定的错误):残留的占位符/标记 (check_placeholders.py)、未定义的 [@key] 引用(check_citation_keys.py)、重复 的参考文献(verify_refs.py,离线确定性)、规范版本与提交版本的哈希不匹配 (sync_submission.py audit),以及面向审稿人的文件中包含内部审计转储 (check_checklist_dump_leak.py)。
  • P1 — 执行并报告 warn,仅在使用 --strict 或 --require ID 时停止: check_xref、 detect_copy_divergence、scope_drift_check、cover_letter_drift_check、 cross_document_n_check、check_cross_artifact_stale;除非指定 --double-blind,否则 check_asset_anonymization 为 P1。
  • 如果某项检查所需的输入不存在(没有渲染后的 docx、没有投稿信、没有副本、没有期刊),则记录为 skipped,绝不会成为阻断项。若检查已运行但失败——发生回溯、退出代码异常,或输入实际存在时仍以 “missing input” 退出(.journal_meta.json 格式错误、投稿信无法解码、不存在的命名 --copy、N 次 扫描中有无法读取的文件)——则记录为 error:submission_safe 为 false,且无论是否使用 --strict,门禁都会以 2 退出。

不要将该报告视为批准。其旧版 submission_safe 字段仅表示“没有已配置的阻断项/错误”;readiness 仍为 not_assessed;可选的捆绑包哈希绑定标识的是运行期间存在的软件包,并不代表逐个文件的视觉检查,也不代表检查了 所有外部检查输入。预检后再次运行 audit,以显示当前、过期或未绑定的证据。冻结会记录字节快照及可用的检查 上下文;它不会运行预检,也不会批准源内容保真度或复用权限。

审计转储泄漏检查(P0)。 /check-reporting 或 /self-review 报告属于内部工作审计,包含自动修复注释、 原始 JSON 区块(compliance_pct、fixable_by_ai、check_reporting_version)、流水线日志路径、 “Action Items”。它不是期刊要求的正式报告清单,即使文件名看起来正式,也绝不能交给审稿人 (例如,复用到后续软件包中的 STROBE_checklist_v4.pdf)。scripts/check_checklist_dump_leak.py --dir submission/ 会扫描软件包中的每个 .md/.docx/.pdf,查找这些标记;任何命中都会记为 P0 leak。预检会对期刊资源目录 运行该检查;冻结前请确认 submission_safe: true。结果写入 qc/checklist_dump_leak.json。

披露与可用性检查(独立运行)。 顶级医学 AI 期刊要求在审稿前提供 AI 使用披露,其中包含四项标记 (版本 + 访问渠道 + 日期/日期范围 + 责任方——工具名称只会触发检查),并提供数据/代码可用性声明。运行 python3 ${CLAUDE_SKILL_DIR}/scripts/check_disclosure_availability.py --manuscript <file> --journal <stem> [--ai-study] [--require data_availability ...] [--strict] (读取 references/journal_availability_policy.json)。若缺少必需声明,或 AI 披露已提供但缺少某项标记/包含占位符,则会阻断;如果期刊要求提供代码库,但声明为“available on reasonable request”,则会产生 P1 警告。结果写入 qc/disclosure_availability_report.json。

工作流

  1. 从 project.yaml 或显式输入中解析规范稿件。
  2. 以请求的模式运行脚本。
  3. 如果 audit 报告 DRIFT,在用户修补规范稿件或将差异记录为仅限日志之前,不要重新指定目标或冻结。切勿静默地将提交内容的编辑合并回 SSOT,也不要隐藏仅限日志的差异——应将其记录为漂移或明确例外。
  4. 如果 build 成功,在最终提交前运行 /verify-refs。
  5. 仅当源哈希匹配时,才将软件包视为当前版本;只能通过 freeze 将其标记为已提交,该命令会写入 .journal_meta.json。

质量门禁

  • Gate 0(预检,冻结前的最后一步):按上文“预检门禁”运行 scripts/preflight_gate.py;退出码非零会阻止冻结。它会协调运行 Gate 1–3、5b、5c、5d、8、9、11、11b、Phase 3b/3c 检查,以及占位符和引用键检查;每个门禁也可以单独运行。

  • Gate 1:规范稿缺失时,阻止冻结。

  • Gate 2:上一次投稿存在尚未解决的偏差时,阻止重新指定目标。

  • Gate 3:将稿件包标记为可安全投稿前,必须通过 /verify-refs 审核。预检中的离线参考文献检查只涵盖重复项和页码占位符;针对 PubMed/CrossRef 在线运行 /verify-refs --strict,才是权威的伪造引用和作者姓名检查。

  • Gate 4(递归遍历 docx):每次 docx 过期字符串审计都必须递归遍历段落、表格和嵌套表格单元格。document.paragraphs 会跳过表格单元格,document.tables 不会递归,而 paragraph.runs 会隐藏 <w:hyperlink> 内的 runs——图、图注和报告清单通常位于 1×1 或嵌套表格中。编辑超链接或域附近的 run 时,应检查段落 XML,而不是 .runs:隐藏的行内元素可能看起来像空的 (),被“修复”后反而变成真正的缺陷。

  • Gate 5(投稿系统自由文本字段):投稿信、数据可用性声明、致谢、摘要和作者贡献通常直接填写在投稿系统中,不在本技能审计的任何 docx 文件内。冻结前,应将投稿系统最终审阅页与正文逐项进行 1:1 比对,并将每个字段视为独立的偏差目标。

  • Gate 5c(投稿系统字段中的 Markdown 残留):直接粘贴的投稿系统 .txt 字段(abstract.txt、keywords.txt……)内容截取自 Markdown,但不会去除其中的 Markdown 标记,因此结尾的 ---、**bold** 或上标 cm^2^ 都会原样发布。预检会运行 scripts/check_portal_field_residue.py --dir portal_fields/(P1,可通过 --strict 提升为强制检查);只扫描 .txt(.md 本就应包含 Markdown)。其 Minor 级别的 char_expansion 提示会标记 ≥/≤:ScholarOne 会将其展开为“{greater than or equal to}”(五个单词),导致词数膨胀——应预先替换为 >=/<=(仅限 ≥/≤;× 和 en dash 粘贴后显示正常)。

  • Gate 5d(图的投稿系统就绪检查):如果问题可从磁盘上的文件判断,图就可能在上传按钮处被拒——文件大小(JACC: Asia 对单张图的上限为 25 MB)和扩展名(SNAPP 仅接受 .tiff/.jpeg/.eps,拒绝 .png)。预检会对 submission/<journal>/figures(或 ./figures)运行 scripts/figure_portal_readiness_check.py --figures-dir <dir>(P1),并输出 FIGURE_OVERSIZE;若提供投稿系统接受的格式,例如 --figure-accept tiff --figure-accept jpeg --figure-accept eps,还会输出 FIGURE_FORMAT_REJECTED。可使用 /make-figures export_portal_tiff.py 重新生成(LZW + RGBA→RGB 扁平化)。没有图目录时会跳过,不会报错。

  • Gate 6(双盲期刊):稿件匿名处理干净,不代表投稿系统中的匿名处理也干净。冻结前,导出投稿系统的匿名审阅 PDF——这是权威的偏差检测器——并在整套上传文件中搜索所有作者标识:稿件;补充材料(尤其是方法日志、一致性指标、修订日志);投稿信(单独上传的文件会对审稿人可见,除非勾选“不在审阅 PDF 中显示”);注册/审批 PDF(PROSPERO、ClinicalTrials.gov、IRB);粘贴了签名的投稿系统 Letter 字段文本;修订轮次中的审稿意见回复。应检查带句点和不带句点的姓名首字母(G.S. 和 GS)、拉丁字母和本国语言文字的全名、机构名称、ORCID ID 以及投稿邮箱域名。

  • Gate 7(纯文本 docx 重建):切勿使用 pandoc --reference-doc=manuscript.docx 来生成审稿回复/投稿信/补充材料等纯文本 docx,因为参考 docx 会将其中嵌入的媒体文件(图文件)一并带入新 docx,使其体积膨胀 50–100 倍。应使用普通命令 pandoc input.md -o output.docx。如果此类文件超过 100 KB,运行 unzip -l output.docx | grep word/media/ 后应无任何输出。

  • Gate 5b(投稿信自由文本偏差):冻结前——参见 Phase 4。

  • Gate 8(跨文档 N 值一致性):冻结前——参见 Phase 5。

  • Gate 9(稿件内部范围偏差):参见 Phase 6。

  • Gate 10(v_(N+1) docx 重新生成):基于已冻结的先前版本构建时——参见 Phase 7。

  • Gate 11(多份副本间的差异):冻结或分发前——参见 Phase 8。

  • Gate 11b(重新构建论点/标题变更后的残留扫描):在修订重新构建某类论点(例如,将“按地点分层的基准测试”改为“整体汇总”)或更改标题中的数字后,旧术语/数值往往会残留在未修改的段落、图例、补充材料或回复信中——即使信中声称已“全文”应用更改。将重新构建差异中的废弃词汇和已取代数值传递给跨文件门禁,它会扫描正文和所有辅助文件:

    python3 "${CLAUDE_SKILL_DIR}/scripts/check_cross_artifact_stale.py" \
        --manuscript manuscript.md --aux supplement/ --aux figures/legends.md --aux revision/response_to_reviewers.md \
        --retired-term "location-stratified benchmark" --old-value 1.72
    

    retired_framing_survivor / stale_old_value 发现项属于 P1 级过期论点位置。--aux 接受文件或文件夹:会读取 .docx 辅助文件,并且只扫描图表脚本(.py/.R)中的过期字面字符串。如果 --aux 中没有可读取的文件,则会以状态码 2 退出,而不是通过;无法读取的文档(.pdf、.pptx……)会列为未检查。对于任何措辞或数字变更,还应在整个 SSOT 目录树中搜索旧字符串,绝不能只搜索其中一部分,并留意子串导致的漏检——精确搜索 expertise-dependent patterns 会通过,但 expertise-dependent evaluation patterns 仍会残留。

  • Gate 12(目标期刊元数据偏差):运行 build / 重新指定目标时,将稿件面向的目标期刊——project.yaml 中的 target(以及稿件页眉/页脚中任何“for submission to X”字符串)——与稿件包的构建目标期刊进行比较,并检查目标期刊要求的结构元数据——摘要标题结构(4 个或 5 个标题)、正文词数限制、引文格式(Vancouver / AMA)、必需元素(Highlights / Central Illustration / Key Points)。若存在不匹配(例如,级联重新指定目标后页眉仍写着前一本期刊,或面向要求 5 个标题的期刊却使用 4 个标题的摘要),应触发目标结构调整——分支到 v_(N+1),并同步所有辅助文件(投稿信、标题页、ICMJE COI 清单)——而不是静默构建。

    # header target vs project.yaml target
    TGT=$(python3 -c "import yaml;print(yaml.safe_load(open('project.yaml')).get('target',''))" 2>/dev/null)
    grep -niE 'for submission to|submitted to|prepared for' manuscript/manuscript.md   # compare against "$TGT"
    
  • Gate 13(正文词数与期刊上限——修订导致篇幅膨胀的陷阱):解决审稿人的主要意见会增加词数,因此修订后的正文可能会悄然超出期刊的字数限制。定稿前以及每次 /revise 后,都要针对目标期刊配置文件的正文上限运行 scripts/check_wordcount_cap.py。WORDCOUNT_OVER_CAP 属于 P0(将方法或敏感性分析的细节移至补充材料);WORDCOUNT_NEAR_CAP(>0.95×)表示下一轮修订就会超限。约束性数字是渲染后的词数(citeproc 会将 [@key] 展开为“(作者 年份)”),因此最好使用构建好的 DOCX 词数,并通过 --rendered-words N 指定;否则,脚本会根据 Markdown 正文和行内引文展开结果进行估算。

    python3 "${CLAUDE_SKILL_DIR}/scripts/check_wordcount_cap.py" \
      --manuscript manuscript/manuscript.md \
      --journal-profile "${CLAUDE_SKILL_DIR}/../find-journal/references/journal_profiles/<Journal>.md" \
      --article-type "Original Article" --out qc/wordcount_cap.json --strict
    # or, deterministic: --limit <the journal's body cap>   (and --rendered-words N from the built DOCX when available)
    

    配置文件中的上限只从结构化字段读取:文章类型表格的正文限制列(| Type | Body Word Limit | Abstract | ... |),或者在没有表格列出该类型时,以该类型开头的列表项(- Original Article (4,000 words, ...))。仅仅提及该类型的正文内容(通常是摘要限制)绝不会被读取;若无法得出唯一数字,或单元格中包含多个数字,脚本会以 2 退出并要求提供 --limit。

  • Gate 14(补充材料结构——编号锁定):由 S{N}_*.md 章节和索引组成、再手动拼接成 _combined.md 的补充材料,在多轮修订中会出现不同步——索引行没有对应文件、文件未列入索引、两个文件使用相同的 S{N},或插入后子章节编号出现缺口(S6.3 后接 S6.5)——导致“补充表 S9”指向错误内容。定稿前,运行 scripts/assemble_supplement.py,以验证索引与文件一一对应,并按索引顺序重建 _combined.md(确保结果可复现,而非手动维护);使用 --manuscript 时,还会报告正文中没有对应章节文件的引用(CALLOUT_WITHOUT_SECTION),以及正文从未引用的章节文件(SECTION_UNCITED)。在 --strict 模式下,四种结构问题均属 P0;覆盖范围问题仅供参考。

    python3 "${CLAUDE_SKILL_DIR}/scripts/assemble_supplement.py" \
      --dir submission/{journal}/supplementary --index 00_index.md \
      --manuscript manuscript/manuscript.md \
      --out submission/{journal}/supplementary/_combined.md \
      --json qc/supplement_structure.json --strict
    

第 3b 阶段 — 替代稿件内容的门户字段

在某些门户中,实际发布的是输入框里的内容,而不是稿件。SNAPP 在 Author Contributions、Competing Interests、Data Availability 和 Acknowledgements 中明确说明了这一点:“这会替代稿件中写入的任何声明,并作为我们发布的内容。”如果某项声明只出现在稿件中,它就会从已发布的记录中消失,而且没有任何提示。以下两项险些如此:

  • 共同第一作者。 标题页脚注中的 †。没有平等贡献复选框 — 除非在 Author Contributions 输入框中填写“X 和 Y 对本工作贡献相同”,否则已发表的论文不会列出共同第一作者。
  • “资助方未参与研究设计……” 结构化的 Research funding 字段要求填写资助方和资助编号,没有地方填写角色免责声明,因此,如果只把 AI 使用说明粘贴到 Acknowledgements 输入框中,这项声明就会丢失。

不要手动编写这些输入框的内容。 从稿件生成,然后检查:

SS="${CLAUDE_SKILL_DIR}/scripts"
# scaffold every replacing field straight from the manuscript (lifts the equal-contribution
# sentence in from the title page, which is the one place --emit cannot copy it from)
python3 "$SS/check_portal_mirror.py" --manuscript manuscript/manuscript.md \
  --profile "<...>/journal_profiles/npj_Digital_Medicine.md" --emit portal_fields/

# then verify nothing was lost on the way to the box
python3 "$SS/check_portal_mirror.py" --manuscript manuscript/manuscript.md \
  --portal-dir portal_fields/ --profile "<...>/npj_Digital_Medicine.md" \
  --out qc/portal_mirror.json
判定触发条件
PORTAL_FIELD_NOT_MIRRORED被替代的稿件章节中有一句话,在该字段的粘贴内容中找不到对应内容。
PORTAL_FIELD_MISSING稿件包含该章节,期刊会替代该章节,但不存在对应内容;该字段发布时为空,或采用门户自动提取的猜测内容。
EQUAL_CONTRIBUTION_NOT_IN_PORTAL稿件声明了平等贡献/共同第一作者,但 Author Contributions 文本中没有。

这三项均为严重问题,且会以状态码 1 退出;预检会将其作为 P1 运行(可通过 --strict 提升严格级别)。

哪些字段会替代稿件内容,是期刊事实,不应靠猜。 该信息从期刊配置文件的 ## Portal Mechanics 块中读取(Fields that REPLACE the manuscript: …)。如果某期刊的门户规则从未记录,此检查会以状态码 2 退出,不作任何断言 — 请在首次投稿时记录该块,不要凭空编造规则。匹配由 _quote_match.py 进行分级,因此粘贴时即使句子换了行,也不会被报告为丢失。

第 3c 阶段 — CRediT 完整性(而非作者顺序)

贡献分类法是一项已发表的事实声明,但某个术语所指的工作往往没有留存在代码库中的记录(合理的 Conceptualization 可能只存在于电子邮件中)。因此,分类法检查设有门槛,佐证检查仅作为提示。

python3 "${CLAUDE_SKILL_DIR}/scripts/check_credit_integrity.py" \
  --manuscript manuscript/manuscript.md --out qc/credit_integrity.json
判定严重性触发条件
CREDIT_TERM_INVALID严重在标注为 CRediT 的章节中使用了官方 14 项以外的术语 — 将“Statistical analysis”“Manuscript writing”“Study design”解读为 CRediT 术语,而这些并非有效术语。消息会指出预期术语。
CREDIT_INITIALS_UNRESOLVED严重首字母缩写与任何作者都不匹配,或与两位作者匹配 — 这是修改署名行后留下的残余问题。
CREDIT_AUTHOR_UNLISTED严重署名行中的作者没有任何贡献归属(根据 ICMJE,这意味着需要核实作者身份,或有一项条款被删掉)。
CREDIT_UNCORROBORATED提示某个术语找不到对应依据 — 例如论文没有图却标注了 Visualization,没有 Code Availability 声明却标注了 Software,或(仅在使用 --contribution-record 时)记录中没有该贡献者。

绝不要对作者顺序或平等贡献标注设置门槛 — 这些事项需要协商,协商本身是合理的。对佐证提示,请提供确认说明;不要因为库外贡献而导致构建失败。署名行中少于两位可解析的作者姓名时,作者/首字母交叉检查会跳过并说明原因;没有贡献章节时,脚本会以状态码 2 退出,不作任何断言。

阶段 4——投稿信自由文本漂移

投稿信中的 ## Article details 区块——正文词数、摘要词数、参考文献数量、表格/图表数量——是一个伴随文件,当稿件从 v_N 分支到 v_(N+1)(重新设定词数上限、重组摘要、后期新增一批参考文献)时,它会过时,而且没有任何 docx 级审计会检查它。scripts/cover_letter_drift_check.py 会统计稿件并与投稿信中的数字声明进行比较:

python "${CLAUDE_SKILL_DIR}/scripts/cover_letter_drift_check.py" \
    --manuscript manuscript.md \
    --cover-letter cover_letter.md \
    --refs refs.bib \
    --out qc/cover_letter_drift.json

参考文献、表格和图表数量必须完全一致;摘要词数允许相差 ±5;正文词数允许相差 5%,如果投稿信将词数写为上限中的占用量(“3,998/4,000 words”),则容差缩小为剩余空间。若发现漂移,请在 v_(N+1) 构建时根据稿件重新生成投稿信。该脚本不会编辑投稿信,因为它是有意撰写的文档。

阶段 5——跨文档 N 值一致性

摘要、正文、PROSPERO 记录、投稿信、补充提取表、INDEX 和 PRISMA 流程图说明都会重复相同的 k included / k excluded / N patients 总数,任何不一致在审稿人看来都像是数据完整性问题或后期编辑失误。 scripts/cross_document_n_check.py 会按类别提取所有“N <名词>”声明(patients、cases、included、excluded、nodules、tumors、studies_total);如果某个类别有多个不同整数值,就属于 P0 漂移。使用 --root 时,它会扫描稿件、摘要、PROSPERO、根目录和各期刊目录(submission/<journal>/)中的投稿信,以及 supplement/ 和 supplementary/。如果匹配到的文件无法作为 UTF-8 读取,该文件会列在 unreadable_files 下(绝不会计入 files_scanned),并且脚本会以 2 退出,因此覆盖不完整不会被误判为通过。

python "${CLAUDE_SKILL_DIR}/scripts/cross_document_n_check.py" \
    --root . \
    --out qc/cross_document_n.json

当项目从 /meta-analysis 阶段 3f.5 冻结了 2_Data/FINAL_POOL_LOCK.yaml 时,请将其作为权威基准传入:

python "${CLAUDE_SKILL_DIR}/scripts/cross_document_n_check.py" \
    --root . \
    --pool-lock 2_Data/FINAL_POOL_LOCK.yaml \
    --out qc/cross_document_n.json

将 qc/cross_document_n.json 中的 submission_safe: false 视为暂停信号。通过追溯各处声明对应的数据文档(提取表、PRISMA 流程 TSV)来解决漂移,并更正与锁定计数不一致的文档。

阶段 6——稿件内部范围漂移

scripts/scope_drift_check.py 可检测两种 P0 模式:

  • SCOPE_DRIFT——局限性/讨论部分中的某个数值锚点(AUC、OR/HR/RR、敏感度/特异度)未出现在方法 + 结果部分中,通常是指一项后期敏感性分析,其主要报告从未出现。
  • PROSPERO_DRIFT——PROSPERO 记录承诺使用一种综合方法(Freeman-Tukey、随机效应 DerSimonian-Laird、双变量、HSROC、Bayesian 等),而方法部分使用了另一种;或者记录已更新,但方法部分仍未同步。如果方法部分写着“no amendment lodged”,这就构成了有记录的静默方案偏离。
python "${CLAUDE_SKILL_DIR}/scripts/scope_drift_check.py" \
    --manuscript manuscript.md \
    --prospero prospero/prospero_v2.md \
    --out qc/scope_drift.json

解决方法:要么 (a) 将该锚点补充到方法 + 结果部分,作为主要报告;要么 (b) 从局限性/讨论部分中删除。对于综合方法漂移,请提交 PROSPERO 修订并更新方法部分使其保持一致——两者必须在投稿前达成一致。

PROSPERO 公共记录的“Print/PDF”导出仅会呈现当前修订;更早的版本只能通过版本历史下拉菜单访问。引用 PROSPERO 版本状态时,切勿只依赖单个 PDF 导出——请分别保存每个已发布版本的 PDF,并在投稿信/补充材料中说明哪个版本作为方法学依据,哪个版本反映的是仅涉及文档的勘误。对于此类勘误(仅涉及叙述事实,不改变方法/纳入资格/综合方法),优先追加一条 Revision-Note,而不是创建新的结构化修订。

阶段 7 — v_(N+1) docx 重新生成关卡

当从冻结的 v_N 软件包构建 v_(N+1) 时(在编辑 Markdown 正文、审稿人反馈轮次或级联拒稿重新定向之后),v_(N+1) docx 必须与 v_N docx 不同。常见的静默回退是执行 cp v_N/manuscript.docx v_(N+1)/manuscript.docx,跳过 pandoc / Zotero CWYW 重新生成步骤:Markdown 已编辑,但提交门户收到的却是冻结的 v_N docx。在 v_(N+1) 提交关卡的最前面运行字节一致性断言——即使上游流水线似乎已经重新生成了 docx:

python3 "${CLAUDE_SKILL_DIR}/scripts/verify_package_integrity.py" \
    --assert-vN-docx-changed \
    --vN-docx SUBMISSION/<journal>/v<N>/manuscript.docx \
    --new-docx SUBMISSION/<journal>/v<N+1>/manuscript.docx

MD5 相同 → 退出代码为 1。修复重新生成步骤前,阻止提交。

阶段 8 — 多份稿件副本差异检查

如果项目需要手动维护多份稿件副本——manuscript.md(工作 SSOT)、manuscript_circulation.md(合作者反馈)和 submission/<journal>/manuscript.md(提交门户)——SSOT 编辑内容往往只会出现在部分副本中。在冻结软件包或发送传阅稿之前,运行定向检测器(SSOT → 各副本):

python3 ${CLAUDE_SKILL_DIR}/scripts/detect_copy_divergence.py \
  --ssot manuscript.md \
  --copy manuscript_circulation.md \
  --copy submission/<journal>/manuscript.md \
  --out qc/copy_divergence.json --strict

它会逐份报告未同步传播的 SSOT 主张(数值断言——n = N、百分比、p、OR/HR/RR、95% CI——以及章节标题)。STALE_COPY(整体状态为 DIVERGENT)属于 P0 阻塞项:重新传播这些主张,或者——更好的做法是——停止手动维护并行副本,通过构建步骤(pandoc 转换)从单一 SSOT 生成传阅稿 / 提交稿变体。只有数字或标题发生更改或缺失时才会登记,不包括措辞差异。仅存在于副本中的数值主张(stale_in_copy,例如传播了 n = 120 后,旁边仍留有旧的 n = 118)也会使副本变为 STALE_COPY;仅存在于副本中的标题(传阅稿封面说明)会列在 copy_only 中,但不会导致该状态。不存在的 --copy 路径会使程序以 2 退出。

阶段 9 — Springer Editorial Manager 打包(无标题页上传栏)

如果 Springer Editorial Manager 期刊仅提供 Manuscript / Figure / Table / Supplementary / LaTeX 上传项类型(没有 Title Page 或 Cover Letter 栏),请阅读 ${CLAUDE_SKILL_DIR}/references/springer_em_packaging.md。

阶段 10 — 修订轮次的带标记(修订跟踪)稿件

每轮修订都需要一份带标记的稿件:与审稿人看到的版本相比,显示修订跟踪的修订稿。

基准版本是 R0,而不是上一轮。 差异比较的基准始终是最初送审的版本;每轮只推进目标版本。编辑需要看到自送审版本以来的所有更改,因此不要比较 v7 和 v8。

Word 的“比较”是唯一安全的生成方式——但可通过脚本操作。 pandiff 和 LibreOffice --compare 会破坏真实稿件中的 OOXML(表格会塌陷,作者单位上标会丢失);不要使用它们。Word for Mac 可通过 AppleScript 使用带有 author name 的 compare,因此构建过程无需 GUI 操作,也无需事后重写 w:author:

python3 "${CLAUDE_SKILL_DIR}/scripts/build_marked_manuscript.py" \
  --original submission/{journal}/R0/manuscript.docx \
  --revised  submission/{journal}/R1/manuscript_clean.docx \
  --out      submission/{journal}/R1/manuscript_marked.docx \
  --author   "Submitting Author" --line-numbers

(仅限 macOS + Word。其他平台请在 Word 中手动生成带标记的文件——然后仍须运行下方的关卡。)

关卡:往返验证,而非 grep

“带标记的文件包含句子 X”这样的检查即使在 Compare 丢弃或重复段落,或将修订分给两个作者时,也会通过。应通过构造来验证——接受所有修订后必须精确还原修订稿,拒绝所有修订后必须精确还原原稿:

python3 "${CLAUDE_SKILL_DIR}/scripts/check_marked_manuscript.py" \
  --marked   submission/{journal}/R1/manuscript_marked.docx \
  --original submission/{journal}/R0/manuscript.docx \
  --revised  submission/{journal}/R1/manuscript_clean.docx \
  --author   "Submitting Author" --strict

此关卡能够识别移动操作:Word 将移位内容编码为 w:moveFrom / w:moveTo,而不是 w:ins / w:del;只了解插入/删除的验证器会看到段落被移动后出现两次,并误判好文件已损坏。如果关卡报告判定结果、准备编写其他 docx 探测脚本,或带标记的文件太大而无法上传,请阅读 ${CLAUDE_SKILL_DIR}/references/marked_manuscript.md。

评论

支持 Markdown