biostochastics/clawbio_bench

GitHub: biostochastics/clawbio_bench

独立的生物信息学审计基准,通过进程隔离验证工具的安全性、正确性与诚实性。

Stars: 3 | Forks: 0

# clawbio_bench ``` ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠛⠉⠉⠉⠈⠉⠉⠙⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⠀⠀⢀⣠⣤⣤⣤⣤⣤⣤⣄⡀⠈⠛⢿⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⠀⢀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠈⠻⣿⣿⣿⣿⣿⣿ ██████ ██ █████ ██ ██ ██████ ██ ██████ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⣠⣾⣿⣿⣿⣿⡿⢿⠛⡟⢿⣿⣿⣿⣿⣷⠀⠀⢹⣿⣿⣿⣿⣿ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢠⣿⣿⣿⣿⣿⡿⡋⠃⠈⠀⠀⠈⠈⢻⣿⣿⣿⠀⠀⠀⣿⣿⣿⣿⣿ ██ ██ ███████ ██ █ ██ ██████ ██ ██ ██ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡃⣿⣿⣿⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣻⣿⣿⣿⣿ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠹⣿⣿⣿⣿⣿⣦⡂⡀⠀⠀⠀⠀⠀⣰⣶⣶⣶⠀⠀⠀⣿⣿⣿⣿⣿ ██████ ███████ ██ ██ ███ ███ ██████ ██ ██████ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠉⠻⣿⣿⣿⣿⣿⣧⣼⣀⣆⣼⣾⣿⣿⣿⣿⠀⠀⢰⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠘⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⣠⣿⣿⣿⣿⣿⣿ ██████ ███████ ███ ██ ██████ ██ ██ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠛⣿⣿⣄⡀⠀⠈⠙⠻⠿⠿⠿⠿⠿⠿⠟⠋⠀⣀⣼⣿⣿⣿⣿⣿⣿⣿ ██ ██ ██ ████ ██ ██ ██ ██ ⣿⣿⣿⣿⣿⣿⣿⠿⠃⠀⢀⣼⣿⣿⣿⣦⣄⣀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿ ██████ █████ ██ ██ ██ ██ ███████ ⣿⣿⣿⣿⣿⠟⠉⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ██ ██ ██ ██ ██ ██ ██ ██ ██ ⣿⣿⡿⢋⠁⢀⣤⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ███████ ██████ ███████ ██ ████ ██████ ██ ██ ⢟⠉⠀⣠⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣷⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ``` [![Version](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fbiostochastics%2Fclawbio_bench%2Fmain%2Fpyproject.toml&query=%24.project.version&prefix=v&label=version&color=blue)](https://github.com/biostochastics/clawbio_bench/releases) [![Python](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fbiostochastics%2Fclawbio_bench%2Fmain%2Fpyproject.toml&query=%24.project.%22requires-python%22&label=python&color=blue)](https://www.python.org) [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/5f5d70396f111848.svg)](https://github.com/biostochastics/clawbio_bench/actions/workflows/ci.yml) [![Tests](https://img.shields.io/badge/tests-245%20passing-brightgreen)](tests/) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![mypy: checked](https://img.shields.io/badge/mypy-checked-blue)](https://mypy-lang.org/) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/biostochastics/clawbio_bench) 大多数生物信息学基准测试回答“它能运行吗?”。这套基准回答 **“它安全、准确、诚实吗?”** —— 每一步都有机器可验证的证据。 - **对于 ClawBio / 工具作者**:在 CI 中运行 `clawbio-bench --smoke` 以捕获提交之间安全性与正确性的回归。 - **对于外部审计员**:使用评分标准设计、真实方法学和判决格式作为参考,以审计其他计算生物学工具。 - **[审计报告(PDF)](clawbio_audit_report_20260406.pdf)** — 一份 21 页的报告,来自对 ClawBio HEAD 的 7 个 harness 运行(v0.1.2 时 147 个测试通过 125 个)。当前套件(v0.1.4)运行 9 个 harness,共 175 个测试用例(参见[覆盖范围](#coverage-scope)),并报告 **163/175(93.1%)** 针对 ClawBio HEAD `e7590141`(2026-04-07),其中在 [已确认发现](#confirmed-findings-at-clawbio-head) 中突出显示。 ### 三个审计维度 | 维度 | 含义 | 示例发现类别 | |---|---|---| | **安全性** | 工具是否拒绝或隔离不安全输入?没有 `shell=True`,对畸形基因型不崩溃,不会静默抑制非零退出。 | `injection_blocked`, `edge_handled`, `exit_handled` | | **正确性** | 工具是否产生正确的*数值答案*?FST 值、表型调用、PRS、HEIM 界。 | `fst_correct`, `correct_determinate`, `score_correct` | | **诚实性** | 工具**报告的实际行为**,而非它声称的行为?诚实性失败的一个例子是:工具计算 Nei 的 GST 却标记输出为“Hudson's FST”,或者 CSV 模式夸大覆盖范围。 | `fst_mislabeled`, `csv_inflated`, `disclosure_failure` | “诚实性”是独特的轴。正确性失败通常显而易见;诚实性失败 subtle、危险,且很少被传统测试套件捕获。 ## 目录 - [Requirements](#requirements) - [Install](#install) - [Quick Start](#quick-start) - [How It Works](#how-it-works) - [Process Isolation — Does ClawBio Actually Run?](#process-isolation--does-clawbio-actually-run) - [What It Produces](#what-it-produces) - [Core Concepts](#core-concepts) - [Coverage Scope](#coverage-scope) - [Harnesses](#harnesses) - [Ground Truth Formats](#ground-truth-formats) - [Verdict Schema as External Contract](#verdict-schema-as-external-contract) - [Core Capabilities](#core-capabilities) - [Implementation Safeguards](#implementation-safeguards) - [Current Scope and Limitations](#current-scope-and-limitations) - [Design Principles](#design-principles) - [Understanding Results (Exit Codes)](#understanding-results-exit-codes) - [Run Tests](#run-tests) - [Continuous Audit (GitHub Actions)](#continuous-audit-github-actions) - [Confirmed Findings at ClawBio HEAD](#confirmed-findings-at-clawbio-head) - [References](#references) - [Roadmap](#roadmap) - [Documentation](#documentation) - [License](#license) ## 要求 - **Python 3.11 或更高版本**(3.11、3.12、3.13、3.14 均在 CI 中测试) - **Git** 在 `PATH` 中可用 - **本地克隆 [ClawBio](https://github.com/ClawBio/ClawBio)** —— 本仓库不捆绑 ClawBio。每次 harness 运行都需要 `--repo /path/to/ClawBio` 参数。 - **numpy 和 pandas** 在基准虚拟环境中 —— ClawBio 的 `clawbio.common` 包无条件导入 `scrna_io`,这需要 numpy 和 pandas 即使在不使用 scRNA 功能时也必须存在。否则 **每个 harness 都会报告 `unroutable_crash` / `harness_error`**,原因是 `ModuleNotFoundError` 而非真实审计发现。请通过 `[dev]` 或 `[finemapping]` 额外依赖自动安装它们。 - **[Typst](https://typst.app)** CLI 在 `PATH` 中 —— 仅用于 PDF 报告生成(`python scripts/generate_report.py`)。可通过 `brew install typst`(macOS)、`cargo install typst-cli` 或从 [typst.app](https://github.com/typst/typst/releases) 下载安装。基准本身无需 Typst,仅报告渲染需要。 - 操作系统:Linux 或 macOS(Windows 未测试) ## 安装 ``` python3.11 -m venv .venv && source .venv/bin/activate pip install -e . # core: msgspec, regex, ruamel.yaml pip install -e ".[dev]" # + pytest, ruff, mypy, pre-commit, rich, numpy, pandas pip install -e ".[all]" # + viz, ui, finemapping, scikit-learn (for CI / daily audit) pip install -e ".[viz]" # + matplotlib for heatmap rendering pip install -e ".[ui]" # + rich for styled CLI output pip install -e ".[finemapping]" # + numpy, pandas for the fine-mapping subprocess driver ``` 核心安装刻意保持最小化 —— 每个运行时依赖都会扩大审计工具的信任基线,因此每个依赖都必须有正当理由(参见[核心能力](#core-capabilities))。 ## 快速开始 假设你已有一个位于 `~/src/ClawBio` 的 ClawBio 检出,最小路径如下: ``` git clone https://github.com/biostochastics/clawbio_bench.git cd clawbio_bench python3.11 -m venv .venv && source .venv/bin/activate pip install -e ".[dev]" # includes numpy/pandas needed by ClawBio clawbio-bench --smoke --repo ~/src/ClawBio ``` 这会在 ClawBio 的 `HEAD` 提交上运行所有 harness(约 25 秒),并将结果写入 `./results/suite//`。 ### 其他常用调用 ``` # 列出可用的测试平台和测试用例数量 clawbio-bench --list # 机器可读的测试平台清单(用于脚本/仪表板) clawbio-bench --list --json # 仅单个测试平台 clawbio-bench --smoke --harness orchestrator --repo ~/src/ClawBio # 预览将要运行的内容而不执行 clawbio-bench --smoke --repo ~/src/ClawBio --dry-run # 最近10次提交 — 长期扫描,静默模式用于CI clawbio-bench --regression-window 10 --repo ~/src/ClawBio -q # 在特定分支上的完整长期扫描 clawbio-bench --all-commits --branch main --repo ~/src/ClawBio # 仅标记的提交 — 每个发布/里程碑的基准测试 clawbio-bench --tagged-commits --repo ~/src/ClawBio # 自定义测试用例目录 clawbio-bench --smoke --harness equity --inputs /my/test_cases --repo ~/src/ClawBio # 渲染热图PNG(需要 [viz] 额外组件) clawbio-bench --heatmap results/suite/20260404_120000/ # 渲染与CI工作流提交到PR的相同Markdown报告 clawbio-bench --render-markdown results/suite/20260404_120000/ \ --baseline /path/to/main-baseline.json # 深度溯源验证(三层 — 参见“产生内容”) clawbio-bench --verify results/suite/20260404_120000/ # 也可作为模块使用 python -m clawbio_bench --smoke --repo ~/src/ClawBio # 版本 + 来源证明 clawbio-bench --version ``` ### CLI 参数参考 | 参数 | 用途 | |---|---| | `--smoke` | 快速检查:仅 HEAD 提交、所有 harness。默认的 CI 网关。 | | `--regression-window N` | 回放当前分支最近 `N` 个提交的每个测试用例。 | | `--all-commits` | 从第一个审计时代提交开始遍历分支上的每个提交(最慢)。 | | `--tagged-commits` | 仅针对标记(发布/里程碑)提交运行。热力图在时间线上标注发布名称。 | | `--commits SHA,SHA,...` | 显式提交列表(诊断模式)。 | | `--branch NAME` | 遍历的分支(默认:`main`)。 | | `--harness NAME` | 仅运行一个 harness(例如 `equity`)。省略则运行全部九个。 | | `--inputs PATH` | 为单个 harness 覆盖捆绑的测试用例目录。 | | `--output DIR` | 结果存放位置。默认:`./results/suite//`。 | | `--repo PATH` | **每个真实运行必需**:本地 ClawBio 检出路径。 | | `--list` | 打印 harness 注册表及测试用例数量。 | | `--list --json` | 同上,机器可读格式。 | | `--dry-run` | 显示计划(提交 × harness × 测试用例)但不执行。 | | `--allow-dirty` | 安全覆盖:即使 ClawBio 工作区不干净也运行。默认情况下,脏仓库会硬性停止以保护链式保管。 | | `--verify DIR` | 三层链式保管重新验证现有结果目录 | | `--heatmap DIR` | 从结果目录渲染 `heatmap.png`(需要 `[viz]` 额外依赖)。 | | `--render-markdown DIR` | 渲染 CI 会生成的 PR 评论 Markdown 报告。 | | `--baseline PATH` | 用于 `--render-markdown` 的基线聚合报告(或目录),以进行差异对比。 | | `-q` / `--quiet` | 抑制每个测试的进度信息。 | | `--no-rich` | 强制使用纯文本表格(即使安装了 `rich`),确保字节稳定的输出用于差异对比。 | | `--version` | 打印版本和来源信息。 | ## 工作原理 `clawbio_bench` 在 **(commits × test_cases) 矩阵** 上运行。对于你选择的每个提交和每个测试用例,都会执行一次 harness,并将该 `(commit, test_case)` 对产生一个判决 —— 即使 harness 本身崩溃(基础设施故障会成为 `harness_error` 判决而非中止整个扫描)。 ``` ┌──────────────────────────────────────────────────────────┐ │ clawbio-bench --smoke / --regression-window │ └──────────────────────────────────────────────────────────┘ │ ▼ ┌────────────────── Matrix runner ──────────────────┐ │ │ │ for commit in selected_commits: │ │ git worktree checkout commit ← isolation │ │ clean_workspace (incl. submodules) │ │ │ │ for test_case in harness.test_cases: │ │ ground_truth = parse_ground_truth(...) │ │ execution = capture_execution(...) │ │ scored = harness.run_single_*(...) │ │ verdict = build_verdict_doc(...) │ │ save_verdict(); save_execution_logs() │ │ │ └────────────────────────────────────────────────────┘ │ ▼ aggregate_report.json · heatmap.png · verdict_hashes.json (per harness) · rendered markdown (optional) ``` 逐步说明: 1. **解析提交集**。`--smoke` → `[HEAD]`。`--regression-window N` → 最近 `N` 个提交。`--all-commits` → 从审计时代根开始的每个提交。`--tagged-commits` → 仅标记(发布)提交。`--commits SHA,...` → 显式列表。 2. **隔离每个提交**。每个提交都在 git 工作树中检出,使用工作树以免修改用户的工作树,并在提交之间递归重置子模块,防止一个脏子模块污染后续提交。 3. **运行每个测试用例**。每个 harness 遍历其捆绑的测试用例,解析地面真值,调用 ClawBio 技能(通过 `capture_execution()`,使用带超时、截断限制的子进程,并可选地重试 argparse 失败),并捕获 `stdout`、`stderr`、`exit_code` 和磁盘上的工件文件。 4. **针对地面真值评分**。每个 harness 应用其评分标准 —— 按类别而非简单的通过/失败。一个发现会落在约 7–10 个命名桶之一(例如 `fst_mislabeled` ≠ `fst_incorrect`),每个桶对应具体的修复路径。 5. **生成判决文档**。`build_verdict_doc()` 组装一个规范、字节排序的 JSON 文档,包含每个输入、输出、地面真值文件的 SHA-256 哈希(并在写入时嵌入判决本身)。 6. **聚合**。每个 harness 生成 `summary.json` / `all_verdicts.json`,套件级 `aggregate_report.json`、`heatmap_data.json` 以及防篡改的 `verdict_hashes.json` 侧车文件。 矩阵模型正是 `--smoke` 约 30 秒(1 个提交 × 175 个测试)的原因,而 `--regression-window 20` 则需数分钟(20 × 175)。 ## 进程隔离 — ClawBio 真的运行了吗? **是的 —— ClawBio 的实际代码确实被执行了。** 不是模拟,也不是重实现。ClawBio **不**与基准共享 Python 解释器。每个测试用例都会通过 `subprocess.run()`(永远不使用 `shell=True`)启动一个独立的 OS 进程,在该进程中运行真实的 ClawBio 代码,基准从捕获的 stdout、stderr、退出码和磁盘文件读取结果。 基准包本身**不包含** `import clawbio` / `from clawbio …` 语句。这是“松散耦合不变量”:审计者与被测者无法相互污染解释器状态,审计工具的信任表面保持在三个运行时依赖(`msgspec`、`regex`、`ruamel.yaml`),如果某个技能在某个提交中缺失或损坏,会产生干净的 `exit 127`,而不是污染整个扫描的 `ModuleNotFoundError`。 ### 视图 1 — 进程隔离在 OS 层面 ``` ═══════════════════════════════════════════════════════════════════════════════ HOST OS (macOS / Linux) ═══════════════════════════════════════════════════════════════════════════════ ┌─────────────────────────────────────────────────────────────────────────┐ │ PROCESS #1 · pid 42000 · the auditor │ │ ──────────────────────────────────────── │ │ argv: clawbio-bench --smoke --repo ~/src/ClawBio │ │ python: /Users/you/clawbio_bench/.venv/bin/python3.14 │ │ imports: clawbio_bench.cli, .core, .harnesses.*, msgspec, regex, │ │ ruamel.yaml ← 3 deps, that's the full list │ │ memory: ~60 MB │ │ │ │ ┌─ clawbio_bench.cli.main() │ │ │ resolves commit set → [HEAD] │ │ │ for each harness in HARNESS_REGISTRY: │ │ │ for each test_case: │ │ │ ┌─ harness_core.capture_execution(cmd=[...]) │ │ │ │ build cmd list │ │ │ │ subprocess.run(cmd, cwd=repo_path, timeout=…, │ │ │ │ capture_output=True, shell=False) │ │ │ │ │ │ │ │ │ │ ← fork() + execve() (OS boundary) │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ ╔════════════════════════════════════════════════════╗ │ │ │ │ ║ PROCESS #2 · pid 42017 · the auditee ║ │ │ │ │ ║ ────────────────────────────────────── ║ │ │ │ │ ║ argv: /.../.venv/bin/python3.14 \ ║ │ │ │ │ ║ ~/src/ClawBio/skills/pharmgx-reporter/ \ ║ │ │ │ │ ║ pharmgx_reporter.py \ ║ │ │ │ │ ║ --input pg_01_cyp2c19.txt \ ║ │ │ │ │ ║ --output results/…/tool_output/ \ ║ │ │ │ │ ║ --no-enrich ║ │ │ │ │ ║ cwd: ~/src/ClawBio ← ClawBio's own worktree ║ │ │ │ │ ║ imports: WHATEVER pharmgx_reporter.py IMPORTS ║ │ │ │ │ ║ (transitive closure of the target repo) ║ │ │ │ │ ║ memory: separate heap, separate GIL, separate ║ │ │ │ │ ║ sys.modules, separate logging state ║ │ │ │ │ ║ ║ │ │ │ │ ║ ┌─ pharmgx_reporter.main() ║ │ │ │ │ ║ │ parse 23andMe TSV ║ │ │ │ │ ║ │ call CPIC phenotype logic ║ │ │ │ │ ║ │ write report.md + result.json ║ │ │ │ │ ║ │ print rationale to stdout ║ │ │ │ │ ║ └─ sys.exit(0) ║ │ │ │ │ ╚════════════════════════════════════════════════════╝ │ │ │ │ │ │ │ │ │ │ ← _exit() (OS boundary, same direction) │ │ │ │ ▼ │ │ │ │ auditor receives: │ │ │ │ · exit_code: int │ │ │ │ · stdout: bytes (up to 10 MB, else truncated) │ │ │ │ · stderr: bytes (same cap) │ │ │ │ · wall_seconds: float │ │ │ │ · (files on disk in tool_output/) │ │ │ │ │ │ │ └─ score verdict · compute SHA-256 on inputs/outputs/logs · │ │ │ build_verdict_doc() · save_verdict() (atomic write) │ │ └────────── │ └─────────────────────────────────────────────────────────────────────────┘ Process #1 never imports anything from ~/src/ClawBio. Process #2 is a fresh Python interpreter — anything the target imports happens entirely in its own sys.modules and dies with the process. Communication is four channels only: argv in, stdout + stderr + exit + files out. ``` ### 视图 2 — 矩阵循环,概览 ``` ┌────────────────────────────────────────────────────────────┐ │ clawbio-bench --smoke │ │ (process #1, the auditor) │ └────────────────────────────────────────────────────────────┘ │ ┌──────────────────────┼──────────────────────┐ ▼ ▼ ▼ commits = [HEAD] test_cases per harness HARNESS_REGISTRY │ │ │ └────────────┬─────────┴──────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────────┐ │ for commit in commits: │ │ git worktree checkout commit (subprocess to git) │ │ clean_workspace(submodules=True) (subprocess to git) │ │ │ │ for harness in HARNESS_REGISTRY: │ │ for test_case in harness.test_cases: │ │ │ │ ┌───────────────────────────────────────────────┐ │ │ │ ground_truth = parse_ground_truth(...) │ │ │ │ │ │ │ │ cmd = [ │ │ │ │ sys.executable, │ │ │ │ str(repo_path/"skills"/""/"*.py"), │ │ │ │ "--input", str(payload), │ │ │ │ "--output", str(tool_output_dir), │ │ │ │ …, │ │ │ │ ] │ │ │ │ │ │ │ │ execution = capture_execution(cmd, cwd=repo) │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ ╔══════════════════════════╗ │ │ │ │ ║ SUBPROCESS ║ │ │ │ │ ║ python skills/.../*.py ║ │ │ │ │ ║ ← actual ClawBio code → ║ │ │ │ │ ║ runs for real ║ │ │ │ │ ║ writes artifacts ║ │ │ │ │ ║ exits with code N ║ │ │ │ │ ╚══════════════════════════╝ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ stdout, stderr, exit_code, tool_output/*.* │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ verdict = score__verdict( │ │ │ │ ground_truth, execution, analysis │ │ │ │ ) │ │ │ │ │ │ │ │ doc = build_verdict_doc( │ │ │ │ verdict, execution, commit_meta, │ │ │ │ chain_of_custody={ │ │ │ │ payload_sha256, stdout_sha256, │ │ │ │ stdout_full_sha256, driver_sha256, … │ │ │ │ } │ │ │ │ ) │ │ │ │ │ │ │ │ save_verdict(doc, …) ← atomic write │ │ │ │ _verdict_sha256 embedded + re-verified │ │ │ └───────────────────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────┘ │ ▼ aggregate_report.json + verdict_hashes.json per harness ``` ### 视图 3 — 三种调用模式并排 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Pattern A — CLI subprocess │ │ Used by: orchestrator, pharmgx, equity, nutrigx, metagenomics, cvr │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ auditor (pid 42000) auditee (pid 42017) │ │ │ │ cmd = [ │ │ sys.executable, │ │ "~/src/ClawBio/skills/pharmgx-reporter/pharmgx_reporter.py", │ │ "--input", "pg_01.txt", │ │ "--output", "results/.../tool_output", │ │ "--no-enrich", │ │ ] │ │ │ │ subprocess.run(cmd, cwd=~/src/ClawBio, shell=False, capture_output=True) │ │ ──────────────────────────────────────▶┌──────────────────────────────┐ │ │ │ python pharmgx_reporter.py │ │ │ │ │ │ │ │ imports: │ │ │ │ · argparse │ │ │ │ · pandas (if ClawBio uses) │ │ │ │ · whatever else the tool │ │ │ │ wants │ │ │ │ │ │ │ │ reads pg_01.txt │ │ │ │ writes tool_output/ │ │ │ │ prints to stdout / stderr │ │ │ │ sys.exit(0) │ │ │ └──────────────────────────────┘ │ │ ◀────────────────────────────────────── exit, stdout, stderr │ │ │ │ scores verdict, hashes everything │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ │ Pattern B — Subprocess driver shim │ │ Used by: finemapping (because the target has NO CLI, just library modules) │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ auditor (pid 42000) driver (pid 42017) │ │ │ │ cmd = [ │ │ sys.executable, │ │ "/drivers/finemapping_driver.py", ← OUR file, not │ │ "--skill-dir", "~/src/ClawBio/skills/fine-mapping", ClawBio's │ │ "--inputs", "test_case/inputs.json", │ │ "--output", "result.json", │ │ ] │ │ │ │ subprocess.run(cmd, cwd=~/src/ClawBio, shell=False) │ │ ──────────────────────────────────────▶┌──────────────────────────────┐ │ │ │ python finemapping_driver.py │ │ │ │ │ │ │ │ sys.path.insert(0, │ │ │ │ "") │ │ │ │ │ │ │ │ ┌──────────────────────────┐ │ │ │ │ │ from core.abf import │ │ │ │ │ │ approximate_bayes_... │ │ │ │ │ │ from core.susie import │ │ │ │ │ │ susie_ibss │ │ │ │ │ │ from core.credible_sets │ │ │ │ │ │ import build_cs │ │ │ │ │ │ ↑ THIS is where │ │ │ │ │ │ ClawBio code gets │ │ │ │ │ │ imported — but in │ │ │ │ │ │ a SEPARATE Python │ │ │ │ │ │ interpreter that │ │ │ │ │ │ will die in ~1 s │ │ │ │ │ └──────────────────────────┘ │ │ │ │ │ │ │ │ run ABF / SuSiE │ │ │ │ json.dump(result) → stdout │ │ │ │ sys.exit({0,1,2}) │ │ │ └──────────────────────────────┘ │ │ ◀────────────────────────────────────── JSON on stdout │ │ │ │ parses JSON, scores, hashes driver file itself (driver_sha256) │ │ │ │ ▶ The auditor's own Python process STILL never touches ClawBio. │ │ The driver is a clawbio_bench DATA FILE — bundled under drivers/ │ │ but explicitly not imported from anywhere in the package. │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ │ Pattern C — AST static analysis │ │ Used by: metagenomics (only, as a secondary channel alongside Pattern A) │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ auditor (pid 42000, no subprocess spawned) │ │ │ │ source_path = repo_path/"skills"/"claw-metagenomics"/"metagenomics.py" │ │ │ │ text = source_path.read_text(errors="replace") ← reads AS TEXT │ │ tree = ast.parse(text, filename=str(source_path)) ← builds syntax tree │ │ NO CODE EXECUTES │ │ │ │ for node in ast.walk(tree): │ │ if subprocess.run(..., shell=True) — found → injection_succeeded │ │ if run_command(critical=False) — found → exit_suppressed │ │ … │ │ │ │ ▶ ast.parse() is lexer + parser, not an interpreter. None of the │ │ source's side effects fire. It's the same mechanism `ruff`, `mypy`, │ │ and `bandit` use to read code without running it. │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### 为什么进程隔离很重要(设计原理) 1. **无共享解释器状态**。导入副作用、猴子补丁、全局日志配置、`sys.path` 修改、C 扩展崩溃等都不会影响审计者,因为目标从未在审计者的进程中运行。 2. **仅子进程错误变得可见**。退出码处理、stderr 通道纪律、argparse 漂移、信号语义、非零退出抑制 —— 这些对内联调用者不可见,正是 `exit_suppressed` / `disclosure_failure` 类别存在的理由。 3. **信任表面保持最小**。`clawbio_bench` 声明三个运行时依赖(`msgspec`、`regex`、`ruamel.yaml`)。如果它导入 ClawBio,那么 ClawBio 的整个传递依赖闭包都会成为审计工具的信任基 —— 而一个审计其自身代码的工具在根本上就是有缺陷的。 4. **技能不存在时的优雅降级**。纵向扫描会遍历早于某技能存在的提交。子进程调用自然会在缺少工具路径时返回 `FileNotFoundError` / 退出 127,而不是在基准中引发 `ModuleNotFoundError` 并破坏整个运行。 ## 产出物 每次运行都会写入一个带时间戳的目录: ``` results/suite/20260404_120000/ ├── aggregate_report.json # suite-level rollup: pass/fail by harness, counts, env ├── orchestrator/ │ ├── manifest.json # run parameters, env, commit set, ground_truth_refs │ ├── summary.json # category histogram, pass rate, persistent failures │ ├── all_verdicts.json # flat list of every verdict in the run │ ├── heatmap_data.json # commits × test_cases grid, category-coded │ ├── verdict_hashes.json # {rel_path: _verdict_sha256} sidecar index │ └── / │ └── / │ ├── verdict.json # ◄─── the canonical unit of audit │ ├── stdout.log # captured ClawBio stdout (pre-truncation hash in verdict) │ └── stderr.log # captured ClawBio stderr ├── equity/ …same layout… ├── pharmgx/ …same layout… ├── nutrigx/ …same layout… ├── metagenomics/…same layout… └── finemapping/ …same layout… ``` ### 示例判决 JSON 一个真实的 `verdict.json`(缩写;哈希和推理已简化以提高可读性 —— 实际输出是规范、按键排序的 JSON,且每个字段完全填充): ``` { "benchmark_name": "pharmgx-reporter", "benchmark_version": "0.1.0", "start_time_utc": "2026-04-04T12:00:03.114Z", "timestamp_utc": "2026-04-04T12:00:04.892Z", "wall_clock_seconds": 1.778, "commit": { "sha": "a1b2c3d4e5f6…", "short_sha": "a1b2c3d", "author": "ClawBio Team", "date_utc": "2026-03-28T09:14:22+00:00", "subject": "pharmgx: handle CYP2C19 *2/*2 diplotype" }, "test_case": { "name": "pg_01_cyp2c19_pm_clopidogrel", "driver": ".../test_cases/pharmgx/pg_01_cyp2c19_pm_clopidogrel/driver.sh", "driver_sha256": "7e4b…", "payload": "input.tsv", "payload_sha256": "d41d8cd…" }, "ground_truth": { "BENCHMARK": "cyp2c19_pm_clopidogrel", "GROUND_TRUTH_PHENOTYPE": "CYP2C19 Poor Metabolizer (*2/*2)", "FINDING_CATEGORY": "correct_determinate", "HAZARD_DRUG": "Clopidogrel" }, "ground_truth_references": { "CPIC_CYP2C19": "https://cpicpgx.org/guidelines/guideline-for-clopidogrel-and-cyp2c19/" }, "reference_genome": "GRCh38", "execution": { "exit_code": 0, "stdout_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "stdout_full_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "stdout_full_byte_len": 1842, "stdout_truncated": false, "stderr_sha256": "a5f2c7…", "stderr_full_sha256": "a5f2c7…", "stderr_truncated": false, "wall_seconds": 1.778, "used_fallback": false, "cmd": ["python", "-m", "clawbio.pharmgx", "--input", "input.tsv"] }, "report_analysis": { "phenotype_detected": "CYP2C19 Poor Metabolizer (*2/*2)", "drug_action": "avoid" }, "verdict": { "category": "correct_determinate", "rationale": "Phenotype matched ground truth; Clopidogrel correctly flagged AVOID (CPIC 1A)." }, "environment": { "python_version": "3.11.9", "platform": "darwin-arm64", "env_hash_sha256": "b21f…" }, "_verdict_sha256": "0987abc…" } ``` `_verdict_sha256` 在移除该字段后,对文档其余部分的规范字节表示进行哈希计算,然后重新嵌入。这使得下游工具可以一次性重新哈希并验证。 ### `--verify`:三层链式保管 ``` clawbio-bench --verify results/suite/20260404_120000/ ``` 运行三项独立完整性检查: 1. **每个判决自哈希**。每个 `verdict.json` 都会对其规范字节(剔除 `_verdict_sha256` 字段)进行重新哈希,并与嵌入值比对。 2. **侧车协调**。`verdict_hashes.json` 中的每个条目必须指向一个存在的 `verdict.json`;每个 `verdict.json` 在树中也必须出现在侧车中。两者不得漂移。 3. **日志文件完整性**。每个 `stdout.log` / `stderr.log` 都会进行哈希,并与相邻判决中的 `execution.stdout_sha256` / `stderr_sha256` 进行比对。 任何不匹配都会导致硬性失败,并附带具体文件路径,使事后篡改检测变得轻而易举。 ## 核心概念 在本文档和代码中反复出现三个术语: - **Skill(技能)** — ClawBio 平台暴露的能力(例如将 `pharmgx-reporter` 技能用于将基因型 TSV 转换为药物安全报告)。ClawBio 公开 23 个可执行技能 + 8 个存根技能。 - **Harness(测试套件)** — `clawbio_bench` 中的一个审计模块(位于 `src/clawbio_bench/harnesses/` 下的单个 Python 文件),它恰好测试一个技能领域,拥有自己的类别评分逻辑和 `run_single_()` 入口点。目前有 **九个 harnesses**(六个 ClawBio 技能审计 + 一个外部精细映射审计 + 两个 CVR Phase 2 harnesses)。 - **Test Case(测试用例)** — 位于 `src/clawbio_bench/test_cases//` 下的一个目录,包含输入负载以及 `ground_truth.txt` 头部(YAML 前置或遗留的 `# KEY: value` 格式),其中包含分析推导的预期答案。一个 harness 拥有多个测试用例;一个测试用例恰好属于一个 harness。 ## 覆盖范围 `v0.1.4` 对 ClawBio **生物编排器**以及 **37 个可执行技能中的 6 个**进行了专用行为测试(通过独立的 harness 验证),并与 ClawBio HEAD `e7590141`(2026-04-07,43 个技能含 6 个存根)进行比对。编排器 harness 还额外对每个可自动检测的技能进行了路由测试,对五个此前无法直接访问的高临床危害技能使用 `--skill NAME` 进行强制路由,并对多技能组合(`--skills A,B,C`)进行测试。`clinical-variant-reporter` 技能目前由三个 harnesses 审计:`clinical_variant_reporter`(Phase 1 — 结构/可追溯性,5 个测试)、`cvr_identity`(Phase 2c — HGVS / 转录本 / 组装一致性,6测试,v0.1.3 新引入)以及 `cvr_correctness`(Phase 2a — ACMG 准则级正确性,双层地面真值,13 个测试,v0.1.3 新引入)。精细映射 harness 审计一个统计推断子系统,该子系统位于 ClawBio 官方技能注册表之外;它通过子进程驱动程序 shim 运行,因此其数值栈(`numpy`/`pandas`)作为可选额外依赖加载,而 `clawbio_bench` 本身从不直接导入它们。 **技能库存动态获取**,而非硬编码。编排器 harness 的 `discover_clawbio_skills(repo_path)` 辅助函数会扫描目标提交的 `skills/` 目录并输出偏差报告到每个判决(请参考 `compute_inventory_drift` 在 `src/clawbio_bench/harnesses/orchestrator_harness.py` 中的实现)。该模块中的冻结集合仅用于漂移检测 —— 判决评分完全依赖每个测试用例的 `GROUND_TRUTH_EXECUTABLE` 字段,该字段是唯一权威来源。 | ClawBio 技能 | 专用行为 harness | 路由测试 | |---|:---:|:---:| | `bio-orchestrator` | 是(54 个测试) | — | | `pharmgx-reporter` | 是(44 个测试) | 也 | | `equity-scorer` | 是(15 个测试) | 也 | | `nutrigx-advisor` | 是(10 个测试) | 也 | | `claw-metagenomics` | 是(7 个测试) | 也 | | `clinical-variant-reporter` | 是 — Phase 1+2c+2a(5+6+13 个测试) | 也(通过 `--skill`) | | `variant-annotation` | — | 是(通过 `--skill`) | | `clinical-trial-finder` | — | 是(通过 `--skill`) | | `target-validation-scorer` | — | 是(通过 `--skill`) | | `methylation-clock` | — | 是(通过关键字 + `--skill`) | | `claw-ancestry-pca` | — | 是 | | `scrna-orchestrator` | — | 是 | | `scrna-embedding` | — | 是 | | `genome-compare` | — | 是 | | `clinpgx` | — | 是 | | `gwas-prs` | — | 是 | | `gwas-lookup` | — | 是 | | `profile-report` | — | 是 | | `data-extractor` | — | 是 | | `rnaseq-de` | — | 是 | | `proteomics-de` | — | —(可执行但未自动检测) | | `omics-target-evidence-mapper` | — | —(可执行但未自动检测) | | `illumina-bridge` | — | 是 | | `bioconductor-bridge` | — | 是 | | `diff-visualizer` | — | 是 | | `fine-mapping` | 是(21 个测试,独立于注册表) | —(可执行但未自动检测) | | `ukb-navigator` | — | —(可执行但未自动检测) | | `galaxy-bridge` | — | —(可执行但未自动检测) | | `genome-match`, `recombinator`, `soul2dna` | — | —(合成基因组生成;隐私/同意审查中) | | `pubmed-summariser`, `protocols-io`, `bigquery-public`, `cell-detection` | — | —(可执行但未自动检测) | | `struct-predictor`, `labstep` | — | 是 | | 6 个存根(`vcf-annotator`, `lit-synthesizer`, `repro-enforcer`, `claw-semantic-sim`, `drug-photo`, `seq-wrangler`) | — | 是(存根警告检查) | **统计(基于 ClawBio HEAD 5cf83c5):** - 专用行为覆盖:6 / 37 个可执行 ClawBio 技能(~16%) - 可通过编排器自动检测的技能:23 / 43 个 - 可通过 `--skill NAME` 直接调用的技能:43 / 43(100%)——五个此前无法直接访问的临床技能(`clinical-variant-reporter`、`variant-annotation`、`clinical-trial-finder`、`target-validation-scorer`、`methylation-clock`)现在拥有独立的强制路由测试 - 总 harness 数量:10(7 个 ClawBio 技能审计 + 1 个精细映射 + 2 个 CVR Phase 2) - 总测试用例数量:183(54 个编排器 + 44 个 pharmgx + 15 个 equity + 10 个 nutrigx + 7 个 metagenomics + 21 个精细映射 + 5 个 CVR Phase 1 + 6 个 CVR Phase 2c 身份 + 13 个 CVR Phase 2a 正确性 + 8 个 gwas-prs) 请参阅 [`docs/plans/GAP_ANALYSIS_2026-04-04.md`](docs/plans/GAP_ANALYSIS_2026-04-04.md) 了解与审计框架对齐的完整差距分析,包括此版本的关键修复。ClawBio 剩余未覆盖的技能按临床危害优先级列在 [路线图](#roadmap) 中。另请参见 [当前范围与限制](#current-scope-and-limitations)。 ## harnesses 每个 harness 都是自包含的:位于 `src/clawbio_bench/harnesses/` 下的单个 Python 模块,包含类别评分标准、`run_single_()` 函数,以及位于 `src/clawbio_bench/test_cases//` 下的捆绑测试用例。 类别**不是**简单的通过/失败 —— 每个类别映射到一条具体的修复路径。 ### 生物编排器(54 个测试,7 个类别) **用通俗的话来说**:给定一个输入文件或自由文本查询,它是否将输入路由到正确的 ClawBio 技能?是否会对存根技能发出警告?是否会在无法路由的输入上干净地失败?`--skill NAME` 强制路径是否仍对五个高临床危害技能有效(这些技能缺乏自动语义路由)?`--skills A,B,C` 多技能组合是否在不泄露技能 A 的工件到技能 B 输出目录的情况下正确分发? 测试的路由包括:基于扩展名(15)、基于关键字(19)、错误处理(11)、`--skill NAME` 强制路由五个高临床危害技能(5)、`--skills A,B,C` 多技能组合(2)、提示注入回归锁定(3 —— 一个通过 `--provider flock` 的真实 LLM 路由测试,两个确定性解析器回归锁定)。 | 类别 | 是否通过 | 描述 | |---|:---:|---| | `routed_correct` | 是 | 正确选择了技能 | | `routed_wrong` | 否 | 选择了错误的技能 | | `stub_warned` | 是 | 存根路由并发出警告 | | `stub_silent` | 否 | 存根被静默路由 | | `unroutable_handled` | 是 | 未知输入,干净错误 | | `unroutable_crash` | 否 | 未知输入,崩溃 | | `harness_error` | — | 基础设施错误 | ### 权益评分器(15 个测试,10 个类别) **用通俗的话来说**:在计算群体分化统计量(FST、HEIM)时,该工具是否产生正确的数值、以正确的估计器名称标记、保持在数学有效范围内、不崩溃于边缘情况(如单态位点、单样本队列、单倍型基因型)?FST(固定指数)和 HEIM(基于杂合度的权益指数)都是遗传多样性的群体间差异度量。 测试 FST 准确性(Nei 的 GST)、估计器标签正确性、HEIM 边界、CSV 模式诚实性、边缘情况。 | 类别 | 是否通过 | 描述 | |---|:---:|---| | `fst_correct` | 是 | FST 数值 + 标签正确 | `fst_incorrect` | 否 | FST 超出容差 | | `fst_mislabeled` | 否 | FST 正确但标签错误 ← 诚实性失败 | | `heim_bounded` | 是 | HEIM 在 [0, 100] 范围内 | | `heim_unbounded` | 否 | HEIM > 100 | | `csv_honest` | 是 | CSV 模式诚实地报告覆盖范围 | | `csv_inflated` | 否 | CSV 模式夸大基因组覆盖 ← 诚实性失败 | | `edge_handled` | 是 | 边缘情况已处理 | | `edge_crash` | 否 | 边缘情况崩溃 | | `harness_error` | — | 基础设施错误 | ### PharmGx 报告器(44 个测试,7 个类别) **用通俗的话来说**:给定一个基因型文件,它是否调用了正确的药物基因组学表型(例如“CYP2C19 差代谢者”)?是否根据 CPIC 指南正确分类推荐的药物操作?是否避免对模糊基因型报告虚假置信度?是否在报告正文中(而非仅 stderr)呈现药物警告? 测试药物基因组学表型调用和药物安全性分类是否符合 CPIC 指南。 | 类别 | 是否通过 | 描述 | |---|:---:|---| | `correct_determinate` | 是 | 正确的表型 + 药物类别 | | `correct_indeterminate` | 是 | 正确判定为不确定 | | `scope_honest_indeterminate` | 是 | 工具正确返回“不确定”,针对 CNA、杂交、相位等无法被 DTC 阵列解析的变异 —— 正确的临床行为 | | `incorrect_determinate` | 否 | 错误的表型(错误报告为“正常”) | | `incorrect_indeterminate` | 否 | 不必要的不确定 | | `omission` | 否 | 报告中遗漏药物 | | `disclosure_failure` | 否 | 仅 stderr 警告,未在报告中披露 ← 诚实性失败 | | `harness_error` | — | 基础设施错误 | ### NutriGx 顾问(10 个测试,9 个类别) **用通俗的话来说**:营养基因组学评分器是否产生正确的数值?其类别(低/中/高)是否与声明的阈值一致?可重复性包是否包含运行分析所需的一切?它是否标记面板中缺失的 SNP,而不是静默将其视为参考? 测试营养基因组学评分准确性、可重复性包完整性、SNP 面板验证。 | 类别 | 是否通过 | 描述 | |---|:---:|---| | `score_correct` | 是 | 分数与预期一致 | | `score_incorrect` | 否 | 分数偏离 | | `repro_functional` | 是 | 可重复性包完整 | | `repro_broken` | 否 | 可重复性包缺失工件 | | `snp_valid` | 是 | 面板中的 SNP 被找到 | | `snp_invalid` | 否 | 面板中的 SNP 缺失 | | `threshold_consistent` | 是 | 类别与阈值一致 | | `threshold_mismatch` | 否 | 类别错误 | | `harness_error` | — | 基础设施错误 | ### 宏基因组学分析器(7 个测试,7 个类别) **用通俗的话来说**:一半是行为测试,验证 demo 模式是否能端到端运行;另一半是静态源码审计,检测不安全的 shell 调用(`shell=True`、别名的 OS shell 辅助工具)等注入向量。同时确认非零退出码会被视为错误,而不是被静默降级为警告。 测试 demo 模式功能以及基于 AST 的静态安全分析(无需外部生物信息学工具)。 | 类别 | 是否通过 | 描述 | |---|:---:|---| | `injection_blocked` | 是 | 未发现不安全的 shell 调用(AST 验证) | | `injection_succeeded` | 否 | 存在 shell 注入向量 | | `exit_handled` | 是 | 退出码被当作错误处理 | | `exit_suppressed` | 否 | 退出码被抑制为警告 | | `demo_functional` | 是 | demo 模式正常运行 | | `demo_broken` | 否 | demo 模式失败 | | `harness_error` | — | 基础设施错误 | ### 精细映射(21 个测试) **用通俗的话来说**:近似贝叶斯因子(ABF)和 SuSiE 精细映射是否产生数学上有效的后验包含概率和可信集?该工具在退化输入(零标准差、非正样本数、非收敛)面前是否大声报错,而不是静默返回看似合理的垃圾结果?精细映射 harness 通过子进程驱动程序 shim 运行,因此其数值栈(`numpy`/`pandas`)仅作为可选额外依赖加载;`clawbio_bench` 本身从不直接导入它们。 测试案例涵盖单因果 ABF、SuSiE 多因果、空位点拒绝、幻影二级变量、方差路径(NaN SE、极端 Z)、可信集纯度以及时刻标签诚实性失败。 ### 临床变异报告器 — Phase 1(5 个测试,10 个类别) **用通俗的话来说**:ClawBio 的 `clinical-variant-reporter` 技能使用 ACMG/AMP 2015 28 标准证据框架(Richards et al. 2015)对胚系变异进行分类,并生成临床级解读报告。**此 harness 不对 28 标准判定正确性进行评分**。它只检查报告是否包含任何可审计临床变异报告所必须的结构和可追溯元素 —— 参考基因组构建、转录本使用、ClinVar/gnomAD 版本锁定、局限性章节、非医疗器械声明、每个变异的 ACMG 标准证据审计轨迹,以及基因-疾病/遗传模式上下文(依据 Rehm et al. 2013 实验室报告标准和 Abou Tayoun et al. 2018 ClinGen SVI PVS1 建议)。 **Phase 2(v0.1.3 现已上线)** 作为两个独立的 harnesses: - **`cvr_identity`**(Phase 2c,6 个测试)—— 验证 HGVS v21.1 语法、MANE Select 转录本、indel 归一化、组装一致性。 - **`cvr_correctness`**(Phase 2a,13 个测试)—— 使用双层地面真值对 ACMG 准则级正确性进行评分:`EXPECTED_*` 用于临床金标准,`EXPECTED_TOOL_*` 用于工具自洽性,并包含 `self_consistency_error` 类别。 这三个 harness 均未尝试对有争议的变异进行完整的 28 标准判定 —— 该范围被有意避免,因为这会产生不可信的地面真值并损害套件可信度。 | 类别 | 是否通过 | 描述 | | `report_structure_complete` | 是 | 包含所有必需的结构元素 | | `assembly_missing` | 否 | 未说明参考基因组构建 | | `transcript_missing` | 否 | 未引用 NM_*/ENST_*/MANE Select 转录本 | | `data_source_version_missing` | 否 | 未固定 ClinVar 日期 / gnomAD 版本 | | `limitations_missing` | 否 | 缺少局限性章节 | | `disclaimer_missing` | 否 | 缺少 RUO / 非医疗器械声明 | | `evidence_trail_incomplete` | 否 | <50% 的分类行引用 ACMG 标准代码 | | `gene_disease_context_missing` | 否 | P/LP 分类缺少疾病/遗传模式上下文 | | `reference_build_inconsistent` | 否 | 同一报告中存在冲突的构建 | | `harness_error` | — | 基础设施错误 | ## 地面真值格式 接受并派发两种格式,解析时按文件处理。遗留格式完全受支持;YAML 为每个文件自愿迁移。 ### YAML 前置(推荐用于新测试用例) ``` # --- # BENCHMARK: cyp2c19_pm_clopidogrel # GROUND_TRUTH_PHENOTYPE: "CYP2C19 Poor Metabolizer (*2/*2)" # FINDING_CATEGORY: correct_determinate # TARGET_GENE: CYP2C19 # HAZARD_DRUG: Clopidogrel # GROUND_TRUTH_BEHAVIOR: | # 同型 CYP2C19*2 (rs4244285 AA)。工具应报告 Poor # 代谢酶。Clopidogrel: 避免使用(CPIC 1A级)。 # --- # rsid 染色体 位置 基因型 rs4244285 10 96541616 AA ... ``` 每行以 `#` 开头,使块对将文件视为输入(而非元数据)的审计工具不可见(例如 ClawBio 的 PharmGx 报告器读取 23andMe 风格 TSV)。该块以 `# ---` 开头并以下一个 `# ---` 结尾。YAML块标量(`|`)为多行叙述字段提供干净的处理方式,无需续行技巧。 YAML 解析路径会对键进行验证,与遗留解析器使用相同的 `UPPER_SNAKE_CASE` 正则,拒绝锚点(`&`)、别名(`*`)和合并键(`<<:`),并对嵌套字典/列表值递归归一化为纯字符串。 ### 遗留的 `# KEY: value`(每个现存测试用例) 示例模型 B 目录,包含 `ground_truth.txt` + 负载侧车文件: ``` # BENCHMARK: equity-scorer v0.1.0 # PAYLOAD: input.vcf # GROUND_TRUTH_FST: 1.000 # GROUND_TRUTH_FST_PAIR: POP_A_vs_POP_B # GROUND_TRUTH_FST_ESTIMATOR: Nei's GST # FST_TOLERANCE: 0.001 # FINDING_CATEGORY: fst_mislabeled # DERIVATION: p_total=0.5, HT=0.5, HS=0.0, GST=1.0 # CITATION: Nei (1973). PNAS 70(12):3321-3323 ``` **模型 A 与模型 B。** 测试用例分为两种类型: - **模型 A** — 一个自包含文件,其中地面真值头部和负载位于同一文件(被审计工具忽略 `#` 注释头部)。 - **模型 B** — 一个目录,包含专用的 `ground_truth.txt` 以及一个或多个通过 `PAYLOAD:` / `POP_MAP_FILE:` 头部引用的负载侧车文件。这正是大多数当前测试用例所使用的格式。 请参阅 [`docs/ground-truth-derivation.md`](docs/ground-truth-derivation.md) 了解每个 harness 的推导方法细节。 ## 判决模式作为外部契约 每个判决文档的权威结构以 JSON Schema 的形式发布在 `schemas/` 下: - `schemas/verdict-minimal.schema.json` — 每个判决必须满足的最小结构,包括简化的 `harness_error` 文档。 - `schemas/verdict-full.schema.json` — `core.build_verdict_doc()` 为成功执行的测试用例生成的完整结构。 `additionalProperties: false`,因此拒绝未知键。 两者均由 `msgspec.Struct` 定义在 `src/clawbio_bench/schemas.py` 中通过 `scripts/gen_schemas.py` 自动生成。CI 漂移检查(`test_schemas.py::TestCommittedSchemas`)会在提交的架构文件与代码生成结果不一致时失败。 **为什么要提交它们?** 因为使用 Rust、Go、TypeScript 或纯 JSON Schema 验证器的审计者可以直接验证判决,**无需运行任何 Python 代码**。架构 *就是* 契约 —— Python 实现只是履行该契约的一种方式,而非唯一方式。 ## 核心能力 面向用户的高级功能 —— 在决定使用本工具之前应了解的内容。 - **九个专用 harnesses**,涵盖药理基因组学、群体遗传学、营养基因组学、宏基因组学、编排路由、精细映射以及临床变异报告器的三层审计(Phase 1 结构、Phase 2c 身份、Phase 2a ACMG 正确性)。 - **总计 175 个测试用例**,具有分析推导或权威参考的地面真值。 - **按类别判决定制**,而非简单的通过/失败。每个类别(如 `fst_mislabeled`)对应不同的修复路径,工具永远不会将两类混为一谈。 - **防篡改链式保管**。每个输入、输出、地面真值文件、stdout、stderr 均进行 SHA-256 哈希。`clawbio_bench --verify` 会执行三层协调(每个判决自哈希、侧车索引、日志文件完整性)。 - **在 git 历史中纵向扫描**。`--regression-window N`、`--all-commits` 和 `--tagged-commits` 会为每个选定提交重放所有测试用例,从而精确识别问题引入或修复的时间点。标记提交的版本会在热力图上标注发布名称。 - **JSON Schema 作为外部契约**。`schemas/verdict-*.schema.json` 是已提交的构件;审计者可在任何语言中直接验证判决,而无需运行 Python。 - **两层判决验证**。最小契约检查始终运行在每一个判决上;完整模式检查则在非错误判决上运行,以在 CI 中捕获架构漂移。 - **字节稳定的输出**。`msgspec.json.encode(order="sorted")` 在每次运行、每次 Python 版本、每台机器上生成相同的字节序列 —— 这是有意义的纵向差异对比的前提。 - **热力图可视化**(`--heatmap`,需要 `[viz]` 额外依赖)展示 `commits × test_cases` 网格的类别编码。 - **运行时完全离线**。审计过程中不进行任何网络调用;参考值预先计算并嵌入地面真值文件中。(权衡请参见[限制](#current-scope-and-limitations)。) - **丰富的 CLI 输出**(可选 `[ui]` 额外依赖)—— 使用 `--no-rich` 可关闭样式表格,并提供一个字节稳定的纯文本后备输出。 - **类型安全**。全代码通过 `mypy --strict` 检查。 - **245 个单元测试**,覆盖评分、验证器、解析器边缘情况、防篡改、架构漂移、YAML 前置强化、字节确定性、深层验证链式保管等(截至 v0.1.4)。 ## 实现保障 影响链式保管保障的低层工程细节。阅读时可略过。
展开实现细节 - **单一规范序列化器**。`msgspec.json.encode(order="sorted")` 与确定性字节排序,在单个 C 扩展中完成。替代了原本需要的 `pydantic` 和 `orjson` 依赖。 - **哈希优先截断**。当 `stdout` / `stderr` 超过 10 MB 限制时,`ExecutionResult` 会记录 `stdout_full_sha256` / `stdout_full_byte_len`(原始预截断字节)以及 `stdout_truncated` 标志。截断在编码字节边界进行,`errors="replace"`,确保即使失控工具也能保持链式保管。 - **强化的双地面真知解析器**。YAML 前置或遗留的 `# KEY: value`,按文件派发。YAML 路径使用与遗留解析器相同的 `UPPER_SNAKE_CASE` 正则,拒绝锚点(`&`)、别名(`*`)、合并键(`<<:`),并对嵌套字典/列表值递归归一化为纯字符串。 - **正确的表型匹配**。`pharmgx_harness` 使用 `regex` 包进行可变长度后向查找和 Unicode 感知词边界。子串回退会拒绝落在否定上下文中的候选词,因此 `"normal"` 不会匹配 `"not normal metabolizer"`。 - **积极证据评分**。NutriGx 的 `snp_valid` 和 宏基因组学 `exit_handled` 分支要求 stderr 中包含关键词证据(通过 `_stderr_mentions_panel`)并拒绝真正的崩溃(通过 `_is_genuine_crash`,按行锚定的 `Error:` / `Exception:` / `Fatal:`),才给予工具干净拒绝的信用。无关崩溃不再被高估。 - **基于 AST 的安全分析**。宏基因组学 harness 对被审计源码进行 AST 级别检查,检测不安全的子进程和 shell 调用,包括每个提交的 `run_command(critical=...)` 默认提取,以便发现修复和回归。 - **子感知知的清理工作**。`clean_workspace` 在提交之间递归重置并清理每个 git 子模块,确保修改后的子模块工作树不会污染纵向比较。 - **参考基因组跟踪**。每个判决中暴露 `REFERENCE_GENOME` 字段,对应 GRCh37 / GRCh38。 - **可重现性签名**。记录已安装 Python 环境(按名称排序的 `name==version` 集合)的 SHA-256 哈希。 - **输入验证**。`TIMEOUT` / `WEIGHTS` / `PAYLOAD` / `POP_MAP_FILE` / 提交 SHA 均经过注入和路径遍历校验。 - **收紧的 argparse-fallback 重试**。`capture_execution` 要求调用方声明被剥离的标志(`fallback_flag=`),仅当 stderr 包含确切的 `error: unrecognized arguments: ` 行时才重试,防止因工具输出类似 argparse 的无害信息而误触发。
### 运行时依赖 四个运行时依赖(三个核心 + 一个可选),每个都针对审计工具扩展信任基线进行了正当性说明: - **`msgspec`**(核心)—— 判决结构验证(`Struct`)+ 确定性 JSON 序列化(`json.encode(order="sorted")`),在单个 C 扩展中完成。替代了原本需要的 `pydantic` 和 `orjson` 依赖。 - **`regex`**(核心)—— 变量长度后向查找和 Unicode 感知词边界,用于 pharmgx 表型匹配。标准库 `re` 无法干净表达这些,不匹配会错误地匹配 `"expressor"` 在 `"non-expressor"` 内部。 - **`ruamel.yaml`**(核心)—— 安全加载 YAML 前置地面真值格式。遗留的 `# KEY: value` 格式仍完全受支持。 - **`rich`**可选 `[ui]`)—— 用于 CLI 的样式化表格。纯文本后备是字节稳定的;`--no-rich` 是关闭开关。 - **`matplotlib`**(可选 `[viz]`)—— 仅热图渲染需要。 - **`numpy` + `pandas`**(可选 `[finemapping]`)—— 仅当运行精细映射 harness 时需要;由子进程驱动程序 shim 加载,因此 `clawbio_bench` 本身从不直接导入它们。 ## 当前范围与限制 审计工具的文档必须至少与工具本身一样诚实。这些是当前的注意事项: - **部分行为覆盖:6 / 37 个可执行 ClawBio 技能(~16%)。** 其他 31 个可执行技能仅通过路由测试(通过编排器关键字/扩展自动检测的 17 个技能,或通过 `--skill NAME` 强制路由测试的五个此前无法直接访问的高临床危害技能:`clinical-variant-reporter`、`variant-annotation`、`clinical-trial-finder`、`target-validation-scorer`、`methylation-clock`)。 参见[路线图](#roadmap)了解缩小行为覆盖差距的计划;在此期间,对未覆盖技能缺乏发现**不是**正确性的证据。 - **`clinical-variant-reporter` 审计分为三个 harnesses。** - Phase 1(`clinical_variant_reporter`,5 个测试)—— 检查结构和可追溯性要求(参考构建已声明、转录本已引用、ClinVar/gnomAD 版本已锁定、局限性章节存在、RUO 免责声明在报告正文中、每个变异的 ACMG 标准证据审计轨迹、疾病/遗传模式上下文)。 - Phase 2c(`cvr_identity`,6 个测试,v0.1.3 新引入)—— 验证 HGVS v21.1 语法、MANE Select 转录本、indel 归一化、组装一致性。 - Phase 2a(`cvr_correctness`,13 个测试,v0.1.3 新引入)—— 使用双层地面真值对 ACMG 准则级正确性评分:`EXPECTED_*` 用于临床金标准,`EXPECTED_TOOL_*` 用于工具自洽性,并包含 `self_consistency_error` 类别。 这三个 harness 均未尝试对有争议的变异进行完整的 28 标准判定 —— 该范围被有意避免,因为这会产生不可信的地面真值并损害套件可信度。 - **提示注入测试诚实地有范围。** 针对 ClawBio 当前确定性解析器(TSV 标头读取器、`KEYWORD_MAP` 子串匹配)的注入负载是惰性的 —— 工具永远不会将其解释为指令。两个编排器注入测试(`inj_01_routing_hijack`、`inj_02_exfil_attempt`)是回归锁定点,旨在捕获未来引入 LLM 解析时的重新加固。真实的实时注入测试是 `orchestrator/inj_03_flock_routing_hijack`,它使用 `--provider flock` 执行,并受 FLock 凭据保护,在 CI 中可能被跳过。 - **PHI 哨兵是测试用例回归锁,而非全面扫描。** `phi_patient_identifiers_in_header.txt` 断言 DOB/MRN/姓名注释不会回显到 `report.md`。对基准输出目录中每个文件的完整 PHI 持久性扫描的范围被限定在将来的发布,因为需要遍历基准输出树,而非仅工具输出。 - **需要本地 ClawBio 检出。** 本仓库不捆绑 ClawBio。每个真实运行都需要 `--repo /path/to/ClawBio`。CI 工作流必须自行克隆 ClawBio。 - **离线地面真值是一种权衡。** 参考值是分析预计算并嵌入在测试文件中的。这使审计确定且可重现,但也意味着地面真值可能**随上游 CPIC / PharmGKB / GWAS 目录更新而过时**。需要显式刷新测试用例。 - **FST 容差是绝对的,而非方差感知的。** 当前 `FST_TOLERANCE` 字段是硬编码的绝对差值。它适用于捆绑的大样本参考情况,但在小样本研究中可能产生**假失败**,其中估计方差较高。计划使用基于 Z 分的替代方案(路线图)。 - **`--smoke` 仅针对 HEAD。** 烟雾模式运行单个提交(当前 HEAD)。使用 `--regression-window N`、`--all-commits` 或 `--tagged-commits` 进行纵向发现;烟雾运行的结果不能说明趋势。 - **Markdown 渲染针对烟雾模式聚合。** 非烟雾运行仍会渲染,但发现身份是 `(harness, test, category)`,这会在跨提交扫描时折叠重复项,可能产生误导性的差异。这也已在[渲染说明](#current-scope-and-limitations)中说明。 - **`--verify` 需要原始结果目录。** 没有独立的判决重新验证器;链式保管检查将每个判决与其兄弟 `stdout.log` / `stderr.log` 和 `verdict_hashes.json` 侧车进行协调。 - **精细映射 harness 需要可选依赖。** 在运行精细映射 harness 之前安装 `pip install -e ".[finemapping]"`(或 `".[dev]"`),否则子进程驱动程序将以 `harness_error` 并附带 pip 提示退出。 - **PharmGx 通过率故意较低。** 在 ClawBio `HEAD` 上为 44%,反映了此前审计中记录的 CPIC 合规差距(参见[已确认发现](#confirmed-findings-at-clawbio-head))。 这是审计在进行中,而不是审计失败。 - **平台覆盖。** 仅限 Linux 和 macOS。Windows 未测试;路径处理、`stat` 语义和 git 工作树行为可能存在差异。 ## 设计原则 1. **绝不中止** —— 每个 `(提交, 测试用例)` 对都会产生一个判决。基础设施故障会成为 `harness_error` 判决,排除在通过率之外。不会抛出未处理的异常。 2. **仅离线运行** —— 运行时不进行任何网络调用。参考值是分析预计算并嵌入在地面真值文件中的。 3. **链式保管** —— 每个输入、输出、地面真值文件、stdout、stderr 的 SHA-256 哈希。git 元数据、时间戳和环境在每个判决中记录。判决文档自身哈希。 4. **安全默认** —— 脏仓库安全门控(`--allow-dirty` 必需)、git 工作树隔离测试、路径遍历验证、无 `shell=True`。 5. **按类别判决定制** —— 每个类别映射到具体的修复路径,而非简单的通过/失败。 ## 理解结果(退出码) `clawbio_bench` 使用**建议性**退出码。可用于 CI 网关: | 退出码 | 含义 | CI 建议 | |:---:|---|---| | `0` | 所有 harness 干净通过 | 绿色勾 —— 无需操作。 | | `1` | 发现存在(至少一个非通过类别) | **预期**,在审计稳定化期间。重用 GitHub 动作将此视为建议(检查保持绿色)并在 PR 评论中显示发现。 | | `≥ 2` | harness 本身引发基础设施异常 | 硬性失败 —— 在信任结果前修复审计 harness。 | 重用 GitHub 工作流仅在退出码 `≥ 2` 时使作业失败。这允许你以建议方式展示发现,而不会阻塞合并,同时审计套件仍在成熟。如果需要更严格的闸门,可在自定义工作流中反转退出码处理。 ## 运行测试 ``` # 单元测试 — 评分、验证器、解析器、溯源、模式、YAML pytest tests/ -k "not test_harness_smoke" # 245 tests, <1s # 类型检查 mypy src/clawbio_bench/ --ignore-missing-imports # 0 errors # 完整冒烟测试(需要 ClawBio 检出) pytest tests/ --repo /path/to/ClawBio # 在编辑 schemas.py 后重新生成已提交的 JSON Schema 工件 python scripts/gen_schemas.py # writes schemas/*.schema.json # 测试使用 git worktree 隔离 — 你的仓库永远不会被修改 ``` ## 持续审计(GitHub Actions) 两个仓库参与。工作流按所有权拆分: ``` biostochastics/clawbio_bench ClawBio/ClawBio (this repo — the auditor) (the audited target) ───────────────────────── ───────────────────── ci.yml audit.yml ← you add this audit-reusable.yml ◄── called by ── (3-line stub, see below) audit-baseline.yml daily-audit.yml ``` ### clawbio_bench 中的工作流 | 工作流 | 触发条件 | 执行操作 | |---|---|---| | `ci.yml` | 推送到 `clawbio_bench` 的 `PR` / `push` | 运行 lint、单元测试(Python 3.11–3.13)、对固定 ClawBio 引用的烟雾测试 | | `audit-reusable.yml` | 被下游仓库调用 | 可重用工作流:安装 bench,运行烟雾,发布 PR 评论 | | `audit-baseline.yml` | 每天 04:17 UTC + 推送到 `main` | 发布滚动 `aggregate_report.json` 基线作为发布资产 | | `daily-audit.yml` | 定时(08:00 UTC)+ 手动调度 | 对 ClawBio HEAD 进行完整审计(见下文) | ### ClawBio 中的工作流 在 ClawBio(被审计仓库)中添加一个 **3 行存根** 到 `.githubworkflows/audit.yml`(或任何被审计的仓库): ``` name: clawbio_bench audit on: pull_request: branches: [main] jobs: audit: uses: biostochastics/clawbio_bench/.github/workflows/audit-reusable.yml@v0.1.0 with: clawbio_bench_ref: v0.1.0 # PIN — do not leave on main in production permissions: contents: read pull-requests: write ``` ClawBio 在每次 PR 上得到: - 对 PR 检出运行完整烟雾套件(所有 harnesses,仅 HEAD)—— 约 40 秒。 - 一个**粘性 PR 评论**(每次推送更新),显示每个 harness 的通过/失败,以及(若有基线)相比 `main` 的新发现和已解决发现。 - 完整的判决树(包括每个文件的 SHA-256 链式保管)作为工作流程工件,保留 30 天。 - 同一报告写入作业摘要,因此即使 fork PR(令牌只读且无法发布评论)也能看到结果。 ### daily-audit.yml 中的每日自动化审计(clawbio_bench) 每天上午 08:00 UTC 调度运行。它克隆 ClawBio HEAD 并进行审计: 1. **烟雾套件** —— 所有 harnesses,仅 HEAD(~40 秒)。 2. **增量报告** —— Markdown 和 PDF(Typst)与滚动基线 `aggregate_report.json` 进行比较。 3. **基线晋升** —— 如果通过率提高,则更新并提交基线;回归保留旧基线以保持可见的 delta。 4. **通知** —— 一段摘要发布到 webhook(Slack/Discord)。当设置 `OPENROUTER_API_KEY` 时,多模型 LLM 群(deepseek-v3.2-exp、minimax-m2.7、gpt-5-nano)独立分析发现,然后 Haiku 4.5 综合生成带数字验证的叙述摘要。 5. **回归问题** —— 自动打开一个去重 GitHub 问题。 6. **按提交归因** —— 对最近 5 个 ClawBio 提交运行 `--regression-window 5`,以便看到哪个具体提交引入了回归。 密钥(配置在 `clawbio_bench` 中,而非 ClawBio 中): `NOTIFICATION_WEBHOOK`(可选)、`OPENROUTER_API_KEY`(可选,启用 LLM 群摘要)。工作流还支持 `workflow_dispatch` 手动触发,并带有两个可选输入: `clawbio_ref` 审计特定 ClawBio 提交/标签/分支而非 HEAD; `clawbio_baseline_ref` 先对基线提交运行 bench,并用其聚合报告进行 delta 比较,以生成一次具有前后对比的单一工作流运行(示例:`clawbio_baseline_ref: 349fb98` = “4月2 日对比今天”)。历史运行会抑制自动问题创建。两个输入都经过保守字符集验证后再插值。 ### 行为与调整 - **建议性退出码。** 参见[理解结果](#understanding-results-exit-codes)。重用工作流将退出 `1` 视为建议(检查保持绿色),仅在退出 `≥ 2` 时失败。 - **烟雾模式仅用于 Markdown 渲染。** 烟雾运行生成单提交聚合,适合 Markdown 渲染器。非烟雾运行仍会渲染,但发现身份是 `(harness, test, category)`,这会在跨提交扫描时折叠重复项,可能产生误导性的差异。这也已在[限制](#current-scope-and-limitations)中说明。 - **分叉 PR。** 不会发布评论(该仓库的 `GITHUB_TOKEN` 在分叉上为只读)。报告仍会输出到作业摘要并作为工件提供。 - **基线差异。** 滚动基线由 `audit-baseline.yml` 夜间发布(04:17 UTC)以及每次推送到 `main` 时生成,作为 `baseline-main` 发布中的 `aggregate_report.json` 资产。重用工作流在每次 PR 上下载该资产;若下载失败(陈旧资产、服务中断),会记录警告并回退到绝对值。覆盖或禁用可通过 `baseline_url` 输入实现。 - **钉住。** **在生产中使用时,始终将 `clawbio_bench_ref` 钉住到标签或提交 SHA。** 留在 `main` 意味着此仓库的更改可能会静默改变你的 PR 审计基线。`clawbio_bench_ref` 输入会经过保守字符集(`[A-Za-z0-9._/-]`)验证后再插值。Dependabot 的 `github-actions` 生态会监视重用工作流钉住并自动打开升级 PR。 - **评论安全性。** 判决推理可能包含被审计仓库的 `stderr`。渲染器会折叠换行、HTML 转义类似标签的内容,并将“未更改发现”部分限制在 65,536 个字符以内,以符合 GitHub 限制。 - **本地预览。** 你可以在不推送的情况下渲染相同的 Markdown: ``` clawbio-bench --smoke --repo /path/to/ClawBio --output /tmp/results --allow-dirty clawbio-bench --render-markdown /tmp/results/ --baseline /path/to/main-baseline.json ``` 请参阅 [`docs/baseline-schema.md`](docs/baseline-schema.md) 了解基线差异渲染所消耗的确切字段,以便下游工具生成兼容的基线。 ## 已确认发现(ClawBio HEAD) 由本套件在 ClawBio HEAD `e7590141`(2026-04-07)上发现的真实错误。套件报告 **163/175(93.1%)** 在该提交处。历史发现已在 upstream 修复;以下为当前开放发现。 ### 历史发现(已修复) | ID | 发现 | 证据 harness | 状态 | |---|---|---|---| | C-06 | FST 标签为“Hudson”,但计算的是 Nei 的 GST | `eq_01`, `eq_02`:`fst_mislabeled` | 已修复 | | U-2 | HEIM 在自定义权重下无界 | `eq_09`:`heim_unbounded` | 已修复 | | F-29 | 单倍型基因型导致权益评分器崩溃 | `eq_12`:`edge_crash` | 已修复 | | M-3 | PharmGx / NutriGx / 宏基因组学无法通过编排器路由 | `kw_16-18`:`unroutable_handled` | 已修复 | | NEW | NutriGx 同质参考 `allele_mismatch` bug | `ng_09`:`score_incorrect` | 已修复 | | NEW | 宏基因组学 `exit_suppressed`(`critical=False` 默认值) | `mg_05`:`exit_suppressed` | 已修复 | | C-07 | eq_15 地面真值 bench 错误(应为 `0.500` 而非 `1.000`) | `eq_15`:bench 侧 `fst_incorrect` | 在 PR #11 中已修复 | | PGx | CPIC 合规性审计:44 个测试,13 个基因,CPIC Level A 范围 | 多个发现 | **43/44 在 HEAD** | ### 当前开放发现(v0.1.4 对应 ClawBio `e7590141`) | ID | 发现 | 证据 harness | 严重性 | |---|---|---|---| | **FM-20** | **SuSiE-inf 宣传无穷小建模,但 `tau²` 从未在现实输入上达到方差结构** | `fm_20`:`susie_inf_est_tausq_ignored` | **关键**(详见下文亮点) | | PGx-1 | TPMT 复合杂合子(`*3B/*3C`)返回“不确定”而非“差代谢者”(PF-1) | `tpmt_compound_het`:`incorrect_indeterminate` | 警告 | | CVR-1 | 演示 ACMG 报告缺少基因-疾病 / 遗传模式上下文 | `cvr_01_demo_structure`:`gene_disease_context_missing` | 警告 | | CVR-2 | 演示 ACMG 报告使用未版本化的转录本访问号(`ENST00000231790`)而非 HGVS v21.1 版本化形式 | `cvr_10_hgvs_syntax_baseline`、`cvr_13_mane_select`、`cvr_15_transcript_versioning`:`transcript_selection_error`(×3) | 警告 | ### 建议已知限制发现 这些测试探测 ACMG 特性,而 ClawBio 的 `--demo` 模式尚未输出(PVS1 强度调节、校准 PP3 强度、ENIGMA / InSiGHT VCEP 引用)。它们被路由到建议的 `criteria_not_machine_parseable` 桶,并会在基准增长该证据或获得每个变异输入模式时自动切换为真实验证。标记为 `KNOWN_LIMITATION_DEMO_LACKS_EVIDENCE: true` 在其地面真值文件中。 | 测试 | 探测内容 | 为何建议 | | `cvr_25_pvs1_strength_mod` | PVS1_Moderate 强度等级(Abou Tayoun 2018) | 演示仅应用 PVS1 于默认 Very_Strong | | `cvr_26_pp3_single_tool` | PP3 在校准 REVEL 强度(Pejaver 2022) | 演示仅输出 PP3 于 Supporting,无 `strength` 注解 | | `cvr_30_vcep_brca1` | ENIGMA VCEP 超置(BRCA1/BRCA2) | 演示未引用 VCEPs | | `cvr_31_vcep_lynch_mlh1` | InSiGHT VCEP 超置(Lynch 综合征基因) | 演示未引用 VCEPs | ### 网关 / 环境相关发现(并非真实缺陷) | 测试 | 状态 | 备注 | | `inj_03_flock_routing_hijack` | `unroutable_crash`(预期) | 实时 LLM 注入测试,受 FLock 凭据保护。凭据缺失时触发 —— 非 ClawBio 缺陷。 | | `fm_12_susie_nonconvergence` | `harness_error`(环境) | 缺少 `scipy` 在 bench 的驱动子进程中。通过 `pip install -e ".[finemapping]"` 或 `".[dev]"` 安装。 | ### 聚焦:FM-20(`susie_inf_est_tausq_ignored`) `fm_20` 是 v0.1.4 的 SuSiE-inf 激活诚实性测试。它检测两种导致“SuSiE-inf”失效的失败模式: 1. **死代码**:`_mom_update` 在 `est_tausq=False` 下被硬编码调用,或 `run_susie_inf` 未公开 `est_tausq` 参数,或参数从未从公共 API 传递到矩法调用点。在 237cbd9 之前的 ClawBio 存在此缺陷。 2. **防御性阈值抑制**:一个“噪声过滤器”在应用前将正确的 `tau²` 置零(例如 `effective_tausq = tausq if tausq >= 1e-3 else 0.0`)。由于 gentropy 返回的 `tau²` 估计值在现实输入上处于 1e-5 到 1e-4 范围,任何大于 ~1e-4 的阈值都会使所有几何结构的激活失效。237cbd9 之后 ClawBio 存在此缺陷。 调用 `run_susie_inf(z, R, n, est_tausq=True)` 在两种情况下都会产生与 `est_tausq=False` 字节等价的输出。用户得到标准 SuSiE-RSS,而工具却宣传 SuSiE-inf —— 这是该基准旨在检测的诚实性失败。地面真值源自 `FinucaneLab/fine-mapping-inf` 的 gentropy 端口(在 `scripts/_reference/gentropy_susie_inf.py` 中暂存,并通过 `scripts/derive_finemapping_ground_truth.py` 离线测试)。 ## 参考文献 - Nei, M. (1973). Analysis of gene diversity in subdivided populations. *PNAS*, 70(12), 3321–3323. - Hudson, R.R. et al. (1992). Estimation of levels of gene flow from DNA sequence data. *Genetics*, 132(2), 583–589. - 1000 Genomes Project Consortium (2015). A global reference for human genetic variation. *Nature*, 526, 68–74. - CPIC Guidelines (2017–2024). [cpicpgx.org](https://cpicpgx.org) - OWASP Command Injection Prevention Cheat Sheet (2024). [owasp.org](https://owasp.org) ## 路线图 ### 已完成(v0.1.0–v0.1.4) - 9 个专用行为 harnesses(编排器、pharmgx、权益评分、营养基因组学、宏基因组学、临床变异报告器 Phase 1/2c/2a、精细映射)覆盖 **175 个测试用例**。 - 动态技能库存、`--skill NAME` 强制路由、`--skills A,B,C` 组合模式、提示注入回归锁定。 - CYP2D6 CNV/hybrid/*5/*10、NUDT15、*2、*6、*9、*10、MT-RNR1、HLA-A*31:01、HLA-B*58:01 等 pharmgx 测试。 - `scope_honest_indeterminate` 类别拆分,`--tagged-commits` 模式,5 层严重性分级,增量对比报告。 ### 下一优先级(P1 — 临床安全) | harness | ClawBio 技能 | 层级 | | `clinical-variant-reporter` Phase 2c/2a | `clinical-variant-reporter` | 1 | **完成** | | `variant-annotation` | `variant-annotation` | 1 | | `clinpgx` | `clinpgx` | 1 | | `gwas-prs` | `gwas-prs` | 1 | | `clinical-trial-finder` | `clinical-trial-finder` | 1 | | `wes-clinical-report` | `wes-clinical-report-en/es` | 1 | | `target-validation-scorer` | `target-validation-scorer` | 2 | | `genome-compare` | `genome-compare` | 2 | | `methylation-clock` | `methylation-clock` | 2 | ### 框架优先级 - YAML 仅地面真值迁移([计划](docs/plans/YAML_MIGRATION_PLAN.md)) - 共享 AST 安全扫描(`core.ast_security_sweep()`) - 并行执行(`--jobs` / `-j`) - 跨枢纽一级安全门(`--tier1-only`) - FST 差分感知 Z 分数,配子型级 PGx 验证 参见 [`ROADMAP.md`](ROADMAP.md) 了解 P2/P3 枢纽、故障类别覆盖矩阵、技能观察清单,以及开放问题。 ## 文档 - **[ROADMAP.md](ROADMAP.md)** — 整合路线图:计划中的枢纽、框架功能、故障类别覆盖、ClawBio 技能库存、 - **[docs/methodology.md](docs/methodology.md)** — 审计方法学和评分标准设计 - **[docs/ground-truth-derivation.md](docs/ground-truth-derivation.md)** — 每个枢纽的参考值计算方式 - **[docs/baseline-schema.md](docs/baseline-schema.md)** — 基线差异渲染所消耗的字段 - **[CONTRIBUTING.md](CONTRIBUTING.md)** — 如何为新的枢纽添加测试用例 - **[CHANGELOG.md](CHANGELOG.md)** — 发行历史 ## 许可证 MIT © 2025–2026 Sergey A. Kornilov (Biostochastics) 及 ClawBio 审计团队。 请参阅 [LICENSE](LICENSE) 获取全文。
标签:Agentic 工具, AI 安全性, AI 工具安全, ClawBio, LLM 工具审计, Python, Python 工具链, 代码审查, 反取证, 安全合规, 安全性测试, 安全评估, 审计, 提示词模板, 无后门, 正确性验证, 瑞士军刀, 生物信息学, 生物信息工具审计, 网络代理, 软件验证, 逆向工具