一个 Demo 从“明确候选病例”开始很自然,但最终验收不能停在这条成功路径。真正需要问的是:关键检测缺失时它会不会乱猜?两份证据冲突时它会不会把冲突藏掉?调用超时、重复提交和越权写入时,系统到底停在哪里?
我把这些问题写成了十二个端到端场景。截图里的 12/12 和 6/6 是当前合成验收套件的执行结果;0.035 ms 则只对应进程内、无 I/O、无模型推理的规则路径。它们证明了有限范围内的工程行为,绝不是临床效果或线上时延承诺。

看图时还有两个细节值得注意:红队区域写的是 pattern tests,不是渗透测试;两张消融卡都显示 Regression detected。我希望评测在故意拆掉安全部件后立刻变红,而不是只在所有组件都开着时给一片绿灯。
十二个场景,先检查“不会怎样错”
每个场景都有合成 fixture、预期状态和自动断言。它们不是十二道医学问答题,而是一条候选筛选工作流必须遵守的行为合同。
第一组检查资格判断与证据链:
- 明确 NSCLC 病例应产生 candidate,且每条标准都有 Evidence;
- 活跃脑转移触发排除;
- 缺失 EGFR 必须是
unknown; - 分期冲突必须进入 manual review;
- 影像和记录不一致时保留双方证据。
第二组检查数据与工具边界:
- 过期协议被阻断;
- PDF 文本里的提示注入被隔离;
- 临时读取超时有限重试并留下恢复记录;
- 重复批准写入只产生一次副作用;
- 未授权写入在 handler 前被拒绝;
- 非 NSCLC 病例被 OOD 门禁阻断。
最后一项是发布边界:
- 模型指标回退时,发布门禁必须失败。
这里最难的一点,是接受 unknown、manual review 和 blocked 也是正确结果。一个医疗 Agent 若永远返回完整答案,通常不是它特别聪明,而是系统没有允许它停下来。
红队和消融,问的不是同一件事
红队尝试越过系统边界。公开版包含三类文档注入、非合成患者标识、未固定模型 revision 和越权工具调用,共六项可执行检查。全部通过只意味着这六个已知模式被挡住,不能写成“系统已通过渗透测试”。
消融反过来把我们自己拆掉。第一组移除冲突保留逻辑,原本应人工复核的病例变成 candidate;第二组在域外检查前改写疾病,非 NSCLC 病例不再被正确阻断。
这两次回退有一个实用价值:如果拆掉安全部件,所有指标仍然不变,那说明指标本身没有覆盖最关心的风险。比起报告“模块很重要”,我更在意评测能否真的捕获失效。
性能数字先说范围,才有意义
项目运行 500 次进程内确定性规则路径,记录 mean、p50、p95 和 max。它可以作为代码回归基线,却不包括网络、数据库、模型推理和并发。
所以我不会把这一条路径的毫秒数字叫作“医疗 Agent 实时响应”。一旦接入真实 FHIR Server、DICOMweb、向量数据库或模型服务,瓶颈和失败模式都会改变。性能报告要先告诉读者测了什么、没测什么,再谈结果。
让实验报告从机器产物生成
make verify 会先生成 JSON 实验产物,再据此渲染完整报告。报告包含七组微型训练、公开试验快照、红队、消融、性能环境、重现命令和限制。
这减少了两个常见错误:代码已经重跑,文章还在引用旧数字;或者手工抄一遍结果时,把 smoke、真实微型参数更新和未执行的大模型配置混成一项成绩。
这套链路仍然只适用于公开合成材料。它让工程实验可复核,不会自动产生临床有效性证据。
一次容器故障,反而比“支持 Docker”更值得保留
项目有 API 与 Web 两个只读容器。最终验收第一次构建时,Docker Hub 拉取基础镜像超时;重试成功后,API 健康检查通过,Web 容器却退出。
追日志后发现,Vite 预览服务需要向 node_modules/.vite-temp 写临时配置,而容器根文件系统保持只读。修复不是撤掉只读限制,只为这个目录挂载 16MB 内存盘。再次启动后,API /health 返回 200 并明确 mode=synthetic、clinical_use=false,Web 也返回 200,两个容器仍保持 no-new-privileges。
这段故障和修复已经记入 PROJECT.md。它说明当前镜像在这条受控路径上如何运行,不说明生产环境的安全审计已完成。
CI、威胁模型和开源教材分别证明什么
GitHub Actions 在每次 push 和 PR 上运行完整 verifier:数据生成、七类实验、测试、编译和前端构建。CodeQL 另行扫描 Python 代码,并按周运行。
CI 绿灯只说明当前 commit 在干净 runner 上完成了约定动作。它不等于依赖不存在未知漏洞,也不能替代威胁建模。因此仓库还维护 SECURITY.md 和 threat model,用来说明资产、信任边界、攻击方式、缓解措施和未解决事项。
教材也独立成了一个公开仓库:24 章正文、实验、研究来源和贡献说明都在这里。下面的截图用于确认项目目录与公开入口,而不是拿 star、fork 或提交次数作为影响力证明。

把代码、实验、教材和文章连起来,是为了让读者能沿着同一条证据链回看:一句文章结论能找到报告,报告能找到脚本,脚本能在合成环境里重新执行。
工作台和手机页,是给人审而不是给演示凑页面
后端返回结构正确,并不代表审核者能安全地读懂它。工作台提供 Review、Patients、Trials、Evidence、Model Lab、Evaluations 和 Audit Log 七个视图;五个教学病例由 FastAPI 的合成 API 提供,审核者可以展开证据、启动流程、在 checkpoint 批准或拒绝,并查看返回的 Agent trace 与恢复事件。
手机端也没有把三栏硬压进 390 像素。它保留审核队列、病例状态和证据覆盖这些第一优先信息,其他内容按窄屏顺序重排。下面这个界面同样来自合成数据路径。

六组视频由 Playwright 连接真实合成 API 录制,其中审核 Demo 会实际执行 pause 与 resume;截图和视频能从仓库脚本重现。它们说明交互和工程连接可演示,不说明患者场景已可部署。
这套项目现在能证明什么,不能证明什么
它能证明我把医疗数据、Evidence 合同、检索、逐标准判断、工具治理、人工中断、评测、安全、前端、容器、CI、教程和公开视频放进了一条可检查的工程链;也能证明我没有把未执行训练或合成结果写成临床结论。
它不能证明模型具有临床有效性,不证明满足任何医疗器械法规,不证明合成数据结果可以外推到真实医院,也不意味着公开 Demo 能直接接入患者工作流。
后续路线仍分三步:M1 适配真实基础设施,如 HAPI FHIR sandbox、DICOMweb fixture server、OMOP/MEDS、PostgreSQL/pgvector、OIDC/ABAC 和 OPA;M2 在合规数据与任务设计之后再比较开放模型、RAG、SFT/QLoRA、DPO 和可验证 GRPO;M3 做独立盲评、一致性、患者/时间/站点切分、校准、漂移和回滚演练。
测试变多,不会自动把项目变成“临床验证”。但一个能被验证、暂停、恢复、审计和治理的 Agent,至少比只会顺着成功案例演示的系统更接近工程现实。
