Implement IIT quality workflow hardening across eQuery deduplication, guard metadata validation, timeline/readability improvements, and chat evidence fallbacks, then synchronize release and development documentation for deployment handoff. Includes migration/scripts for open eQuery dedupe guards, orchestration/status semantics, report/tool readability fixes, and updated module status plus deployment checklist. Made-with: Cursor
7.9 KiB
7.9 KiB
IIT / CRA Agent 最小复现项目对账执行手册(Phase 1)
文档版本:v1.0
创建日期:2026-03-08
目标:用最小复现项目定位根因,不做盲修
适用问题:报告与事件不一致、AI 实时流水不一致、AI 对话结论错误
1. 执行原则
- 先对账,后修复:每个异常必须先确认“错在数据、规则、聚合、还是展示”。
- 单项目封闭验证:只使用“纳入排除标准测试”项目,不混其他项目。
- 同一时间窗口:所有 API / SQL 在同一时段采样,避免时间漂移。
- 一条问题一条证据链:必须保留“输入 -> 处理中间态 -> 输出”。
2. 最小复现项目准备
项目:纳入排除标准测试
固定对象:
- 患者:
2 / 3 / 4(至少包含不完整录入与违规样本) - 事件:筛选期 + 第一次月经周期结束时(若项目定义如此)
- 规则:D1/D2/D3/D4/D6 至少各有 1 条命中场景
冻结窗口:
- 执行前停止自动批任务(避免数据持续变化)
- 手动执行一次“一键全量质控”,记录触发时间 T0
- 所有采样以 T0 后 1-3 分钟为准
3. 四层对账流程(按顺序)
3.1 事实层(REDCap 是否联通)
目标:确认“源头有数据”。
检查项:
- REDCap 中是否存在目标患者/事件数据
record_summary是否包含对应record_idSyncManager最近同步时间是否晚于 T0
判定:
- REDCap 有、平台无 -> 联通/同步问题
- REDCap 无 -> 上游录入问题,不是质控引擎问题
3.2 执行层(规则是否正确执行)
目标:确认“规则判断是否符合临床预期”。
检查项:
qc_field_status是否有该患者对应 D1/D2/D3/D6 记录status/severity/message/actual_value/expected_value是否合理qc_event_status是否与字段级状态一致
判定:
- 执行结果本身错 -> 规则定义/引擎问题
- 执行结果正确、展示错 -> 聚合/前端问题
3.3 聚合层(报表和大盘是否同口径)
目标:确认“同名指标是否来自同一口径与同一快照”。
检查项:
- 大盘:
getQcCockpitData - 报告:
getQcReport/refreshQcReport - 趋势:
getTrend - D1/D2/D3D4/D6:各报表 API
重点看:
- 通过率口径(按受试者 vs 按日志)
- 健康分是否来自
healthScore真实值 - 报告缓存是否过期/未刷新
3.4 对话层(AI 工具链路是否选对)
目标:确认“AI 回答错误是查询错还是推理错”。
检查项:
- 问题触发了哪个工具(
read_report/look_up_data/check_quality/search_knowledge) - 工具返回数据是否完整(如实验室检查字段是否缺失)
- 最终回答是否与工具结果一致
判定:
- 工具返回错 -> 数据查询/映射/项目隔离问题
- 工具返回对、回答错 -> Prompt/回答策略问题
4. 针对当前三大类问题的定位矩阵
4.1 第一大类:报告与关键事件
| 现象 | 优先怀疑 | 第一检查点 |
|---|---|---|
| D1/D2/D3D4/D6 与维度评分不一致 | 聚合口径漂移 | getStats() vs 各报表 SQL |
| 质控 0 个受试者 | 执行未落库或 projectId 错 | qc_field_status 是否有该项目数据 |
| 待处理 252 但健康分 100 | 健康分 fallback / 评分权重缺陷 | 前端 healthScore fallback、HealthScoreEngine 维度权重 |
| 上方通过率 100,下方趋势 33 | 趋势口径不同 | getTrend() 当前读 iit_qc_logs |
| 质控完成无热力图 | qc_event_status 空或事件列构建失败 |
getHeatmapData() 查询结果 |
| 执行摘要无信息 | 报告缓存旧 / 生成失败 | iit_qc_reports 最新记录 + refresh |
| 报告分 64 vs 大盘 100 | 报告快照与实时不一致 | report.generatedAt vs cockpit now |
| D1 无数据 | D1 规则缺失或 rule_category 错 | qc_field_status where D1 |
| D2 事件数=1 且明细异常 | D2 统计规则/activeEvents定义不清 | getCompletenessReport() 的 byRecordEvent |
| 已回复仍显示 0 | 状态机未推进或统计口径错 | iit_equeries.status 分布 |
| 无“重开质疑”操作 | 前端缺动作入口(后端有状态) | EQueryPage 操作列 |
4.2 第二大类:AI 实时工作流水
| 现象 | 优先怀疑 | 第一检查点 |
|---|---|---|
| 流水问题总数 444 vs 待处理 252 | 指标对象不同 | 时间线来自 qc_field_status,待处理来自 iit_equeries |
| 事件编码生成逻辑不明 | 事件标签映射缺失 | eventLabel 来源:qc_event_status / fallback |
| 日期筛选按钮无效 | API 过滤未生效或前端未传 | getTimeline(date=YYYY-MM-DD) 返回是否变化 |
4.3 第三大类:AI 对话助手
| 现象 | 优先怀疑 | 第一检查点 |
|---|---|---|
| 已签署知情显示 0 | 工具选路错误或字段未映射 | look_up_data 查询字段覆盖 |
| 3号患者严重问题被说成无问题 | read_report 缓存滞后或筛选逻辑错 | QcReportService 缓存时间与 issue 列表 |
| 总体通过率异常(分项非0,总体0) | 聚合口径错误 | 报告 summary.passRate 公式 |
| 查询患者2信息不全 | 工具默认返回字段不完整 | look_up_data 默认 data 结构 |
| 4号患者访视名错误/状态描述偏差 | eventLabel 回退技术ID + 业务叙述模板粗糙 | eventLabel 链路与回答模板 |
5. 执行清单(逐项打勾)
5.1 一次完整排查(建议 2-3 小时)
- 执行
batch-qc,记录 T0、返回totalRecords/totalEventCombinations/passRate - 拉取驾驶舱:
qc-cockpit - 拉取报告:
qc-cockpit/report(先读缓存,再 refresh) - 拉取趋势:
qc-cockpit/trend - 拉取时间线:
qc-cockpit/timeline - 拉取 D1/D2/D3D4/D6 报表
- 拉取
field-issues(critical + warning) - 拉取 eQuery stats 与 list
- 对 5 条 AI 问答样例做工具链路记录
5.2 SQL 对账模板(只读)
以下为只读核对 SQL,请在测试库或只读会话执行。
-- 1) 项目级统计快照
SELECT project_id, total_records, passed_records, failed_records, warning_records,
health_score, health_grade, d1_pass_rate, d2_pass_rate, d3_pass_rate, d5_pass_rate, d6_pass_rate, d7_pass_rate
FROM iit_schema.qc_project_stats
WHERE project_id = :project_id;
-- 2) 字段级问题总量(SSOT)
SELECT status, severity, rule_category, COUNT(*) AS cnt
FROM iit_schema.qc_field_status
WHERE project_id = :project_id
GROUP BY status, severity, rule_category
ORDER BY rule_category, status, severity;
-- 3) 事件级状态
SELECT record_id, event_id, event_label, status, fields_total, fields_passed, fields_failed, fields_warning
FROM iit_schema.qc_event_status
WHERE project_id = :project_id
ORDER BY record_id, event_id;
-- 4) eQuery 状态分布
SELECT status, COUNT(*) AS cnt
FROM iit_schema.iit_equeries
WHERE project_id = :project_id
GROUP BY status
ORDER BY status;
6. 修复优先级建议(按风险)
P0(先修):
- 通过率口径统一(大盘/趋势/报告明确区分)
- 健康分来源统一(禁前端 fallback 推算)
- 报告缓存刷新策略(批量质控后强制刷新并透出快照时间)
- 时间线与 eQuery 统计文案区分(避免同名误读)
P1(随后):
- EQuery “重开”前端操作入口(后端状态机已支持)
- D2“活跃事件/缺失字段”定义可视化说明
- AI 对话输出模板升级(访视表格化 + 证据引用)
P2(优化):
- 工具调用 trace 可视化(问题 -> 工具 -> 结果 -> 回答)
- 指标字典落地到接口 schema,前后端共享类型
7. 本阶段交付物要求
完成 Phase 1 后,必须输出:
问题-根因对照表(你列出的每条问题都要有结论)证据包(API 返回 + SQL 结果 + 截图)修复方案分批计划(P0/P1/P2 + 影响面 + 回归用例)
没有这三项,不进入大规模代码修改。