muse-agent-example/docs/plans/2026-08-28-能力原型间收敛方案.md

263 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 能力原型间收敛方案(意图 / 问题 / 解决方案)
日期:2026-08-28
范围:`agent-example/` 全仓结构裁决;不新增运行时能力。
状态:取代 [2026-08-24-双底座适配接缝](2026-08-24-双底座适配接缝.md) 作为当前执行入口。该 plan 的 DSH 真实模型、只读工具闭集、Muse 业务旅程三项未验收工作**冻结降级**为本方案 P2;已完成的无宿主门禁与失败闭环保留。
证据基线:Git 跟踪 914 文件(2026-08-28 复核);核心实现 41 文件占 4.5%;`dispatch_agent_task.py` 743 行;Pi runner 4 处调用、`muse_role` 直调 8 处、`chat_governed` 直调 6 处;`muse-cloud` 已有 9 个业务模块。远程 PG `muse-example` 库存量 978 MB / 23.5 万行(2026-08-28 实测,含抽取成果与向量)。
修正记录:2026-08-28 存储裁决修正——「文件系统代替数据库」改为「文件 + 本地 SQLite 分治」;万级章节、千级卡片、高频 run 与向量检索必须有库,纯文件方案会产生几十万小文件且丧失关联查询。
---
## 1. 我的意图(第一性原理)
终极目标只有一句话:
> **写出能上起点月票榜前十、番茄月榜前十的小说。**
它由三个支撑性质构成,每个性质对应一组**最小必要实现**,其余皆为可删重量:
| 性质 | 定义 | 最小必要实现 | 不需要 |
|---|---|---|---|
| 写得好 | 题材承诺、前三章启动、前十章追读、人物、声音、钩子 | 方法 skill(文本)+ 角色定义 + 一条写作流程链 | 43 个带脚本的 muse skill 仪式 |
| 可回放 | 同一冻结输入、同一条链、可重跑、可对比 | 冻结快照 + 本地库 append-only 运行表 + 同链重跑 | 远程数据库服务、raw vault、证据账本系统 |
| 可复利 | 观察 → 教训 → 验证 → 升格 → 下次实际消费 | 会话事件流 + 人审记录(含修订 diff,web 审查工作台录入)→ lesson(证据强制绑定)→ 人批准 → merge 进 skill → A/B 回放归因 | 无记录支撑的 skill 文本自我迭代、通用作品管理产品外壳 |
| 上榜(外部结果) | 内部质量门无法证明,需要外部反馈归因 | 起点/番茄数据人工导出 + 导入格式 + 归因对比 | 自动爬虫(合规风险) |
判定原则:**凡是不在这张表右二列的实现,都是通往目标的摩擦,不是资产。**
## 2. 现有问题(按证据排序)
| # | 问题 | 证据 |
|---|---|---|
| P1 | 四个系统叠在一个仓库:创作生产、Agent 执行底座、评测实验室、观测控制台 | `muse/` 340 + `framework/` 299 + `tests/` 109 文件的职责分布 |
| P2 | 三条模型执行路线并存且不共享接口 | Pi runner(dispatch + 2 bridge + two_phase_writer);`muse_role` 直调 8 处;`chat_governed` 直调 6 处 |
| P3 | 名词多义:Agent = 角色 + 进程;Skill = 方法文本 + 业务命令 + 测试对象;Harness = 运行支架 + 回放评测 + 开发测试 | 同一 `skills.json` 同时充当运行时清单与开发测试清单 |
| P4 | 方法 skill 存了三份:源 + 两份字节级相同的生成投影 | `.agent/skills`(148 md)+ `framework/catalog/{dsh,pi}`(280 文件,占全仓 30.7%) |
| P5 | 数据层形态错误,且两面都不成立:卡片/向量/运行/快照这类高频与检索数据需要库;但库不应是远程共享 PG 加证据账本系统;纯文件方案在万级章节 + 千级卡片 + 高频 run 下产生几十万小文件 | 卡片与向量依赖远程 PG(100.64.0.8 共享实例、pgvector 挂在共享容器内、凭据明文入库);record-run-evidence 10 脚本构成账本系统;运行记录走文件目录会随频率爆炸 |
| P6 | 与产品栈平行:monorepo 内 `muse-cloud` 已有 9 个业务模块,`agent-example/muse/` 用 Python 又实现一遍 content/knowledge/authority | `muse/authority` 54 文件(其中 db 31)与 muse-module-content/knowledge 职责重叠 |
| P9 | 复利的数据基础缺口:候选采纳无人审结构与人的标识(creator/updater 分不清人与脚本);人改写产物的修订 diff 无处落;skill 与会话证据无配对链 | `example_candidate` 只有 agent 语义审查位;108 的 lesson 状态机有 decided_by 但蒸馏来源无 review 配对;`.agent/skills` 148 md 无证据链,属未验证假设 |
| P7 | 外部反馈缺口:无读者/榜单数据的采集、导入与归因链 | 全仓搜索无留存/追读/月票反馈回路;这是唯一真正的**能力**缺口 |
| P8 | 核心占比失衡:核心实现 41/914 = 4.5%,95% 是脚本/测试/投影/规则/文本 | 互斥分类统计(2026-08-28) |
问题的共同根因:**把"治理"做成了默认路径**——每个动作都要过装配、策略、落库、回执的流水线,而不是把治理做成可插拔的旁路。
## 3. 解决方案
### 3.1 定位裁决
> **`agent-example` = 能力原型间**:验证"AI 能否写出上榜小说"这条链。
> 产品功能(作品管理、用户采纳、知识库、看板)归 `muse-cloud` / `muse-studio`。
> 验证成立的能力**移植**进产品栈;原型间不长期持有产品实现,不与产品栈平行生长。
### 3.2 结构裁决:4 层 / 3+1 域
不采用六层合同层——正交穷尽是分析工具,不是实施蓝图;层级越多,每次任务的读取成本越高。
| 层 | 内容 | 规模上限 |
|---|---|---|
| L0 资产 | 角色定义、方法 skill(纯文本) | 按需增长 |
| L1 执行底座 | 协议 + 两个执行器 + 宿主适配 | ≤ 10 个文件 |
| L2 业务流程 | 写作链、上下文冻结、回放链 | 收敛不扩张 |
| L3 数据 | works / runs / lessons | gitignore 为主 |
| 领域 | 职责 |
|---|---|
| 资产域 | `agents/` + `skills/` |
| 执行域 | `runtime/` |
| 业务域 | `muse/` |
| 验证平面 | `tests/`(含适配器一致性测试;"adapter-harness"不是独立域) |
Skill 三分法随之落地:方法 skill(模型消费,纯文本)归 `skills/`;Muse 业务能力(有副作用)归 `muse/**/`;回放场景(驱动评测)归 `muse/replay/cases/`。三者不共享 catalog。
### 3.3 目标目录结构
```text
agent-example/
├── agents/ # L0:角色定义
│ └── <role>.md
├── skills/ # L0:方法 skill 唯一源(扁平)
│ └── <skill>/
│ ├── SKILL.md
│ └── references/*.md # 升格的 lesson merge 到这里
├── runtime/ # L1:执行底座(替代 framework/,≤10 文件)
│ ├── protocol.py # Request / Event / Result + 校验
│ ├── agent_executor.py # 多轮 Agent 调用
│ ├── completion_executor.py # 单次受治理调用(吸收 muse_role)
│ ├── runs.py # 不可变 run 目录读写
│ └── adapters/{pi,dsh}.py # 每宿主一薄文件
├── muse/ # L2:业务流程
│ ├── flow/ # plan-chapter → write → gate → adopt
│ ├── context/ # assemble / freeze
│ └── replay/ # cases/ + 重跑 + 对比
├── web/ # L2 人机接口:人审工作台(薄)
│ ├── app.py # 只读 muse.db + 三个写端点
│ └── static/ # 待审队列 / 审查详情(diff 并排) / lesson 审批
├── lessons/ # L3:复利源(文件,进 git)
│ ├── pending/ # agent 产出的候选教训
│ └── confirmed/ # 人确认后待升格
├── data/ # L3:运行数据(gitignore)
│ ├── muse.db # 本地 SQLite 单文件:卡片/向量/运行/快照/候选
│ └── works/<book>/chapters/ # Canonical 正文(文件权威,库只存索引)
├── tests/
│ ├── protocol/ # 合同测试
│ ├── adapters/ # 适配器一致性
│ └── e2e/ # 一章全链 + 一次回放
└── docs/
```
### 3.4 关键合同
**存储分治合同(按访问模式,不按偏好)**
| 数据 | 访问模式 | 存储 |
|---|---|---|
| 方法 skill / 角色 | 人读改、要 diff | 文件 + git |
| lessons | 人读改内容 + 状态机流转 | 内容文件;状态、证据绑定、decided_by 在 db |
| 正文 Canonical(万级/作品) | 人审稿改稿 | 文件为权威,库只存索引(path + 哈希 + 关系) |
| 实体卡片(千级) | 关联查询、倒排 | `data/muse.db` |
| 嵌入向量(万级 × 1024 维) | 近邻检索 | db 内 blob + 暴力扫;量级超出再上 sqlite-vec |
| 运行记录(高频 append) | 回放取单条、analytics | db 内 append-only 表 |
| 冻结快照(每 run 一份) | 回放整取 | db |
库的形态是**本地单文件 SQLite**,不是远程服务。理由:回放确定性(run 前 `cp muse.db` 即数据基线快照,哈希即冻结);自包含(不依赖 infra 在线、不与产品栈共享实例);无服务进程;凭据退出仓库。现有 2334 行 PG DDL 为标准 SQL,平移成本低;`vector(1024)` 列改 blob + numpy。
**run 记录合同(回放的全部秘密)**
```sql
runs(id, created_at, kind, input_json, output_text, meta_json, skill_set_hash, baseline_hash)
-- input_json:冻结快照内容 + prompt + 角色版本 + 模型 + 参数
-- output_text:原始产出,append 后不可变
-- meta_json:门禁结果、外部反馈指针
-- skill_set_hash:本次消费的 skill 集哈希(效果归因的关键)
-- baseline_hash:运行开始时 muse.db 基线哈希(可选快照副本)
```
回放 = 取一行 `input_json` 重跑 `muse/flow` 同一入口,diff `output_text`。一次运行 = 一行 append,不在磁盘新增小文件。不存在第二条回放系统。
**记录合同(复利的数据基础,平移自现有 example_agent_event / example_lesson 合同)**
```sql
events(run_id, seq, kind, role, tool_name, payload_json, created_at)
-- 完整会话流:user/assistant 消息、工具调用与返回、门禁结果、模型元数据
-- 判断 agent 说了什么、对不对的原始事实
reviews(id, run_id, target, action, reviewer, reason, created_at)
-- 人审动作:action ∈ adopt / reject / revise;target ∈ candidate / lesson / chapter
-- reviewer 必填——人与 agent 自评必须可区分
revisions(id, review_id, kind, before_text, after_text, created_at)
-- 人改写 agent 产物的完整前后文——蒸馏的最高价值监督信号
lessons(id, source_run_ids, source_review_ids, kind, title, content_path,
status, decided_by, decided_at, rationale, target_ref)
-- status: proposed → reviewing → promoted/rejected,自动升格 DB 级拒绝
-- source_run_ids / source_review_ids 强制非空:无证据指针的教训不许登记
```
lesson 内容存 `lessons/` 文件(人读改),状态机与证据绑定在 db。砍掉的是远程 PG 与十脚本流水线的形态,保留的是事件流、人审状态机、证据绑定这些合同。
**存量数据迁移合同(PG → SQLite,分类迁移非全量搬迁)**
现状:远程 PG `muse-example` 库 978 MB / 23.5 万行(2026-08-28 实测)。分三类处置:
| 类别 | 内容 | 去向 |
|---|---|---|
| 成果数据(含真实 LLM 成本,必迁) | knowledge_draft 25,020 / knowledge_embedding 41,551 / content_chapter+block 23,566 / knowledge_entity·document·base / reference_work / ai_flavor_case 788 / rule 26 / voice_baseline 2 | cards、向量 blob、`data/sources/<book>/` 文件 + 索引;人感规则进 skill |
| 记录数据(复利原料,迁) | run_receipt 31 / candidate+cas 43 / **user_decision 6(回填 reviews,reviewer 保留)** / planning_section 10 / context_freeze 10 | runs / snapshots / reviews |
| 过程数据(不迁) | upgrade_audit 91,600 / parse_task+scaffold 23,554 / upgrade_card_state·presence·alias·window 21,406 / clean_log / revalidation 3,156 | PG 库迁移验收后转只读归档,不删除 |
变换规则:剥离 Yudao 框架字段(tenant_id/creator/updater/deleted);`vector(1024)` 逐行转 float32 bytes 入 blob;参考书章节导出为文件。历史 `example_agent_event` / `raw_content` 为空表,无存量会话记录可迁——记录合同自新架构起积累。
**两个执行器接口**
```text
AgentExecutor 多轮会话、工具调用、事件流、宿主适配
CompletionExecutor 单次 prompt/response、结构化输出、模型治理
DeterministicTool 无模型确定性操作(快照、校验、状态迁移)
```
`muse_role` 并入 CompletionExecutor;`chat_governed` 各调用点改走同一接口。框架不认识 `writer`、`work_id`、候选状态。
**蒸馏闭环(复利的完整回路)**
```text
events(会话)+ reviews(人审)+ revisions(修订 diff)
→ 蒸馏任务(本身也是 run,kind=distill,input 携带 run_ids/review_ids)
→ lesson 登记(db:证据指针强制 + 状态机;内容:lessons/ 文件)
→ 人批准(reviews 再记一条:reviewer + rationale)
→ merge 进 skills/<skill>/references/(git commit 可追溯)
→ 下次运行 skill_set_hash 变化
→ A/B 回放:同题、同 baseline、新旧 skill 集各跑 → 盲评对比 → 归因
```
判断 agent 对错的三个信号源:机械门禁(gate 结果进 events,便宜即时)、人审(reviews/revisions,最高权重)、外部反馈(P2,延迟终极)。缺任何一层,复利都退化为无监督的自我总结。
**skill 定位修正**:`skills/` 现有文本是来自通用方法论的初始先验,不是已验证知识。复利闭环的职责是逐步用本项目 events + reviews 蒸馏出的验证知识替换/修订它们;无归因证据的 skill 变更不进 references。
**投影合同**:`skills/` 是唯一源;投影生成到各宿主原生位置(`.pi/skills/` 等)并 gitignore。Git 中不存在第二份 skill 副本。
### 3.5 现有 → 目标映射
| 现有 | 去向 |
|---|---|
| `.agent/agents`、`.agent/skills` | 移到顶层 `agents/`、`skills/`,扁平化 |
| `framework/catalog/{dsh,pi}`(280 文件) | 删出 git;投影生成到宿主原生位置 |
| `framework/primitives` + `adapters` | 收进 `runtime/` |
| `dispatch_agent_task.py`(743 行) | 拆:装配 → `muse/flow`;执行 → `runtime/agent_executor`;登记 → `runtime/runs.py` |
| `muse_role` | 并入 `runtime/completion_executor.py` |
| `muse/content`、`flow`、`context` | 保留,收敛为 `muse/flow` + `muse/context` |
| `quality/replay` | 移为 `muse/replay`,改用生产链入口 |
| `humanization` | 降为 `skills/humanization-*` 方法 skill + 少量门禁脚本 |
| `authority/db`(31 个 PG DDL) | schema 平移为 `data/muse.db` 的版本化 SQLite 迁移;远程 PG 依赖与明文凭据退出 |
| `record-run-evidence`(10 脚本) | 合同平移进 SQLite:event 流、raw 全文、lesson 状态机的表设计照搬;十脚本流水线形态废弃 |
| `studio/` | 收缩为 `web/` 人审工作台:审查阅读保留(复利闭环的数据采集端),丢弃产品外壳(作品管理、用户体系、多租户归 muse-studio) |
| `tests/skills/`(102 文件) | 按 owner 归档到各模块;停止为每个脚本新增仪式性测试 |
### 3.6 迁移顺序(每步配机械门禁)
执行状态(每完成一步在此打标,格式:`[x] YYYY-MM-DD <一句话证据>`;新会话从第一个未勾选项繼续):
- [x] P0.1 删 catalog 双投影 [x] 2026-08-28 git ls-files framework/catalog 为空;generate 写入 .pi/skills 与 .dsh/skills(各 15 个,gitignore);架构测试 12 项绿
- [x] P0.2 拆 dispatch_agent_task [x] 2026-08-28 CLI 66 行;runtime 纯度门绿;dispatch 离线测试 37 项绿
- [x] P0.3 建 data/muse.db(runs/events/reviews/revisions/cards) [x] 2026-08-28 WAL+五表;dispatch 假 launcher 写入 run+events;revise 含 revisions;同 input 重跑 output 一致;git status 不因运行新增未忽略文件
- [x] P0.4 存量迁移 PG → SQLite [x] 2026-08-28 成果+记录 COUNT pg=sqlite 成对相等(含 document/base/refwork/candidate/cas/planning/freeze);向量抽样余弦≈1.0;章节 11785=11785;reviews=6;muse.db 150MB;生产派发默认不写 PG
- [x] P1.4 蒸馏闭环(lesson 证据强制 + 人批准 + skill 升格) [x] 2026-08-28 空证据指针被拒;一条 lesson 经 run/review id 升格进 references
- [x] P1.5 回放链改用生产 flow 入口 [x] 2026-08-28 muse.replay.production_run_dispatch is muse.flow.dispatch.run_dispatch
- [x] P1.6 人审工作台 web/ [x] 2026-08-28 写面仅 reviews/revisions/adopt;adopt 只记 reviews
- [x] P2.6 外部反馈导入与归因 [x] 2026-08-28 起点/番茄 CSV 导入产出归因报告
- [x] P2.7 dsh/claude 适配 + 归因分析页 [x] 2026-08-28 Pi/DSH/Claude 适配器一致性测试绿
**P0 —— 冻结一切新功能,先减重**
| 步骤 | 内容 | 验收门禁 |
|---|---|---|
| P0.1 | 删 catalog 双投影出 git,投影直生成到宿主目录 | `git ls-files | grep catalog` 为空;干净 clone 后投影命令可重跑;架构测试更新为校验宿主原生位置 |
| P0.2 | 拆 `dispatch_agent_task.py` | 该文件删除或 < 100 行;`runtime/` 无 muse 业务 import(复用 `test_framework_port_purity` 模式) |
| P0.3 | `data/muse.db` 落地:runs / events / reviews / revisions / cards 表 + 迁移骨架;freeze-context 与 search-knowledge 对接(向量 blob + 暴力扫) | 一次真实写作运行写入完整 run + events 行;一条人审动作写入 reviews(revise 时含 revisions diff);同 input 重跑可 diff;`git status` 不因运行产生新文件 |
| P0.4 | 存量迁移工具 `migrate_pg_to_sqlite.py`:按上表分类导出成果与记录数据,过程数据留 PG | 成果表行数逐一对账相等;向量抽样 PG vs SQLite 余弦相似度 = 1.0;章节导出文件数 = 行数且抽读完好;user_decision 回填 reviews 行数 = 6;报告 muse.db 体积(预期 < 300MB);验收后 PG 库转只读 |
**P1 —— 复利闭环**
| 步骤 | 内容 | 验收门禁 |
|---|---|---|
| P1.4 | 蒸馏闭环:lesson 登记(证据指针强制)+ 人批准 + skill 升格 + skill_set_hash 记录 | 一条 lesson 从 source_run_ids/review_ids 到 merge 进 references 全链可追溯;无证据指针的 lesson 被 DB 拒绝;一次 A/B 回放产出新旧 skill 集归因对比 |
| P1.6 | 人审工作台 `web/`:待审队列 + 审查详情(候选/冻结输入/门禁/diff 并排,revise 即录 revisions)+ lesson 审批;写面仅 reviews / revisions / adopt(adopt 调用 flow,不自行写文件) | 一次完整 adopt → revise(含 before/after diff)→ reviews 落库全程在 web 完成;web 不产生 reviews/revisions 之外的表写路径 |
| P1.5 | 回放链改用生产 flow 入口 | replay 入口与生产 flow import 同一模块;不存在平行执行代码 |
**P2 —— 补缺口与后置项**
| 步骤 | 内容 | 验收门禁 |
|---|---|---|
| P2.6 | 外部反馈导入格式(起点/番茄人工导出)+ 归因对比 | 一份导入数据 → 一份归因报告 |
| P2.7 | dsh / claude 适配;归因/分析页(A/B 对比、runs 浏览,并入 web/) | 适配器一致性测试通过 |
### 3.7 明确不做(防复发清单)
- 不新增第六层合同层、第八个领域、"统一治理入口"
- 不引入远程数据库服务;`data/muse.db` 的 schema 变更走版本化迁移文件,凭据不入库
- 不为每个业务脚本配仪式性测试;测试只留在 protocol / adapters / e2e 三处
- 不把 DSH 扩展排在 P2 之前
- 不让运行记录落到文件系统:一次运行 = 一行 append;正文文件仅在 Canonical 采纳后产生
- 不接受无 source_run_ids / source_review_ids 的 lesson;人审动作只落 reviews 表,reviewer 必填
- `web/` 只做审查与阅读:待审队列、审查详情、lesson 审批、归因分析;不做作品管理、用户体系、编辑器全家桶——产品外壳归 muse-studio