Files
2026-03-15 10:15:02 +08:00

6.8 KiB
Raw Permalink Blame History

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.pyrun() 方法

      • 在创建 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.pycreate_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.pyrun() 方法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
    • 4.3 编写 T4 属性测试:有备注即完成

      • tests/test_p52_note_service_properties.py 中编写
      • Property 8: 有备注即完成回访任务,不依赖 AI 评分 — 对任意 ai_scoreNone/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. 实现 T5trigger_scheduler last_run_at 事务安全

    • 6.1 修改 apps/backend/app/services/trigger_scheduler.py

      • fire_event()handler 接受可选 conn 参数,在 handler 最终 commit 前附带更新 last_run_athandler 失败时整个事务回滚last_run_at 不更新)
      • check_scheduled_jobs():同理,将 last_run_atnext_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. 实现 T6cron 默认值改为 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

      • 幂等 UPDATEUPDATE biz.trigger_jobs SET trigger_config = jsonb_set(trigger_config, '{cron_expression}', '"0 7 * * *"') WHERE job_name = 'task_generator'
      • 包含回滚注释
      • Requirements: 6.1
  • 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 次迭代