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