6.8 KiB
Implementation Plan: P4 前置依赖修复
Overview
6 个定点修复,修正 P4 核心业务层与 Spec 的实现偏差。T1/T2 已在之前修复中完成,仅需属性测试验证;T3/T4/T5/T6 需要代码变更。所有修改限于现有服务层内部逻辑,无新表、无新接口。
测试框架:Hypothesis(项目已有依赖),测试文件位于 tests/ 目录。
Tasks
-
1. 验证 T1(任务列表)和 T2(召回检测器)已有实现 + 属性测试
-
1.1 编写 T1 属性测试:任务列表状态过滤、排序、abandon_reason 一致性
- 创建
tests/test_p52_task_list_properties.py - 提取
get_task_list的过滤和排序逻辑为纯函数(或 mock DB 层),用 Hypothesis 生成随机任务集合 - Property 1: 任务列表状态过滤 — 仅返回 active/abandoned,不含 completed/inactive
- Property 2: 任务列表排序正确性 — abandoned 排在 active 之后,active 内部按 is_pinned DESC, priority_score DESC NULLS LAST, created_at ASC
- Property 3: abandon_reason 与 status 一致性不变量 — active → null, abandoned → 非空字符串
- Validates: Requirements 1.1, 1.2, 1.3, 1.4
- 创建
-
1.2 编写 T2 属性测试:召回检测器仅完成 recall 类型任务
- 在
tests/test_p52_recall_detector_properties.py中编写 - 用 Hypothesis 生成包含四种 task_type 的任务集合和服务记录
- Property 4: 召回检测器仅完成 recall 类型任务 — high_priority_recall/priority_recall 被完成,follow_up_visit/relationship_building 状态不变
- Validates: Requirements 2.1, 2.2, 2.3
- 在
-
-
2. Checkpoint — 验证 T1/T2 属性测试通过
- Ensure all tests pass, ask the user if questions arise.
-
3. 实现 T3:备注回溯重分类器冲突处理
-
3.1 修改
apps/backend/app/services/note_reclassifier.py的run()方法- 在创建 follow_up_visit 任务前,查询同 (site_id, assistant_id, member_id) 是否已有 follow_up_visit 任务
- 已有
completed→ 跳过创建(回访完成语义已满足) - 已有
active→ 旧任务标记inactive,记录superseded历史,创建新任务 - 不存在(或仅有 inactive/abandoned)→ 正常创建
- 确保重复触发相同 payload 不产生唯一约束冲突
- Requirements: 3.1, 3.2, 3.3, 3.4
-
3.2 编写 T3 属性测试:冲突处理三分支
- 在
tests/test_p52_note_reclassifier_properties.py中编写 - Property 5: 已完成回访任务阻止新建 — 存在 completed 的 follow_up_visit 时跳过创建
- Property 6: active 回访任务被顶替 — 旧任务 → inactive + superseded 历史,新任务创建
- Property 7: 无冲突时正常创建 — 不存在 follow_up_visit(或仅 inactive/abandoned)时正常创建
- Validates: Requirements 3.1, 3.2, 3.3, 3.4
- 在
-
-
4. 实现 T4:回访完成条件改为「有备注即完成」
-
4.1 修改
apps/backend/app/services/note_service.py的create_note()方法- 当
note_type == "follow_up"且task_id is not None时:- 保留
ai_analyze_note()占位调用,返回值仅用于更新ai_score字段 - 不论
ai_score如何,有备注即标记关联的 active follow_up_visit 任务为completed - 记录
completed_by_note历史
- 保留
- Requirements: 4.1, 4.2, 4.3
- 当
-
4.2 修改
apps/backend/app/services/note_reclassifier.py的run()方法(T4 部分)- 去掉 AI 评分判定逻辑(
ai_score >= 6条件) - 保留
ai_analyze_note()占位调用 - 找到备注(
note_id is not None)→ 创建status='completed'的回访任务(回溯完成) - 未找到备注(
note_id is None)→ 创建status='active'的回访任务(等待备注) - 注意:此步骤需与 3.1 的冲突处理逻辑协同,冲突检查在任务创建前执行
- Requirements: 4.4, 4.5
- 去掉 AI 评分判定逻辑(
-
4.3 编写 T4 属性测试:有备注即完成
- 在
tests/test_p52_note_service_properties.py中编写 - Property 8: 有备注即完成回访任务,不依赖 AI 评分 — 对任意 ai_score(None/0-5/6-10),提交备注后 active follow_up_visit 任务都标记 completed
- Property 9: 回溯有备注时创建 completed 回访任务 — note_reclassifier 找到备注 → status='completed'
- Property 10: 回溯无备注时创建 active 回访任务 — note_reclassifier 未找到备注 → status='active'
- Validates: Requirements 4.2, 4.3, 4.4, 4.5
- 在
-
-
5. Checkpoint — 验证 T3/T4 实现和测试通过
- Ensure all tests pass, ask the user if questions arise.
-
6. 实现 T5:trigger_scheduler last_run_at 事务安全
-
6.1 修改
apps/backend/app/services/trigger_scheduler.pyfire_event():handler 接受可选conn参数,在 handler 最终 commit 前附带更新last_run_at;handler 失败时整个事务回滚(last_run_at 不更新)check_scheduled_jobs():同理,将last_run_at和next_run_at更新纳入 handler 事务范围- 需同步修改
recall_detector.run()和note_reclassifier.run()的签名,接受可选conn参数 - Requirements: 5.1, 5.2, 5.3
-
6.2 编写 T5 属性测试:事务一致性
- 在
tests/test_p52_trigger_scheduler_properties.py中编写 - Property 11: 触发器 last_run_at 事务一致性 — handler 成功 → last_run_at 更新;handler 异常 → last_run_at 不变(整个事务回滚)
- Validates: Requirements 5.1, 5.2
- 在
-
-
7. 实现 T6:cron 默认值改为 07:00 + 迁移脚本
-
7.1 修改
apps/backend/app/services/trigger_scheduler.py的_calculate_next_run()- 将
trigger_config.get("cron_expression", "0 4 * * *")改为"0 7 * * *" - Requirements: 6.2, 6.3
- 将
-
7.2 创建迁移脚本
db/zqyy_app/migrations/2026-03-15__p52_update_cron_0700.sql- 幂等 UPDATE:
UPDATE biz.trigger_jobs SET trigger_config = jsonb_set(trigger_config, '{cron_expression}', '"0 7 * * *"') WHERE job_name = 'task_generator' - 包含回滚注释
- Requirements: 6.1
- 幂等 UPDATE:
-
-
8. Final checkpoint — 全部测试通过
- Ensure all tests pass, ask the user if questions arise.
- 运行
pytest tests/test_p52_*.py -v验证所有 P5.2 属性测试通过
Notes
- Tasks marked with
*are optional and can be skipped for faster MVP - T1/T2 已在之前修复中实现,任务 1 仅编写属性测试验证覆盖
- T3 和 T4 对
note_reclassifier.py有交叉修改,任务 3.1 和 4.2 需协同实施 - T5 涉及 handler 签名变更,需同步修改 recall_detector 和 note_reclassifier
- T6 种子数据已是
0 7 * * *,迁移脚本为幂等更新确保生产环境一致 - 属性测试使用 Hypothesis,每个属性最少 100 次迭代