关于 sync-submission
sync-submission 是用于同步规范稿件与期刊投稿包的技能,面向管理多期刊稿件的研究团队。它通过哈希审计、构建、预检和冻结记录追踪差异与状态,但冻结不代表审批或内容保真已验证。
主要功能
- 01审计投稿包与规范稿件的差异
- 02按声明文件构建投稿包并记录元数据
- 03冻结字节快照及可用检查上下文
- 04运行可配置的投稿前检查门
- 05扫描双盲投稿材料中的作者标识
- 06生成同步审计和质量检查报告
适用场景
- 01检查期刊投稿包是否与规范稿件同步
- 02在投稿前构建并登记最终材料
- 03运行门禁检查后冻结提交版本
- 04查找双盲材料中的作者身份信息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aperivue/ medsci-skills --skill sync-submission安装后在 Claude Code 中输入/sync-submission确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/build_synthetic_bundle.pyreferences/bundle_workflow.mdjournal_availability_policy.jsonmarked_manuscript.mdspringer_em_packaging.mdscripts/_quote_match.py_yaml_frontmatter.pyassemble_supplement.pyauthor_registry_example.yamlblind_sweep.pybuild_marked_manuscript.pycheck_asset_anonymization.pycheck_checklist_dump_leak.pycheck_credit_integrity.pycheck_cross_artifact_stale.pycheck_disclosure_availability.pycheck_marked_manuscript.pycheck_portal_field_residue.pycheck_portal_mirror.pycheck_wordcount_cap.pycover_letter_drift_check.pyscripts/check_portal_field_residue_challenge/problem.mdverify.shscripts/check_portal_field_residue_challenge/fixture/negative/abstract.txtkeywords.txtscripts/check_portal_field_residue_challenge/fixture/positive/abstract.txttake_home.txtscripts/credit_integrity_challenge/verify.shscripts/credit_integrity_challenge/fixture/manuscript_bad.mdmanuscript_good.md详细介绍
同步投稿包
确保规范稿件与期刊专用投稿包保持一致。
将 submission/{journal}/ 视为派生输出,并记录其状态是最新、过期还是已冻结。
输入
- 包含
project.yaml的项目根目录,或规范稿件的直接路径。 - 期刊简称,例如
chest、ryai、academic_radiology。 - 可选模式:
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。
工作流
- 从
project.yaml或显式输入中解析规范稿件。 - 以请求的模式运行脚本。
- 如果
audit报告DRIFT,在用户修补规范稿件或将差异记录为仅限日志之前,不要重新指定目标或冻结。切勿静默地将提交内容的编辑合并回 SSOT,也不要隐藏仅限日志的差异——应将其记录为漂移或明确例外。 - 如果
build成功,在最终提交前运行/verify-refs。 - 仅当源哈希匹配时,才将软件包视为当前版本;只能通过
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.72retired_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。