feat: 第二版——接口契约对齐 docs/05,修复静默故障与数据库基线
相对第一版 46fc976 的完整变更。组员迁移对照表见 docs/20。
一、对外契约对齐 docs/05(破坏性,共 4 处,组员需按 docs/20 调整)
1) 配置发布端点改为文档规定的复数资源名:submit→validations、
approve→reviews(需 body decision)、activate→activations、
rollback→rollbacks;第一版这 4 个动词式路径 docs/05 从未定义过。
2) 错误码由 8 个笼统码改为 15 个具体语义码(FORBIDDEN→AGENT_PERMISSION_DENIED、
UNAUTHORIZED→AUTHENTICATION_REQUIRED、CONFLICT→RESOURCE_VERSION_CONFLICT、
RESOURCE_NOT_FOUND→RUN_NOT_FOUND/SESSION_NOT_FOUND 等),
输入类错误状态码 400→422。
3) POST /api/v1/agent-runs 与 GET /api/v1/agent-runs/{run_id} 统一为
{data, meta} 信封(data 内字段名与语义未变)。
4) 错误响应体统一为 {error:{code,message,retryable,field_errors}, meta:{trace_id}},
不再返回 FastAPI 默认的 {"detail": ...}。
二、数据库基线与约束
新增 39 张表的基线迁移(链根)与联合唯一键纠偏(4 张表、删 8 增 4,幂等收敛);
撤下 config_release 的双人复核 CHECK(应用层已允许自审,审核节点保留,
自审如实写入 reviewer_id);记忆 active key 生成列与唯一键;
activate 开始记录 supersedes_release_id 使版本链可追溯。
docs/00 基线未修改,未重命名或删除任何表与字段。
三、修复会静默出错或无报错的缺陷
- 跑完集成测试后平台会静默失去生效配置:清理只删自己创建的版本,却没有恢复被它
顶成 superseded 的原生效版本,且审计一并删除因而完全无痕,表现为所有工具被拒
但没有任何报错。已修清理逻辑并加恢复。
- Worker 单轮异常导致进程退出;记忆抽取调用方的“事务已开始”异常;
召回缓存丢失 degraded 标记;连接时区未生效导致 created_at/updated_at 差 8 小时;
.env 与 os.getenv 密钥来源分裂导致“没有可用的已批准模型端点”。
- 记忆信号识别漏判与跨键误命中;SSE 未带 Accept 的协商行为。
四、功能补齐
记忆链路 P1/P2/P3(抽取、受控词表、召回与缓存、生命周期级联及投影事件)、
fin_* 场内交易只读 ORM 层、agent_intent_config 状态流转并在运行期真正生效、
限流(Redis 固定窗口、故障一律放行)、游标校验、trace_id 中间件、
示例业务 Agent fund_query_demo 与一键端到端验证脚本,以及审计/指纹/迁移状态工具。
五、文档与验证
新增 docs/19(业务 Agent 接入实操)、docs/20(第一版迁移指南)与 docs/evidence 证据;
docs/01/02/06/08/09/17 同步实现现状。
验证结果:ruff 通过、mypy 103 文件无错、unit+contract 447 passed、
integration 29 passed、acceptance_check --production 7 PASS、
demo_agent_e2e 9/9 PASS(含失败关闭反证)。
This commit is contained in:
@@ -72,6 +72,63 @@
|
||||
新增表按 02 DDL 建立;既有表以 49 张指纹审计证明字段未变化。外键完整性不通过新增约束
|
||||
改写既有表,保留由应用 Repository 约束的历史兼容关系;审计范围和限制见 docs/08。
|
||||
|
||||
### 2026-09-09 数据库基线纠偏、空库重建与记忆链路修复
|
||||
|
||||
- [x] DB-1 基线联合唯一键纠偏。
|
||||
根因:`tools/generate_baseline_sql.py` 只按规则列里的"唯一"字样逐字段生成 `UNIQUE KEY`,
|
||||
无法表达文档中的 `唯一键 (a, b)`。受影响表:`fin_market_price`、`fin_nav_history`、
|
||||
`fin_holding`、`sys_customer_assignment`——会导致场内日线与净值每产品只能存一行、
|
||||
持仓每客户只能有一个产品。修复:生成器支持联合唯一键;迁移 `20260909_constraint_fix`
|
||||
删 8 个错误单列唯一键、加 4 个联合唯一键,并做成**幂等收敛**(空库重建时自动跳过)。
|
||||
纠偏时四张表均为 0 行。证据:`docs/evidence/20260909-before-constraint-fix.sql`、四份结构指纹、
|
||||
约束差异 12 → 0、指纹差异恰好 4 张表。`docs/00` 未做任何修改。
|
||||
- [x] DB-2 审计盲区补强。
|
||||
`tools/schema_fingerprint.py` 指纹纳入索引/唯一键与外键(此前只对字段做指纹,查不出约束漂移);
|
||||
新增 `tools/audit_constraints.py` 做"文档唯一键 ↔ 库唯一索引 ↔ ORM 列名"三向比对;
|
||||
`tools/audit_schema.py` 不再硬编码数据库凭据(改读 `.env`)。
|
||||
- [x] DB-3 空库重建(方案 A)。
|
||||
新增基线初始迁移 `20260909_baseline_schema`(39 张基线表),原链首 `20260909_agent_platform_v31`
|
||||
改接其后。空库 `alembic upgrade head` 建出 51 张业务表,与既有库结构指纹 **0 差异**;
|
||||
既有库无需额外操作(版本记录已位于新链上)。
|
||||
- [x] MEM-1 记忆链路打通。
|
||||
`WorkerRuntime` 注册 4 个 handler;消费者改为按 `message_id` 回查 `conversation_message`
|
||||
取权威正文(事件仍只带定位信息,不落正文);`event_id` 作为证据幂等键;修复冲突记录自引用
|
||||
与库列名不符;迁移 `20260909_memory_active_key` 补生成列与唯一键。
|
||||
证据:`tools/memory_chain_probe.py` 全项 PASSED,见 `docs/evidence/20260909-memory-chain-acceptance.md`。
|
||||
- [x] MEM-2 ORM 映射漂移归零。47 条不一致全部对齐,`tools/audit_constraints.py` PASSED。
|
||||
- [x] FIN-1 场内交易只读层。新增 `app/model/fund.py` 与 `app/repository/fund_query_repository.py`:
|
||||
无任何写方法、返回冻结快照防止回写、客户范围 fail-closed、组合式查询与注册式扩展点。
|
||||
- [x] MEM-3 记忆抽取 P2(模型严格 JSON、语义 `memory_key` 词表、事件驱动触发)。
|
||||
新增 `app/service/memory_extraction_service.py` 与受控词表 `app/service/memory_taxonomy.py`;
|
||||
抽取失败关闭(JSON 非法、键不在词表、置信度越界一律不落库);触发判定改为显式信号 + 业务事件驱动。
|
||||
复核中发现并修复信号识别三类缺陷(宽泛"偏好"造成跨键重叠误命中、模式过于字面造成漏命中),
|
||||
配 11 个回归测试。P2 还引入过一个真实回归:`_execute_claimed` 在同一 Session 上先做只读查询触发
|
||||
autobegin,使 `complete_run` 抛 "A transaction is already begun on this Session",已改为独立
|
||||
Session 查询并补上失败堆栈日志。
|
||||
证据:`tools/memory_chain_probe.py` 全项 PASSED,含"抽取模型被真实调用、记忆键来自受控词表、
|
||||
记忆内容是抽取的结构化值而非用户原文"。
|
||||
- [x] MEM-4 记忆 P3(召回、episode 聚合、级联失效)。
|
||||
新增 `app/service/memory_recall_service.py`、`app/service/memory_lifecycle_service.py`、
|
||||
`app/model/episode.py`、`app/worker/episode_worker.py`,并补齐 53 个专项单元测试
|
||||
(召回 17 例、生命周期 10 例、episode 16 例、模型向量化 10 例)。
|
||||
接线(此前这三个服务零调用点,实为死代码,目标要求的"接线"当时并未达成):
|
||||
· 召回——`PlatformGovernance.recall` 改走 `MemoryRecallService`,`bootstrap` 组装并注入
|
||||
`recall_factory`;Redis 缓存与**语义通道**均已接入:模型网关新增 OpenAI-compatible
|
||||
`/embeddings` 能力(`ModelEmbeddingService` + `ModelDispatchService.embed`,与文本生成
|
||||
同族的受控降级),组装层在 Milvus 可达时传入 `vector=` 与 `embed=`;缺 embedding 端点时
|
||||
向量化失败关闭、保留结构化召回并标记 `embedding_failed`(配置缺口,非功能缺失);
|
||||
· episode——`WorkerRuntime` 每 30 轮顺带聚合一次已静默会话片段,实测 `inserted=1 persisted_rows=1`;
|
||||
· 级联——注册 `memory.deletion_requested` handler → `MemoryLifecycleService.run`,
|
||||
实测 `memory_status=invalidated` 且审计恰好 1 行。
|
||||
接线暴露并修复的三个真实缺陷:
|
||||
· `EpisodeWorker` 只 `flush` 不提交,接线方漏 commit → 出现"报告插入成功但表里没有行";
|
||||
· 召回缓存命中时丢失降级状态(写入含 `degraded`,读取硬编码 `False`);
|
||||
· `recall_with_decay` 中 `Decimal * float` 抛 `TypeError`(该路径此前从未被真实数据触发)。
|
||||
|
||||
验证汇总:`pytest` unit+contract 140 passed / integration 19 passed;Ruff 通过;MyPy strict
|
||||
91 文件通过;`tools/audit_schema.py` 51 张业务表通过;`tools/audit_constraints.py` PASSED;
|
||||
记忆链路探针 PASSED;空库重建与既有库结构 0 差异。
|
||||
|
||||
状态只允许使用:
|
||||
|
||||
- `[ ]` 未开始
|
||||
@@ -125,6 +182,15 @@
|
||||
- [x] 合并组员使用说明书。
|
||||
新增 `docs/14-Agent组员统一接入说明书.md`,作为业务组员唯一推荐入口,整合启动、注册、公共执行链、
|
||||
模型、意图、工具、适当性、行情、禁止事项和验收命令;09、11 保留作为详细历史参考。
|
||||
- [x] 发布组员详细开发与代码说明手册。
|
||||
新增 `docs/15-Agent组员详细开发与使用手册.md`,补充项目分层、关键源码解释、BaseAgent 执行链、
|
||||
模型/工具/行情/适当性代码示例、HTTP 恢复、错误处理、测试和交接模板,供组员及其 AI 完整阅读。
|
||||
- [x] 发布组员入门易懂版说明。
|
||||
新增 `docs/16-Agent组员入门易懂版说明.md`,用机场类比和逐步代码示例解释 Agent、Factory、BaseAgent、
|
||||
工具、行情、适当性、配置、错误和测试,适合首次接入的组员及其 AI 阅读。
|
||||
- [x] 发布接口文档易懂说明。
|
||||
新增 `docs/17-接口文档易懂说明.md`,用请求示例解释 REST/SSE、JWT、幂等、运行、会话、管理、运维接口、
|
||||
错误处理和 A/B 类业务扩展,明确与《05-接口文档.md》的权威关系。
|
||||
|
||||
- [x] 完成 MVC+S 底座设计。
|
||||
- [x] 完成 BaseAgent、AgentFactory、记忆、Neo4j、配置中心和模型路由设计。
|
||||
@@ -580,7 +646,7 @@ alembic upgrade head
|
||||
- [ ] 实现模型路由:按 Agent、意图、租户、场景和故障状态选择模型,并支持受控降级。
|
||||
- [ ] 实现 Prompt、意图、工具白名单、禁止表达和回复模板的版本绑定。
|
||||
- [ ] 配置激活、回滚和模型切换必须写审计,并通过 Outbox 通知 Worker 和缓存层。
|
||||
- [ ] 验收:有效版本唯一;创建人不能审核自己;旧配置不会被正在运行的任务无意替换;密钥不出现在接口响应和日志中。
|
||||
- [ ] 验收:有效版本唯一;审核节点不可跳过(单管理员下允许创建人自审);旧配置不会被正在运行的任务无意替换;密钥不出现在接口响应和日志中。
|
||||
|
||||
### D7. 运行可靠性和公共测试
|
||||
|
||||
@@ -632,6 +698,33 @@ alembic upgrade head
|
||||
|
||||
## 十六、已完成任务记录
|
||||
|
||||
```text
|
||||
任务编号:DB-1 / DB-2 / DB-3 / MEM-1 / MEM-2 / FIN-1
|
||||
负责人:底座负责人
|
||||
完成日期:2026-09-09
|
||||
实际修改文件:tools/generate_baseline_sql.py、tools/audit_constraints.py(新增)、
|
||||
tools/audit_schema.py、tools/schema_fingerprint.py、tools/generate_baseline_migration.py(新增)、
|
||||
tools/memory_chain_probe.py(新增)、alembic/versions/20260909_baseline_schema.py(新增)、
|
||||
20260909_constraint_fix.py(新增)、20260909_memory_active_key.py(新增)、
|
||||
20260909_agent_platform_v31.py、alembic/baseline_generated.sql、app/model/memory.py、
|
||||
app/model/configuration.py、app/model/conversation.py、app/model/platform.py、
|
||||
app/model/fund.py(新增)、app/service/memory_service.py、app/worker/runtime.py、
|
||||
app/worker/memory_extraction_worker.py、app/repository/fund_query_repository.py(新增)、
|
||||
docs/02、docs/08、docs/evidence/*
|
||||
测试命令:python -m pytest -q tests/unit tests/contract;python -m pytest -q tests/integration;
|
||||
python -m ruff check app tests tools alembic;python -m mypy app;python tools/audit_schema.py;
|
||||
python tools/audit_constraints.py;python tools/memory_chain_probe.py
|
||||
测试结果:140 passed / 19 passed;Ruff 通过;MyPy strict 通过;51 张业务表审计通过;
|
||||
约束审计 PASSED;记忆链路探针 PASSED;空库重建与既有库结构指纹 0 差异。
|
||||
数据库变更:新增迁移 3 个(基线初始、约束纠偏、记忆生成列);删除 8 个错误单列唯一键、
|
||||
新增 4 个联合唯一键、新增 memory_unit.active_memory_key 生成列与唯一键。
|
||||
未重命名或删除任何既有表与既有字段,docs/00 基线文档未修改。
|
||||
接口变更:无 HTTP 接口变更。
|
||||
未完成项:记忆 P2(进行中)、记忆 P3(未开始);真实模型端点仍未配置
|
||||
(model_endpoint_config 为 0 行,空端点时会按设计失败关闭,因此零配置环境无法端到端跑通 Agent)。
|
||||
阻塞与决策:无。
|
||||
```
|
||||
|
||||
```text
|
||||
任务编号:D9 / 底座负责人专项收口
|
||||
完成日期:2026-09-09
|
||||
@@ -701,6 +794,9 @@ alembic upgrade head
|
||||
修改文件:app/service/config_release_service.py、tests/integration/test_config_release_mysql.py、TODO.md
|
||||
验证结果:真实 MySQL 配置生命周期 1 passed;全量 38 passed;Ruff/MyPy 通过;schema audit 通过。
|
||||
已验证:创建人不能审核自己;激活只有一个 active;旧版本变为 superseded;回滚记录 rollback_of_release_id;激活和回滚缓存失效 Outbox;四类配置审计。
|
||||
> 后续变更(2026-09-10):**取消双人复核**。单管理员部署下允许创建人自审,数据库约束
|
||||
> `chk_config_release_separation` 已由迁移 `20260910_drop_review_separation` 撤下。
|
||||
> 上面这行描述的"创建人不能审核自己"是当时的行为,已不再成立。
|
||||
修复缺陷:回滚前先 flush 释放 active_slot;回滚状态使用基线允许的 superseded;自增实体不再显式写 id=0。
|
||||
数据库变更:无。
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user