Commit b9495f57b70136ea1e2b22d52ab488fe75f74d77
1 parent
514ec3d5
docs(27-P3C): §十六 批 5 实施记录(第 1-2 步)
记两条这一批换来的东西:
1. 加列时把 CREATE INDEX 写进建表块,会让**所有存量库一启动就炸** ——
建表块先于迁移块执行,存量库上 CREATE TABLE IF NOT EXISTS 是 no-op,
索引引用的那一列还不存在。而新建库(单测默认路径)完全正常。
由此得到一条可复用的规矩:凡是加列,必须同时测「存量库重启」那条路 ——
新建库的路径由每个单测天然覆盖,存量库那条没人走,而生产上只有存量库。
2. 回填沿用原 taskId 而不是新发:conversations/task-{taskId} 是目录名、
汇报链路按它查找、summary 里互相引用。换 id 等于把引用全断掉,
而回填的目的恰恰是别让历史消失。
并记下第 3 步动手前的前提:/task/dispatch 的 URL 与请求体印在
tools-base.md 里(所有 agent 的工具说明),一个字不能改;而 agent-chat.js
在 8-19 被另一个会话大改过,预研写在那之前,所以要重新读现状再动手。
顺带记一处过期且已咬过人的:tools-base.md 印的是 localhost:3000,
实际端口是 3010 —— 回填出来的派单正文里有人手写「端口 3010,不是 3000」
在纠正它。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Showing
1 changed file
with
62 additions
and
1 deletions
docs/todo/system-design/27-p3c-goal-task-model.md
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | 2 | ||
| 3 | > **所属**: [27 Graph Agent 架构](./27-graph-agent-architecture.md) 的 **P3 收尾**(P3C),直接续 [27-P3/P4 执行控制台](./27-p3-p4-work-graph-console.md) §四.B 与 [27-P3B 真跑跑道](./27-p3b-real-run-runway.md)。 | 3 | > **所属**: [27 Graph Agent 架构](./27-graph-agent-architecture.md) 的 **P3 收尾**(P3C),直接续 [27-P3/P4 执行控制台](./27-p3-p4-work-graph-console.md) §四.B 与 [27-P3B 真跑跑道](./27-p3b-real-run-runway.md)。 |
| 4 | > **日期**: 2026-08-18 | 4 | > **日期**: 2026-08-18 |
| 5 | -> **状态**: **批 1-4 已实施并全绿**(见 §十三 / §十四 / §十五 实施记录)。批 5 未开工,预研方案已就绪。开放问题已全部关闭。 | 5 | +> **状态**: **批 1-4 已实施并全绿**(§十三 / §十四 / §十五)。**批 5 进行中**(§十六:第 1-2 步已落地,第 3-6 步未做)。开放问题已全部关闭。 |
| 6 | > **⚠️ 批次与 phase 的对应不是一一对齐的**,判断「这份能不能搬进 done」时按批看,别按文档名看: | 6 | > **⚠️ 批次与 phase 的对应不是一一对齐的**,判断「这份能不能搬进 done」时按批看,别按文档名看: |
| 7 | > · **批 1-3 = 真正的 P3 收尾**(goal/task 两级模型 + `task-planning` + 排队),本文档的主体; | 7 | > · **批 1-3 = 真正的 P3 收尾**(goal/task 两级模型 + `task-planning` + 排队),本文档的主体; |
| 8 | > · **批 4(并行)归 [27-P4](./27-p4-parallel-and-artifacts.md) §一.3**,那边是设计权威,本文档只服从(见 §五.2 的警示块); | 8 | > · **批 4(并行)归 [27-P4](./27-p4-parallel-and-artifacts.md) §一.3**,那边是设计权威,本文档只服从(见 §五.2 的警示块); |
| @@ -1065,3 +1065,64 @@ manual,授权早就给过了,让它自己接回来是**兑现人刚才那次 | @@ -1065,3 +1065,64 @@ manual,授权早就给过了,让它自己接回来是**兑现人刚才那次 | ||
| 1065 | 2. **机器级闸门仍然不存在**:`SessionPool` 没有 `maxSessions`,`task-queue.js` 另有个 `MAX_CONCURRENT=3` | 1065 | 2. **机器级闸门仍然不存在**:`SessionPool` 没有 `maxSessions`,`task-queue.js` 另有个 `MAX_CONCURRENT=3` |
| 1066 | 抢同一台机器。批 4 只放开了公司级额度(硬上限 20),机器压不压得住没有任何守卫。 | 1066 | 抢同一台机器。批 4 只放开了公司级额度(硬上限 20),机器压不压得住没有任何守卫。 |
| 1067 | 3. 批 5(两套任务体系统一)未开工,预研方案已就绪。 | 1067 | 3. 批 5(两套任务体系统一)未开工,预研方案已就绪。 |
| 1068 | + | ||
| 1069 | +--- | ||
| 1070 | + | ||
| 1071 | +## 十六、批 5 实施记录(2026-08-19/20,进行中) | ||
| 1072 | + | ||
| 1073 | +> 体例同 §十三~§十五。**本节随批 5 推进增量补写**,未做的步骤明确标出来。 | ||
| 1074 | + | ||
| 1075 | +### 16.1 进度 | ||
| 1076 | + | ||
| 1077 | +| 步 | 内容 | 状态 | | ||
| 1078 | +|---|---|---| | ||
| 1079 | +| 1 | `tasks` 表吸收 `executor` / `assignee_agent_id` / `parent_task_id` | ✅ `5cd91c3` | | ||
| 1080 | +| 2 | `system/tasklog/*.json` 回填进 `tasks` 表 | ✅ `514ec3d` | | ||
| 1081 | +| 3 | `/task/dispatch` 改写 `tasks` 表(**URL 与请求体一个字不动**) | ⏳ 未做 | | ||
| 1082 | +| 4 | 30 分钟去重从「扫目录」改成一条 SQL | ⏳ 未做 | | ||
| 1083 | +| 5 | `GET /api/tasks` 改读表;删 `TaskService.getAggregatedTasks()` 的会话反推 | ⏳ 未做 | | ||
| 1084 | +| 6 | 调度器只管 `executor='graph'` | ⏳ 未做 | | ||
| 1085 | + | ||
| 1086 | +全量:**131 文件 / 1251 测试全绿**。 | ||
| 1087 | + | ||
| 1088 | +### 16.2 第 1 步踩到的:一个会让**所有存量库开不了**的顺序问题 | ||
| 1089 | + | ||
| 1090 | +第一版把 `CREATE INDEX ... ON tasks(assignee_agent_id)` 写进了建表块。**建表块整体先于迁移块执行**, | ||
| 1091 | +而存量库上 `CREATE TABLE IF NOT EXISTS tasks` 是 no-op —— 表还是批 4 的形态、没有那一列, | ||
| 1092 | +于是这句索引直接抛 `no such column`,`getDb()` 起不来。 | ||
| 1093 | + | ||
| 1094 | +**新建库完全正常**(单测默认走的就是这条路),所以只测新建库根本看不见这个洞。 | ||
| 1095 | +是专门去跑「批 4 形态的库重启一次」才撞出来的。索引已挪进迁移块、排在 ALTER 之后, | ||
| 1096 | +守卫见 `tasks-executor-migration.test.js`。 | ||
| 1097 | + | ||
| 1098 | +> 由此得到一条可复用的规矩:**凡是加列,必须同时测「存量库重启」这条路**。 | ||
| 1099 | +> 新建库的路径由每个单测天然覆盖,存量库那条没人走 —— 而生产上只有存量库。 | ||
| 1100 | + | ||
| 1101 | +已知不对称(写在代码注释里):`ALTER TABLE ADD COLUMN` 加不了 CHECK 也加不了外键, | ||
| 1102 | +所以存量库上 `executor` 的取值域**只由应用层守**,与新建库的 CHECK 不同源。 | ||
| 1103 | + | ||
| 1104 | +### 16.3 第 2 步的关键判断:沿用原 `taskId` | ||
| 1105 | + | ||
| 1106 | +回填时**不新发 id**。理由是引用面:`conversations/task-{taskId}` 是目录名、汇报链路按 taskId | ||
| 1107 | +找回这条派单、summary 里互相引用。换 id 等于把这些引用全断掉,**而回填的目的恰恰是 | ||
| 1108 | +「别让历史消失」**。 | ||
| 1109 | + | ||
| 1110 | +`company_id` 落保留 id `_global`:tasklog 的行**没有 company 这一维**(`from`/`to` 都是本体 id), | ||
| 1111 | +全局 agent 的会话本来就落在这个 id 下(28 §5.1)。刻意不去猜某条派单「其实属于哪家公司」—— | ||
| 1112 | +猜错会让它出现在错误的公司任务列表里,那比「都归 `_global`」更难发现。 | ||
| 1113 | + | ||
| 1114 | +实跑:4 条派单全部回填成功、零失败;再跑一次全部跳过、零新增。 | ||
| 1115 | + | ||
| 1116 | +### 16.4 第 3 步(下一步)的前提,动手前必须先核实 | ||
| 1117 | + | ||
| 1118 | +`POST /api/agent/task/dispatch` 与 `/task/report` 的 **URL 与请求体形态一个字都不能改** —— | ||
| 1119 | +它们印在 `packages/agent-core/base/common/tools-base.md` 里,是**所有 agent 的工具说明**, | ||
| 1120 | +改它等于同时改所有 agent 的提示词。 | ||
| 1121 | + | ||
| 1122 | +而 `server/routes/agent-chat.js` 在 2026-08-19 被另一个会话大改过(会话回收 / `IdleTimer` / | ||
| 1123 | +`CALL_KINDS` / 进程泄漏修复,见 `310a2b2` / `2092a2e` / `b0b2b62`)。**预研是在那之前写的**, | ||
| 1124 | +所以第 3 步动手前要重新读一遍现状,而不是照预研的描述改。 | ||
| 1125 | + | ||
| 1126 | +> 顺带记一处过期:`tools-base.md` 里印的是 `http://localhost:3000`,而实际端口是 **3010** | ||
| 1127 | +> (`server/config.js`)。已经真咬过人 —— 回填出来的派单正文里有人手写了「端口 3010,不是 3000」 | ||
| 1128 | +> 来纠正它。这一处该在第 3 步一起改(改的是端口不是契约形态)。 |