Files
AIclinicalresearch/docs/03-业务模块/IIT Manager Agent/09-技术评审报告/2026-03-08-IIT-CRA-指标口径与SSOT对照表-Phase0.md
HaHafeng a666649fd4 feat(iit): harden QC pipeline consistency and release artifacts
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
2026-03-08 21:54:35 +08:00

6.2 KiB
Raw Blame History

IIT / CRA Agent 指标口径与 SSOT 对照表Phase 0

文档版本v1.0
创建日期2026-03-08
适用范围IIT 业务端大盘 / 报告与关键事件 / AI 实时工作流水 / AI 对话
目标:先统一“同名指标”的定义和数据源,再进入修复,避免反复打补丁


1. 背景与问题定义

当前线上/测试反馈的核心不是单点报错,而是同一指标在多个页面口径不一致,例如:

  • 大盘通过率与趋势通过率不一致
  • 报告页健康分与大盘健康分不一致
  • 时间线问题数与待处理 eQuery 不一致
  • 报告中 D1/D2/D3D4/D6 与下方维度评分对不上

这些问题在工程上属于口径漂移metric drift,必须先冻结 SSOTSingle Source of Truth再排查数据同步、规则执行、前端展示。


2. 指标分层模型(必须统一)

IIT 指标按 4 层定义,禁止跨层混算:

  1. 事实层Raw FactsREDCap 原始记录与事件数据
  2. 执行层QC Resultsqc_field_status / qc_event_status 的规则执行结果
  3. 聚合层Project Statsiit_qc_project_statsiit_record_summary 的聚合快照
  4. 呈现层UI/APIDashboard/Reports/AiStream/AiChat

约束:

  • 呈现层不允许重新发明计算公式,只消费聚合层或执行层
  • 同一名称指标只能有一个“主口径”
  • 不同用途的指标必须显式命名(例如“按受试者通过率”与“按事件通过率”)

3. 核心指标 SSOT 对照表(冻结版)

3.1 项目健康度与通过率

指标名 业务定义 SSOT 来源 当前代码入口 备注
healthScore 健康度总分0-100 iit_qc_project_stats.health_score iitQcCockpitService.getStats() 不允许前端 fallback 推导
healthGrade 健康度等级 iit_qc_project_stats.health_grade iitQcCockpitService.getStats() 同上
passRate (大盘) 按受试者通过率 passed_records / total_records iitQcCockpitService.getStats() 保留 1 位小数
passRate (趋势) 按日志条目通过率(旧) iit_qc_logs 分组计算 iitQcCockpitController.getTrend() 与大盘不是同一口径,必须重命名或替换

结论:

  • 当前“通过率”至少有两种口径UI 未标注必然引发“100% vs 33%”类问题。

3.2 D1/D2/D3D4/D6 报表

报表 业务定义 SSOT 来源 当前查询入口
D1 筛选入选 入排规则是否通过 qc_field_statusD1 + record_summary(受试者全集) iitQcCockpitService.getEligibilityReport()
D2 完整性 缺失字段率 qc_field_statusD2 iitQcCockpitService.getCompletenessReport()
D3/D4 质疑跟踪 eQuery 生命周期 iit_equeries iitQcCockpitService.getEqueryLogReport()
D6 方案偏离 访视超窗等偏离 qc_field_statusD6 iitQcCockpitService.getDeviationReport()

结论:

  • D 类报表与大盘维度评分来自不同聚合路径时,必须明确“时点一致性”(同一批次同一时刻)。

3.3 AI 实时工作流水

指标 业务定义 SSOT 来源 当前入口 风险
timeline total 时间线受试者总数 qc_field_status 聚合 + pass 补充 iitQcCockpitController.getTimeline() 与 eQuery 总数不是同一概念
red/yellow 问题数 每受试者 FAIL/WARNING 汇总 qc_field_status getTimeline() 应与 field-issues 可对账
事件中文名 event display label qc_event_status.event_label getTimeline() LEFT JOIN 空值时会回退技术名

3.4 AI 对话

语义工具 主要数据源 适用问题 当前实现
read_report QcReportService 缓存报告 通过率、问题统计、趋势摘要 ToolsService
look_up_data REDCap 原始数据 单患者字段值、原始记录核查 ToolsService
check_quality QcExecutor 实时执行 用户明确要求“重跑质控” ToolsService
search_knowledge 项目知识库RAG 方案文本、入排标准文本 ToolsService

结论:

  • 对话错误不等于“模型幻觉”,优先排查是否选错工具或工具查询不完整。

4. 现存口径漂移点(已识别)

  1. 趋势口径漂移

    • 趋势接口仍从 iit_qc_logs 计算通过率;大盘通过率来自 iit_qc_project_stats
    • 导致“卡片 100%,趋势 33%”。
  2. 健康分 fallback 风险

    • 大盘前端在 healthScore 缺失时回退为 Math.round(passRate)
    • 数据未准备好时会把通过率误当健康分,造成“待处理质疑很多但仍 100 分”。
  3. 报告缓存时点风险

    • read_report 优先读缓存报告(默认有效期 24h若未及时刷新会滞后于大盘/流水。
  4. “总数”语义混淆

    • 时间线问题数、eQuery 待处理数、D3D4 报表数本质是不同对象UI 文案未区分。
  5. 展示字段名兼容风险

    • eventLabel/fieldLabel 空,前端回退技术字段名;用户会误判为“事件名错误”。

5. 冻结规则(修复期强制执行)

  1. 页面上所有“通过率”必须标注口径:

    • 按受试者record
    • 按事件record-event
    • 按规则检查条目field-level checks
  2. 健康度评分只允许来自 healthScoreEngine 落库结果,不允许前端推算。

  3. 报告页、大盘、AI 对话必须显示“统计快照时间”,便于用户识别时点差异。

  4. UI 文案新增说明:

    • “待处理质疑”来自 iit_equeries
    • “时间线问题总数”来自 qc_field_status
  5. 涉及 D1/D2/D3D4/D6 的变更,必须附带“口径回归测试”记录。


6. Phase 1 进入条件

满足以下条件后,才进入根因排查与代码修复:

  • 本文“SSOT 对照表”已被团队确认(产品/研发/质控)
  • 每个页面核心指标已标注口径
  • 已选定“最小复现项目”与冻结时间窗口

Phase 1 执行手册见:
docs/03-业务模块/IIT Manager Agent/09-技术评审报告/2026-03-08-IIT-CRA-最小复现项目对账执行手册-Phase1.md