| name | deterministic-pipeline |
| description | 把一个分析需求写成可复现的 Nextflow 或 Snakemake 工作流,含测试、容器 digest 固定、参考版本固定、provenance 输出。当用户要求做 RNA-seq/WGS/WES/ATAC-seq/单细胞分析、跑 nf-core 流程、批量处理测序数据、或需要"可复现的分析流程"时使用。也在需要把一段探索性 notebook 固化成生产流程时使用。 |
| allowed-tools | Read, Write, Edit, Grep, Glob, Bash(nextflow *), Bash(nf-test *), Bash(snakemake *), Bash(nf-core *), Bash(pytest *), Bash(docker buildx imagetools *), mcp__biomni__* |
| model | opus |
| effort | high |
写确定性流水线(而不是跑分析)
这个 skill 的唯一目的:把 LLM 挪到可复现边界之外
为什么这不是洁癖,而是必需: 托管 LLM 的输出不可复现,且原因在调用方控制范围外。
2025-09 的实验结果推翻了通常的解释 —— 真正原因不是"并发 + 浮点非结合律"
(kernel 单独运行是确定的),而是缺乏 batch invariance:生产环境用
continuous batching,请求的 batch size 随服务端负载波动,reduction order
随之变化。实测在 Qwen3-235B 上,1000 次 temperature=0 的相同请求产生了
80 种不同输出。
结论:temperature=0 不构成可复现性保证。所以:
智能体编写并启动流水线;DAG 引擎确定性执行;人在边界处签字。
这样 Nextflow 的 -resume 任务哈希(11 项输入)、WRROC provenance、
容器 digest、nf-test 全部落在确定性一侧,不被 LLM 污染。
Seqera Co-Scientist 是这个分工的现成范例。
硬性检查清单(G_I 门会逐条机器验证,过不了不放行)
1. 测试先写,流水线后写
这是唯一同时满足 verifier's law 五个性质(客观真值 / 验证快 / 可扩展 /
低噪 / 连续奖励)的验证档位。best-of-N 采样只在存在自动验证器的领域可扩展 ——
没有测试,后面所有的迭代都是在猜。
nf-test init
nf-test generate process modules/local/my_process/main.nf
nf-test test --profile test
nf-test 已同行评审(GigaScience 14),报告 CI 时间下降最多 80%。
2. 容器 digest 固定,永不用 tag
// ❌ 错
container 'quay.io/biocontainers/samtools:1.21--h50ea8bc_0'
// ❌ 更错
container 'biocontainers/samtools:latest'
// ✅ 对
container 'quay.io/biocontainers/samtools@sha256:2f7f9d5a...(64 位十六进制)'
取 digest:docker buildx imagetools inspect <image>:<tag>。
理由:tag 可被重新推送,既是可复现性漏洞也是供应链攻击面。
3. 参考序列/注释显式固定,禁用 iGenomes
固定值由 session 注入(LAB_REF_ENSEMBL / LAB_REF_GENCODE / LAB_REF_REFSEQ)。
禁止 --genome GRCh38(走 iGenomes) —— nf-core 自己的文档警告
iGenomes 的人类注释停留在 Ensembl release 75。
params.fasta = "${params.ref_base}/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz"
params.gtf = "${params.ref_base}/gencode.v50.primary_assembly.annotation.gtf.gz"
params.ref_provenance = "Ensembl 116 / GENCODE 50; downloaded 2026-07-01; md5 in assets/ref.md5"
考虑用 refgenie 的 sequence-derived digest 做跨流程基因组身份校验。
4. 阳性对照与守恒断言写进流水线,不留给报告
process QC_ASSERT {
input: path counts
output: path "assert.ok"
script:
"""
python - <<'PY'
import anndata as ad, sys
a = ad.read_h5ad("${counts}")
# 守恒:过滤前后细胞数只减不增
assert a.n_obs <= int("${params.n_obs_before}"), "细胞数增加了 —— 过滤逻辑有误"
# 维度:基因数与注释一致
assert a.n_vars == ${params.n_genes_expected}, f"基因数 {a.n_vars} != 期望"
# 阳性对照:管家基因必须在高表达区间
for g in ["ACTB", "GAPDH"]:
assert g in a.var_names, f"阳性对照 {g} 缺失"
open("assert.ok","w").write("ok")
PY
"""
}
5. 随机性:传 generator,不设全局种子
NumPy NEP 19(Status: Final)明确 legacy RandomState 只为单测目的冻结,
不保证跨版本复现整个程序。原文推荐做法:"instantiate a generator object
with a seed and pass it around"。
rng = np.random.default_rng(params.seed)
np.random.seed(params.seed)
sklearn 的 random_state:CV splitter 用 int(这样 fold 才可比)。
不要传共享的 RandomState 实例 —— clone()(被 GridSearchCV、
StackingClassifier 使用)会复制出共用并互相消耗同一 RNG 的估计器。
6. 环境锁定
优先 pixi.lock(多平台完全解析);R 侧 renv.lock;
conda 用 explicit spec。channel 顺序 bioconda > conda-forge,
channel_priority: strict,避开 defaults(Anaconda 2024-03 ToS 对
≥200 员工的商业组织收费)。
⚠️ uv 只管 Python,不管编译型生物信息二进制 —— 它补充 conda,不替代。
7. provenance 必须产出
Nextflow 没有 -with-provenance 标志。两条路:
nf-prov 插件(v1.7.0):-plugins nf-prov,可输出 wrroc / bco / dag / gexf
- 或 25.04+ 的实验性 lineage:
lineage.enabled、lid://、nextflow lineage diff
⚠️ 区分清楚:nf-core pipelines rocrate 产出的是前瞻性 crate(描述仓库),
运行时的回溯性 provenance 是 nf-prov 的活。
8. 缓存陷阱
-resume 的默认输入文件哈希是 path + mtime + size,不是内容。
共享文件系统上时间戳不一致会导致缓存误失效 —— 用 cache 'deep'(哈希内容)
或 cache 'lenient'(name + size)。
若某个 process 修改了自己的输入文件,它无法被 resume。
Snakemake 变体
用 checkpoint 做有界的 DAG 重评估(5.4 起支持,早于 LLM):
checkpoints.somestep.get(...) 抛 IncompleteCheckpointException 作为延迟信号。
容器化用 --sdm conda apptainer(--use-conda 在 8+ 已被取代)。
--report 默认输出含运行统计、provenance 与拓扑的自包含 HTML。
nf-core 使用注意
nf-core tools v4.0.2 起 裸 nf-core lint / nf-core create 已移除,
必须带 pipelines 子命令前缀:nf-core pipelines lint。
Nextflow 26.04 起 strict syntax 为默认,禁止 for/while、switch、
import、class 声明 —— 老代码需要改写。
交付物
pipelines/<name>.nf(或 .smk)
tests/(nf-test 或 pytest),必须全绿
assets/ref.md5、pixi.lock
nextflow.config 含 digest-pinned 容器与机构 profile
docs/<name>.md:一段"这个流程做什么、不做什么、已知失败模式"