PMFlow/docs/GLM5_SIGNAL_PLANNER_IMPLEME...

251 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GLM-5 Signal Planner + 增量任务包管理实施清单(可打勾执行版)
> 使用规则:严格按步骤推进;每个步骤完成后再勾选;未完成禁止进入下一步。
## 0. 全局硬约束(执行前必须确认)
- [x] 所有业务写操作必须通过 service/repository 入口调用。
- [x] 严禁在调用链路散落裸 ORM `insert/update/commit`。
- [x] 数据库结构改动仅通过 Alembic migration。
- [x] API 统一包络:`{code, message, data}`。
- [x] 后端契约变更必须同步前端 TS 类型与文档。
- [x] 删除任何代码前必须执行 `FIND_USAGE` 并留证据。
- [x] 发现违例立即停止并输出 `[VIOLATION: 裸写位置]`。
- [x] 模型选择必须接口化配置,禁止在业务代码写死 `provider/model/api_env`。
## 1. 执行总览(里程碑)
- [x] Step 0:基线文档与自动增量机制
- [x] Step 1:Signal Planner 数据层改造
- [x] Step 2:写入服务收口(StrategicAnalysis + Outbox)
- [x] Step 3:SignalPlannerService 接入
- [x] Step 4:主链路触发与路由配置
- [x] Step 5:模型灵活配置(接口化,禁止写死)
- [x] Step 6:前端展示与侧边栏新增功能
- [x] Step 7:脏代码/无用代码删减
- [ ] Step 8:验收与交付
---
## Step 0:基线文档与自动增量机制
### 入口条件
- [x] 项目当前主分支可读,文档目录可写。
### 执行项
- [x] 新建 `docs/architecture/MASTER_CONTRACT.md`
- [x] 新建 `docs/architecture/API_CONTRACTS.md`
- [x] 新建 `docs/architecture/DATAFLOW.md`
- [x] 新建 `docs/architecture/TASK_BRIEF_TEMPLATE.md`
- [x] 新建 `scripts/gen_task_brief.sh`(自动生成增量任务包)
- [x] 新建 `scripts/check_contract_sync.sh`(契约同步检查)
- [x] CI 增加 contract-check job
### 完成标志
- [x] 本地可自动生成一份有效增量任务包
- [x] CI 可检测契约文档未同步并正确失败
---
## Step 1:Signal Planner 数据层改造
### 入口条件
- [x] Step 0 完成
### 执行项
- [x] 新增 migration:`signals.planner_status VARCHAR(20) DEFAULT 'pending'`
- [x] 新增 migration:`signals.planner_analyzed_at TIMESTAMP`
- [x] 新增 migration:`signals.planner_assignee_user_id INTEGER`
- [x] 为 `planner_status` 增加索引
- [x] 同步更新 `backend/app/models/signal.py`
### 完成标志
- [x] `alembic upgrade` 后表结构正确
- [x] ORM 模型可读写三字段
---
## Step 2:写入服务收口
### 入口条件
- [x] Step 1 完成
### 执行项
- [x] 新建 `backend/app/services/signal_strategic_analysis_service.py`
- [x] 实现 `merge_and_save(db, signal_id, planner_result, tenant_id)`
- [x] 实现 `mark_failed(db, signal_id, tenant_id, reason)`
- [x] 新建 `backend/app/services/feishu_outbox_service.py`
- [x] 实现 `enqueue(db, chat_id, text, source_message_id, dedupe_seed)`
- [x] 幂等策略复用 `reply_hash`,不新增 outbox 冗余字段
### 完成标志
- [x] 新增 service 覆盖 Planner 写回与补发入队
- [x] 新增 service 文件中无业务外层裸写调用
---
## Step 3:SignalPlannerService 接入
### 入口条件
- [x] Step 2 完成
### 执行项
- [x] 新建 `backend/app/services/signal_planner_service.py`
- [x] `analyze(...)` 内部使用独立 `AsyncSessionLocal`
- [x] 上下文查询使用现网字段:`signals.matched_project_id`
- [x] 成员查询通过 `user_projects -> users -> user_workloads -> user_skill_bindings -> skill_tags`
- [x] 调用 `llm_service.generate_structured_object(function_name="signal_planner_analyze")`
- [x] 成功路径调用 `SignalStrategicAnalysisService.merge_and_save`
- [x] 失败路径调用 `SignalStrategicAnalysisService.mark_failed`
- [x] 补发路径调用 `FeishuOutboxService.enqueue`
### 完成标志
- [x] Planner 失败不阻断主链路
- [x] Planner 成功后 `strategic_analysis.ai_planner` 写回成功
---
## Step 4:主链路触发与路由配置
### 入口条件
- [x] Step 3 完成
### 执行项
- [x] 修改 `backend/app/services/ai_pmo_kernel_service.py`
- [x] `signal.create` 成功提交后 `create_task(SignalPlannerService.analyze(...))`
- [x] 在 `backend/app/config/ai_prompts.py` 增加 `PROMPT_SIGNAL_PLANNER`
- [x] 在 LLM 结构化 schema 注册 `signal_planner_analyze`
- [x] 更新 `backend/.control_plane/pmflow-routing-rules.json` 添加 high tier 路由
### 完成标志
- [x] 触发点仅在 commit 后
- [x] 路由命中 `signal_planner_analyze`
---
## Step 5:模型灵活配置(接口化,禁止写死)
### 入口条件
- [x] Step 4 完成
### 执行项
- [x] 新建后端配置接口:`backend/app/api/model_routing.py`
- [x] 新建后端服务:`backend/app/services/model_routing_service.py`
- [x] 提供查询接口:按 `function_name` 读取当前生效模型路由
- [x] 提供更新接口:按 `function_name` 更新 `provider/model/api_env/tier`
- [x] 配置持久化到统一配置源(数据库 Integration 或统一配置表)
- [x] `SignalPlannerService` 改为运行时读取 `signal_planner_analyze` 路由配置,不在代码中写死模型
- [x] 保留默认兜底:当配置缺失时走安全默认路由,但记录告警日志
- [x] 增加权限控制:仅管理员可修改模型路由配置
- [x] 增加审计:每次配置变更写 `operation_log`
### 完成标志
- [x] 通过接口切换模型后,Planner 无需改代码即可生效
- [x] 业务代码中不存在写死的 `signal_planner_analyze -> GLM-5` 绑定
---
## Step 6:前端展示与侧边栏新增功能
### 入口条件
- [x] Step 5 完成
### 执行项(Signal 展示)
- [x] 修改 `backend/app/api/sstc.py` 返回 planner 字段与 `strategic_analysis`
- [x] 修改 `frontend/src/api/sstc.ts` 扩展 `SSTCSignal` 类型
- [x] 修改 `frontend/src/components/sstc/SignalContentHoverCard.tsx`
- [x] `planner_status=pending` 显示“AI 分析中...”
- [x] `planner_status=completed` 显示分析区块
- [x] `planner_status=failed` 不显示分析区块
### 执行项(侧边栏任务包管理)
- [x] 修改 `frontend/src/components/layout/Sidebar.tsx` 增加入口:`增量任务包中心`
- [x] 修改 `frontend/src/components/layout/Sidebar.tsx` 增加入口:`任务包模板管理`
- [x] 修改 `frontend/src/components/layout/Sidebar.tsx` 增加入口:`任务包生成记录`
- [x] 修改 `frontend/src/components/layout/Sidebar.tsx` 增加入口:`契约同步看板`
- [x] 新建页面 `frontend/src/pages/TaskBriefCenterPage.tsx`
- [x] 新建页面 `frontend/src/pages/TaskBriefTemplatePage.tsx`
- [x] 新建页面 `frontend/src/pages/TaskBriefRunsPage.tsx`
- [x] 新建页面 `frontend/src/pages/ContractSyncBoardPage.tsx`
- [x] 修改 `frontend/src/router/index.tsx` 注册新路由
- [x] 新建 `frontend/src/api/taskBriefs.ts`
- [x] 新建后端 `backend/app/api/task_briefs.py`
- [x] 新建后端 `backend/app/services/task_brief_service.py`
- [x] 新增模型路由管理入口:`模型路由配置`
- [x] 新建页面 `frontend/src/pages/ModelRoutingConfigPage.tsx`
- [x] 新建前端 API `frontend/src/api/modelRouting.ts`
- [x] 页面通过接口读取/更新 `signal_planner_analyze` 模型映射
### 完成标志
- [x] 侧边栏 4 个新入口均可访问
- [x] 任务包管理基础流程可跑通
- [x] 模型路由可在前端页面配置并即时生效
---
## Step 7:脏代码/无用代码删减(强制)
### 入口条件
- [x] Step 6 完成
### 执行项
- [x] 清理未使用 imports/variables/functions/components/routes
- [x] 清理重复工具函数与废弃 fallback 分支
- [x] 删除无效 feature flag 与历史临时代码
- [x] 清理无引用 API 封装与页面入口
- [x] 每一处删除前后均有 `FIND_USAGE` 结果留档
### 门禁
- [x] PR 附“删除清单 + 引用扫描结果”
- [x] 删除后构建与回归通过,否则回退该删除批次
### 完成标志
- [x] 无死代码残留在本次改动链路
- [x] 无跨域误删
---
## Step 8:验收与交付
### 入口条件
- [x] Step 7 完成
### 功能验收
- [ ] 飞书触发后信号主链路正常入库
- [x] 30 秒内 `planner_status=completed`
- [x] `strategic_analysis.ai_planner` 非空
- [x] 相同消息补发不重复入队
- [x] 通过模型路由接口切换模型后,Planner 走新模型且结果正常
### 数据库只读验收
- [x] 执行:
- `SELECT planner_status, planner_analyzed_at, strategic_analysis::jsonb->'ai_planner' FROM signals ORDER BY created_at DESC LIMIT 1;`
- [x] 三项均符合预期
### 构建验收
- [x] `python -m py_compile` 通过
- [x] `npm run build` 通过
- [x] `tsc --noEmit` 零错误
### 文档验收
- [x] `MASTER_CONTRACT.md` 同步
- [x] `API_CONTRACTS.md` 同步
- [x] `DATAFLOW.md` 同步
- [x] `CLAUDE.md` 同步
### 交付物
- [x] 变更文件清单
- [ ] 飞书补发记录截图
- [ ] 数据库查询截图
- [x] 侧边栏新增功能截图
- [x] 模型路由接口调用与生效截图
- [x] 脏代码删减清单与 `FIND_USAGE` 证据
### Step 7/8 执行证据(2026-03-12)
- 删除清单:
- `frontend/src/api/modelRouting.ts` 删除零引用方法 `modelRoutingApi.getFunction`
- `backend/app/services/model_routing_service.py` 修复 JSON 浅拷贝导致配置更新不落库
- `backend/app/services/task_brief_service.py` 修复 JSON 浅拷贝导致任务包配置更新不落库
- `backend/app/services/signal_planner_service.py` 增加结构化失败降级与 `25s` 硬超时收敛
- FIND_USAGE(删除前后):
- 删除前:`rg -n "modelRoutingApi\\.getFunction|getFunction\\(" frontend/src` 命中 `frontend/src/api/modelRouting.ts:38`
- 删除后:同命令无输出(0 命中)
- 共享符号追踪:`rg -n "class SignalPlannerService|SignalPlannerService\\.analyze\\(" backend/app` 命中 `signal_planner_service.py` 与 `ai_pmo_kernel_service.py:1695`
- 功能验收样本:
- `signal_id=273`:`elapsed_seconds=30`,`planner_status=completed`,`ai_planner_state=NOT_NULL`
- 重复消息幂等:`source_message_id=dedupe-signal-1773313023` 在 `ingest_events/work_items` 计数均为 `1`
- 模型路由覆盖生效日志:`函数覆盖路由命中:function=signal_planner_analyze, provider=glm, model=qwen-plus`
- 截图产物:
- `docs/task_briefs/sidebar_new_entries_20260312.png`
- `docs/task_briefs/model_routing_override_effective_20260312.png`
- [BOUNDARY: 当前任务未接入飞书真实回调流量,`飞书补发记录截图` 与 `数据库查询截图` 需人工在目标环境补齐]