Features: - Add editable variable selection in workflow plan (SingleVarSelect + MultiVarTags) - Implement 3-layer flexible interception (warning bar + icon + blocking dialog) - Add tool_param_constraints.json for 12 statistical tools parameter validation - Add PATCH /workflow/:id/params API with Zod structural validation - Implement synchronous parameter sync before execution (Promise chaining) - Fix LLM hallucination by strict system prompt constraints - Fix DynamicReport object-based rows compatibility (R baseline_table) - Fix Word export row.map error with same normalization logic - Restore inferGroupingVar for smart default variable selection - Add ReactMarkdown rendering in SSAChatPane - Update SSA module status document to v3.5 Modified files: - backend: workflow.routes, ChatHandlerService, SystemPromptService, FlowTemplateService - frontend: WorkflowTimeline, SSAWorkspacePane, DynamicReport, SSAChatPane, ssaStore, ssa.css - config: tool_param_constraints.json (new) - docs: SSA status doc, team review reports Tested: Cohort study end-to-end execution + report export verified Co-authored-by: Cursor <cursoragent@cursor.com>
6.9 KiB
6.9 KiB
架构与统计双重视角审查报告:分析方案变量可编辑化 V2 修订版
审查对象: plan_editable_variables_27d3a9fd.plan.md 及 团队 UX 修正反馈 文档状态: V2 修订版 (采纳“柔性拦截”方案) 审查时间: 2026-02-23
总体评级: 🌟 A+ 级 (方向极其正确,兼顾了学术严谨与用户掌控感) 核心裁决: 批准开发。团队提出的“软提示 + 强引导”完美解决了级联失效的体验问题,但必须配合后端的“强防火墙”才能安全落地。
一、 视角一:资深统计学专家的评估
“不要替医生做决定,但要给医生最专业的警告。”
1. 极度认可的改进
- 尊重临床逻辑:AI 经常会把“住院天数”和“年龄”搞混,或者漏掉医生特别关心的某个协变量。允许医生在执行前把遗漏的变量(Tag)加回来,这才是真正懂临床的工具。
- 按类型分组展示:下拉面板将连续变量和分类变量分开展示,极大地降低了医生寻找变量的认知负荷。
2. 统计学视角的隐形陷阱 (The Statistical Blind Spot)
仅仅区分“分类 (Categorical)”和“连续 (Continuous)”是远远不够的。不同的统计方法对变量有着极其严苛的专属要求:
- 二元 Logistic 回归陷阱:该方法要求结局指标(Y)必须且只能是二分类变量(如:死/活,0/1)。如果用户选了 3 分类的“血型”,后端的 R 代码将无法计算。
- T 检验陷阱:独立样本 T 检验的分组变量(X)必须是二分类变量。如果是 3 分类变量,必须用 ANOVA。
🛠️ 统计专家的修正建议:引入“细粒度统计类型过滤” (Soft Filtering)
前端的下拉框候选项(Options),不能仅仅根据 type === 'categorical' 来过滤,必须与当前 Step 绑定的统计方法建立映射提示。
- 建议实现:前端在渲染下拉框时,读取该统计工具的 params_schema。对于不完全符合最佳统计条件的变量,不要禁用 (Do not disable),但可以在该选项旁打上一个 ⚠️ 标记,提示其可能不适配当前方法。
二、 视角二:资深架构师的评估
“前端可以极致柔性,后端必须绝对刚性。”
1. 架构师高度赞赏的决策 (Brilliant Architectural Choices)
- 后端 PATCH API 的设计 (方案 A):
这是非常正统的 RESTful 设计。用户修改参数后,先 PATCH /params 更新数据库实体,然后再触发 executeWorkflow。这保证了数据库中的 Plan 永远是 Single Source of Truth(单一事实来源),避免了前端传来“幽灵参数”导致历史记录无法复现的灾难。
2. 工程视角的潜在风险与柔性化解 (Engineering Risks & Solutions)
🚨 风险 1:UI 状态与执行动作的竞态条件 (Race Condition)
- 场景:用户在前端刚从下拉框里切换了变量,还没等组件把 state 同步完毕,或者还没等 PATCH 接口返回 200 OK,用户就光速点击了“开始执行分析”按钮。
- 后果:executeWorkflow 可能会拿着数据库里旧的参数去执行。
- 修正建议:
“开始执行分析”按钮必须绑定一个复合动作(Promise Chaining):
async function handleExecute() {
setExecuting(true);
// 1. 必须先 await 等待 PATCH 成功
if (hasUnsavedChanges) {
await api.patchWorkflowParams(workflowId, modifiedSteps);
}
// 2. 然后再触发执行
startSseExecution(workflowId);
}
🚨 风险 2:级联失效与重新规划的边界 (Cascading Invalidation)
- 场景:AI 原本规划了 [描述统计 -> T检验 -> Mann-Whitney]。此时,用户在“描述统计”那一步,强行把结局变量从“连续数值”换成了“分类文本”。此时下游的 T检验 已经彻底失去了统计学意义。
- 团队极佳的破局方案(柔性拦截与知情同意): 绝对不采用“硬限制”锁定下拉框(这会引发极大的用户反感)。采用团队设计的**“软提示 + 重新规划引导”**机制:
- 即时反馈:当检测到用户的修改导致变量类型与当前统计方法(params_schema)失配时,在 StepCard 顶部即时显示黄色警告条:“⚠️ 当前变量类型已变更,可能导致当前统计方法失效。”
- 视觉打标:在该步骤的卡片右上角亮起一个红/黄警告图标。
- 阻断与授权弹窗 (Informed Consent):如果用户无视警告,强行点击【开始执行分析】,系统拦截并弹窗:"检测到您修改的变量类型(如:分类变量)与当前统计方法(T检验)不匹配,强制执行可能导致报错或结论无效。建议您在对话框告诉 AI 重新生成方案。是否仍要强行执行?" [ 取消并重新对话 ] [ 强行执行 ]
- 架构师点评:这种设计堪称完美。把控制权给用户,把免责声明做足。
🚨 风险 3:Zod Schema 的后端防御底线 (Backend Defense) - 生死线
- 场景:既然前端允许用户点击“强行执行”,那么非法的参数就一定会穿透到后端。
- 架构底线:
新增的 PATCH /api/v1/ssa/workflow/:workflowId/params 接口,绝对不能因为接收到了脏数据而导致 Node.js 崩溃。 必须使用对应 R 工具的 Zod Schema 进行校验。如果接收到了离谱的参数(比如把一个字符串数组传给了要求 Boolean 的字段),后端必须捕获并转化为优雅的 400 Bad Request;如果参数类型合法但统计学不合法,放行给 R 引擎,由 R 引擎内部的 tryCatch 捕获并返回给前端清晰的 Error Log 即可。
三、 终极结论与实施调整指南 (Actionable Summary)
团队对于 UX 交互边界的把握非常高级,"软提示+强引导"方案完美化解了系统的刻板印象。
为了让计划完美落地,请在开发中落实以下 3 个关键动作:
- 前端交互柔性化 (UI Soft Filter):
- 实现黄条警告和“强行执行确认弹窗”。这需要前端在渲染时,将当前选择的变量类型与工具的 params_schema 需求类型进行实时比对计算。
- 同步阻塞执行 (Sync Block Patch):
- 确保“执行按钮”的 onClick 事件中,严格包含 await patchApi(),并在进行网络请求时将按钮置为 loading 状态。
- 后端的参数防火墙 (Backend Firewall Patch):
- 为 PATCH API 建立坚固的 Zod 校验,确保前端传来的强行覆盖数据,最多只会导致 R 引擎的“业务计算报错”,而绝对不会导致 Node.js 服务的“系统级崩溃”。
批示:完全批准按照此修订计划执行开发!在赋予用户自由的同时守住后端的安全底线,这套交互将成为医疗 SaaS 的标杆。