# 任务书 02:CEUS 定量 把旧项目的 CEUS(超声造影视频)定量算法迁到本仓库,在本机显卡上跑完全部病例。对每段视频,程序要圈出病灶、画出亮度随时间变化的曲线、挑出关键帧、算出灌注指标,最后由 build 把每例的 7 张关键帧和指标装进资料库的超声一路。资料库里原有医生截的关键结构图,加上这 7 张,一共 8 张图。 对应 `research-wiki/explanation/结构.md` 第七部分第 3 步。前提:任务书 01 已完成(提交 bceb01e)。 一份任务书分四个阶段,每个阶段做完单独提交,四个阶段都完成后一起交报告(负责人 2026-10-16:「任务书一份」)。 来源: - 负责人 2026-10-16 定:CEUS 代码「直接一个个迁移」,不在本机重跑旧代码作对比基线(design 0002 决定 4)。 - 负责人 2026-10-16 定:「推注开始时间s」是视频第 0 秒时已经推注了多少秒;40 例没有医生标的造影剂到达时间,关键帧全部由程序从曲线上算或按推注时间取(design 0002 决定 5、6)。 - 负责人 2026-10-16 定:MedSAM2 用最快的方式装(从远程服务器拷代码和权重);紫圈的颜色阈值先照搬旧值,记为待定问题(`待定问题/08`);先把关键帧和指标放进资料库,「一个患者的资料库中有 8 帧」。 - 其余做法(四处已知问题怎么改、中间文件的布局、复用的键、对外接口)是监督者 2026-10-16 提出的,负责人确认任务书时一并认可。 ## 先认识几个词 - **CEUS、造影画面**:往静脉推注造影剂后连续录下的超声视频。超声机录像时屏幕左右各一半:一半是造影画面(造影剂到了就变亮),另一半是普通灰阶超声画面。哪一半是造影画面,各例不一定相同。 - **绿框**:医生在造影画面上画的病灶框,烧录在视频里。 - **紫圈**:医生用紫色轮廓圈的一块正常胰腺(003、010、012 例圈的是肝,033 例没有),用作对照(`待定问题/08`)。 - **提示帧**:绿框位置或形状明显变化的那几帧。程序把这几帧的绿框交给分割模型,告诉它「病灶在这里」。 - **MedSAM2**:医学图像分割模型(GitHub `bowang-lab/MedSAM2`),给它几帧的提示,它能把病灶轮廓传播到整段视频的每一帧。要用显卡,是整个流程里最慢的一步。 - **ROI**:最终圈出的病灶区域。**暗区**:病灶里装囊液、不进造影剂、一直发黑的部分。 - **TIC**(时间-强度曲线):ROI 平均亮度随时间的变化,先变亮再变暗。用 Lognormal(对数正态)形状的光滑曲线去拟合它,后面的时刻和指标都在拟合出的光滑曲线上算。 - **关键帧**:B0(刚开始变亮之前)、D1(开始变亮)、D2(变亮最快)、D3(最亮)、D4(变暗最快)这 5 张从拟合曲线上取;F1、F2 是推注后第 20、60 秒。定义见 `结构.md` 第四部分「CEUS 中间文件」。 - **灌注指标**:从拟合曲线算出的 11 个数(峰值强度、达峰时间、洗入速率等),口径仿照商用造影定量软件 VueBOX。 - **`work/`**:中间文件目录,不进 git,可以删掉重算。 - **两套编号**:本任务书的「第一阶段」到「第四阶段」是你交付的四个阶段;「第 1 步」到「第 9 步」是一段视频在 CEUS 定量里依次经过的 9 步(`结构.md` 第四部分有表):1 解码与分屏,2 找绿框、选提示帧,3 MedSAM2 分割,4 整理轮廓(平滑、与绿框融合),5 找暗区,6 TIC 采样,7 拟合,8 关键帧,9 灌注指标。 - **在哪一半上分割**:沿用旧代码。绿框画在造影那一半;造影画面里病灶边界随造影剂进出时明时暗,所以旧代码把绿框挪到灰阶那一半,让 MedSAM2 在灰阶画面上分割,再把轮廓挪回造影那一半,在造影画面上采亮度。 - **监督者**:和负责人讨论、写任务书并验收的会话;执行者是拿着这份任务书写代码的你。 ## 开工前先读 - `AGENTS.md`:全部,尤其是「不设默认值」「罕见情况怎么办」「错误怎么处理」「测试」。 - `research-wiki/explanation/结构.md`:第二部分(框架图)、第三部分(ceus、segment 的职责和「几条边界」)、第四部分(「CEUS 定量的产物」的 9 步和关键帧表)、第五部分(「配置」、文件格式、导入契约)、第八部分(任务书 01 已有的接口)。 - `research-wiki/design/0002-四段流水线与两个库.md`:决定 4、5、6。 - `research-wiki/待定问题/01`(绿框在最终轮廓里占多少)、`02`(参数何时冻结)、`07`(图上的信息栏)、`08`(紫圈阈值)。这一步都不处理,只要知道它们存在、不要顺手改。 - `research-wiki/任务书/01-装配两个库.md` 和 `src/cadx/` 现有代码。 - 旧代码(只读,路径相对 `reference/CADx-4-CAD/`): - `app/domain/ceus_roi/` 除 `service.py` 外的 17 个模块,约 7300 行,都不依赖数据库或 HTTP。 - `app/providers/video_decoder.py`(视频解码)。 - 实际跑出 40 例结果的三个脚本:`debugs/t1_local_debug.py` 做第 1–6 步,用子进程调 `debugs/medsam2_local_track.py` 做分割;`debugs/tic_lognormal_replay.py` 读轨迹,做 TIC、拟合、关键帧和指标。**迁移时以这条路径的行为为准**,`service.py` 不搬。 - `config/ceus_roi_default.yaml`:108 个参数。 - `tests/unit/` 下 19 个算法测试文件(约 303 个测试,全用合成数据)。 **旧测试怎么接新配置**:配置去掉默认值以后,旧测试里靠默认值构造配置的地方,改成由一个夹具读入 `config/ceus.yaml`,需要不同取值的测试用 `model_copy(update=...)` 改那一项;断言和预期值不改。 **旧脚本里的编排逻辑放哪**:两个 debug 脚本里按顺序调用各模块的那部分逻辑,收进 ceus 对外的两段接口(第二阶段「ceus 对外交出什么」);`scripts/ceus_quant.py` 只管读配置、找病例、读写文件、分割缓存和逐例循环。 **病人资料不进任何文字**:报告、提交说明、测试、日志里只写结构和计数,不写病例号、视频号、诊断和报告原文。 ## 先修任务书 01 的一处 任务书 01 的执行者报告:关键图格式不对(不是 PNG、16 位、带透明)时,`library` 抛 `ValueError`,整次构建停下。这是只落在一个病例上的问题,按 `AGENTS.md`「错误怎么处理」应该跳过这一例。 要做: - library 提供 `check_key_image(path) -> str | None`:能原样重编码时返回 None,不能时返回原因。现在 `_write_clean_png` 里的那几条判断移到这里。 - build 在写资料库之前对每例调它,返回原因的,这一例跳过,记为 **C14**「关键图能原样重编码」,涉及值写原因。 - `_write_clean_png` 里的判断保留为断言性质的报错(走到这里说明 build 漏了检查)。 - 补测试:一例关键图带透明,这一例被跳过、记 C14、其余照常进库。 - `结构.md` 第八部分相应几行改掉。 和第一阶段一起提交,提交说明里写明。 ## 第一阶段:底层和分割之前的算法 迁移以下模块到 `src/cadx/ceus/`(文件名加 `_` 前缀,对外只经 `__init__.py`):geometry、视频解码(旧 `video_decoder.py`)、配置(旧 `research_config.py`)、split_screen、green_prompt、prompt_frames、mapping。 ### 怎么迁 - 逐个模块照旧代码搬,去掉产品层的东西(数据库、settings、日志框架、`app.*` 的引用),注释和 docstring 改成中文、只写现在做什么和为什么。 - 对应的旧测试一起搬,改 import,断言和预期值不改。旧测试要是因为下面「四处要改的地方」而不再成立,删掉或改写那一条,在报告里逐条列出。 - 视频解码:旧代码先把整段视频读成字节、写临时文件,再整段读进内存。改成直接按路径用 cv2 打开、逐帧读。行为(读出的帧和时间戳)不变。`test_video_decoder` 原来要一段真实样例视频,改成在测试里用 cv2 现造一段几十帧的小视频。 ### 配置 - 旧 `research_config.py` 的 22 个 pydantic 配置类搬过来,**去掉全部默认值**(旧 schema 里约 134 处),每个字段必填;`strict=True`、`extra="forbid"`、`frozen=True`,规则同 `结构.md` 第五部分「配置」。 - 新建 `config/ceus.yaml`:数值逐个照抄旧 `ceus_roi_default.yaml`。每个参数的注释写明出处:旧 yaml 注释里引的出处(临床口径契约、旧 findings、旧 design)照抄并注明「出自旧项目」;没有出处的写「旧项目工程侧定的,无出处」。不改任何数值(`待定问题/02`)。 - `ceus.yaml` 分三段:`paths`(交付包位置、`runs/` 和 `work/` 位置)、`segment`(分割设置,第二阶段加)、`ceus`(算法参数)。字段定义各归其主:`ceus` 段归 ceus,`segment` 段归 segment,最外层和 `paths` 由 `scripts/ceus_quant.py` 定义,它读整份文件、把各段交给各自的模型校验。第一阶段先只有 `paths` 和 `ceus` 两段。 - 下面「四处要改的地方」用不到的旧字段(映射锚点(改成每段视频配准,见下文第 1 条)、`source_view`、只给 `service.py` 用的裁黑边设置、D1 取医生时刻的那个模式开关)直接删掉,不留着不用。 ### 四处要改的地方 这四处在旧代码里是错的,或者在 40 例上会出问题,按下面改,各配手算预期值的测试。 1. **左右两半之间的坐标换算:每段视频单独配准。** 程序要把造影画面上的绿框挪到灰阶那一半的同一解剖位置,分割完再把轮廓挪回来采亮度。 - 为什么要配准:旧代码用一对写死的锚点(旧 yaml 第 45–49 行、旧 `mapping.py:91–135`)给所有视频同一个平移量。这对锚点是在一段样本上量的。执行者 2026-10-16 在 8 段视频(覆盖全部 5 种帧宽)上实测:两个视图左上角对齐之后,还剩 −10 到 +182 像素的水平错位,竖直方向 0 到 5 像素。原因是造影那一半的扇形左边有一段黑边,灰阶那一半的扇形贴着分屏线。同一帧宽的两段视频,错位也可能不同。所以平移量既不能写死,也不能只用视图左上角相减。 - 改成:第 1 步分屏之后,在两半的扇形区内对边缘图做互相关,估出 (dx, dy);再用模板匹配独立估一次。两者之差不超过 `ceus.yaml` 里的门槛,取互相关的值;超过就这一例第 1 步失败,原因写「两半配准不一致」。映射仍是「视图局部坐标 + 这个平移」,不做缩放和旋转。 - 门槛:先在 34 例上跑两种方法、看差值分布,再定门槛写进 `ceus.yaml`。注释写明依据,即差值分布的几个分位数。 - 测试:用合成分屏图,已知偏移至少 3 组(含负的水平偏移和非零的竖直偏移),断言估出的偏移等于设定值;再做一张两种方法会给出不同结果的图,断言这一例失败。 - 目视核对用子 Agent,不用人,见下文「配准的目视核对」。 2. **造影画面在哪一半。** 旧代码配置写死造影在左半(旧 yaml 第 15–16 行),013 例造影在右半,找不到绿框。改成:两半各自按旧代码的办法选提示帧(`collect_prompt_observations` + `select_prompt_frames`,参数不变),选出至少一帧就算「这一半有绿框」;恰好一半有,这一半就是造影画面;两半都找到或都找不到,这一例失败,记原因。测试:合成视频,绿框分别在左、在右、两边都有、两边都没有。 3. **D1 不用医生的时刻。** 旧关键帧代码有一个模式让 D1 直接取医生标注的造影剂到达时间(旧 `anchor_frames.py:203–206`)。这条路删掉,只保留从拟合曲线算 D1(design 0002 决定 6)。 4. **推注时间的换算。** X 是超声报告表的「推注开始时间s」,含义是视频第 0 秒时已经推注了 X 秒。F1 取视频第 20 − X 秒,F2 取第 60 − X 秒,取帧的容差窗口照旧 `anchor_frames` 段对 F1、F2 的设置;落在视频之外(小于 0 或超过视频末尾),这一帧记为未定位,写明原因,不拿别的帧补(`结构.md` 第四部分)。旧代码按「推注发生在视频第 X 秒」处理(旧 `anchor_frames.py:204` 的符号),要改。测试手算:X = 7 时 F1 在第 13 秒、F2 在第 53 秒;X = 25 时 F1 在第 −5 秒,未定位。 另有两处旧 debug 路径和 `service.py` 不一样,**按 debug 路径**,因为 40 例的结果是它跑出来的:不裁画面黑边;找分屏线只用均匀抽的 25 帧。 ### 收尾点 上面的模块和测试都搬完,`make check` 通过,提交。 ## 第二阶段:分割和后半段算法 ### MedSAM2 - 从远程服务器拷代码和权重(ssh/rsync 一律走 `wangwenhan@202.38.247.58`,见 `AGENTS.md`「本机环境的坑」): - 代码:远程 `/home/wangwenhan/MedSAM2/`,排除 `checkpoints/` 和 `data/`(约 25MB),连同 `.git` 一起拷到本机 `reference/MedSAM2/`,提交号从这个 `.git` 读出,不写死。它是 GitHub `bowang-lab/MedSAM2` 的 332f30d 提交,远程只改了 `download.sh`,不影响代码。 - 权重:只拷 `checkpoints/MedSAM2_latest.pt`(约 156MB)到本机 `models/MedSAM2_latest.pt`。 - 用 `SAM2_BUILD_CUDA=0 uv add --editable reference/MedSAM2` 装进项目环境(不编译 CUDA 扩展;旧项目也没用它)。装完确认 torch 能看到本机显卡。`guides/开发环境.md` 写明这几步,下一个人在新机器上照着就能装好。 - segment 模块(`src/cadx/segment/`):从旧 `medsam2_local_track.py` 改写,**在同一进程里调用**,不再开子进程和 conda 环境。对外一个函数:输入逐帧图像(只是要分割的那一半画面)、若干提示帧的病灶掩码、分割设置,输出每一帧的病灶掩码。它不认识分屏和绿框(`结构.md` 第三部分)。MedSAM2 要求帧以 jpg 文件放在一个目录里,临时目录由 segment 自己建、自己删。 - 分割设置(权重路径、模型配置路径、设备、旧脚本里的两个 offload 开关)写进 `ceus.yaml` 的 `segment` 段,字段定义在 segment 里,全部必填。权重路径不写死在代码里。 - 导入契约:`cadx` 里只有 segment 能引用 `torch`、`sam2`(改 `pyproject.toml` 里现有那条)。 ### 其余模块 迁移 polygons、dark_region、reference_region、tic_fitting、tic、anchor_frames、perfusion_metrics、trajectory、tic_curves、tic_plot、overlay,旧测试一起搬,做法同第一阶段。 - 绿框在最终轮廓里的融合权重(旧 `roi_shape` 段)照搬,写在 `ceus.yaml` 里(`待定问题/01`)。 - 紫圈的颜色阈值(旧 `pan_source` 段)照搬(`待定问题/08`)。 - 关键帧各时刻的容差窗口,逐个核对出处,写进 `ceus.yaml` 的注释(`结构.md` 第四部分)。 ### ceus 对外交出什么 ceus 不能引用 segment(`结构.md` 第三部分依赖表),所以分两段对外: 1. 第一段:输入视频路径和参数,做第 1–2 步,交出分屏结果、哪一半是造影画面、要交给分割的那一半的逐帧图像,以及提示帧的掩码。 2. 第二段:输入第一段的结果、分割得到的逐帧掩码、推注时间 X 和参数,做第 4–9 步,交出轨迹、TIC 曲线、拟合、7 个关键帧的定位结果、灌注指标。 两段中间由 `scripts/ceus_quant.py` 调 segment。具体类型由执行者定,写进 `结构.md` 第八部分。 ### 收尾点 全部模块和测试搬完,`make check` 通过。另写一条标 `gpu` 的测试:在一段合成小视频上真的调一次 MedSAM2,输出掩码的帧数和尺寸对。跑通后提交。 ## 第三阶段:`scripts/ceus_quant.py`,跑全部病例 ### 跑哪些病例 用 delivery 读交付包,跑**检查全部通过的病例**(目前 34 例)。C14(关键图)在 build 时才查,被它跳过的病例 CEUS 照跑,build 时不用就是了。医生改完数据重新交付后,再跑一次。 delivery 的 `CaseRecord` 目前没有视频路径和推注时间,加上这两项(C04、C08 已经检查过它们)。 ### 输出 CEUS 的结果会进资料库,最终可能写进论文,按 `AGENTS.md` 硬性约束 5 要能追到一次真跑的原始记录,所以每次运行放在 `runs/ceus/` 下、只追加不删;只有能重算的分割缓存放 `work/`。 ``` runs/ ceus/<运行号>/ snapshot/ 快照:git 状态、ceus.yaml 原文、权重文件的 SHA-256、MedSAM2 的提交号 failed.csv 失败的病例:视频号、失败在第几步、原因 <视频号>/ trajectory.npz 逐帧轮廓(格式同旧 trajectory.py) tic_curves.npz 曲线(格式同旧 tic_curves.py) summary.json 拟合结果、灌注指标、紫圈检出率、7 个关键帧的定位(帧号、视频时间、状态、未定位的原因) tic.png 曲线图,标出 D1–D4 overlay.mp4 带轮廓的回放视频,供人目视检查 keyframes/<槽位>.png 定位到的关键帧,B0、D1……F2,未定位的槽位没有文件 work/ segment_cache/<键>/masks.npz ``` - 运行号的格式同构建号(用 runs 的 `make_build_id`)。运行目录先写成 `.partial`,跑完再改名,已存在就报错,规则同任务书 01。 - 关键帧图是该帧的**整幅原始画面**(左右两半都在),不裁剪。给超声专家时裁不裁、怎么遮信息栏,留给会诊任务书(`待定问题/07`)。 - 只有分割结果跨运行复用(`结构.md` 第四部分)。键是下面几样拼起来的 SHA-256:视频文件的 SHA-256、第 1–3 步用到的全部算法参数(规范化成 JSON;不含设备和两个 offload 开关,它们不改变结果)、权重文件的 SHA-256、MedSAM2 的提交号(从 `reference/MedSAM2/.git` 读)。键相同就直接读缓存,不调显卡。缓存目录也是先写 `.partial` 再改名。 - 某一例在第 1–6 步失败(包括第一阶段第 2 条的「两半都有或都没有绿框」、选不出提示帧),这一例记进 `failed.csv`、接着跑下一例,和交付资料的问题同一个规矩(`AGENTS.md`「错误怎么处理」)。拟合没过质量门不算失败:D1–D4 记为未定位、灌注指标写 null,原因写进 `summary.json`,F1、F2 照常按推注时间取。个别关键帧槽位未定位也不算失败。 - 终端只打印计数:总例数、成功数、按步分的失败数、关键帧按槽位分的定位数、耗时。不打印视频号。 `scripts/ceus_quant.py` 只接收 `--config config/ceus.yaml`。全部病例要跑一阵子,放进 tmux,日志写到文件。 ### 配准的目视核对(全量运行之前做) 配准错了不会报错,只会让 TIC 采在病灶旁边,所以全量运行之前,34 例逐例做一次目视核对。核对由子 Agent 来做,负责人不看(负责人 2026-10-16 同意)。子 Agent 判得准不准事先不知道,所以必须混入阴性对照:对照没判出来,这次核对就作废。 1. **出图**:新写 `scripts/ceus_align_review.py --config config/ceus.yaml`,只做第 1 步,不需要显卡。 - 每例出两张图,都只截扇形区:一张棋盘拼图(两半按配准结果交替拼接);一张边缘叠加图(灰阶那一半的边缘画红色,造影那一半配准后的边缘画绿色,重合处呈黄色)。 - 另挑约 10 例,把配准结果故意错开 15–30 像素(方向随机),出同样的两张图,当阴性对照。 - 全部图用随机编号命名、打乱顺序,放进 `runs/ceus_align/<运行号>/images/`。编号和「哪一例、是不是对照、用的 (dx, dy)、视频 SHA-256」的对照表写进同目录的 `key.csv`。这份表不给子 Agent 看。 2. **判读**:派两个互不知情的全新子 Agent,各自看完 `images/` 全部图。每张只判三档:对齐、没对齐、看不清,外加一句依据(例如「血管在棋盘交界处错开」)。 - prompt 里不提有对照,也不提对照的比例。 - 子 Agent 只写编号、判定和依据,不抄图上的字(AGENTS.md 硬性约束 3)。 - 两份判读写成 `verdicts_a.csv`、`verdicts_b.csv`。 3. **计分**:用脚本对照 `key.csv`。 - 任一个子 Agent 把某张阴性对照判成「对齐」或「看不清」,这次核对作废,报告里写明。不放宽标准、不换说法重问。 - 对照都过了:真实病例只有两个子 Agent 都判「对齐」才算通过,其余记为不通过。结果写进 `review.csv`(视频 SHA-256、(dx, dy)、通过与否、两份判定)。 4. **接进全量运行**:`ceus.yaml` 的 `paths` 段加必填字段 `align_review`,指向这次核对的 `review.csv`。 - `ceus_quant` 第 1 步算出配准后,按视频 SHA-256 查这份表:不通过的病例,第 1 步失败,原因写「配准目视核对未通过」。 - 表里没有这段视频,或者 (dx, dy) 和表里记的不一样,直接报错停下:说明核对的不是这次跑的东西。 - 这份 `review.csv` 拷进运行快照。 5. 监督者验收时会自己抽几张图核对。 ### 收尾点 在本机跑完全部病例,提交代码(`runs/`、`work/` 不进 git)。 ## 第四阶段:build 装入 CEUS 结果 - `build.yaml` 加一个必填字段 `ceus_run`:某次 CEUS 运行目录的路径,或者 null(不装 CEUS 结果,就是现在的情况)。 - 不为 null 时,build 按视频号找到每例的 CEUS 结果。这一例在 `failed.csv` 里或者找不到结果目录,这一例跳过,记为 **C15**「CEUS 定量结果齐全」,涉及值写失败阶段和原因。CEUS 失败的病例要不要改成「超声不可评价、仍参与会诊」,等 `待定问题/03` 定,这一步按跳过处理。 - 资料库超声一路加: - `ultrasound/keyframes/<槽位>.png`:定位到的关键帧,经 library 去掉附加数据重新编码(同 `key.png`)。加上原有的 `key.png`,每例最多 8 张图。 - `ultrasound/tic.json`:从 `summary.json` 里只挑这几样,此外什么都不写:旧 `tic.py` 四条曲线(病灶整体、病灶去暗区、紫圈、背景圆)各自的拟合是否成功和拟合优度;灌注指标(同旧 replay `summary.json` 的 `perfusion_metrics` 段);紫圈曲线是否可用;7 个槽位各自定位到没有,定位到的写视频时间(秒),未定位的写原因。视频号、文件路径、配置、帧号都不写。 - 资料库 `manifest.json` 的 CEUS 来源字段写 CEUS 运行号。 - 泄露扫描的禁词表加上视频文件名;扫描范围加上 `tic.json`。 - 用 `ceus_run` 指向第三阶段的那次运行,重新构建一次真实资料库,跑 `scripts/scan_library.py`。 ### 收尾点 测试通过、真实构建和扫描跑完,提交。 ## 测试 预期值照本任务书文字和旧测试写,不从新实现里推。 - 第一阶段的四处修改:各条手算测试,见上文。 - 旧测试:19 个文件中的 18 个(`test_tic_lognormal_replay` 不搬,它测的是旧 replay 脚本读标注工作簿的逻辑,第 3、4 条修改后不再适用)。conftest 里设产品层环境变量的那个夹具不搬。 - segment:一条 `gpu` 测试(第二阶段收尾点)。 - 分割缓存:同样的输入第二次运行不调 segment(用 pytest 的 monkeypatch 把脚本里用到的 segment 函数换成计数的假函数,不为测试加参数);改一个第 1–3 步的参数,键就变。 - 配准核对接入:`review.csv` 里判不通过的病例进 `failed.csv`;表里没有这段视频或 (dx, dy) 对不上时报错。 - `ceus_quant`:合成的两例小视频,一例正常、一例两半都没有绿框,后者进 `failed.csv`,前者有完整输出。 - build:C15 跳过;`tic.json` 只有上面列的几样;keyframes 的附加数据被去掉。 ## 规模 | 模块 | 预期行数 | | --- | --- | | ceus | 6000–7500(照搬旧算法,去掉产品层) | | segment | 150–300 | | `scripts/ceus_quant.py` | ≤ 300 | | `scripts/ceus_align_review.py`(出图和计分) | ≤ 250 | | delivery、library、build 的增量 | 各 ≤ 150 | 超过区间上限的两倍就停下检查。完成后更新:`结构.md` 第六部分实际行数、第八部分 ceus 和 segment 的对外接口;`guides/开发环境.md`(MedSAM2 怎么装);新写 `guides/CEUS定量.md`(怎么跑、产物在哪、怎么看 `failed.csv` 和 `overlay.mp4`,过一轮「硕士生阅读」);`WORK_LOG.md`。 ## 审阅 - 这一步大部分是「其余部分」那一档(`AGENTS.md`「两档标准」),写完派一个全新上下文的子 Agent 审阅:只给它本任务书、`结构.md` 第三到第五部分和 diff,让它重点看「四处要改的地方」是否改对、迁移有没有漏掉旧代码里的分支、关键帧和指标有没有算错。 - 第四阶段改的是资料库(决定专家能看见什么),属于账本级,另派一个全新上下文的子 Agent 单独审这部分,找:CEUS 结果里有没有带进视频号、文件名、医生的判断;CEUS 失败的病例有没有进库。 - Codex 可用时再加一轮对抗审查(`/codex:rescue --fresh --wait`)。 - 意见的处理同任务书 01。子 Agent 的 prompt 里写明本机 `grep`、`find` 用 `/usr/bin/` 下的版本。 ## 报告 四个阶段都完成后,在回复里交一份报告。已验证的事实、推断、未验证的部分分开写。 1. 四个提交号;各模块行数。 2. `make check` 的完整输出;`gpu` 测试的输出。 3. 旧测试:搬了多少条,删改了哪些、为什么。 4. 真实运行:运行号、跑了几例、成功几例、按步分的失败数、关键帧按槽位分的定位数、总耗时和显存峰值。 5. **配准**:两种方法差值的分布和定下的门槛;目视核对的运行号;阴性对照各判对几张;真实病例通过、不通过、看不清各几例;两个子 Agent 判定不一致几例。另给每种帧宽各 1 例的棋盘图路径,供监督者抽查。 6. **紫圈检出率**:每例一个数(有多少比例的帧认出了紫圈),只报分布(最小、四分位、最大),以及低于 50% 的有几例。给 `待定问题/08` 用。 7. **请负责人目视检查的样例**:挑 3 例 `overlay.mp4` 和 `tic.png` 的路径(成功、关键帧缺槽位、紫圈检出率最低的各一例),只给路径不描述内容。 8. 重新构建的资料库:构建号、进库数、C15 跳过数、扫描结果。 9. 审阅意见和处理。 10. 和本任务书、`结构.md`、`AGENTS.md` 不一致的地方,以及为什么。 10. 规则不清楚的地方:哪里犹豫、哪里靠猜。没有就写「没有」。