251 lines
10 KiB
Markdown
251 lines
10 KiB
Markdown
# 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=dashscope, model=qwen-plus`
|
||
- 截图产物:
|
||
- `docs/task_briefs/sidebar_new_entries_20260312.png`
|
||
- `docs/task_briefs/model_routing_override_effective_20260312.png`
|
||
- [BOUNDARY: 当前任务未接入飞书真实回调流量,`飞书补发记录截图` 与 `数据库查询截图` 需人工在目标环境补齐]
|