Commit 35307d15b38c4452b9c3ca4db602ec2555ef2b06
1 parent
d279c17f
docs(29-dream): dream 设计草案 —— 四条取舍已拍板,附实查到的原料现状
28-followups §1.1 一直是「方向已定、设计未定」。这份把取舍摆出来并记下拍板结果。 ## 先看清原料:它现在是脏的(全部实查,不是推测) · **写进 memory 的不是「事实」,是截断的日志行**。appendToMemoryMd 的全部逻辑是 「取第一行、砍到 80/100 字符」。cto/_global 的实际内容里,三条「关键事实」是 `🔧 [TOOL_CALL] Bash (ID: toolu_01RsQ...)` —— 工具调用 id。 §5.6b 点名的错误版本是「自动把原文写进共享 SKILL.md」;**现在这套已经是那个错误的 单公司版**,只是还没跨公司共享,所以还没造成泄漏。 · 长期记忆是一个 3000 字符的滚动窗口,没有按重要性保留的机制。 · 96 个「公司态目录」里混着 train/ workspace/ 和**带时间戳的测试残留** (tmp-w7-*-1786986291739-*、qroute-co-13/14)。dream 第一步「枚举所有公司」 现在没有可靠答案 —— 可靠的答案在 company_agents 表里,目录只能用来定位文件。 · 75 份 memory.md 里只有 7 份有非模板内容。**dream 现在几乎没有原料。** ## 四条拍板(2026-08-20) A 去敏 = 独立判定 agent + 写作要求。失效方向是「少沉淀」不是「泄漏」—— 两种错代价不对称时判据偏向贵的那侧,与 P3B §八 FAILING_VERDICTS 同一条经验。 B 落点 = memory/ 与 SKILL.md 都写,**必要时迭代 soul.md / agent.md**。 C 触发 = 定时每日一次。 D 顺序 = 上游修复与 dream 一起做。 ## B 把范围扩大了,随之而来的约束单列一节 「本体只有一份」意味着写 agent.md / soul.md 影响**所有雇了它的公司**, 而不是提炼出这条经验的那一家。所以四个落点按可逆性分层,并记了四条硬约束: · agent.md 有一处 2000 字符截断 —— **作用点要说准**:那是给规划 agent 看的 「角色定义摘录」(graph-engine.js:915),agent 自己那条装配链不截断。 判据因此是「保证前 2000 字符仍然自足」,不是「不许追加」。 (初稿我按记忆写成「装配时只读前 2000 字」,查了代码才改对。) · 这四个里三个是 git 跟踪的**定义**,不是运行态 —— dream 改它们会进 git status。 · 毕业闸门读这些文件,写坏会让本体雇不进任何公司。 · 必须能分别回滚:经验写坏只影响上下文,agent.md 写坏影响所有公司。 ## 还没定的 决策 D(提炼质量怎么评);B.2 里「定义文件直接写还是走提案」—— 我建议走提案并写进了推进步骤,但那是建议不是拍板。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Showing
1 changed file
with
216 additions
and
0 deletions
docs/todo/system-design/29-dream-design.md
0 → 100644
| 1 | +# 29-DREAM · 经验汇流(dream)—— 设计草案 | |
| 2 | + | |
| 3 | +> **所属**: [28 Agent 注册表统一](../../done/system-design/28-agent-registry-unification.md) §5.6b 锁住的那条约束的下游设计;未确认项来源 [28-followups §1.1](./28-followups.md)。 | |
| 4 | +> **日期**: 2026-08-20 | |
| 5 | +> **状态**: 📝 **四条取舍已由用户拍板(2026-08-20,见 §三),实现未开始。** | |
| 6 | +> 标 ✅ 的是已生效的约束或有实测证据的事实;标 🔒 的是本轮拍板的决定。 | |
| 7 | + | |
| 8 | +--- | |
| 9 | + | |
| 10 | +## 〇、一句话 | |
| 11 | + | |
| 12 | +dream 是设想中定时跑的一套逻辑:整理**所有 agent 在所有公司**的 history 与 memory, | |
| 13 | +**显式提炼**后沉淀到 skill memory 上,让经验跨公司汇流,而**不泄漏任何一家公司的具体信息**。 | |
| 14 | + | |
| 15 | +--- | |
| 16 | + | |
| 17 | +## 一、开工前先看清原料:它现在是脏的 | |
| 18 | + | |
| 19 | +> 这一节全是**实查 2026-08-20 的仓库状态**得到的,不是推测。 | |
| 20 | +> 结论很直接:**在原料变干净之前,做提炼是没有意义的**——垃圾进,垃圾出。 | |
| 21 | + | |
| 22 | +### 1.1 现在写进 memory 的不是「事实」,是截断的日志行 | |
| 23 | + | |
| 24 | +`memory-service.appendToMemoryMd()` 的全部逻辑是: | |
| 25 | + | |
| 26 | +```js | |
| 27 | +const taskOneLine = (task || '').split('\n')[0].substring(0, 80); | |
| 28 | +const resultOneLine = (result || '').split('\n')[0].substring(0, 100); | |
| 29 | +const entry = `- [${timestamp}] ${taskOneLine} → ${resultOneLine}`; | |
| 30 | +``` | |
| 31 | + | |
| 32 | +**取第一行、砍到 80/100 字符**。这不是提炼,是搬运 + 截断。 | |
| 33 | +`cto/_global/memory/memory.md` 的实际内容: | |
| 34 | + | |
| 35 | +``` | |
| 36 | +## 关键事实 | |
| 37 | +- [2026-08-20] [TASK from ceo] → ..._global/` 下不新增 `callback-*` 目录。反向验证过:临时把 `isTestEnv` 改成 `() => false`,该用例 FAIL。 | |
| 38 | +- [2026-08-20] [SYSTEM HEARTBEAT] → 🔧 [TOOL_CALL] Bash (ID: toolu_01RsQ3gh5niCFyUZMFZj2hxF) | |
| 39 | +- [2026-08-20] [SYSTEM HEARTBEAT] → 🔧 [TOOL_CALL] Bash (ID: toolu_01MG6RqDgqcRCi5ageGk84Kt) | |
| 40 | +``` | |
| 41 | + | |
| 42 | +后三条是**工具调用 id**。它们作为「关键事实」被写下来、被注入下一轮提示词、 | |
| 43 | +并且会成为 dream 的原料。第一条更糟:它是一句话的**中段**(开头被截掉了), | |
| 44 | +读起来像事实,其实缺主语。 | |
| 45 | + | |
| 46 | +> §5.6b 说的错误版本是「每轮对话自动把原文写进共享 SKILL.md」。 | |
| 47 | +> **现在这套已经是那个错误版本的单公司版了** —— 只是还没跨公司共享,所以还没泄漏。 | |
| 48 | +> dream 如果直接消费它,等于把这个错误放大到跨公司。 | |
| 49 | + | |
| 50 | +### 1.2 长期记忆是一个 3000 字符的滚动窗口 | |
| 51 | + | |
| 52 | +`MAX_MEMORY_MD_SIZE = 3000`。超了就截。所以「长期记忆」实际是**最近若干条截断日志**, | |
| 53 | +没有任何按重要性保留的机制。 | |
| 54 | + | |
| 55 | +### 1.3 「公司态目录」里有不是公司的东西 | |
| 56 | + | |
| 57 | +`system/agents/{aid}/{cid}/` 是约定,不是校验。实查 96 个二级目录里混着: | |
| 58 | + | |
| 59 | +| 形态 | 例子 | 是什么 | | |
| 60 | +|---|---|---| | |
| 61 | +| 真公司 | `e2e-demo` / `mycompany` / `idearun` | ✅ dream 的原料 | | |
| 62 | +| 保留段 | `_global` | 全局 agent 的落点,算不算「一家公司」需要定 ❓ | | |
| 63 | +| ArenaSK 时代的运行态 | `train/` `workspace/` | ❌ 不是公司,是训练 / 工作目录 | | |
| 64 | +| **测试残留** | `tmp-w7-bootstrap-1786986291739-9n2xv`、`qroute-co-13/14`、`zz-*` | ❌ 夹具,且**带时间戳**,会无限增长 | | |
| 65 | + | |
| 66 | +**dream 的第一步「枚举所有公司」现在没有可靠答案。** | |
| 67 | +可靠的答案在库里:`company_agents` 表(28 批次 4 起「这家公司雇了谁」的唯一真相源)。 | |
| 68 | +目录只能用来定位文件,不能用来枚举公司。 | |
| 69 | + | |
| 70 | +### 1.4 绝大多数 memory 是空模板 | |
| 71 | + | |
| 72 | +75 份 `memory.md` 里,**只有 7 份**有非模板内容(`innovator-evolver` / `master` / | |
| 73 | +`org-innovator` / `innovator-digest` / `innovator-hunt` / `coo` / `qa-judge`), | |
| 74 | +其余全是 `_(刚入职,尚无记忆)_`。 | |
| 75 | + | |
| 76 | +> 这条对设计有直接影响:**dream 现在跑起来几乎没有原料**。 | |
| 77 | +> 它的价值随「真跑的量」增长,不是上线即有收益的东西。 | |
| 78 | + | |
| 79 | +--- | |
| 80 | + | |
| 81 | +## 二、已经生效的约束(不随设计变化) | |
| 82 | + | |
| 83 | +✅ **公司态目录是 dream 的唯一原料,不许被任何清理策略当垃圾扫掉**(§5.6b)。 | |
| 84 | +任务态(`{aid}/{cid}/{taskId}/`)可清,公司态(`{aid}/{cid}/memory/` 与 `conversations/`)不可清。 | |
| 85 | + | |
| 86 | +✅ **沉淀必须是提炼后的抽象,不是自动搬运原文。** | |
| 87 | +错误版本真的发生过(28 号第一轮验收挖出的最严重 blocker):直接灌原始对话 | |
| 88 | += 把 A 公司的机密喂给 B 公司。 | |
| 89 | + | |
| 90 | +✅ **目录布局本身就是 dream 的主查询索引**: | |
| 91 | +`某个 agent 在所有公司的全部记忆 == glob: system/agents/{aid}/*/memory/`,一个 glob 就够。 | |
| 92 | +(前提是 1.3 那个「二级目录不都是公司」的问题被解决。) | |
| 93 | + | |
| 94 | +--- | |
| 95 | + | |
| 96 | +## 三、需要定的取舍 | |
| 97 | + | |
| 98 | +### 🔒 决策 A —— 去敏的判据:**独立判定 agent + 写作要求**(2026-08-20 拍板) | |
| 99 | + | |
| 100 | +**定案 = A3 + A1 组合**:提炼 agent 按 A1 的写作要求产出,产出后由**另一个只负责判 | |
| 101 | +「这段话能不能给别家公司看」的 agent** 过闸门,判不准就拒绝沉淀。 | |
| 102 | + | |
| 103 | +理由(也是本仓库反复验证过的一条):**两种错的代价不对称时,判据要偏向贵的那一侧** | |
| 104 | +(P3B §八 关于 `FAILING_VERDICTS` 的那段)。「少沉淀一条经验」与「泄漏一次机密」显然不对称。 | |
| 105 | +失效方向因此是「少沉淀」,不是「泄漏」。 | |
| 106 | + | |
| 107 | +下面三种形态的对比留档,说明为什么选它。 | |
| 108 | + | |
| 109 | +### 决策 A 的备选(留档) | |
| 110 | + | |
| 111 | +这是**安全边界**,也是整个设计里唯一「做错了会造成真实损害」的一条。三种可选形态: | |
| 112 | + | |
| 113 | +| 方案 | 判据 | 代价 | | |
| 114 | +|---|---|---| | |
| 115 | +| **A1 白名单式**:只允许提炼成「不含任何专有名词的方法论」 | 产出里不许出现公司 id、人名、产品名、URL、文件路径 | 最安全;但也最容易把有用的经验一起滤掉(「给 X 公司做官网时发现静态站点要先定验收脚本」→ 只剩「要先定验收脚本」) | | |
| 116 | +| **A2 黑名单式**:过滤已知敏感模式后放行 | 正则 / LLM 扫一遍公司 id、密钥形态、路径 | 保留信息量更多;**漏一个模式就是一次泄漏**,而且是静默的 | | |
| 117 | +| **A3 二次判定**:提炼 agent 产出后,由**另一个** agent 只负责判「这段话能不能给别家公司看」 | 判定是一次独立的 agent 调用,双方不共享上下文 | 成本翻倍;但与本仓库既有的 validator / triager 模式同构,且**失效方向可控**(判不准就拒绝沉淀,宁可少沉淀) | | |
| 118 | + | |
| 119 | +### 🔒 决策 B —— 沉淀落点:**四个都要,按「改动的可逆性」分层**(2026-08-20 拍板) | |
| 120 | + | |
| 121 | +用户定的是:`system/agents/{aid}/memory/` **和** `SKILL.md` 都要写, | |
| 122 | +**必要时还要迭代 `soul.md` / `agent.md`**。 | |
| 123 | + | |
| 124 | +这比原来三选一的范围大得多,**因为它引入了「agent 改写自己的定义」这件事**。 | |
| 125 | +下面这一节是这个决定的直接后果,不是可选的补充说明。 | |
| 126 | + | |
| 127 | +#### B.1 四个落点不是一回事,风险差三个数量级 | |
| 128 | + | |
| 129 | +| 落点 | 是什么 | 谁受影响 | 可逆性 | | |
| 130 | +|---|---|---|---| | |
| 131 | +| `{aid}/memory/`(本体根) | **经验积累**,跨公司那一份 | 只影响这个 agent 读到的上下文 | 删掉即可,无副作用 | | |
| 132 | +| `SKILL.md` | **能力定义**:这个 agent 会什么 | 同上,但会进 Skill 市场的语义 | 覆盖前留旧版即可回滚 | | |
| 133 | +| `soul.md` | **人格**:它怎么说话、怎么取舍 | 所有雇了这个本体的公司 | 改坏了表现为「行为漂了」,**不报错** | | |
| 134 | +| `agent.md` | **行为契约**:它必须做什么、禁止做什么 | 所有雇了这个本体的公司 | 改坏了可能让整条链路静默失效 | | |
| 135 | + | |
| 136 | +**28 号的核心裁决是「本体只有一份」** —— 所以写 `agent.md` / `soul.md` 的影响面是 | |
| 137 | +**所有雇了它的公司**,而不是提炼出这条经验的那一家。这恰恰是 §5.6b 担心的那种扩散, | |
| 138 | +只不过现在是**有意为之**。因此它必须比前两个落点多两道东西: | |
| 139 | + | |
| 140 | +#### B.2 写定义文件的硬约束(这几条不是建议) | |
| 141 | + | |
| 142 | +1. ✅ **`agent.md` 有一处 2000 字符的截断,但作用点要说准**: | |
| 143 | + `graph-engine.js:915` 给**规划 agent** 看的「角色定义摘录」只取 | |
| 144 | + `agent.md` 的**前 2000 字符**(`readFileSync(f).slice(0, 2000)`), | |
| 145 | + 超出部分静默丢弃。agent 自己那条装配链(`prompt-builder`)**不截断**,读全文。 | |
| 146 | + → 后果是:dream 往 `agent.md` **末尾追加**内容,规划侧读到的画像不会变; | |
| 147 | + 但如果追加把重要约束**顶到 2000 之后**(例如重写时调整了顺序),规划侧会无声地少看到那一段。 | |
| 148 | + → 判据:写 `agent.md` 时**保证前 2000 字符仍然自足**(职能说清楚), | |
| 149 | + 新增内容往后放;改动后应当有一条检查盯住这个窗口。 | |
| 150 | +2. ✅ **这四个文件里有三个是 git 跟踪的定义**(`agent.md` / `soul.md` / `SKILL.md`), | |
| 151 | + 不是运行态。dream 改它们 = 改仓库里的文件 → 会被边界守卫看见,也会进 `git status`。 | |
| 152 | + → 需要明确:dream 的产出是**直接落盘**还是**提案 + 人工合并**。 | |
| 153 | +3. ✅ **毕业闸门读这些文件**(`missingBodyDefinition` / `promoteDraftIfComplete`)。 | |
| 154 | + 把 `agent.md` 写空 / 写坏会让本体退回「定义没填满」,**雇不进任何公司**。 | |
| 155 | +4. ✅ **必须可回滚且能分别回滚**:经验沉淀写坏了只影响上下文,`agent.md` 写坏了影响所有公司。 | |
| 156 | + 两者混在同一次提交里,回滚粒度就没了。 | |
| 157 | + | |
| 158 | +> **建议(仍需你定)**:`memory/` 与 `SKILL.md` 由 dream 直接写; | |
| 159 | +> `soul.md` / `agent.md` 只产出**提案**(写到 `{aid}/memory/proposals/` 下),由人过一眼再合并。 | |
| 160 | +> 理由是上面第 1、3 条:这两个文件写坏的失效方向都是**静默**的,而 dream 的产出目前 | |
| 161 | +> 没有任何质量评价手段(决策 D 未定)。 | |
| 162 | + | |
| 163 | +### 决策 B 的备选(留档) | |
| 164 | + | |
| 165 | +「skill memory」目前**没有对应的实体**。候选落点: | |
| 166 | + | |
| 167 | +| 落点 | 形态 | 问题 | | |
| 168 | +|---|---|---| | |
| 169 | +| **B1** `system/agents/{aid}/memory/`(本体根,跨公司那一份) | 与公司态并列,一个 agent 一份跨公司经验 | 目前只有 `zz-scaffold-readonly-fresh` 有这个目录,等于新建一层;**但它天然与 §5.6b 的 glob 对齐**,读的时候本体根 + 各公司态一起加载 | | |
| 170 | +| **B2** 本体的 `SKILL.md` | 复用现有概念(5 个本体已有 SKILL.md) | **这正是 §5.6b 点名的错误版本的落点**;SKILL.md 是「能力定义」,不是「经验积累」,混在一起之后没法分别回滚 | | |
| 171 | +| **B3** `<repo>/../data/skills/` 那 27,059 条 Skill 仓库 | 与 ArenaSK 的 Skill 市场打通 | 那是**面向分发**的仓库,写进去等于对外发布;且跨了两个 data 根 | | |
| 172 | + | |
| 173 | +(拍板结果见上:B1 与 B2 都要,另加 `soul.md` / `agent.md` 两个定义落点。) | |
| 174 | + | |
| 175 | +### 🔒 决策 C —— 触发时机:**定时,每日一次**(2026-08-20 拍板) | |
| 176 | + | |
| 177 | +备选留档如下。 | |
| 178 | + | |
| 179 | +> ⚠️ **与 §1.4 的冲突要知道**:实查 75 份 `memory.md` 里只有 7 份有非模板内容, | |
| 180 | +> 所以每日跑起来**绝大多数 agent 会是空转**。这不是反对定时,是要求实现时做到: | |
| 181 | +> **没有新原料就不起 agent 调用**(判据:上次 dream 之后有没有新的 session 摘要), | |
| 182 | +> 否则每天会有几十次「读完发现没东西」的 LLM 调用在烧钱,而且日志里全是噪声。 | |
| 183 | + | |
| 184 | +| 方案 | 说明 | | |
| 185 | +|---|---| | |
| 186 | +| **C1 定时**(如每日一次) | 简单;但没有真跑的日子会空转,有大量真跑的日子又攒得太多 | | |
| 187 | +| **C2 按量**(某 agent 新增 N 条 session 摘要后触发) | 与实际产出量对齐;需要一个计数落点 | | |
| 188 | +| **C3 手动**(控制台一个按钮 + API) | 先手动跑一段时间看提炼质量,稳定了再自动 | | |
| 189 | + | |
| 190 | +### ❓ 决策 D —— 提炼质量怎么评 / 失败怎么办 | |
| 191 | + | |
| 192 | +这一条**可以先不定**,但要知道它没定: | |
| 193 | + | |
| 194 | +- 没有评价手段时,dream 的产出**无法验证对错**——它和 FDE 那边 | |
| 195 | + 「LLM 自己汇报分数」的问题是同一个(见 [architecture_todo_list](../future/architecture_todo_list.md) §1)。 | |
| 196 | +- 一个便宜的起步:dream 每次产出都**保留原料指针**(哪几条 session 提炼出这一条), | |
| 197 | + 人抽查时能顺着回去看。**可追溯**比「可评分」便宜得多,也更早有用。 | |
| 198 | + | |
| 199 | +--- | |
| 200 | + | |
| 201 | +## 四、推进顺序 🔒 **上游与 dream 一起做**(2026-08-20 拍板) | |
| 202 | + | |
| 203 | +用户定的是两件一起做,不分先后。拆成可验收的步骤: | |
| 204 | + | |
| 205 | +| 步 | 内容 | 为什么不能省 | | |
| 206 | +|---|---|---| | |
| 207 | +| 1 | **`appendToMemoryMd` 停止截断搬运**(§1.1) | 它现在把工具调用 id 当「关键事实」写进 `memory.md` 并注入**每一轮**提示词。dream 直接消费它 = 把这个错误放大到跨公司 | | |
| 208 | +| 2 | **「有哪些公司」改查 `company_agents` 表**(§1.3) | 目录里混着 `train/` `workspace/` 和带时间戳的测试残留,拿目录枚举公司必然把它们当原料 | | |
| 209 | +| 3 | **dream v0**:枚举 → 提炼 agent → 去敏判定 agent(决策 A)→ 写 `memory/` + `SKILL.md` | 主体 | | |
| 210 | +| 4 | **定义文件走提案**(决策 B.2 建议):`soul.md` / `agent.md` 只产出提案 | 两者写坏的失效方向都是静默的,而质量评价(决策 D)还没定 | | |
| 211 | +| 5 | **可追溯**:每条沉淀记住它是从哪几条 session 提炼来的(决策 D 的便宜起步) | 没有它,dream 的产出无法验证对错 —— 与 FDE 那边「LLM 自己汇报分数」是同一个问题 | | |
| 212 | + | |
| 213 | +**空转保护**(决策 C 的直接要求):没有新原料就不起 agent 调用。 | |
| 214 | + | |
| 215 | +> 本文档仍**不是实现规格**。决策 D(质量怎么评)未定;B.2 里「定义文件直接写还是走提案」 | |
| 216 | +> 也还需要你点头 —— 我按「走提案」写在了步骤 4,但那是我的建议,不是你拍的板。 | ... | ... |