Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
228cf74468 | ||
|
|
0f5df5147e | ||
|
|
b3ca409cfc | ||
|
|
4a3ca0eb5a | ||
|
|
9a46785ee0 | ||
|
|
cc54cdac76 | ||
|
|
b37f45ff61 | ||
|
|
077ebdf184 | ||
|
|
e986a85436 | ||
|
|
19b77a28bc | ||
|
|
3a82eec74c | ||
|
|
352b7aa540 | ||
|
|
a379a9fbe6 | ||
|
|
0f6d6974ef | ||
|
|
3947a12700 | ||
|
|
3e43193f45 | ||
|
|
1f8ad3b99b | ||
|
|
9206e0d77c | ||
|
|
238f90e92a | ||
|
|
d3c9b4554e |
@@ -0,0 +1,86 @@
|
||||
# 智能体工作流质量改进:诊断、裁定与分期计划
|
||||
|
||||
状态:**已获实施授权(2026-10-09,六项裁定见 §3)**;owner:weichen;
|
||||
主任务:Dev 仓 `feature/agent-quality-phase01`(Phase 0+1 首个增量)。
|
||||
撰写日期:2026-10-09。诊断依据:dev 实例真实运行转录(PG pg1 13 次 run + 旧
|
||||
SQLite 53 次,共 62 条助手消息、263 次工具调用;模型 MiniMax-M2.7-highspeed,
|
||||
direct 入口),对照本机 ZCode v3.14.3 源码与 codex/opencode/pi/Kimi CLI/Cursor
|
||||
公开资料(2026-10-09 抓取)。诊断证据级别 SELF(本地观察与复算)。
|
||||
|
||||
本文件是该改进方向的主记录:目标、裁定、分期与验收以本文为准;
|
||||
各阶段实施细节与结果记在对应任务卡,不回写复述。
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题陈述
|
||||
|
||||
与 codex / pi / kimi / cursor / zcode / opencode 相比,本系统直连对话路径在
|
||||
「工作细致、详细、完善」上存在可测差距。真实转录中定位到的失败链(均已复核):
|
||||
|
||||
1. **信息逐轮衰减**:跨轮上下文由界面消息有损重建——工具结果只回放 160 字
|
||||
摘要、参数截断、二进制原件占位、思考内容丢弃;上传材料只在「本轮」注入。
|
||||
后续轮次在摘要的摘要上工作,细节靠编造补齐(实测:「详细方案」中 85%/95%
|
||||
准确率、8000–10000 字等数字在原始转录中不存在;日期星期错配)。
|
||||
2. **修改模型倒挂**:交付物由一次性整段生成脚本产出(docx 无源文件),任何
|
||||
修改=整篇重写重跑(实测一轮 24 次工具调用 9 次失败、6KB 脚本重跑 8 次)。
|
||||
3. **检查失效且误报**:终轮评分的 lint 子进程无 PYTHONPATH 而静默失败(同一
|
||||
docx 带 PYTHONPATH 9 个 error,评分器里 0 个);终轮检查重评已被替代的旧
|
||||
工件导致死循环;可读性规则把表格单元格「项目概述撰写」判成栏目式标题;
|
||||
历史工件渲染格式 `[产出工件 …]` 与伪造标记检查同形,模型照抄即被拦。
|
||||
4. **最终答复与事实脱节**:composeFinal 只见 160 字摘要,产出了不存在的章节
|
||||
列表和「我会调整后再提交」类未兑现承诺。
|
||||
5. **过程性根因**:无任务级评测。任务卡验证=单测+mock,真实模型被列为非目标;
|
||||
evalgold 只有 1 条规则,eval/ab.go 无运行记录。
|
||||
|
||||
## 2. 根因归纳(按影响排序)
|
||||
|
||||
1. 上下文保真度不足(影响最大)——产品没有把内核的追加式会话记录当权威上下文。
|
||||
2. 工具与修改流程不适合交付物领域——没有「读源码→精确改→编译→看诊断」的对应物。
|
||||
3. 质量控制是事后把关而非让模型自己做好,且把关本身不可靠。
|
||||
4. 行为指引薄弱(何时建计划/失败换路/坚持到完成),工具描述只有一行。
|
||||
5. 没有以真实模型结果为准的评测回路。
|
||||
|
||||
内核能力(read/edit/grep/glob、超长落盘、压缩、会话树)大多已在 agent-native
|
||||
就位,问题主要在产品组装层(`modules/backend/internal/runtime|ctxasm|quality`)。
|
||||
|
||||
## 3. 用户裁定(2026-10-09,授权实施)
|
||||
|
||||
| # | 事项 | 裁定 |
|
||||
|---|---|---|
|
||||
| 1 | 直连对话开放工具与能力 | **开放,尽可能实现和开放所有的工具和能力**(推翻 2026-09-30 预览案「fs 工具实现但不默认提供」的默认关闭裁定) |
|
||||
| 2 | 跨轮上下文以内核会话记录为准 | **同意**(重新生成/排除/回滚映射为会话树分支操作) |
|
||||
| 3 | 交付物 Markdown 源码化 + 构建器 | **可以,但必须保留生成各类文件(docx/xlsx/pptx/pdf/图片等)的能力** |
|
||||
| 4 | composeFinal 与关键词评分降级 | **按建议**:Phase 2/3 落地后 composeFinal 默认关闭(仅异常兜底);关键词评分移出拦截路径、只作评测指标 |
|
||||
| 5 | 更强模型评测 | **可以,预算无上限** |
|
||||
| 6 | 行为面改动须附真实模型评测 | **按建议**:写入 Dev 仓 policy/delivery.md |
|
||||
|
||||
## 4. 分期与验收
|
||||
|
||||
每阶段独立任务卡 + PR;改动提示词/工具/上下文/门禁的 PR 须附 eval/live
|
||||
真实模型前后对照(裁定 6)。评测口径:`modules/backend/eval/live/`
|
||||
(golden 任务集 + 指标:工具失败率、整篇重跑数、是否读原件、计划使用率、
|
||||
检查误报/死循环、终轮与工件一致性、未核实数字)。
|
||||
|
||||
| 阶段 | 内容 | 验收 |
|
||||
|---|---|---|
|
||||
| **P0 评测基线** | eval/live 运行器 + tasks.json + 指标报告;before/after 各跑一次 | 基线报告能复现 §1 失败链 |
|
||||
| **P1 缺陷修复** | §1.3 的检查失效与误报七项 | 检查误报清零;两条死循环链消失 |
|
||||
| **P2 上下文保真** | 内核会话记录为权威跨轮上下文;窗口按模型真实窗口(token,实测校准);被清结果落盘留路径+预览;上传材料持久 `inputs/*.md`;交错思考模型回传 `<think>`;接上 9 段压缩模板 | 后续轮 100% 读原件;「更详细」不整篇重写;未核实数字显著下降 |
|
||||
| **P3 工具开放 + 交付物源码化** | 内核 read/edit/grep/glob 接入直连(沙箱=会话工作区);交付物 = Markdown 源文件 + `housestyle.build` 确定性渲染(自动 lint,诊断指向源行);写入即诊断;`housestyle.api` 签名查询;保留 run_python 全类型生成能力(裁定 3) | 工具失败率 ≤8%;修改请求整篇重建 ≤1 次;API 幽灵调用消失 |
|
||||
| **P4 行为指引** | 基座提示词「工作方法」段(建计划/失败两次换路/先查 API/坚持到完成/结论先行终稿);重写高频工具描述;计划提醒常开;按模型分提示词(先 MiniMax) | 多步任务计划使用率 ≥80%;终稿承诺未兑现清零 |
|
||||
| **P5 门禁精简** | 拦截型检查只留硬事实(工件存在/lint 零 error/引用存在);新增事实一致性检查(数字/日期/人名回溯材料);验证器按需触发+异模型 | 检查死循环 0;未核实数字显著下降 |
|
||||
| **模型 A/B** | 同一评测集换更强主模型对照(裁定 5,无预算上限) | 区分模型与 harness 各自的贡献,输出选型建议 |
|
||||
|
||||
## 5. 不在本文范围
|
||||
|
||||
- 操作系统级沙箱、多租户隔离策略(沿用现状与既有声明)。
|
||||
- 小队(squad)路径的同批改造——先修直连主路径,squad 经 A/B 对照跟进。
|
||||
- AGENTS.md/DESIGN.md 层面的仓库治理变更。
|
||||
|
||||
## 6. 记录与证据
|
||||
|
||||
- 诊断细节与复现命令:2026-10-09 会话记录(本文件只留结论与指针)。
|
||||
- before 基线:`eval-live/before-main-1ebd46e.json`(任务卡 evidence 引用)。
|
||||
- 关联:[Agent 栈总案](2026-10-02-agent-stack-completion.md)(库分期不受本文影响)、
|
||||
[文件预览与保留能力](2026-09-30-file-preview-and-reserved-capabilities.md)(其 §2.3
|
||||
的 fs 工具默认关闭裁定被本文裁定 1 推翻,以本文为准)。
|
||||
@@ -0,0 +1,124 @@
|
||||
# EXT 申请包 · G1:回合内共享检索、命令即工具、项目列表共享与执行后端接口(B-1/B-2/B-3 + B-5②)
|
||||
|
||||
状态:**proposed(2026-10-09)**;owner:weichen;需求依据 = RDM 评审与实施方案 V1.1
|
||||
(`Agent-System-RDM docs/proposals/2026-10-09-V22-review-and-implementation-plan.md` §3.3/§3.4/§5.3,
|
||||
owner 2026-10-09 Q1–Q8 批复;Q4=方案 A,Q2=暂时禁用+隔离档)。
|
||||
撰写日期:2026-10-09。配套:[扩展面兼容与演进](2026-10-01-extension-compat-policy.md)、
|
||||
[EXT 申请包 C1–C7](2026-10-08-ext-c1-c7-rdm-shared-contracts.md)(EXT-6…EXT-12)。
|
||||
|
||||
## 0. 总则
|
||||
|
||||
- 本包四条申请按既有序列顺延 **EXT-13…EXT-16**;最终编号以受理评审为准。
|
||||
- 分期(对齐 RDM 方案 §5.2):B-1(EXT-13)与 B-3(EXT-15)为 **G1 序 4 的硬前置**
|
||||
(成员智能体看不到项目知识 = R04 路径不通);B-2(EXT-14)为 G2/V0.1 端到端的硬前置
|
||||
(对话入口无法触达 `rdm.*`);B-5②(EXT-16)为 G2-8 原型的前置。
|
||||
- SurfaceVersion 影响:EXT-14 触及 `pkg/extension` 导出面(命令规格新字段)→ 需升
|
||||
SurfaceVersion 并同步 surface.txt;EXT-13/15/16 为 internal 行为扩展,不改导出面
|
||||
(EXT-16 若只加 `Options` 字段则属加法,见 §4)。
|
||||
|
||||
## 1. EXT-13(←B-1)回合内共享检索:智能体的检索遵循项目共享授权
|
||||
|
||||
- **场景**:RDM R04/R05——成员 B 的智能体在**回合内**(ReAct 循环的 `knowledge_search`
|
||||
工具与自动知识注入)必须能检索到成员 A 已发布的项目知识;现状只能看到本人 owner 的
|
||||
知识。HTTP 面(`/api/…/search`)已走 `RetrieveShared`(EXT-8 余项,Dev #269/#273),
|
||||
但回合内两条路径仍是 owner-only:
|
||||
- `internal/runmgr/runmgr.go:726-736` `runCtx.Retrieve` → `retriever.Retrieve(ctx, c.run.Owner, q)`(owner-only);
|
||||
- `internal/app/hostcaps.go:64-66` `hostcaps.search`(进程内 `Host.KnowledgeSearch` 底座)→ `pipe.Retrieve(owner)`(owner-only)。
|
||||
结果:同一个成员,页面搜索能看到共享知识,**智能体对话里看不到**——「所有用户的智能体
|
||||
应当能够看到项目级的共享信息」(用户补充材料 §2树1图)走不通。
|
||||
- **希望公开面**:组合根把 EXT-8 适配器(`Server.ProjectAuthz` 同款判定函数)注入
|
||||
runmgr 与 hostcaps:两条检索路径在本人 owner 两路(全文+向量)如常之外,追加
|
||||
「经适配器放行的共享两路」——与 HTTP 面 `rag.Pipeline.RetrieveShared` 完全同一实现与
|
||||
同一授权判定(复用 `sharedVisible`/`SearchKnowledgeShared`,不另造第二套语义)。
|
||||
进程内 `Host.KnowledgeSearch` 同步走共享版。
|
||||
- **为何组合不出**:`RetrieveShared` 已存在,但 runmgr/hostcaps 没有适配器的引用——
|
||||
适配器槽在 `internal/app/hostcaps.go` 的 `projectAuthz`,由组合根在装载扩展后注入
|
||||
Server;runmgr 的构造早于扩展装载,且 `Manager` 无该依赖。下游无法经任何公开面把
|
||||
「按 owner 判定共享」的回调递进回合执行路径。
|
||||
- **兼容方式**:适配器未注册=现状(本人两路);注册后共享命中追加、RRF 融合。
|
||||
不动 `pkg/extension` 导出面,SurfaceVersion 不变。
|
||||
- **验收**:同项目两人+另一项目一人(RDM 成员表桩):成员 B 发起对话,模型经
|
||||
`knowledge_search` 命中 A 已发布的知识切片(共享命中出现在工具结果);未授权者与
|
||||
跨项目者为零命中;`Host.KnowledgeSearch`(hostapi 与进程内两形态)行为一致;
|
||||
未注册适配器时与现状逐字节一致(回归)。
|
||||
|
||||
## 2. EXT-14(←B-2)插件命令即工具:`exposeAsTool`(Q4 方案 A)
|
||||
|
||||
- **场景**:RDM V0.1 端到端(C-11)要求「从空项目创建到生成项目建议书,全对话完成」;
|
||||
RDM 的全部能力(两树一网读写、上传、起草、追溯查询)都登记为 `rdm.*` 命令,而智能体
|
||||
回合的工具清单里没有任何插件命令——模型既不能检索笔记树,也不能发起 `rdm.draft.compose`。
|
||||
U0 §3.3/方案 §3.3 裁定走**方案 A**:命令经命令总线暴露为工具,四入口同源
|
||||
(button/card/slash/chat)自然延伸出第五入口「智能体」。
|
||||
- **希望公开面**:命令规格(`agentcommand.CommandSpec` 经 `Registry.AddCommandHandler`
|
||||
登记的 JSON)新增可选字段 `"exposeAsTool": {"risk": "low|medium|high"}`(缺省不暴露)。
|
||||
runmgr 装配工具清单时,把带该字段的命令投影为工具描述(名称=命令 id,参数=命令
|
||||
paramsSchema);模型调用该工具时,**不分发为工具执行,而是构造 `cmdbus.Request` 经
|
||||
命令总线分发**(Entrance="agent",Actor=会话 owner,ConversationID=当前会话)——
|
||||
同一审计信封、同一 HITL 内联确认卡(`risk=high` 或命令规格要求确认时照常弹卡)、
|
||||
同一危险分级。
|
||||
- **为何组合不出**:`Registry` 只有 AddSkill/AddCommand/AddCommandHandler/Note/
|
||||
RegisterResourceAuthorizer;工具注册表(`tools.Registry`)与命令总线之间没有任何
|
||||
桥接;MCP 通道(方案 B)绕过命令总线与确认卡,与 SR-E6/HITL 门禁冲突,已被 Q4 否决。
|
||||
- **兼容方式**:`pkg/extension` 命令规格加可选字段=导出面加法,SurfaceVersion 升
|
||||
(建议 2.6.0-experimental)+ surface.txt 同步。缺省(不写 exposeAsTool)=现状零差异。
|
||||
- **验收**:带 `exposeAsTool` 的 `/rdm.ping` 出现在模型工具清单且调用返回回执,
|
||||
审计信封 Entrance="agent" 与按钮入口同源;`risk=high` 的暴露命令在对话内触发内联
|
||||
确认卡;不带字段的命令不出现;RDM 侧 `rdm.trace`/`rdm.baseline` 等只读命令可在
|
||||
回合内被模型调用(成员 B 场景结合 EXT-13)。
|
||||
|
||||
## 3. EXT-15(←B-3)项目列表与建会话的共享放行(SR-G10)
|
||||
|
||||
- **场景**:RDM R03——成员 B 被加入项目后「界面自动出现该项目,可直接开始工作(新建
|
||||
对话)」。基座 `projects` 表按 owner 硬隔离(`store/projects.go:22-34`):
|
||||
- `GET /api/projects`(`server.go:438-441` `listProjects`)只返回本人 owner 的项目——成员看不到共享项目;
|
||||
- `POST /api/projects/{id}/conversations`(`store/projects.go:124-130`)校验「项目属于请求者」——成员在共享项目下建会话被 404。
|
||||
EXT-8 已放行的入口(工件三入口、SSE 项目流、检索)不含这两处。
|
||||
- **希望公开面**:这两处入口在 owner 自有判定未命中时咨询同一 EXT-8 适配器:
|
||||
`listProjects` 追加经适配器放行的项目(去重、标注 `shared: true` 字段供前端区分
|
||||
展示);`CreateConversation` 的归属校验放宽为「本人自有 **或** 适配器放行」。会话
|
||||
本身仍归属创建者(owner 不变),只是创建权扩展到成员。
|
||||
- **为何组合不出**:`ListProjects(owner)` 的 SQL 按 owner 过滤,无回调;建会话校验在
|
||||
store 层硬编码。与 C4(EXT-8)同因:纯下游无法改变基座 owner 过滤。
|
||||
- **兼容方式**:未注册适配器=现状;放行结果带审计。internal 行为扩展,SurfaceVersion
|
||||
不变。
|
||||
- **验收**:成员 B 的 `GET /api/projects` 含共享项目(shared 标注)且不含未授权项目;
|
||||
B 在共享项目下 `POST conversations` 成功、会话 owner=B;撤销成员后两者立即拒绝;
|
||||
项目拥有者视角无任何变化。
|
||||
|
||||
## 4. EXT-16(←B-5②)执行后端接口:隔离执行档(Q2 阶段二,G2-8 原型)
|
||||
|
||||
- **场景**:Q2 裁定「暂时禁用,但后续执行任务时肯定还是要代码执行能力」。v0.2.0 已
|
||||
交付启动级硬关闭(`Options.DisableExecTools`,Backend #110);隔离档是恢复执行能力的
|
||||
路径:执行的是**模型生成的代码**,须按不可信代码对待(方案 §3.4):只读系统根、仅挂
|
||||
会话工作目录与技能目录、默认无网、cgroup 资源限额、硬超时、按项目 venv 只读挂载;
|
||||
本机已实测 `bwrap --unshare-all` 可用(无特权 userns 被 AppArmor 限制,bwrap 专门
|
||||
策略放行)。
|
||||
- **希望公开面**:`internal/tools/exec_interpreter.go` 的进程启动点抽象为「执行后端」
|
||||
接口(`ExecBackend`:`Run(spec) → result`),启动参数选择后端:
|
||||
`ExecBackend = direct | sandbox`(缺省 direct=现状)。sandbox 后端以 bwrap 实现
|
||||
(资源限额经 systemd-run/cgroup v2)。`extension.Options` 增加
|
||||
`ExecBackend string`(加法;空=direct)。`DisableExecTools` 保留为最终兜底,优先级
|
||||
高于后端选择。
|
||||
- **为何组合不出**:现实现直接 `exec.Command`(`runInterpreter`),无后端抽象;沙箱
|
||||
参数组装(bind 清单、网络命名空间、限额)属平台面,下游插件无法注入。
|
||||
- **兼容方式**:缺省 direct=逐字节现状;`Options` 加字段=SurfaceVersion 升。RDM 在
|
||||
G3-7 才切换 sandbox;G1–G2 期间维持 `DisableExecTools=true`。
|
||||
- **验收**:sandbox 后端下逃逸负例全部被拦——读 `~/.secrets`、读其他会话目录、访问
|
||||
外网、fork 炸弹、超时不可杀均为拒绝/杀灭;会话工作目录内 docx 生成任务成功且产物
|
||||
可登记;direct 后端与现状一致(回归)。
|
||||
|
||||
## 5. 不在本申请包(显式排除)
|
||||
|
||||
- EXT-6/7/10/12 完整形态:仍在 C1–C7 包(EXT-6…12)受理轨道,节奏不变。
|
||||
- 提示词随执行可用性切换(`base.deliverables` 在禁用期的降级文案):基座自有任务,
|
||||
不占 EXT 编号。
|
||||
- UI 仓 nightly runner 修复:与代码无关(rolldown 原生绑定缺失),另立任务。
|
||||
|
||||
## 6. 受理建议
|
||||
|
||||
| 申请 | 内容 | 优先级 | 兼容 |
|
||||
|---|---|---|---|
|
||||
| EXT-13 回合内共享检索 | G1 序 4 硬前置(R04/R05) | **P0 最先** | 不变(internal) |
|
||||
| EXT-15 项目列表/建会话共享 | G1 序 4(R03/SR-G10) | P0 | 不变(internal) |
|
||||
| EXT-14 命令即工具 | G2/V0.1 端到端硬前置(Q4 方案 A) | P1 | 升(加字段) |
|
||||
| EXT-16 执行后端接口 | G2-8 原型(Q2 阶段二) | P1 | 升(加字段) |
|
||||
@@ -0,0 +1,242 @@
|
||||
# 子代理分工、模型分级路由与任务沙箱:调研与方案
|
||||
|
||||
状态:**proposed(2026-10-10)**;owner:weichen;方向来源:用户 2026-10-10 会话
|
||||
(①充分利用子代理;②复杂任务用 dmxapi 的 Sonnet/Opus,常规任务用 MiniMax-M2.7-highspeed;
|
||||
③记录并规划毫秒/亚秒级任务沙箱,**暂不实现**;④对「体感不如 codex/claude code/kimi」的判断)。
|
||||
本文是这四件事的主记录;未经评审的部分一律为「待确认」,不因被记录而视为已批准。
|
||||
|
||||
依据级别:本机实测为 **SELF**(命令与输出见任务卡 evidence 与 §7 复现脚本);外部资料为
|
||||
一手页面抓取(访问日 2026-10-10,URL 在 §8);推断明确标注「推断」。
|
||||
|
||||
## 0. 结论先行
|
||||
|
||||
1. **方向对,落点要改。** 子代理只在「读多写少、可并行、输出冗长」的环节净收益为正;
|
||||
交付物的写作与关键决策保持单线程(单一写者)。把复杂任务**整单**交给 Claude,会把最贵、
|
||||
最慢的模型放在 token 最多的工具循环里——A/B 里 opus-5-5 耗时约 4.7 倍、工具失败更多。
|
||||
证据更支持**按阶段/角色路由**:Claude 只做 token 少、杠杆大的环节(复杂任务的规划简报、
|
||||
终稿综合、独立核查),检索、阅读、抽取、跑 Python、排版留给 MiniMax。
|
||||
2. **「体感差」不能主要归因于 MiniMax。** 同一模型换 harness 的分差与相邻代际换模型同量级
|
||||
(MiniMax-M2.1 换 harness 差 7.0 分;同 harness 换成 Opus 4.5 差 3.9–7.4 分 [H11])。
|
||||
本机实测还发现两处直接拖累体感的协议层问题(§1.2),应先修再下结论。
|
||||
3. **「编造数字」更像模型属性,但可以用机制压住。** 同 harness 下 7→0 支持这一点;但
|
||||
24 个相关观测里「0 处」的 95% 置信上界约 12.5%,不足以宣称清零(§1.3)。数字溯源闸门
|
||||
比换模型便宜,且两者可叠加。
|
||||
4. **沙箱:现在的需求表述里有三处需要修正**(§4.1)——overlay 不是快照、快照只是把冲突
|
||||
推迟到合并、「立即销毁」必须先留存审计材料。修正后,本机条件下 **bwrap + 冻结基底 +
|
||||
overlay** 能做到约 7ms 启动(实测),足够作为默认档;microVM 档只在需要更强隔离时启用。
|
||||
|
||||
## 1. 现状核实(SELF,2026-10-10)
|
||||
|
||||
### 1.1 已有能力(源码,backend `421fee8`,其 deps/agent-native `3b92cb6`)
|
||||
|
||||
| 能力 | 现状 | 位置 |
|
||||
|---|---|---|
|
||||
| 子代理委派 | 模型可调 `delegate_task`,参数 `agent∈{general,explore,research,plan,verify,writer}`、`task`、`background`;深度 1(子不能再派) | `internal/runtime/llm.go:310`、`internal/runtime/llm_direct.go:668`、`internal/runmgr/runmgr.go:1462` |
|
||||
| 子代理模型 | 由画像 frontmatter 决定:`writer` 用 `chat` 档,其余 7 个用 `lightweight` 档;调用方**不能**指定模型 | `internal/prompts/library/agent-sub-*.md`、`internal/runtime/sub_loop.go:48` |
|
||||
| 模型档位 | 只有两档:`models.chat` 与 `models.lightweight`(轻量档空则回落主档),另有 `models.chat.fallbacks` 回退链 | `internal/runtime/model.go:54,84`、`internal/settings/settings.go:73-84` |
|
||||
| 评审/验证 | `review_findings` 并行 1–3 个审查子代理再逐条验证;验证子代理输出 `VERDICT` | `internal/runtime/llm.go:311`、`agent-sub-verify.md` |
|
||||
| LLM 协议 | 后端恒走 OpenAI chat 协议(`openLLMClient` 不设 `Protocol`);内核已实现 Anthropic Messages 客户端(含 `cache_control`)但**产品未接线** | `internal/runtime/llm.go:491`、`deps/agent-native/runtime/llm/anthropic.go` |
|
||||
| 工具并行 | 内核支持 `ExecParallel`,直连路径未设置 → 默认**串行**执行同一回合的多个工具调用 | `deps/agent-native/runtime/loop.go:203,596`、`internal/runtime/llm_direct.go:268` |
|
||||
| 执行隔离 | EXT-16:`run_shell`/`run_python` 可选 bwrap 档(断网、只读根、tmpfs 遮蔽 `/home` `/tmp`、仅会话目录可写、ulimit、超时杀命名空间);缺省 direct | `internal/tools/exec_backend.go` |
|
||||
|
||||
### 1.2 本机实测发现的问题
|
||||
|
||||
| # | 发现 | 影响 | 证据 |
|
||||
|---|---|---|---|
|
||||
| F1 | **子代理结论被压成 160 字**:直连路径 `delegate_task` 只把 `res.Summary` 回给父,而 `Summary` 是子代理全文的前 160 字(全文在 `res.Text` 里,被丢弃) | 子代理做完的检索/调研结论,父代理只看到开头一句;这与「上下文防火墙」的用法正好相反,也会诱发父代理凭摘要补细节 | `llm_direct.go:697-700`、`runmgr.go` finishChild(`Summary = truncate(fullText, 160)`) |
|
||||
| F2 | **MiniMax 思考内容混在正文流里**:OpenAI 兼容流式接口默认把思考放进 `content` 的 `<think>` 块;后端在回合结束时才剥离 | 回合进行中前端收到的 `message.delta` 先是一大段思考原文,界面上「正文」区域先显示推理过程;思考计时也不准。官方提供 `reasoning_split=true`,实测开启后思考改走独立的 `reasoning_content`/`reasoning_details` 字段(3/3 次),TTFT 中位数 0.69s | `llm_direct.go:418-475`;probe2 实测(§7) |
|
||||
| F3 | **sandbox 档下交付物生成跑不通**:python-docx/openpyxl/python-pptx 装在 `~/.local`,被 `--tmpfs /home` 遮蔽;`run_python` 描述里「缺失时 pip install --user」在断网档也失效 | RDM 计划 G3-7 切 sandbox 时,docx/xlsx/pptx 生成会直接失败;EXT-16 的「docx 生成任务成功」验收用的是 `printf` 桩,未覆盖真实库 | bench2/bench3 实测:EXT-16 同形参数下 `import docx` → ModuleNotFoundError;只读挂载依赖层后 `import docx, openpyxl, pptx` 成功 |
|
||||
| F4 | **Claude 走兼容协议丢能力**:经 dmxapi/lmuai 的 OpenAI 兼容接口,4 个 Claude 型号都不返回思考字段;改走 dmxapi 的 `/v1/messages` 原生接口,第二次调用 `cache_read_input_tokens=5043`(缓存生效) | A/B 中 Claude 一侧每步按全价重算前缀、没有思考回传——47 分钟的耗时与工具失败部分可归因于此(推断,需日志确认) | anthropic_probe 实测(§7) |
|
||||
| F5 | 直连路径工具串行 | 模型一次发出多个独立检索时逐个等待;4 个被测模型都能在一个回合里给出 2 个并行 tool_calls | probe 实测(§7) |
|
||||
|
||||
### 1.3 A/B 数据的正确读法
|
||||
|
||||
内部 A/B(`.task/model-ab/ab-opus.json` 对 `.task/phase05-eval/after-p5.json`,4 任务 6 回合):
|
||||
MiniMax 编造数字 7、约 10 分钟、工具 97/失败 19;opus-5-5 编造 0、约 47 分钟、工具 99/失败 33。
|
||||
|
||||
- 样本小且相关:「0 处」的 95% 置信上界约 3/24≈12.5%(rule of three)[R39],不能宣称清零。
|
||||
- 两侧都不在最佳状态:Claude 一侧走兼容协议(F4);MiniMax 一侧思考回传已实现
|
||||
(`context.thinkReplay=auto`,`ctxasm.go:206`),但流式分流有 F2 问题。
|
||||
- 速度:公开测速两者相近(opus-5-5 约 96 t/s [H25],M2.7-highspeed 官方约 100 TPS [H4];
|
||||
本机短文本实测 48.9 对 50.7 t/s),所以 4.7 倍耗时更可能来自思考量、步数、重试与无缓存(推断)。
|
||||
- Vectara 有据摘要幻觉率 M2.7 12.9%、Opus 4.6 12.2%、Sonnet 4.6 10.6% [R40]:「读懂原文」差距
|
||||
不大;差距更可能出在「缺数据时去猜」(推断)。
|
||||
|
||||
### 1.4 其余现状(补充核实,SELF)
|
||||
|
||||
- 评测:`eval/live` 是 go test(env:`AGENT_EVAL_BASE` 实例地址、`AGENT_EVAL_TASKS` 过滤、
|
||||
`AGENT_EVAL_TURN_TIMEOUT`),golden 任务 4 个(`tasks.json`);A/B 工具 `eval/ab.go`、`switch.go`。
|
||||
- 打断/插话:有 `CancelRun`(停止按钮)与子代理中断续跑;**没有**「运行中用户输入排队、
|
||||
当前工具结束后本轮送达」的 steering 队列(未找到实现)。
|
||||
- 检查点:文件写入有改前快照日志(`runmgr/rewind.go` `NoteFileCheckpoint`)。
|
||||
- 直连路径声明 13 个工具;提示词库 base-* 共约 6.7KB(base-deliverables 5.2KB 最大)。
|
||||
|
||||
## 2. 子代理分工:证据与方案
|
||||
|
||||
### 2.1 证据要点(外部,来源见 §8)
|
||||
|
||||
- **有益面**:广度优先检索(Anthropic 多智能体研究系统:主+子比单 Opus 高 90.2%,复杂查询
|
||||
耗时最多降 90%,代价 token 约 15 倍 [R13]);上下文防火墙——18 个模型都随输入变长退化
|
||||
[R14],子代理只回 1–2k token 摘要 [R17];fresh-context 审阅(Devin Review 均 2 bug/PR,
|
||||
58% 严重 [R20])。
|
||||
- **有害面**:写入耦合(并行写手风格冲突,「多代理贡献智能、写入保持单线程」是当前可行解
|
||||
[R19][R20]);顺序任务 −39%~−70%、单代理基线 >45% 时加代理为负收益、无中心校验时误差
|
||||
放大 17.2 倍 [R21];Claude Code 官方也建议迭代密集/共享上下文/延迟敏感时留在主会话 [R1]。
|
||||
- **契约**:委派带目标/输出格式/工具面/边界/预算;回传浓缩结论 + 证据指针(文件/行),
|
||||
大产物落盘只回引用 [R13][R17];限额:禁嵌套、并发 3–5、按复杂度分档 [R7][R13][R21]。
|
||||
|
||||
### 2.2 方案(增量,每项独立任务卡)
|
||||
|
||||
| # | 内容 | 验收(可判定) |
|
||||
|---|---|---|
|
||||
| D1 | **修 F1**:`delegate_task` 回传改为「子代理全文(上限 4k 字)+ 超长落盘 `subagent-result.txt` 只回指针 + 工件摘要行」——内核 `subagent.CapParentText` 已有此语义(backend 侧没走它) | eval/live 前后对照:父代理引用子代理结论的回合,其终稿中来自子代理的事实不再凭摘要补齐;单测覆盖超长截断 |
|
||||
| D2 | **委派简报规范**:`delegate_task` 描述与 base-method 提示补「简报四要素」(目标、输出格式、工具/来源边界、完成判据),禁止把大块原文粘进 task | 提示词 diff + eval/live 计划/委派质量指标不回退 |
|
||||
| D3 | **并行工具执行**:直连路径设置 `ToolExecution=parallel`(读类工具并发、写类串行的区分后续再议) | 同回合多工具调用 wall-time 下降(评测记录);事件序号仍单调 |
|
||||
| D4 | **证据账本子代理**:research/explore 画像的输出格式改为「结论 + 原文引用(文件/页/行)+ source_id」,数字必须带 source_id 或 Python 计算 ID;终稿前由确定性校验拦截(接质量计划 P5 的事实一致性检查) | 编造数字在闸门处被拦且计数;子代理回传含引用率 100% |
|
||||
| D5 | **角色×模型矩阵**(依赖 §3 R2):新增/调整画像的 `model:` 支持 `claude-*` 档;`writer` 保持 chat 档,新增 `composer`(终稿综合)与 `planner-complex`(复杂任务规划简报)画像走强模型档 | 画像 frontmatter 生效(SubagentSpec 解析);评测 A3/A5 组可配置 |
|
||||
|
||||
边界:子代理深度维持 1(现状即禁嵌套);并发上限维持产品侧 3;本方案不引入子代理间通信。
|
||||
|
||||
## 3. 模型分级路由:证据与方案
|
||||
|
||||
### 3.1 证据要点
|
||||
|
||||
- **整单路由不划算**:我们的 A/B 中 opus-5-5 耗时约 4.7 倍、工具失败 33 vs 19;公开测速两者
|
||||
相近(§1.3)。Devin Fusion 的教训:强模型当全程主控只降本 33%,且「判断即交付物」的难题
|
||||
上掉分 [R30][R31]。
|
||||
- **按阶段/角色路由有正证据**:Sonnet 执行 + Opus 顾问 +2.7pp 且降本 11.9%;Haiku + Opus 顾问
|
||||
在 BrowseComp 19.7%→41.2% [R32];Aider「强规划+便宜编辑」$13.29 得 64.0% 胜 o1 单跑 $186.5
|
||||
得 61.7% [R12]。反例也存在(BrowseComp-Plus 上弱编排+强子代理更好 [R21])——**放哪一层必须
|
||||
实测**,这正是 R3 实验的目的。
|
||||
- **协议与缓存**:Claude 经 OpenAI 兼容层不回思考、不支持缓存、忽略 strict(官方文档 [H37],
|
||||
本机 F4 实测缓存恢复);缓存按 tools→system→messages 前缀匹配,中途改工具集会整缓存失效
|
||||
[R35][R36] → 模型切换只应发生在阶段边界,每角色固定 system/tools 前缀。
|
||||
|
||||
### 3.2 方案
|
||||
|
||||
| # | 内容 | 验收 |
|
||||
|---|---|---|
|
||||
| R1 | **Claude 原生协议接线**:`models.chat.protocol = openai-chat \| anthropic`(设置项),anthropic 时用内核现成的 `llm/anthropic.go` 客户端(base 指向 dmxapi `/v1/messages` 根),回传 thinking 块与 signature、挂 `cache_control` 断点、usage 记缓存读写(N3 计费拆分已有字段) | 同会话第二次调用 `cache_read_input_tokens>0`(SELF 复现 F4 的探针即验收集);thinking 块原样回传(删改会 400 [H24]) |
|
||||
| R2 | **角色路由表**:设置新增 `models.<role>`(role∈composer/planner/verifier,缺省回落 chat 档);画像 frontmatter `model: <role或具体型号>`。默认建议:chat=MiniMax-M2.7-highspeed(不变)、composer=claude-sonnet-5(dmxapi,原生协议)、verifier=异模型(deepseek-v4-flash 或 claude)、复杂任务 planner=claude。Opus 系列留给最难任务手动指定 | 角色解析链单测;`models` 列表来自各端点 `/v1/models`(已核实 dmxapi 有 sonnet-4-6/sonnet-5/opus-4-6/opus-5-5 等,见任务卡 evidence) |
|
||||
| R3 | **路由 A/B 实验**(扩展现有 eval/ab.go):组别 A0 全 MiniMax / A2 MiniMax+数字闸门 / A3 A2+Claude 终稿 / A4 A2+Claude 核查 / A5 Claude 规划+终稿+核查、MiniMax 执行;关键组加 Sonnet 变体。指标:无来源数字占比、含编造交付物比例、pass^3、p50/p95 耗时、分角色成本(含缓存)、工具失败分类。样本:30–50 任务×3 次(宣称编造率<5% 需 ≥60 份零编造样本 [R39]);<3pp 差异慎下结论 [R49] | 选型报告入任务卡,来源 GATE/SELF 标注 |
|
||||
| R4 | **升级规则进 harness**(不依赖模型自觉 [R20]):连续 N 次工具失败、闸门拦截无来源数字、检索「未找到」三类事件触发 advisor 咨询或角色升级 | 评测中升级触发可观测;误升级率记录 |
|
||||
|
||||
运维事实(2026-10-10,SELF):lmuai 月额度已耗尽($1303.32/$1300,2026-11-05 重置)——R1/R3
|
||||
的 Claude 侧建议先走 dmxapi(余额 ¥0.48,**需充值**,此前 A/B 卡估算全量对照 ¥50–100)。
|
||||
|
||||
## 4. 任务沙箱:记录与规划(**不立即实现**)
|
||||
|
||||
### 4.1 对原始思路的三处修正
|
||||
|
||||
1. **「overlay 隔离他人变更」不成立**:内核文档明确「下层在挂载期间被修改的行为是未定义的」
|
||||
[S1];本机实测运行中的沙箱能看到下层后续修改(bench2 第 5 段)。**一致视图必须来自不可变
|
||||
基底**(冻结副本或 git commit 物化),而不是叠在活动目录上的 overlay。
|
||||
2. **快照只是把冲突推迟到合并**:Codex cloud/container-use/Cursor 都以 diff/PR 回收,冲突在
|
||||
写回时用基线校验暴露 [S23][S28][S26]。「互不影响」的成本是写回时的三方合并与人工兜底,
|
||||
设计里必须显式包含这一步,否则快照只是把失败挪到了最后。
|
||||
3. **「立即销毁」与审计有张力**:销毁的应是计算资源与可写层;转录、diff、工件哈希、环境
|
||||
清单要按 TTL 封存(Codex 删前存快照 [S23]、container-use 留命令史 [S28]、Cursor 留工件
|
||||
[S26])。本仓的证据门禁(AGENTS.md)同样要求可复核输出——封存记录是硬约束。
|
||||
|
||||
另一处简化:硬链接克隆(cp -al)对「原子替换写入」是安全的(rename 换 inode),但对原地
|
||||
写入会穿透(共享 inode)——本机实测(bench3 第 3 段)。只可作为「可检测」方案并配
|
||||
sha256/mtime 清单复核,不可当作完整快照。
|
||||
|
||||
### 4.2 目标形态(任务工作区沙箱)
|
||||
|
||||
一次任务 = 冻结基底(会话/项目材料的不可变视图)+ 私有可写层 + 确定性依赖层 + 出口管控 +
|
||||
回收(diff 与工件清单)+ 封存后销毁。智能体在其中任意折腾不破坏原始资料;产出经校验写回。
|
||||
|
||||
### 4.3 分层架构与延迟预算(本机实测,SELF)
|
||||
|
||||
| 层 | 机制 | 启动 | 适用 | 备注 |
|
||||
|---|---|---|---|---|
|
||||
| L0 进程沙箱 | bwrap(EXT-16 现状)+ 依赖层只读挂载 | **p50 7.3ms**(/bin/true,n=30);带 overlay 同为 ~7ms | 默认:解释器执行、交付物生成 | 修 F3 后 python-docx 全链路可用(import 60ms、1 页 docx 76ms) |
|
||||
| L0.5 工作区沙箱 | L0 + `--overlay-src <冻结基底> --overlay <宿主upper>` | ~7ms(实测) | **多任务并发、需要一致基底与可回收 diff 时** | upper 即增量;快照语义来自冻结基底而非 overlay |
|
||||
| L1 容器 | docker(overlayfs 驱动) | `run --rm` p50 142ms(redis:7 true,n=10) | 依赖隔离更强、镜像化环境 | 可加 warm pool 压冷启动;单机自托管无障碍 |
|
||||
| L2 microVM | Firecracker/gVisor | 未实测;E2B 等托管方当前文档只称 "fast Linux VM"(量化数字已不可得,**未经证实**) | 不可信代码、最强隔离 | 本机有 /dev/kvm;引入与维护成本高,暂缓 |
|
||||
|
||||
支撑件(与层正交):
|
||||
|
||||
- **冻结基底**:git 材料以 commit SHA 物化(同 SHA 只物化一次、多任务只读共享);非 git 材料
|
||||
用 cp -al + sha256 清单(写回前复核,变了即判基底失效)。git worktree add 实测 192 文件
|
||||
11ms,overlay 直接盖工作树 ~10ms,两者都够快。
|
||||
- **依赖层**:项目 venv / site-packages 只读 bind(实测修复 F3;RDM 方案 §3.4 原有此意)。
|
||||
- **数据库**:SQLite 用 `VACUUM INTO` 取一致快照 [S32];PG 用零连接模板库克隆(PG18 XFS 上
|
||||
有 CLONE,ext4 上是复制 [S11][S37]——量级以库大小为准,必要时评估独立 XFS 卷给 reflink)。
|
||||
- **网络**:默认无网(现状);将来要放开时,按 sandbox-runtime 的形态做出口代理白名单 +
|
||||
代理侧凭据注入(密钥不进沙箱)[S-RT]。
|
||||
- **回收与写回**:沙箱退出后读 upper → 生成 `git diff --binary` 补丁 + 工件 sha256 清单;
|
||||
写回用 CAS(目标当前哈希==基底哈希 → 原子替换;不等 → `git merge-file` 三方合并,冲突停给
|
||||
人);写回前留前像。git 目标用 `update-ref <ref> <new> <old>`(本身就是 CAS)[S46]。
|
||||
- **封存**:base SHA、补丁、工件哈希、转录指针、环境清单(依赖层版本)、退出码,按 TTL 留存
|
||||
后销毁工作区目录。
|
||||
|
||||
### 4.4 与现网的关系
|
||||
|
||||
- EXT-16 sandbox 档是**进程级**隔离(单次命令);本节是**任务级工作区**,两者叠加而非替代。
|
||||
首个落地形态:ExecSpec 增加工作区概念,sandbox 档把「会话目录 bind」换成「冻结基底 overlay
|
||||
+ 私有 upper」。
|
||||
- 已知缺口顺带记录:小队内核 ExecConfig、工作流 ScriptCommand 仍 direct(EXT-16 卡内遗留);
|
||||
沙箱档覆盖它们是前置条件之一。
|
||||
|
||||
### 4.5 非目标与开放问题
|
||||
|
||||
- 不做多租户硬隔离与 OS 级安全声明(沿用质量计划 §5 边界)。
|
||||
- 开放:是否划独立 XFS 卷换 reflink;gVisor 试用;warm pool 是否值得(L0 已 7ms,大概率不值);
|
||||
Windows/macOS 不在范围。
|
||||
|
||||
## 5. 分期与验收总表
|
||||
|
||||
| 增量 | 内容 | 依赖 | 备注 |
|
||||
|---|---|---|---|
|
||||
| E1(P0 快修)✅ | F1 委派回传、F2 reasoning_split、F5 并行工具、F3 依赖层 | 无 | **已完成(2026-10-10)**:Agent-Native #42/#43/#44 + Backend #127 + Dev PR(任务卡 feature/agent-e1-parallel-fixes)。验证:F2 实测正文 0 泄漏、F3 sandbox 实测 IMPORTS-OK、F5 实测同回合并发重叠;eval 对照工具失败 19→11,未核实数字 7→12(E3 待做,见任务卡) |
|
||||
| E2 | R1 Claude 原生协议 + 缓存观测 | E1(F2 同类协议改动可同批) | dmxapi 需充值 |
|
||||
| E3 ✅ | D4 证据账本 + 数字闸门 | 无(接质量计划 P5) | **已完成(2026-10-10)**:Backend #130、Dev #311(任务卡 feature/agent-e3-evidence-gate)。标注感知豁免(分句判定)+ 两轮修正(变化才二拦)+ base.deliverables v6 数字溯源规则 + 子代理引用格式;eval 对照未核实数字 12→5(未标注 3)、工具调用 93→63 |
|
||||
| E4 ✅(R4+账本) | R2 角色路由 + D5 画像 | E2 | **R4 与账本已完成(2026-10-11,MiniMax 版)**:Backend #131–#134、Dev #315(任务卡 feature/agent-e4-escalation-ledger)——滑窗失败提醒(端到端日志实证)、检索空命中提醒、source_id 账本(83 标记);Claude 角色档按模型指示暂缓;eval 四轮对照无恶化 |
|
||||
| E5 ✅(R3 部分) | R3+R4 路由 A/B 与升级规则 | E2–E4 | **R3 已完成(2026-10-10,MiniMax 家族版)**:Dev #313(任务卡 feature/agent-e5-model-ab)三臂对照(hs / 全M3 / hs+M3轻量)——建议默认 chat=MiniMax-M3(未标注编造 1、失败最少、时长持平、单价减半);R4 升级规则仍待做 |
|
||||
| S0-1 ✅ | §4.4 首个落地形态:冻结基底 overlay + CAS 回收 + 变更摘要(--exec-workspace overlay) | 用户 2026-10-11「继续完成下一步」 | **已完成(2026-10-11)**:Backend #135/#136、Dev #318(任务卡 feature/agent-s0-workspace-overlay)——bwrap 集成 3 + live 端到端(失败零落地/新增/修改/-ws 清理);S0-2(fs 联合读/任务级工作区/封存)待授权 |
|
||||
|
||||
## 6. 与既有规划的关系
|
||||
|
||||
- [智能体工作流质量改进](2026-10-09-agent-quality-improvement-plan.md):本文是其「模型 A/B」
|
||||
结论的后续与 P4/P5 的延伸(D4 与 P5 合流;E5 继承 A/B 方法论并扩大样本)。
|
||||
- [EXT 申请包 G1](2026-10-09-ext-g1-b1-b3-exec-backend.md):E1-F3 修复其 sandbox 档的交付物
|
||||
缺口;§4 工作区沙箱是 EXT-16 的演进方向。
|
||||
- [RDM 阶段总案](2026-10-07-rdm-phase-plan.md):G3-7 切 sandbox 前置依赖 F3 修复。
|
||||
- Agent 栈 N2 WP5(子代理/后台派生):D1–D5 在产品层消费其内核端口,不改内核契约。
|
||||
|
||||
## 7. 本机实测的复现要点(SELF,脚本存于任务卡 evidence 同目录说明)
|
||||
|
||||
- 启动延迟:bwrap 命名空间 / +overlay / +持久 upper 各 30 次(bench.sh、bench2.sh §3)。
|
||||
- F2:`reasoning_split=true` 前后各 3 次流式(probe2.py,观察 delta 字段分布)。
|
||||
- F3:EXT-16 同形参数下 `import docx` 失败 vs 只读挂载 `~/.local/.../site-packages` 后成功
|
||||
(bench2 §1–2、bench3 §1–2)。
|
||||
- F4:dmxapi `/v1/messages` 连续两次调用,第二次 `cache_read_input_tokens=5043`。
|
||||
- overlay 非快照:运行中沙箱读到下层并发修改(bench2 §5);cp -al 对 rename 安全、对原地写
|
||||
穿透(bench3 §3)。
|
||||
- docker 冷启动 10 次(bench.sh)。
|
||||
|
||||
## 8. 来源(除标注 SELF 外均为 2026-10-10 抓取的一手页面)
|
||||
|
||||
- [S1] Linux 内核 overlayfs 文档:https://docs.kernel.org/filesystems/overlayfs.html
|
||||
- [S11] BoringSQL instant database clones:https://boringsql.com/posts/instant-database-clones/
|
||||
- [S23] Codex environments/git-worktrees:https://learn.chatgpt.com/docs/environments/git-worktrees
|
||||
- [S26] Cursor cloud agent:https://cursor.com/docs/cloud-agent
|
||||
- [S28] container-use CLI:https://container-use.com/cli-reference.md
|
||||
- [S32] SQLite VACUUM INTO:https://www.sqlite.org/lang_vacuum.html
|
||||
- [S37] PostgreSQL 18 release notes:https://www.postgresql.org/docs/release/18.0/
|
||||
- [S46] git-update-ref:https://git-scm.com/docs/git-update-ref
|
||||
- [S-RT] Anthropic sandbox-runtime(Linux=bwrap+seccomp、网络默认全拒+代理白名单+凭据注入、
|
||||
Apache-2.0):https://github.com/anthropics/sandbox-runtime
|
||||
- [S-CX] Codex sandboxing(Linux 用 bwrap;read-only/workspace-write/danger-full-access):
|
||||
https://learn.chatgpt.com/docs/sandboxing
|
||||
- [H4] MiniMax 定价与速度:https://platform.minimax.io/docs/pricing/overview 、
|
||||
https://platform.minimax.io/docs/guides/text-generation
|
||||
- [H24] Claude thinking 块回传要求:https://platform.claude.com/docs/en/build-with-claude/extended-thinking
|
||||
- [H25] Artificial Analysis(opus-5-5 96.4 t/s 等):https://artificialanalysis.ai/models/claude-opus-5-5
|
||||
- [H37] Claude OpenAI SDK 兼容层限制:https://platform.claude.com/docs/en/api/openai-sdk
|
||||
- [R1][R12][R13][R14][R17][R19][R20][R21][R30][R31][R32][R35][R36][R39][R40][R49] 子代理与
|
||||
路由调研来源清单见任务卡「调研来源」节(Claude Code docs、Anthropic/Cognition 工程博客、
|
||||
arXiv 2512.08296 等,URL 全量随卡保存)。
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
---
|
||||
title: 多人协作存储与分布式演进方案 - Plan
|
||||
type: refactor
|
||||
date: 2026-10-11
|
||||
execution: code
|
||||
product_contract_source: ce-plan-bootstrap
|
||||
---
|
||||
|
||||
# 多人协作存储与分布式演进方案 - Plan
|
||||
|
||||
修订:r1;确认状态:**已批准(2026-10-11 用户指示「按方案开始改造」)**;推进状态:方案获批发布,实施自首选增量 U1+U2 启动;业务实施/迁移/压测/部署仍为 NOT_RUN,逐项以实施任务卡为准。
|
||||
需求来源:2026-10-11 用户要求完善 SQLite、PostgreSQL/pgvector、Redis 分工;随后确认“10–100 人,多人多项目多会话并行,未来支持多服务分布式”。
|
||||
需求负责人:weichen;方案编制:Codex;实施及运维负责人:待指定。更新时间:2026-10-11(Asia/Shanghai)。
|
||||
关联任务:Dev `.task/feature-collaboration-storage-plan.md`(方案任务,已发布);后续 U1+U2 实施由独立任务承接。
|
||||
正文中的源码路径以 Agent-System-Dev 为根;工作包中的 `internal/` 简写指 `modules/backend/internal/`;文内相对链接以本文为根。
|
||||
|
||||
## 1. 推荐结论与边界
|
||||
|
||||
团队部署以 PostgreSQL 作为共享业务状态的唯一权威,pgvector 承担数据库内向量查询,Redis 承担可丢失的缓存与限流。SQLite 保留给个人嵌入式使用、离线工具及可以重建的本机状态,不承载团队共享写入或跨主机运行所有权。
|
||||
|
||||
第一阶段交付单应用实例的可靠团队部署;第二阶段补齐执行所有权、持久命令、共享工件与事件追赶,再开放多个应用实例和 Worker。通过接口和数据归属为服务拆分做准备,当前不要求微服务化、Kubernetes、分片或引入另一套消息中间件。
|
||||
|
||||
“不会出现错误”不能成为无条件承诺。工程目标是:在定义的故障模型下,不静默丢失已确认数据、不覆盖他人的并发更新、不产生未经识别的重复副作用、不越权;异常可发现、可追踪、可恢复。冲突可以返回明确的 409,超载可以返回 429,依赖故障可以返回 503,它们必须有清楚的重试语义。
|
||||
|
||||
本方案是[双档存储 D17–D24](2026-09-30-dual-tier-storage-and-multitenancy.md)的候选增补,批准前不改写原已采纳决策。拟调整的是团队部署的默认与必需条件,以及 D24 原来排除的跨实例执行能力;保留个人 SQLite 档、非容器部署、现有检索契约与序号语义。
|
||||
|
||||
## 2. 当前事实与差距
|
||||
|
||||
源码调查基线:Dev `73c901fa341a3653d6e0826d0da3497507995482`,Backend `eda90ed310f37f7352e24a8096d932dbf320cd73`,Documents `9a46785ee0f19540c79f83b4e4544572b5217ac2`,Agent-Squad `490b0b2dfa1567cb16ff7a7230fd78e52bc2938e`,Agent-Native `c348441691e8bdab784a03aa9be64d53dacff341`。
|
||||
来源均为 **SELF·源码/本机只读观察**;没有真实并发故障重放。命令、对象 SHA 和原始输出见[调查收据](../records/2026-10-11-collaboration-storage-audit-receipt.json),启动收据见任务卡。
|
||||
|
||||
| 对象 | 当前可核实事实 | 方案含义 |
|
||||
|---|---|---|
|
||||
| Dev 运行实例 | `runtime/dev/bin/agent-system`、8788 端口打开 `runtime/dev/data/agent-system.db` 及 WAL;二进制 build revision 为 `017b40f76156905eabe8323ae2bfe800f47fb8bd` | 当前服务确实使用 SQLite;运行版本与上述源码基线不同,源码缺陷不冒充已在该二进制重现 |
|
||||
| 本机安装 | Homebrew 列出 PostgreSQL 18.6、pgvector 0.8.7、Redis 8.10.2 | 仅证明安装;目标 PG 实例、目标库扩展启用、角色与可用性未验证,不据此批准切换 |
|
||||
| Backend 存储 | `internal/app/app.go:105` 按 DSN 选 PG,否则 SQLite;`store/store.go:50` SQLite WAL、busy_timeout=5000、单连接;PG 池固定 16/8 | 无需重写全部存储层;需团队档显式配置、连接预算和真实 PG 测试 |
|
||||
| 已有一致性基础 | `store/dialect.go:49` PG 事务咨询锁;消息 seq 唯一约束、requestId 去重和 HITL 条件更新 | 保留并扩展,不把已有能力列作全新建设;这些能力不等于跨实例运行互斥 |
|
||||
| Run 所有权 | `runmgr/runmgr.go:1113` 用进程内 map 占用会话;`store/messages.go:120` 直接创建 run | 两实例可能各自认为空闲;需共享占用和有效执行代次 |
|
||||
| 取消与审批 | `runmgr/runmgr.go:1326,1422` 依赖本实例 active 句柄;HITL 先落卡,再查句柄 | 请求落在非执行实例时存在命令不生效或卡已处理但执行未被唤醒的风险 |
|
||||
| 跨实例事件 | `pgbus/pgbus.go` 每批通知末 seq,Listener 只 `EventAt` 取末条;断线后对原连接继续 Wait | 静态可见批内中间事件遗漏及重连缺口;`server/server.go:376` 的 SSE 重放/去重不能修复已越过的游标 |
|
||||
| schema 迁移 | `store/migrate.go:migrate` 每次 Open 执行迁移;DDL 事务提交后另行插入迁移版本 | 并发启动与两步间崩溃存在风险;切 PG 前先改为单迁移入口与原子版本登记 |
|
||||
| 向量查询 | `store/vectors.go` 读取 BYTEA,应用内计算余弦;`migrate.go` 未把向量列建成 pgvector 类型 | 安装 pgvector 不代表启用;复用 RRF 管线,分阶段改为数据库 top-k |
|
||||
| Redis | `ratelimit/ratelimit.go:65` 独立 INCR/EXPIRE,EXPIRE 错误未处理;请求异常默认放行;app 默认限额 0 | 当前只是可选共享限流,需原子窗口、鉴权/TLS配置、容量保护与可观察的降级 |
|
||||
| 本地文件 | `blobstore` 默认本地目录;Backend Squad 入口未传 Store,回落 FileStore;checkpoint 写 `.agentx/checkpoints.jsonl` | PG DSN 不会迁走这些状态;工件、执行工作区、checkpoint 要分别处理 |
|
||||
| 独立 Squad | 独立 CLI 使用 `adapters/sqlite/runstore.go` 的 `orchestration.db`;这不是 Backend 实际接线 | 不把迁移该 SQLite 文件当作 Backend 分布式改造完成 |
|
||||
| 验证 | PG/Redis 集成由 `AGENT_PG_TEST_DSN`/`AGENT_REDIS_TEST_ADDR` 控制;当前 CI YAML 没有显式准备这两种服务 | 缺变量会跳过关键测试;CI 通过不能自动证明真 PG/Redis 或双进程链路通过 |
|
||||
|
||||
已有规划衔接:Q1 已记录 Store 收敛但仍留 platform→squad 队列桥接等余项;N3 原案与归档卡的 JournalOnly 落地不同,应以当前接线确定权威。共享权限沿用 EXT-8 授权适配器与 RDM 的成员/角色职责,不新建第二套成员模型。历史报告用于定位,不能替代当前验收。远端调查发现 Backend [#135](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Backend/pulls/135) 正在增加 S0 工作区 overlay/frozen base/CAS apply;U5 必须复用并核对其契约,不能另造冲突的工作区实现。该 PR 尚未作为本案已合入依赖。其他被查仓当时未返回 open PR,详见收据;实施启动时重新核对。
|
||||
|
||||
## 3. 需求与可判定结果
|
||||
|
||||
| ID | 需求 | 优先级 | 验收条件 |
|
||||
|---|---|---|---|
|
||||
| R1 | 支持 10–100 人、多项目、多会话并行 | P0 | 在固定环境与下述负载下完成真实业务链路;容量结果绑定组件 SHA、配置和数据集 |
|
||||
| R2 | 团队数据有唯一共享权威 | P0 | 团队档无有效 PG 配置或连接失败时拒绝就绪,不自动建立本地 SQLite 继续服务 |
|
||||
| R3 | 并发提交和编辑不静默覆盖 | P0 | 同 requestId 返回同一逻辑结果;同版本竞争写入最多一个成功,其余明确冲突;不同会话并行 |
|
||||
| R4 | 跨实例运行与命令可恢复 | P1,多实例前置 | 同会话主 run 单一有效 owner;旧 epoch 写入拒绝;任意 API 实例取消/HITL 均到达执行者 |
|
||||
| R5 | 事件有序、可追赶 | P0/P1 | 批处理、掉通知、重连和慢消费者后可按游标补齐全部已提交事件;不因收到末 seq 而跳过中间事件 |
|
||||
| R6 | 项目权限在所有数据入口一致 | P0 | 读取、写入、SSE、检索、下载与工具入口均校验当前授权;撤权后的新请求无泄漏 |
|
||||
| R7 | 数据和运行状态可恢复 | P0 | SQLite→PG 演练无遗漏;备份恢复含文件与权限映射;未知副作用停在可见恢复状态,不盲目重试 |
|
||||
| R8 | 高负载下有界且可观察 | P0 | 队列、活跃 Agent、DB 连接、工具/模型请求都有上限;超载行为、等待时间和错误分类可观测 |
|
||||
| R9 | 向量检索随数据增长扩展 | P1 | 数据库 top-k 与原精确基线对照;授权过滤正确;模型/维度/版本不混用;ANN 有召回率与延迟证据 |
|
||||
| R10 | 支持未来多服务部署 | P1/P2 | 先验证两个真实 API/Worker 进程共享服务;业务表有模块 owner,后续服务通过契约操作他方数据 |
|
||||
|
||||
R1 的人数及未来分布式方向由用户确认;下列量化指标是**建议的验收合同,待批准,不是当前性能结论**:
|
||||
|
||||
- 基准环境建议:Linux、8 vCPU、32 GiB RAM、NVMe,记录 PG/应用的实际配额与网络;两实例验证分为同机多进程和后续双主机两种证据。
|
||||
- 阶梯负载:10→30→100 在线用户,最多 300 SSE 连接;初始全局活跃 Agent 执行预算 20(包含子代理)、每用户 2、索引任务 4。待执行队列最多 200,按用户/项目公平分配。已接纳 run 数与实际执行许可分别计数;父 run 等待子代理/HITL 时让出执行许可、保留会话所有权,恢复执行须重新获许可,避免额度用尽时父子互等。以上阈值由实测调整。
|
||||
- 数据量建议:100 万条消息/事件量级、10 万知识分块、多个项目与交叉授权用户;另测 100 万分块扩展档。记录数据分布与热点,不能只测空库。
|
||||
- 非模型普通 API:P95≤300ms、P99≤1s;SSE 持久事件可见延迟 P95≤1s;非预期失败率≤0.1%。预期限流/冲突单列,不能排除后不报告。
|
||||
- 先跑 60 分钟稳定负载,再跑 2 小时混合长稳;持续记录实际成功吞吐、排队、CPU/内存/IO、连接等待和模型配额。模拟模型用于容量基线,另保留真实模型少量全链路验证。
|
||||
- 数据正确性不变量在全部测试中零违反。数据库/Worker 故障恢复建议 RTO≤15 分钟;灾难恢复建议 RPO≤5 分钟、RTO≤60 分钟。主机/存储全毁不在单机“零丢失”承诺内;若要求该场景 RPO=0,需另行批准同步复制、故障域与可用性取舍。
|
||||
|
||||
## 4. 技术决策与目标结构
|
||||
|
||||
KTD1. **区分 local 与 team 部署档。** local 保留 SQLite;team 强制 PG、认证、独立实例 ID、受控工具执行和启动诊断。PG 暂时不可用时返回未就绪,不切回 SQLite。个人档不因浏览器人数变多而自动升级。
|
||||
|
||||
KTD2. **PG 保存持久业务与调度事实。** 用户/项目/会话/消息/卡片/运行/幂等记录/命令/事件/checkpoint 元数据以 PG 为准。Redis 不成为任务完成、审批通过或永久幂等的唯一证据。初期使用同一 PG 实例和有归属的逻辑表/角色;后续拆服务时明确表的唯一写入模块,避免所有服务无约束共享整库。
|
||||
|
||||
KTD2 的全部状态收敛以 U5 完成为界;此前有明确的单实例过渡边界,不能提前把本地状态当成缓存:
|
||||
|
||||
| 数据 | 首期单实例团队版 | U5 后多实例版 |
|
||||
|---|---|---|
|
||||
| Backend 业务记录、幂等与恢复隔离标记 | PG 权威 | PG 权威 |
|
||||
| 尚未改造的 Squad FileStore、checkpoint、续跑标记 | 唯一实例的本地权威文件,联合备份,禁止跨机接管 | 版本/归属元数据在 PG,大内容在共享对象存储 |
|
||||
| 工件 | 本地对象目录,持久备份与 DB 清单绑定 | 共享不可变对象与 PG 发布记录 |
|
||||
| 临时执行目录 | 单实例/单 owner;先分类再清理 | owner+epoch 控制的可恢复工作区 |
|
||||
|
||||
KTD3. **一个会话一次主执行,不同会话并行。** 推荐独立 conversation_execution 占用行,以 owner/会话唯一键、run_id、epoch、lease_until 约束;不对所有 runs 加“会话唯一”,以免禁止正常子代理。事务内完成权限检查、请求幂等、消息、主 run 和调度记录,接收成功以事务提交为准。
|
||||
|
||||
KTD4. **短事务领取,租约与 fencing 配套。** Worker 通过 PG 行锁和 SKIP LOCKED 领取到期任务;事务提交后执行,模型/工具等待不得持有数据库事务。续租、事件追加、checkpoint、终态写入都校验 run+epoch。租约用 DB 时间,执行实例 ID 与每次启动的 generation 分开。旧 Worker 恢复后不能提交;租约过期也不等于外部命令已经停止。
|
||||
|
||||
KTD5. **持久命令与提交事件同事务。** 取消/HITL/调度命令写入 PG inbox/outbox,带唯一 command_id、逻辑 run、执行代次与处理状态。运行级取消意图交给当前 owner,即使接受后发生接管也不能丢失;HITL 绑定稳定 gate_id+gate_version,新 owner 消费时重验 gate 与权限,过期审批明确拒绝而不静默丢弃。执行结果及确认仍须校验当前 epoch。批准数据与待投递命令原子提交,执行者幂等消费,处理确认与执行效果分别记录。关键外部动作必须有目标端幂等键、可查询凭据或人工恢复路径;超时结果未知时进入 recovering,不宣称任意工具 exactly-once。
|
||||
|
||||
KTD6. **事件表是重放依据,NOTIFY 仅作唤醒。** 事件提交与 outbox 同事务;需要时在同事务使用 pg_notify。监听端维护每流连续 cursor,从 EventsAfter 分页追赶到通知水位;不能直接跳到末 seq。重建连接→LISTEN 生效→补查水位/积压,再转实时。增加周期补查,覆盖通知丢失、断线与通知前后竞争。只有落库事件才能发布可恢复的 SSE ID;纯瞬时进度明确可丢失,不冒充已确认业务数据。
|
||||
|
||||
KTD7. **数据库乐观并发控制。** 项目设置、卡片、文档元数据等读改写带 version/expected_version;冲突返回 409 及新版本引用。重要唯一性/外键落在数据库,事务失败按错误类型有界重试整笔事务;提交结果未知先按幂等键查询。不能无限重试模型调用或发送动作。[PG 事务隔离与重试](https://www.postgresql.org/docs/current/transaction-iso.html)。
|
||||
|
||||
KTD8. **数据库迁移独立于普通启动。** 单一 migrator 取得数据库锁,执行 append-only 版本;可事务化 DDL 与版本登记同事务。应用仅核对兼容版本和就绪状态。不能放入事务的在线索引变更单列可恢复运维步骤,不夹入普通迁移后声称原子。使用扩展→回填→切读写→收缩,保留兼容窗口。
|
||||
|
||||
KTD9. **工件共享,工作区有执行 owner。** 先保留 blobstore 接口;跨主机上线前实现并验收 S3 兼容对象存储,DB 保存不可变对象键、校验和、版本与就绪状态。发布前先完整写对象再提交引用,失败孤儿可清理;删除采用标记和延迟 GC。工作区、检查点与 Squad 状态分开设计:checkpoint/调度版本入 PG,大内容入对象存储,本地工作区是受 owner/epoch 控制的暂存执行目录;需要接管时按清单恢复。共享目录和文件 rename 不能替代跨机所有权。
|
||||
|
||||
KTD10. **Redis 只保存可恢复的加速状态。** 保留共享限流,改为 Lua 原子计数+过期或等价原子算法,键包含实例群/完整时间窗/owner,支持 ACL 凭据/TLS、连接与请求超时。故障时普通读取可降到本地保守限流;创建 Agent/昂贵工具等写入口仍受 PG admission 硬预算保护,不能无界放行。缓存带授权/内容版本,撤权同步失效或重新校验;先证明命中收益再加缓存。[Redis INCR 限流模式](https://redis.io/docs/latest/commands/incr/)、[分布式锁限制](https://redis.io/docs/latest/develop/clients/patterns/distributed-locks/)。
|
||||
|
||||
KTD11. **pgvector 按“正确→测量→ANN”推进。** 复用现有全文+RRF+可选 rerank,先补 embedding profile/model/revision/dimension/content_hash/generation 身份,禁止同维不同模型混查;迁移为 vector 列并在 PG 做过滤和精确 top-k,再用基线对照决定 HNSW。权限适配器不能直接变成 SQL 时,由适配器提供受限授权候选集合或采用有界分批取候选+最终实时鉴权,不得无界加载所有 owner 后在内存过滤。授权过滤后的召回率单独验证;ANN 需要迭代扫描/分区等策略时以模型维度和版本实测选择。[pgvector 官方说明](https://github.com/pgvector/pgvector)。
|
||||
|
||||
KTD12. **先管理连接池,再决定 PgBouncer。** 使 MaxOpen/Idle/IdleTime/Lifetime、查询超时可配置并输出脱敏有效值;总连接预算包含所有 API、Worker、LISTEN、migrator、监控与维护预留。100 在线用户不等于 100 DB 连接。未来接 PgBouncer transaction pooling 时 LISTEN 必须使用直连或 session pool 独立 DSN,迁移也走直连,并验证 pgx prepared statement 配置。[PgBouncer 兼容表](https://www.pgbouncer.org/features.html)。
|
||||
|
||||
KTD13. **共享可读不等于可写或可批准。** 当前 EXT-8 `ProjectAuthz` 是只读 bool 契约。U3 先列 read/edit/approve/execute/admin 的动作授权矩阵,复用下游角色,不另建成员权威;需要共享写入时以版本化公开契约扩展 action-aware 授权,旧只读适配器不得自动获得写入能力。未配置的动作默认拒绝,Host/工具/API 均走同一授权结论;审批职责分离仍由下游规则判定。SSE 发送后续数据、异步任务开始和工件下载时重新校验当前授权,缓存失效不承担唯一安全责任。
|
||||
|
||||
KTD14. **迁移副本按原数据敏感级别保护。** 备份、导出、WAL、工件和测试副本使用专用角色及受限目录;传输与静态备份加密,解密材料保存在独立受管秘密存储并纳入恢复演练。日志/报告只留统计与哈希,禁止正文、令牌及密钥明文;测试使用脱敏数据。U1 固定保留期限、存放位置、访问者与清理责任,未知项阻塞正式导出。正式恢复演练同时验证凭据可用性与非授权者无法访问副本。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
U[10–100 用户] --> G[入口与认证]
|
||||
G --> A[API 实例 A / B]
|
||||
A --> P[(PostgreSQL + pgvector)]
|
||||
A --> R[(Redis 限流 / 可重建缓存)]
|
||||
P --> W[Worker 领取任务 / 持久命令]
|
||||
W --> P
|
||||
W --> X[受控工具工作区 / 模型服务]
|
||||
W --> O[(共享对象存储)]
|
||||
A --> O
|
||||
P --> E[事件追赶 / 本地订阅]
|
||||
E --> U
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as 用户
|
||||
participant A as 任意 API
|
||||
participant P as PostgreSQL
|
||||
participant W as 执行 Worker
|
||||
C->>A: 提交 requestId / expected_version
|
||||
A->>P: 短事务:鉴权、幂等、占用、消息、run、任务
|
||||
P-->>A: commit / 冲突
|
||||
A-->>C: 已受理与 runId / 明确冲突
|
||||
W->>P: 领取任务并取得 epoch
|
||||
W->>W: 事务外执行模型与工具
|
||||
W->>P: 按 epoch 提交结果与事件
|
||||
P-->>A: 唤醒后按 cursor 补齐
|
||||
A-->>C: SSE 已提交事件
|
||||
```
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> queued
|
||||
queued --> running: 原子领取并分配 epoch
|
||||
running --> waiting: 持久 HITL
|
||||
waiting --> running: 幂等命令消费
|
||||
running --> completed: 有效 epoch 原子结算
|
||||
running --> recovering: 失联或副作用结果未知
|
||||
waiting --> recovering: owner 失效
|
||||
recovering --> queued: 已核对可安全重试
|
||||
recovering --> interrupted: 需人工处理或不可恢复
|
||||
queued --> cancelled: 取消命令生效
|
||||
running --> cancelled: 执行者确认停止
|
||||
```
|
||||
|
||||
## 5. 实施顺序与工作包
|
||||
|
||||
每个阶段评审后再进入下阶段;以下均为待批准计划,不因写入文档取得实施授权。新测试文件标“新增”;现有测试只作为扩展入口,本次未运行。普通基座改动在 Backend;公开持久接口确需变化时才同步 Native/Squad/Core,并由 Dev 固定组合测试,不全库改造。
|
||||
|
||||
### U1. 冻结目标、数据归属与基准环境
|
||||
|
||||
对应 R1/R2/R7/R8。先确定目标为 Dev 团队实例及其实际发布制品,记录脱敏配置来源、DB 实例/版本/扩展、数据数量与归属、文件清单、磁盘容量、峰值和恢复目标。RDM 独立业务库、旧 Agent-System 治理库另列,不能把一次 DSN 切换宣称覆盖它们。
|
||||
范围:`runtime/dev` 部署配置(实施时核对文件位置)、`modules/backend/internal/config/config.go`、文档运行手册。
|
||||
产物:固定部署清单、迁移映射、容量合同(区分接纳与执行许可)、隔离测试库/目录/端口方案、KTD14 的副本保护与保留合同;确认暂态 Worker 文件哪些可重建,哪些必须迁移。
|
||||
验收:仅操作批准的实例和测试资源;共享数据凭据不打印;未知 owner 或未定位的权威文件阻塞迁移。测试:脱敏配置诊断及缺项校验,业务压测依后续 U7。
|
||||
|
||||
### U2. 团队 PG 档、迁移器与真实数据库门禁
|
||||
|
||||
依赖 U1;对应 R2/R3/R7。修改 `internal/config/config.go`、`internal/app/app.go`、`internal/store/store.go`、`internal/store/migrate.go` 及 CLI;按 KTD1/KTD8/KTD12 实施。
|
||||
CI 增加隔离原生 PG/Redis 生命周期及明确必跑标记,固定组件/扩展版本;缺少真实测试服务时该 job 失败而非跳过。
|
||||
测试:扩展 `internal/config/config_test.go`、`internal/store/store_test.go`;新增 `internal/store/migrate_atomic_test.go`。覆盖 team 缺 DSN/PG 故障拒绝启动、local SQLite 正常、两个 migrator 竞争、DDL 与账本中间崩溃、旧 schema 升级、PG bool/时间/空 JSON/唯一约束与全文扩展。
|
||||
出口:真 PG 完整 CRUD/认证/会话/SSE/检索/卡片链路通过;仅该出口不宣布多实例安全。schema 变更的组合测试与业务迁移是不同动作。
|
||||
|
||||
### U3. 请求原子性、版本冲突与受控容量
|
||||
|
||||
依赖 U2;对应 R3/R6/R7/R8。修改 `internal/server/server.go`、`internal/store/messages.go`、`internal/store/cards.go`、`internal/cardsvc/cardsvc.go`、设置读改写及 `internal/runmgr`。收口 KTD3/KTD7 的事务边界;保留现有 seq 约束。按 KTD10 完成 Redis 原子限流、配置与异常策略;PG 记录共享 admission 预算。按 KTD13 完成动作授权矩阵与所需公开扩展的兼容计划;涉及共享编辑时 Core/Host 与下游适配器一起验收。
|
||||
先补最小持久恢复隔离:为未知副作用记录 recovery hold,`ResumeInterruptedChildren` 等所有启动续跑入口必须跳过,人工核对后显式解除。概念状态 recovering 可以先由独立隔离记录表达;扩展 Core 枚举时走公开契约版本,不假定当前已有此状态。完整租约接管留 U5。
|
||||
测试:扩展 `internal/server/admission_test.go`、`internal/ratelimit/ratelimit_test.go`;新增 `internal/store/admission_pg_test.go`、`internal/store/card_version_test.go`、`internal/runmgr/recovery_hold_test.go`。覆盖相同请求重放、事务部分失败、同版本竞争、动作越权、子代理预算计入全局、所有父 run 占满额度后同时派生仍能前进、未知副作用重启不自动续跑、队列满、Redis 断连/恢复/键过期。
|
||||
出口:单 API 团队模式达到不变量与有界行为;不会把 20 个 Agent 配置值当作已证明容量。
|
||||
|
||||
### U4. 可切换的迁移与恢复演练
|
||||
|
||||
依赖 U2/U3;对应 R2/R7。新增 `modules/backend/cmd/storage-migrate/` 或等价受管运维入口,明确只处理 Backend 库;不得直接执行 SQLite dump 作为 PG SQL。迁移实例以 migration_id、source_snapshot_id、source_schema_version 固定来源,记录表级完成与最终验证完成标记;仅同一冻结快照可续传,其他非空目标拒绝。迁移报告包括每表计数、主键映射、按主键分批规范化内容校验和、外键/owner/权限检查及工件哈希。
|
||||
测试:新增迁移工具的 `main_test.go` 与 `integration_test.go`,固定脱敏 SQLite 夹具覆盖全部当前 schema、布尔/空值/时间/JSON/Unicode/二进制向量/秘密字段、幂等重复导入、缺文件、未知 owner、断点重试及目标已含数据拒绝。
|
||||
操作顺序与回退见第 6 节。出口:隔离环境迁移与恢复验证完成,由用户批准窗口后才切正式服务。
|
||||
|
||||
### U5. 执行所有权、持久命令与共享状态
|
||||
|
||||
依赖 U3,团队现网切换不必等待整个 U5;对应 R4/R6/R7/R10。修改 `internal/runmgr`、`internal/store/recovery.go`、`internal/squadadapter`、`internal/runtime/squad_runner.go`、`internal/blobstore`;新增 Store 的 lease/inbox/outbox 与 PG RunStore 适配器。
|
||||
按 KTD4/KTD5/KTD9 设计 Native checkpoint 接口,继续支持 local 文件实现;不把 JournalOnly 日志误当作业务上下文权威。Worker 工具沙箱与访问范围沿用现有方向,在执行端检查当前身份和 epoch。
|
||||
测试:新增 `internal/runmgr/multi_instance_test.go`、`internal/store/lease_pg_test.go`、`internal/blobstore/object_store_test.go`;扩展 `internal/runmgr/recovery_test.go`。必须启动两个真实进程:同会话争抢、不同会话并行、跨实例取消/HITL、命令提交后消费前 owner 换代、旧 gate 的审批明确失效、Worker 被杀、旧 Worker 迟到结算/写事件/写文件、失联重连、副作用结果未知、文件缺失/重复发布。
|
||||
出口:所有写入和工具副作用的失效 owner 处理有实证后,才允许第二实例承接写请求;故障状态可见,不能仅靠粘性路由。
|
||||
|
||||
### U6. 事件追赶与数据库向量检索
|
||||
|
||||
U6 内分三个交付切片,稳定工作包 ID 不变:事件追赶/重连修复依赖 U2,可与 U3 并行;事务 outbox 与投递闭环依赖 U5;向量 schema 与查询改造依赖 U2 迁移器及 U3 授权合同。对应 R5/R6/R9。
|
||||
事件:修改 `internal/pgbus/pgbus.go`、`internal/runmgr/events.go`、`internal/server/server.go`、Store 事件接口。扩展 `internal/pgbus/pgbus_test.go`,新增 `internal/server/sse_gap_test.go`:批次 64 条全部可见、断线补齐、通知丢失、订阅与补查竞争、1000+ 分页、慢消费者、撤权后新事件拒绝。第一切片完成只证明追赶修复,不声称 KTD6 的事务 outbox 已就位。
|
||||
向量:修改 `internal/store/vectors.go`、`internal/store/migrate.go` 与现有知识索引管线;新增 `internal/store/pgvector_test.go`。验证模型身份/维度隔离、内容更新/删除原子性、回填中重启、索引未完成可降级、中文全文混合、共享授权后 top-k、撤权、与精确检索 Recall@10 对照(建议≥0.95,待批准)。索引构建不得拖垮前台连接/IO。
|
||||
出口:先验证正确与有界,再按容量结果决定 HNSW 与缓存;绝不以 extension 存在替代查询计划/召回证据。
|
||||
|
||||
### U7. 压测、故障验收与分布式放行
|
||||
|
||||
依赖 U2/U3/U4;双实例验收另依赖 U5/U6。对应全部 R。首期单实例放行必须完整重放现有入口的 R6 权限矩阵(含 SSE 后续事件、共享检索、下载、Host/工具与撤权),并证明 U3 恢复隔离;不能等 U5/U6 才验证这些 P0 要求。跨实例传播与接管的新增验证随 U5/U6。新增 Dev `tests/load/collaboration/` 与 `tests/integration/multi-instance/`,由隔离测试入口负责启动/回收自己创建的资源。
|
||||
按第 3 节负载合同和第 7 节矩阵测量,记录原始 k6/pgbench、服务指标与数据不变量;pgbench 只测数据库能力,不能替代业务 API/SSE/Agent 验收。正式测试不打生产服务。
|
||||
出口:单实例团队、双进程、双主机分别出具结果;CI 身份/链接/SHA 或独立 REPLAY 可核验才用于放行。本地 SELF 只能作辅助。变更智能体行为时补真实模型前后任务级对照。
|
||||
|
||||
远期 P2:需求达到后再拆 API/Worker/索引服务,按表归属收紧角色;引入 PG 高可用与自动故障转移、对象存储冗余、可选 PgBouncer。服务拆分与 DB 复制是两件事;Redis 集群、读副本和缓存不能替代主库一致性,读后写敏感路径保持主库读取或显式一致性令牌。
|
||||
|
||||
## 6. SQLite → PostgreSQL 切换和恢复
|
||||
|
||||
1. 固定源服务制品、全部数据库/文件路径与目标空库;指定迁移 owner、窗口、可接受中断和回退判据。先做只读盘点与隔离演练,不接触其他服务的数据。
|
||||
2. 为 SQLite 做一致性备份(应用已有 Backup/VACUUM INTO 或官方备份路径),同时生成工件/checkpoint/工作区清单。活跃 WAL 数据库不能只复制 `.db` 文件;检查备份可打开且内容与清单匹配。
|
||||
3. 预演使用独立测试目标 PG,由 migrator 建 schema/扩展,再按依赖顺序导入。显式保留 ID、幂等键、事件 seq、哈希/秘密、用户归属、共享范围、审批状态,调整序列值和类型。预演库不成为正式目标;所有副本遵守 KTD14。
|
||||
4. 最终窗口暂停新写与调度,等待或安全收口在途 run;无法确认外部副作用的 run 写入 U3 的持久 recovery hold。停止全部旧写者后取最终一致性快照,导入新空正式目标;按 U4 的同快照迁移身份续传。全量对账与验收抽样完成并写入完成标记后才可切入口,保留只读源备份及过渡期权威文件。目标已服务或身份不同的非空库不得覆盖。
|
||||
5. 仅一个入口切到 PG,检查版本/配置指纹、库身份与数据归属,执行用户登录、项目、会话、审批、检索、下载的冒烟;应用 fail-closed,不能故障后回 SQLite。原库不再写,不使用临时双写制造两个权威。
|
||||
6. **PG 接受新写入前**可撤回切换,确认目标未产生业务写后恢复 SQLite。**PG 接受新写入后**禁止直接指回旧 SQLite;优先保留 PG 回退兼容应用或向前修复。确需反向迁移,重新冻结写者、导出 PG 增量、对账并批准专门回迁方案。
|
||||
7. 建立 pg_dump 逻辑备份,以及 pg_basebackup(或等价物理基础备份)+ 连续 WAL 归档/PITR,并与对象存储版本/清单联合恢复;pg_dump 不能用作 WAL 回放的基础备份,保留足够不可变对象。每次演练恢复到新目标,核对应用可用与权限/文件完整性,不能把“备份命令成功”当作可恢复。
|
||||
|
||||
SQLite 本身支持可靠事务与多人经同一应用访问;WAL 提升读写并发,但同一数据库仍只有一个 writer,且不适合多主机通过网络文件系统共享 WAL。取舍基于写负载、进程拓扑、恢复与运维目标,不用“超过某人数 SQLite 就出错”的判断。[SQLite WAL 官方文档](https://sqlite.org/wal.html)。
|
||||
|
||||
## 7. 最小验收矩阵
|
||||
|
||||
| 场景 | 必须观察到的结果 | 对应 |
|
||||
|---|---|---|
|
||||
| 同 requestId 并发/网络超时后重试 | 一个逻辑请求和同一 run,不重做已经确认的副作用 | R3/U3/U5 |
|
||||
| 两实例同会话不同请求 | 仅一个主执行;另一个排队或明确冲突,子代理不受错误唯一约束阻断 | R3/R4/U5 |
|
||||
| 多项目并行、热点会话、满额度父子派生 | 公平、有界;等待父 run 不阻塞子 run 获得许可,所有任务能前进或得到有界拒绝 | R1/R8/U3/U7 |
|
||||
| 并发修改同卡/设置 | 成功与冲突可辨认,无最后写入静默覆盖 | R3/U3 |
|
||||
| 在 B 提交 A 所有 run 的取消/HITL,消费前换 owner | 命令持久、唯一消费;取消随逻辑 run 生效,HITL 重验 gate 版本,卡片与 run 最终一致 | R4/U5 |
|
||||
| Worker 崩溃/暂停超过租约后恢复 | 新 owner 可受控接管;旧 epoch 不能提交;不明副作用不自动重放 | R4/R7/U5 |
|
||||
| PG 断连/提交响应丢失 | 依赖不可用有界失败;恢复按幂等记录核对,不自动切 SQLite | R2/R3/U3 |
|
||||
| Redis 断连/INCR 后崩溃 | 不改变业务事实;昂贵任务仍受硬预算;恢复无永久计数键错误 | R8/U3 |
|
||||
| 批事件/断开 LISTEN/通知丢失 | 所有已提交事件按连续 cursor 追赶,重放不跳洞 | R5/U6 |
|
||||
| 撤销成员权限/跨 owner 猜测 ID | 新请求、流后续事件与下载/检索/工具均不泄漏 | R6/U3/U5/U6 |
|
||||
| 多模型向量/过滤后 top-k | 不混模型,权限正确,召回/延迟达批准阈值 | R9/U6 |
|
||||
| 迁移崩溃/坏文件/未知 owner | 阻止切换;重试不重复导入,不隐式公开历史数据 | R7/U4 |
|
||||
| 磁盘满/备份恢复/整机失效 | 清楚拒绝写入和报警;在约定故障模型与 RPO/RTO 下恢复 | R7/U4/U7 |
|
||||
|
||||
## 8. 工具、观测与交付
|
||||
|
||||
本轮未安装软件、修改配置、运行迁移、重启服务或压测。brew 已有三项服务软件,当前瓶颈主要是接线与一致性机制,暂不重复安装。未来压测可通过 [brew 安装 k6](https://formulae.brew.sh/formula/k6);PgBouncer 只在连接测量证明有必要后安装。安装授权不等于对共享数据库升级、创建扩展或变更服务的授权;执行前核对目标、版本与既有占用。
|
||||
|
||||
必需观测:API P95/P99与预期/非预期错误,DB pool wait/连接数/慢查询/锁等待,队列长度/最老年龄,run 租约/过期写拒绝/未知副作用,SSE cursor lag/补查次数,Redis 错误与降级,检索耗时/召回抽样,备份时间与恢复结果。日志只记录 request/run/owner 的安全标识,不记录 DSN、密钥或文档正文。
|
||||
|
||||
当前交付仅为 r1 方案与 SELF 调查记录。需求人数已确认;容量阈值、正式数据/部署目标、迁移窗口、灾难恢复等级和实施阶段尚待人工评审。没有业务测试 PASS、独立 REPLAY、CI GATE 或已部署声明。
|
||||
|
||||
方案静态审阅及修订处置见[审阅记录](../records/2026-10-11-collaboration-storage-plan-review.md)。Agent 审阅不替代人工批准或实现验收。
|
||||
|
||||
首选下一增量是 **U1 + U2 的详细实施与测试合同**:固定目标实例与 PG 测试环境,解决团队档、迁移原子性和真实数据库测试门禁。U6 的事件正确性修复可在单独授权后并行;不要先增加应用副本。各实现任务启动前复核在途 PR 与依赖 SHA,再按 Dev 的 evidence/task-sync/组合验证流程交付。
|
||||
@@ -12,6 +12,7 @@
|
||||
| 基座与下游如何分工,如何申请扩展 | [基座路线图](2026-10-01-base-extension-roadmap.md),配套插件契约与兼容规则 | 公开扩展面、插件 v2、质量回路、工程基座 | weichen |
|
||||
| 三个智能体库如何继续演进 | [Agent 栈总案](2026-10-02-agent-stack-completion.md),阶段细化见 N1/Q1/I1、N2、N3、Q2/Q3 | R0/R1/D1、N1–N3、Q1–Q3、I1–I2、阶段评测 | weichen |
|
||||
| RDM 下游的大目标和消费者里程碑是什么 | [RDM 阶段总案](2026-10-07-rdm-phase-plan.md) | P0–P4,对应 MS0'、MS1–MS4及发布前置 | weichen |
|
||||
| 10–100 人协作与未来分布式如何演进 | [协作存储与分布式方案](2026-10-11-collaboration-storage-and-distribution.md) | 团队 PG 档 → 迁移恢复 → 多实例执行与故障验收;r1 已批准(2026-10-11),实施自 U1+U2 启动 | 需求:weichen;实施/运维待指定 |
|
||||
|
||||
以上是依据文内显式范围和引用形成的阅读入口,不是新增优先级或批准结论。N2 阶段案未单列 owner,
|
||||
应由负责人补齐;不能仅凭任务创建人推断全部规划的负责人。
|
||||
@@ -74,7 +75,10 @@ Dev 链接均指向对应任务 PR,可从其任务卡继续追溯组件 PR;
|
||||
| [N2 实施案](2026-10-07-agent-stack-n2-plan.md) | 栈总案 N2 的六 WP:上下文、协议、工具、skills、子代理、装配 | 未单列确认状态及 owner;正文称 N2 开工 | Documents [#42](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Documents/pulls/42) 已合入;Dev [#244](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/244) 已合入(merge `7e3ba10`),闭卡 [#247](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/247)。卡内自述六 WP 落地;本索引未重放 |
|
||||
| [N3 实施案](2026-10-07-agent-stack-n3-plan.md) | 栈总案 N3:持久与可观测 | 页首未单列确认状态及 owner;正文称 N3 开工 | Documents [#43](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Documents/pulls/43) 已合入;Dev [#248](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/248) 已合入(merge `2836a87`),闭卡 [#249](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/249)。卡内自述六 WP 落地;本索引未重放 |
|
||||
| [Q2/Q3 实施案](2026-10-07-agent-stack-q2q3-plans.md) | 栈总案 Q2 拓扑与 Q3 收敛互通 | 页首未单列确认状态及 owner | Documents [#44](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Documents/pulls/44) 已合入;Dev [#250](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/250) 采纳方案,[#251](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/251)(merge `452c00a`)与 [#253](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/253)(merge `c8ce4eb`)已合入。卡内自述 Q2/Q3 落地;本索引未重放 |
|
||||
| [智能体工作流质量改进](2026-10-09-agent-quality-improvement-plan.md) | 直连主路径质量:诊断→六项裁定→P0–P5 分期 + 模型 A/B;推翻 fs 工具默认关闭裁定 | 已获实施授权(2026-10-09 六项裁定);首个增量 feature/agent-quality-phase01 | 随本提案 PR;诊断 SELF(真实运行转录);基线报告见任务卡 |
|
||||
| [EXT 申请包 C1–C7](2026-10-08-ext-c1-c7-rdm-shared-contracts.md) | RDM 多人共享契约的基座最小扩展申请(EXT-6…EXT-12):身份停用/受管配置/授权适配器/索引发布/分发守卫/Host 工厂/投影过滤 | proposed;需求依据=RDM U0 主记录(D1–D9 裁定,2026-10-08 合入) | 随本提案 PR;每条现状证据为 SELF·源码级(Dev 34a2bbe/backend fe7c245),运行态 NOT_RUN;受理后逐条另立实现任务 |
|
||||
| [EXT 申请包 G1](2026-10-09-ext-g1-b1-b3-exec-backend.md) | EXT-13…16:回合内共享检索、命令即工具、项目列表共享、执行后端接口 | proposed;需求依据=RDM 方案 V1.1 §3.3/§3.4/§5.3(2026-10-09 批复) | Documents [#52](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Documents/pulls/52) 已合入;EXT-16 已实施(Dev #285,见其任务卡),其余受理评审待定。本行由本次索引维护补充 |
|
||||
| [子代理分工、模型分级路由与任务沙箱](2026-10-10-agent-delegation-routing-sandbox.md) | 方向主记录:委派契约与角色路由方案(E1–E5 增量)+ 任务工作区沙箱设计(仅记录不实施);修正 overlay≠快照等三处假设 | proposed(2026-10-10);E1、E3、E4(R4+账本)、E5(R3)、S0-1 已完成(E4:Dev #315;S0-1:Backend #135/#136、Dev #318,2026-10-11);E2 暂缓(模型指示)、S0-2 待授权 | 随本提案 PR;现状核查与启动延迟为 SELF(任务卡 evidence);外部来源 URL 全量随任务卡 |
|
||||
|
||||
原查询的 19 份原文中,14 份显式标注 owner 为 weichen。双档存储、启动配置面、跨会话读取、文件预览和
|
||||
N2 实施案这五份未单列 owner,其中预览案仅写“作者:weichen + Agent”。同步新增的 N3 与 Q2/Q3 案页首也未单列 owner。
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,31 @@
|
||||
# 协作存储方案 r1 静态审阅记录
|
||||
|
||||
对象:[方案 r1](../proposals/2026-10-11-collaboration-storage-and-distribution.md)。
|
||||
日期:2026-10-11(Asia/Shanghai)。来源:SELF,Agent 辅助静态审阅。
|
||||
三个 Agent 分别兼任两个视角:coherence/scope-guardian、feasibility/adversarial、security/product。
|
||||
同一 Agent 的两个视角不互相独立;没有跨模型审阅、独立测试重放、CI GATE 或人工批准。
|
||||
使用 ce-doc-review 的检查视角,覆盖与边界以本记录为准,不声称已运行额外外部模型审阅。
|
||||
|
||||
## 发现与处置
|
||||
|
||||
| 发现 | 原方案后果 | 修订处置 | 复核 |
|
||||
|---|---|---|---|
|
||||
| 正式导入与非空目标拒绝冲突 | 预演后可能无法最终导入,或放宽规则混入其他快照 | U4/§6 分开预演与正式空目标;migration_id+快照身份,只有同快照可续传,验证完成后切入口 | 原审阅 Agent 已确认文本闭合 |
|
||||
| 恢复隔离晚于首期切换 | 现有 ResumeInterruptedChildren 可能自动重派未知副作用任务 | U3 前移持久 recovery hold,启动续跑跳过,U7 放行前验证 | 原审阅 Agent 已确认文本闭合 |
|
||||
| 命令只绑定旧 epoch | owner 切换后取消或审批意图可能丢失 | KTD5 区分逻辑 run 取消、gate/version 审批与按 epoch 验证的执行结果 | 原审阅 Agent 已确认文本闭合 |
|
||||
| 父子共享额度可能互等 | 父 run 占满许可并等待不能启动的子 run | §3/U3 区分接纳数与执行许可,等待父 run 让出许可但保留会话所有权 | 原审阅 Agent 已确认文本闭合 |
|
||||
| U6 先于 outbox 依赖 | 提前声明事务投递机制完成或重复建设 | U6 分追赶修复、outbox、向量三个切片并分别列前置 | 原审阅 Agent 已确认文本闭合 |
|
||||
| P0 权限检查落到后期 | 首期团队版可能未验证 SSE/检索/工具撤权 | U7 单实例放行前验证完整现有 R6 入口矩阵;新增跨机能力另验 | 原审阅 Agent 已确认文本闭合 |
|
||||
| 过渡期本地权威未说清 | 尚未迁移的 checkpoint/续跑文件可能被当缓存清除 | KTD2 增加首期与多实例期归属表,联合备份,U5 前禁止跨机接管 | 原审阅 Agent 已确认文本闭合 |
|
||||
| 只读适配器不足以判断写入/审批 | 可能把共享可读扩大成可写 | KTD13/U3 指定动作授权矩阵、版本化兼容与默认拒绝,不新建成员权威 | 原审阅 Agent 已确认文本闭合 |
|
||||
| 迁移/备份敏感副本保护未列 | 源库秘密可能经备份旁路暴露 | KTD14 指定访问、加密、密钥分离、保留与恢复验证;正式导出前缺项阻塞 | 原审阅 Agent 已确认文本闭合 |
|
||||
|
||||
主编另依据 PostgreSQL 官方 PITR 文档修正备份描述:pg_dump 是逻辑备份,不能作为 WAL 回放基础;PITR 使用物理基础备份加连续 WAL。未改变用户确认的规模与未来分布式方向。
|
||||
|
||||
## 剩余决策与验证边界
|
||||
|
||||
- 10–100 人、多项目、多会话及未来多服务分布式:用户已确认需求方向。
|
||||
- 量化容量/恢复目标、正式实例和数据归属、迁移窗口、资源与实施阶段:待人工评审。
|
||||
- 本记录只说明文档中的九项问题已经改写并由原 Agent 复读,不说明实现缺陷已修复。
|
||||
- 实施、真实 PG/Redis 测试、压测、故障注入、数据迁移、恢复演练与部署:全部 NOT_RUN。
|
||||
- 方案正文与调查收据的字节摘要由文档检查命令写入 Dev 任务卡,作为本次候选身份;本文件不手写命令结果。
|
||||
Reference in New Issue
Block a user