فهرست منبع

详化脚本构建业务与技术架构分析

SamLee 1 روز پیش
والد
کامیت
39f6eae217
2فایلهای تغییر یافته به همراه791 افزوده شده و 40 حذف شده
  1. 338 12
      脚本构建业务流程分析.md
  2. 453 28
      脚本构建技术架构分析.md

+ 338 - 12
脚本构建业务流程分析.md

@@ -1,10 +1,13 @@
 # ScriptBuild 脚本构建:业务流程分析
 
-> 源码路径:/Users/samlee/Documents/works/脚本构建第二版/aiddit/pattern/patter_from_global_and_build  
-> 分析日期:2026-07-17  
-> 本地分支:script_build_refactor_0709  
-> 本地提交:3b2db59(修复数据来源映射与缺失语义)  
-> 分析方式:静态代码、Prompt、模型与测试结构交叉阅读;未连接线上数据库,未实际发起 ScriptBuild 运行。
+> 上一代真实源码:`/home/sam/image_article_comprehension/aiddit/pattern/patter_from_global_and_build`<br>
+> 本项目:`/home/sam/script-build-and-framework`<br>
+> 分析日期:2026-07-18<br>
+> 上一代分支:script_build_refactor_0709<br>
+> 上一代提交:cc0e2a5<br>
+> 分析方式:逐段阅读入口 Agent、Prompt、工具 Schema/执行体、ORM模型、MySQL DDL迁移、HTTP 和前端消费链,并与本项目 `agent`/`visualization` 现状交叉核对。本次未使用源码中的生产凭据连接外部数据库;所称“DB 证据”指 ORM、迁移 DDL 和已有只读投影代码,不伪称是生产行抽样。
+
+> 证据引用约定:文中 `[代码:文件:行号]`、`[DDL:文件:行号]`、`[Prompt:文件:行号]` 均相对于上述上一代源码根目录;`[现项目:路径:行号]` 相对于本项目根目录。“代码保证”与“Prompt 要求”在本文严格分开。
 
 本文只回答业务问题:系统在为谁生产什么、各 Agent 如何协作、一次构建如何从选题走到正式脚本、候选分支如何评审和合并,以及哪些业务规则目前真正由代码保证。
 
@@ -14,7 +17,7 @@
 
 它的核心业务闭环是:
 
-1. 主 Agent 读取选题、账号人设和策略,冻结本次脚本方向
+1. 主 Agent 读取选题、账号人设和策略,保存本次脚本方向,并按 Prompt 规约将其冻结
 2. 主 Agent 按轮次提出一个阶段目标。
 3. 每一轮把目标拆成一条或多条有边界的实施路径。
 4. 实施 Agent 在独立分支中检索证据并写入段落、元素或段落—元素关系。
@@ -26,9 +29,9 @@
 从业务角度看,这套流程有四个关键特点:
 
 - 最终产物不是一段不可拆解的大文本,而是由段落、元素以及段落—元素关系组成的结构化脚本。
-- branch_id=0 是唯一正式成品;实施 Agent 产出的候选内容必须经过评估和主 Agent 决策后才能进入成品
+- branch_id=0 是唯一正式成品;按业务规约,实施 Agent 产出的候选内容应先经评估和主 Agent 决策再进入成品,但 merge 代码尚未校验评估报告
 - 构建不是一次性生成,而是按“定方向—分轮次—多路径试写—横评—合并—整体评估”的闭环逐步完成。
-- 写作过程要求先取证再创作,并记录证据采用理由,使脚本内容能够追溯到案例、Pattern、外部资料或创作知识
+- 写作过程要求先取证再创作,并记录分支级证据取舍理由;它已提供可追溯基础,但尚不能把每个写入单元严格闭合到某次 retrieval 调用
 
 ## 2. 业务对象与统一语言
 
@@ -38,7 +41,7 @@
 
 ### 2.2 脚本方向
 
-script_direction 是主 Agent 在正式写作前冻结的总目标。它包括 1~3 个脚本目标,以及可选的领域信息和评估维度。它的业务意义是避免实施过程中不断改变“这篇脚本到底要解决什么问题”。
+script_direction 是主 Agent 在正式写作前生成的总目标。Prompt 规定它包含 1~3 个脚本目标及可选的领域评估维度,且“一次写入、全程冻结”;但实现中 `save_script_direction` 只校验非空并直接覆盖字段,没有 compare-and-set 或禁止二次写入。因此“冻结”是当前业务规约,不是代码不变式。[Prompt:prompts/script/script_build_system_v2.md:22-26][代码:script_build_agent_tools.py:3959-4006]
 
 ### 2.3 Round
 
@@ -67,7 +70,7 @@ Path 是一轮中的一条实施路线。每条路线至少包含:
 - 竞争:多个分支解决同一目标,但采用不同侧重点,最终择优。
 - 分工:多个分支解决互不重叠的子目标,可以组合合并。
 
-代码要求一轮只能选择一种模式,不能在同一轮混用。
+Prompt 要求每轮统一选择竞争或分工,且数据模型只在 Round 级存一个 mode,不能表达逐路混用;但代码允许 `mode=None`,所以“必须二选一”尚未完全强制。[代码:script_build_agent_tools.py:2212-2237]
 
 ### 2.7 Evidence 与 DataDecision
 
@@ -367,9 +370,9 @@ DataDecision 不只是日志文本,后续可以回答“这段内容为什么
 
 即使模型试图越权,也拿不到不属于该角色的工具,比单纯在 Prompt 中禁止更可靠。
 
-### 7.6 可观测数据比较完整
+### 7.6 可观测数据类型较多,但引用闭合仍有缺口
 
-Trace、日志、结构化事件、Round、Branch、任务计划和决策表共同提供了较好的运行解释基础。
+Trace、日志、结构化事件、Round、Branch、任务计划和决策表共同提供了解释基础;但事件是 best-effort,DataDecision 没有强制指向具体取数调用,旧详情页也不消费结构化 Event所以应表述为“有多种观测数据”,不应表述为“因果链已完整”。[代码:script_build_event_emit.py:215-223][代码:models.py:664-680][现项目:visualization/EVENT_AUDIT_AND_GAPS.md:7-16]
 
 ## 8. 代码规则与 Prompt 规则的边界
 
@@ -400,3 +403,326 @@ ScriptBuild 的核心设计方向是对的:主 Agent 管方向与决策、实
 - 一套只存在于 Prompt、注释和 Agent 自觉中。
 
 下一步最有价值的工作,是优先把“成品必须来自 base、最终评估必须有效、策略与 Prompt 必须可复现、分支合并必须无冲突”这四类规则变成确定性的应用层合同,再处理 Worker 和 Trace 的生产可靠性。这样既保留现有 Agent SDK 和多 Agent 优势,又能显著降低“看起来运行成功、实际成品不对”的概率。
+
+## 10. 三个平面与当前采用状态
+
+本项目现在同时存在三套不同语义的对象。它们可以被适配,但不能直接改名后当成同一个东西。
+
+| 平面 | 当前真源 | 关键对象 | 已证明的采用状态 |
+|---|---|---|---|
+| 上一代脚本业务平面 | MySQL 中的 ScriptBuild 业务表 | Record、Round、Path、Branch、base、Paragraph、Element、Decision | 外部源码已实现;本次未验证生产部署/实际行 |
+| 本项目 `agent` 通用控制平面 | TaskLedger | Mission/Root Task、child Task、Attempt、ArtifactSnapshot、Validation、PlannerDecision、Operation、Event、Trace | 代码与可执行 E2E 已实现;没有证据表明 legacy ScriptBuild 已接入 |
+| `visualization` 业务读模型 | legacy ScriptBuild MySQL 表的只读投影 | Run/Round/Branch/Retrieval/Evaluation/Artifact 页面节点 | 当前 Provider/Repository 仍直接读 legacy 表,没有使用 `OrchestrationClient` |
+
+对应证据是:`agent` 公开了通用 orchestration 入口,但 visualization Provider 的主键仍是 `script_build_id`,Repository 查询的是 ScriptBuildRecord/Round/Branch/Decision/Paragraph 等旧表。[现项目:agent/agent/__init__.py:30-53][现项目:visualization/backend/app/providers.py:8-64][现项目:visualization/backend/app/repositories.py:65-221]
+
+## 11. 完整输入合同
+
+### 11.1 现有 Topic 发起
+
+`POST /api/pattern/script_builds` 的请求字段是:
+
+| 字段 | 类型/默认值 | 业务语义 | 代码校验 |
+|---|---|---|---|
+| `execution_id` | int,必填 | Pattern execution 挂载点 | 只由 Pydantic 验类型 |
+| `topic_build_id` | int,必填 | TopicBuild 挂载点 | 未校验与 topic/execution 的归属关系 |
+| `topic_id` | int,必填 | 要生成脚本的选题 | 只校验该 ID 存在 |
+| `agent_type` | `AigcAgent` | 执行器类型 | 只接受 `AigcAgent` |
+| `agent_config` | object/null | 主模型、子 Agent 模型、temperature、max_iterations | 模型必须在白名单;temperature 0~2;iterations 1~500 |
+| `data_source_url` | URL string | library/pattern 读取根地址 | 这个入口不做 URL 安全校验 |
+| `strategies_always_on` | int[]/null | 启动时全文注入的 script 策略 ID | 非 script 类型的策略被跳过 |
+| `strategies_on_demand` | int[]/null | 只注入元信息,运行时用 `load_strategy` 加载 | 同上 |
+
+请求定义与配置验证见 [代码:pattern_server.py:1452-1523];普通入口只查 `topic_id` 存在即原样写入三个挂载 ID,而 ORM 又没有数据库外键,因此存在跨 build/execution 错挂风险。[代码:pattern_server.py:1626-1652][代码:models.py:496-503]
+
+### 11.2 上传 Topic JSON 发起
+
+上传模式接受 `json_data`、可选的人工修订 `account_name`、模型配置、数据源和策略。解析器要求:
+
+- 根必须是 JSON object,必须存在非空「选题融合」。
+- 可从 `target_post.channel_account_name` 读取人设账号,接口显式 `account_name` 优先。
+- 依次读「灵感点/目的点/关键点」;「实质/形式」是 dict-of-lists,「意图」是 list。
+- 元素取「名称/说明」,在每个点内以 `(dimension, element_name)` 去重;完全解不出元素则报 400。
+- 正式入库时在一个事务中合成 upload TopicBuildRecord、Topic、Point、CompositionItem 和 PointItemRelation,再单独创建 ScriptBuildRecord。
+
+解析与落库实现见 [代码:script_build_agent_common.py:250-433],接口见 [代码:pattern_server.py:1668-1769]。
+
+### 11.3 Agent 真正收到的运行时输入
+
+HTTP body 不会原样成为一个大 Prompt。运行时组合是:
+
+1. main system prompt = DB `script_build_system` 或文件 `script_build_system_v2.md` + 子 Agent/评估运行附录。
+2. user message = always-on 策略全文 + on-demand 策略元数据 + `请为选题 ID=N 生成一个结构化创作脚本`。
+3. TopicBuildRecord.personal_config 含账号时,再附加 `选题的人设账号=...`。
+4. ContextVar 保存 execution/topic/build/data-source/strategies/branch/round/current-goal,工具调用不需要模型重复传这些 ID。
+
+证据:[代码:script_build_agent_common.py:81-214][代码:script_build_agent_context.py:12-34]。
+
+## 12. 完整输出合同与真相分层
+
+| 输出 | 存储/读取位置 | 消费者看到什么 | 是否最终真相 |
+|---|---|---|---|
+| 主记录 | `script_build_record` | status、summary、direction、config、token/cost、counts、error/time | 运行概况真相,但 counts 有分支污染缺陷 |
+| 正式脚本 | paragraph/element/link 且 `branch_id=0` | 层级段落、四类列/原子点、元素及关联 | 是 legacy 业务成品真相 |
+| 候选补丁 | 同三张工作表且 `branch_id>0` + branch ledger | overlay 后的候选脚本、实现任务、状态、自评/决策理由 | 不是成品,除非 merge |
+| 取证/决策 | data_decision、multipath_decision、task_plan、domain_info | 实现步骤、证据取舍、跨路决策、领域事实 | 是过程记账,并非严格闭合的因果图 |
+| 评估 | subagent Markdown 结果/日志/事件 body | 单表或多表评估报告 | Prompt 要求使用,没有稳定的强类型业务表 |
+| 观测 | DB log、DB event/body、`.trace` | 线性日志、工具/模型/代理事件、message trace | 不是业务真源;event 还是 best-effort |
+
+旧详情 API 只返回 active base 段落/元素和有效关联,另加 topic/build/decision trace/post/script 参考数据;Round、Branch、task plan、data/multipath decisions、domain info 和 structured events 不在该响应中。[代码:pattern_server.py:2280-2442]
+
+## 13. 一轮真实业务步骤的输入、写入与输出
+
+| # | 主体 | 输入 | 调用/工具 | 持久化变化 | 可观测输出 | 失败后语义 |
+|---:|---|---|---|---|---|---|
+| 0 | HTTP | Topic 挂载 ID、模型、策略 | create endpoint | INSERT running record | `script_build_id` | 400/404;已创建后的 worker 失败走 record.failed |
+| 1 | main | Topic、persona、strategy | topic/persona tools、`save_script_direction` | record.direction | tool event/log | 方向生成不足可按 Prompt 无总目标继续 |
+| 2 | main | 上轮报告 + 总目标 + base | `begin_round(goal)` | INSERT round,前 open 轮改 done | `{round_index,rounds_remaining}` + marker | 第 16 轮被代码拒绝 |
+| 3 | main | 当前目标 | `record_multipath_plan(paths,mode,note)` | UPDATE round plan;为每路 INSERT/reuse open branch | `path_index -> branch_id` | 未 begin_round、空 paths、非法 mode、竞争 emphasis 缺失/重复均拒绝 |
+| 4 | main | 带「路序号:N」的有界任务 | `implement_paths` 或 `agent(script_implementer)` | 不新分配 branch;更新 branch.impl_task/subtrace/self_assessment | 每路成功/异常摘要 | 并发 gather `return_exceptions=True`,允许部分路失败 |
+| 5 | implementer | task、base overlay、当前 branch | `record_task_plan` | upsert plan steps | plan JSON | 首次结构写入前无 plan 会被部分 create 工具拒绝 |
+| 6 | implementer/retriever | 每步 data_needs | `agent(retrieve_data_*)` + 读工具 | 取数本身多为只读;外搜可有 case log | subagent result/trace/event | 空召回应把 plan step 标为受阻,但主要靠 Prompt |
+| 7 | implementer | 取回证据 | `record_data_decision` | INSERT data decision(branch+round) | decision JSON | sources 可选,代码不保证每次写入都先记账 |
+| 8 | implementer | 原子创作动作 | create/update/link tools | 当前 branch 中 INSERT/COW/update/link | IDs + partial errors | 多个批量工具是部分成功,调用方必须检查 `errors` |
+| 9 | evaluator | 本批 branch IDs、目标 | `script_multipath_evaluator` | 一般不写业务表 | 逐支报告 + 对比建议 | 建议不具有操作权 |
+| 10 | main | 评估报告 | merge/park/discard | merge 改 base,discard 删工作行,两者操作前保存 snapshot;park 只保留工作行并改状态 | branch status/reasoning/counts | 多分支 merge 没有强冲突检测 |
+| 11 | main | 整批处置结果 | `record_multipath_decision` | INSERT batch decision | decision ID/JSON | 代码不检验 branch_ids 是否已全部终局 |
+| 12 | evaluator | 当前 base、Topic、direction、persona | `script_evaluator` | 报告主要留在 trace/log/event | 通过/部分通过/需要回退 + 引领目标 | 报告没有强类型 Validation 记录 |
+| 13 | main | 报告 + base | next round 或 status/summary tools | record.status/summary/counts/time | 终态响应 | success 的评估通过条件没有代码强制 |
+
+关键行为证据:Round 上限与收口 [代码:script_build_agent_tools.py:2120-2189];分支预分配/幂等复用 [代码:script_build_agent_tools.py:2197-2286];并发派发 [代码:ScriptBuildAigcAgent.py:681-813];取证和书写纪律 [Prompt:prompts/script/script_implementer.md:64-190];评估双模式 [Prompt:prompts/script/script_build_eval_agent.md:1-40]。
+
+## 14. 工具与外部介质全景
+
+### 14.1 按角色的业务工具
+
+| 角色 | 只读输入 | 规划/决策 | 写入/终态 | 委派 |
+|---|---|---|---|---|
+| main | topic、persona、script snapshot/stats/direction、domain、branches/snapshots | think、begin_round、multipath_plan、multipath_decision | merge/park/discard、base 清理、save_direction、status、summary | implementer、multipath evaluator、base evaluator |
+| implementer | topic、persona/section patterns、script/direction/domain | task plan、step status、data decision | domain append、paragraph/atom/element/link create/update/delete | 四类 retriever |
+| pattern retriever | script snapshot | think | 无 | `query_pattern_qa` |
+| decode retriever | script snapshot | think | 无 | `search_script_decode_case` |
+| external retriever | script snapshot | think | 无业务产物写入 | `external_search_case`、`load_images` |
+| knowledge retriever | 无脚本写入 | think | 无 | `search_knowledge` |
+| multipath evaluator | branch/base snapshots、data decisions、topic/persona/direction/domain/stats | think + 取证 | 无分支处置权 | 最多按 Prompt 委派 3 次 retriever |
+| base evaluator | base snapshot/stats、topic/persona/direction/domain | think + 取证 | 无 status 写权 | 最多按 Prompt 委派 3 次 retriever |
+
+这不只是 Prompt 列表:运行时把各角色工具白名单注册到 preset,再由 `tools_exclusive=True` 限制主 Runner。[代码:script_build_tool_runtime.py:24-140][代码:ScriptBuildAigcAgent.py:290-427][代码:ScriptBuildAigcAgent.py:814-848]
+
+### 14.2 工具 Schema 与执行约定
+
+- 57 个脚本工具的 name/description/JSON Schema 来自 `script_build_tool_schemas.json`;Pattern 工具另由 HTTP adapter 提供 schema。
+- registry 把 OpenAI function schema 绑定到 async wrapper;wrapper 用 `asyncio.to_thread` 调同步业务函数,成功封成 `ToolResult.output`,异常封成 `ToolResult.error`。
+- `content_range` 容忍 Gemini 传 JSON string,在路由层解码成 object。
+- `load_images` 是特殊多模态工具,schema/执行体不在 JSON 中;它下载图片、转 base64 并返回 images。
+- `SCRIPT_TOOL_FIXTURE=record|replay` 可以包装同步执行器,用于调试取数工具。
+
+证据:[代码:script_build_tool_runtime.py:145-166][代码:script_build_tool_runtime.py:191-350][代码:script_build_tool_runtime.py:355-449]。
+
+### 14.3 外部系统输入输出
+
+| 系统 | 输入 | 输出 | 调用方 | 失败语义 |
+|---|---|---|---|---|
+| OpenRouter/LLM | messages、model、temperature、tools | assistant/tool calls + usage/cost | AgentRunner 及旧评估补全 | 异常最终可使 build.failed;子 trace usage 从磁盘汇总 |
+| Pattern QA | 自然语言 `message` | 结构化 Pattern/Relation 取数 | pattern retriever | 内部封装提交+轮询;空召回应降级 |
+| Decode/PGVector | keyword/account/filter/top_k/return_field | 帖子脚本解构 case | decode retriever | DB/向量查询失败返工具 error |
+| External search | keyword/platform/max_count | post ID、title/body/images 等 case | external retriever | 可记外搜 case log;外部网络故障不应被当为业务证据 |
+| Knowledge | keyword/max_count | 本地创作知识条目 | knowledge retriever | 空召回 |
+| Library detail | post/script IDs | 帖子和解构脚本详情 | detail API 和参考工具 | 详情 API 两次最长 30s 调用异常被吞并返空,响应未标 partial |
+| Image URL | URL 列表 | 图片 bytes/base64/multimodal content | external retriever/implementer | 无统一域名/私网白名单,属 SSRF 边界 |
+
+## 15. 真实接口样例
+
+以下不是臆造的新 API,而是按 `ScriptBuildRequest` 和真实返回代码组装的可调用形状。ID 值是说明用示例,不声称来自生产行。
+
+```http
+POST /api/pattern/script_builds
+Content-Type: application/json
+
+{
+  "execution_id": 12,
+  "topic_build_id": 34,
+  "topic_id": 56,
+  "agent_type": "AigcAgent",
+  "agent_config": {
+    "model_name": "claude-sonnet-5",
+    "temperature": 0.3,
+    "max_iterations": 120,
+    "model_name_implementer": "claude-sonnet-5",
+    "model_name_script_evaluator": "claude-sonnet-5",
+    "model_name_means_pattern_relation": "gemini-3-flash-preview"
+  },
+  "data_source_url": "https://library.example.invalid",
+  "strategies_always_on": [1],
+  "strategies_on_demand": [2]
+}
+```
+
+```json
+{
+  "success": true,
+  "message": "脚本构建任务已提交",
+  "script_build_id": 901
+}
+```
+
+这个 200 响应只表示“主记录已写入且后台线程已启动”,不表示脚本成功。[代码:pattern_server.py:1614-1665]
+
+上传 dry-run 样例:
+
+```json
+{
+  "json_data": {
+    "选题融合": "用一次反差经历说明为什么出发前要做功课",
+    "target_post": {"channel_account_name": "账号A"},
+    "灵感点": [{
+      "点": "反差开场",
+      "点描述": "先给错误预期,再揭示真实结果",
+      "实质": {"具体元素": [{"名称": "人物A", "说明": "主角"}]},
+      "形式": {"整体形式": [{"名称": "反转", "说明": "结尾翻转"}]}
+    }]
+  }
+}
+```
+
+dry-run 返回 `account_name/topic_fusion/point_count/item_count/point_type_stats/points`;正式 `/from_topic_json` 另返 `script_build_id/topic_id/topic_build_id`。[代码:pattern_server.py:1672-1769]
+
+一路内部工具输入样例:
+
+```json
+{
+  "paths": [
+    {
+      "path_index": 1,
+      "action": "增",
+      "target": "开场结构",
+      "method": "产生脉络",
+      "emphasis": "以真帖反差铺垫结构为主",
+      "path_type": "内容"
+    },
+    {
+      "path_index": 2,
+      "action": "增",
+      "target": "开场结构",
+      "method": "产生脉络",
+      "emphasis": "以账号历史段落节奏为主",
+      "path_type": "内容"
+    }
+  ],
+  "mode": "竞争",
+  "note": "同一 target 的两种结构策略"
+}
+```
+
+真实响应为 `{"success":true,"round_index":1,"path_count":2,"branches":[{"path_index":1,"branch_id":B1},{"path_index":2,"branch_id":B2}]}`,后续 tasks 必须以「路序号:1/2」开头。[代码:script_build_agent_tools.py:2197-2286][代码:ScriptBuildAigcAgent.py:681-813]
+
+## 16. 一个端到端数据行演化示例
+
+下表是“代码可生成的真实行形状”,用虚拟 ID 展示关联;它不是生产抽样。这种标注是必要的,因为本次没有使用源码中的生产凭据查远程库。
+
+| 时点 | 表/对象 | 关键值 | 含义 |
+|---|---|---|---|
+| T0 | record | `id=901,status=running,topic_id=56` | HTTP 已提交 |
+| T1 | record | `script_direction="..."` | 主 Agent 保存总目标 |
+| T2 | round | `round_index=1,goal="建立开场",status=open` | 第一轮 |
+| T3 | branch | `branch_id=1/2,round=1,status=open` | 竞争的两路预分配 patch |
+| T4 | task_plan | `(901,1,"1")`、`(901,2,"1")` | 两个 implementer 各自的原子计划 |
+| T5 | data_decision | `branch_id=1,sources=[{data_type,data_id,data_content}]` | 分支 1 的证据取舍 |
+| T6 | paragraph | `id=1001,branch_id=1,base_ref_id=null` | 候选新段落,未进成品 |
+| T7 | paragraph | `id=1002,branch_id=2,base_ref_id=null` | 第二个候选 |
+| T8 | branch 1 | `content_snapshot={overlay...},status=merged` | 评估后选 1 |
+| T9 | paragraph 1001 | `branch_id=0` | merge 把新行转为 base |
+| T10 | branch 2 | `content_snapshot={overlay...},status=discarded` | 工作行被物理删除,快照保留 |
+| T11 | multipath_decision | `branch_ids=[1,2]` | 主 Agent 记录本批选/弃理由 |
+| T12 | record | `status=success|partial,summary=...,counts=...` | 整体评估后收口 |
+
+merge/discard 的行级变化与快照保留证据见 [代码:script_build_branch_core.py:166-304][代码:script_build_agent_tools.py:2024-2108]。
+
+### 16.1 仓库内真实历史解构样本
+
+外部源码不只有接口定义,还包含真实历史脚本解构索引。`script_embedding_search/index/manifest.json:1-11` 记录的本地索引构建于 2026-06-24,使用 `qwen/qwen3-embedding-8b`、512 维 float16,包含 115 帖、45,972 chunks、323,632 tokens。这是仓库内真实数据证据,不是 ScriptBuild 运行行。
+
+其中历史帖子 `67b455800000000029016c2c` 的第一段真实包含:
+
+- 主题主维度「制作环节=成品安利」,从维度「食材组合=腊肠炒饭」、「风味特征=咸香浓郁」。
+- 形式包含特写、单图、段落叙述、情绪化安利、高饱和、暖色调、俯拍。
+- 作用包含「段间位置=开篇引入」、「段间衔接=引出下一段」、「段内作用=吸引注意力」。
+- `content_range` 指向图片 1、2 以及标题/正文,并且 theme/form/function/feeling/full_description 列文本均存在。
+
+原始证据见 [数据样本:script_embedding_search/script_decode_raw_data/一餐一卉/67b455800000000029016c2c.json:1-178]。它在业务上可被 decode retriever 召回,再由 implementer 把“哪些字段被采用/改写/重排”记到 `record_data_decision`,最后映射到候选 Paragraph 的 atoms 与文本。它不能被误称为某次 ScriptBuild 已经成功 merge 的数据库记录。
+
+## 17. 异常、停止、重试与续跑
+
+| 场景 | 当前行为 | 业务后果 |
+|---|---|---|
+| 主 run 抛异常 | 若 record 仍 running/stopping,改 failed、写截断 error/end_time;返 `success=false` | 已分步 commit 的段落/分支不回滚 |
+| 子路异常 | `gather(return_exceptions=True)` 汇总各路 | 可继续评估其他成功路,需主 Agent 正确收口失败分支 |
+| stop | 查本进程 Runner registry、要求 trace 目录存在,跨线程 `runner.stop`,改 stopping | 进程重启后 registry 丢失,无法仅凭 DB stop |
+| retry | 根据旧记录预填参数并新建一次 build | 是新 ID,不是原地重试 |
+| tail resume | 原 trace_id + 尾部历史,空 user messages | 在原 Trace 上继续 |
+| rewind | 可直接覆盖某 message JSON 的 tool result,截断/改写 DB LONGTEXT log,从 after_sequence 续跑 | 旧工具结果和旧日志不保留为不可变修订,审计链被覆写 |
+| trace volume 丢失 | stop/resume 前返 422 | DB 业务行仍在,但无法按 Agent 历史恢复 |
+
+证据:[代码:ScriptBuildAigcAgent.py:1128-1153][代码:pattern_server.py:2486-2527][代码:pattern_server.py:2548-2713]。
+
+## 18. 旧业务与当前通用 Framework 的非等价映射
+
+| legacy 概念 | framework 可承载的关系 | 为什么不能 1:1 改名 |
+|---|---|---|
+| ScriptBuild 运行使命 | Root TaskSpec.objective / `root_objective` | 表达“基于 topic/persona/strategy 产出结构化脚本”,允许 Planner revise |
+| 冻结的 `script_direction` | 带 version/hash 的业务 Artifact 或 Task context ref | 不是 Root objective 副本;Root revise 不应覆写已冻结方向 |
+| Round | 可由 Planner 创建的一组 child tasks 或 host metadata 表达 | framework 不内建 Round,也不假设每批 task 都是业务轮次 |
+| Path | child TaskSpec 可表达一个有界目标 | Path 还有 action/method/path_type/competition 等脚本领域字段,需业务 context/artifact |
+| Branch | 可作为 Worker artifact 或外部 patch ref | Attempt 是一次执行,Branch 是可持久候选补丁,两者生命周期不同 |
+| merge | Planner ACCEPT 后触发业务 merge command | ACCEPT 是证据充分的计划决策,不会自动帮脚本表执行 COW merge |
+| multipath evaluation | ValidationReport 可验单个 Task/Attempt/Artifact | legacy 报告是一次横跨多分支的对比,需另一个业务 evaluator task/aggregate artifact |
+| base | 最终业务 Artifact 的 URI/摘要 | Ledger 不存 Paragraph 正文;ArtifactSnapshotView 只给 hash/refs,正文仍由业务存储读取 |
+
+当前 framework 的通用闭环是:Root TaskSpec → Planner 创建/修订 child Task → dispatch → Attempt 创建时冻结直接子任务 ACCEPT Decision IDs → Worker submission → immutable ArtifactSnapshot → 独立 Validator → Planner accept/repair/retry/revise/split/block → Root 自身 Attempt/Validation/ACCEPT。[现项目:agent/agent/docs/orchestration-v1.md:70-98][现项目:agent/agent/orchestration/coordinator.py:1060-1073][现项目:agent/agent/orchestration/coordinator.py:2760-2889]
+
+该闭环已在本项目黑盒 E2E 中真实运行:只经 `agent` 公开入口启动,child v1 验证失败后 revise,v2 验证通过并 ACCEPT,Root objective revise,Root Worker 只消费被冻结的 child ACCEPT Decision,最后 SDK-only 读 Snapshot/Completion/Artifact/Event/Trace 并校验 Decision→Attempt→Validation→Artifact→Trace 闭合。这是“可执行 framework 样例”,不是“legacy 生产 ScriptBuild 样本”。[现项目:agent/tests/test_framework_observation_e2e.py:32-140]
+
+## 19. Visualization 当前消费链与接入缺口
+
+当前 visualization 不是通用 orchestration UI。它的只读 Repository 直接把 legacy 业务表投影成脚本故事:
+
+- Record 表述 Run 状态/方向/结果;Round/Branch 表述每轮候选与处置。
+- DataDecision 只表示 implementer 对数据的采用/排除;MultipathDecision 只表示 main 对候选批次的处置。
+- DomainInfo 是 build 全局累加事实;Event/body 只补充运行活动,不覆盖业务表。
+- 当前 Round.multipath_plan 是当前保存值,不是完整历史版本。
+
+证据:[现项目:visualization/DATA_SOURCE_CONTRACT.md:3-29][现项目:visualization/README.md:20-42]。
+
+要接新 framework,需要 anti-corruption/projector 层,而不是把 Provider URL 换成 Mission Snapshot:
+
+1. 用 MissionSnapshot 解析 Task/Attempt/Validation/Decision 的通用因果。
+2. 用 Artifact refs 调脚本业务 adapter,取 Round/Branch/Paragraph/Element 等业务正文。
+3. 用 correlated Trace 补充模型/工具详情,而不从 Event payload 复制业务对象。
+4. 显式定义“哪些 child tasks 组成一轮”和“哪个 artifact 是候选 branch”的业务绑定;通用 Event v2 本身不带 Round/Branch。
+
+## 20. 业务验收清单
+
+### 20.1 输入和挂载
+
+- 同时校验 execution→topic_build→topic 归属,不只查 topic 存在。
+- 上传 JSON dry-run 与正式落库使用同一 parser/version,错误能指到缺字段。
+- 运行记录保存实际 Prompt/strategy/model 的版本或 hash,不只存名称。
+
+### 20.2 候选和成品
+
+- open/parked/discarded 分支不影响成品计数和 success 存在性检查。
+- 同一 target/base_ref 的冲突分支不能 combine;merge 要有明确冲突报告。
+- 不同分支的 link/parent 不能交叉引用;所有引用必须限定 build + base/当前 branch。
+- discard 后无孤儿 link,快照与决策理由仍可读。
+
+### 20.3 证据和验证
+
+- 每个写入单元都能关联到 DataDecision,DataDecision 再关联具体 retrieval invocation/trace,而不只靠文本 ID。
+- 整体评估要成为强类型 Validation,包含快照 hash、criterion results、verdict、evidence refs。
+- success 只能由针对当前 base snapshot 的通过验证触发;验证后任何写入都使旧报告失效。
+
+### 20.4 观测和恢复
+
+- 最终能从 Decision 追到 Attempt、Validation、ArtifactSnapshot 和 Trace,所有 ID 属于同一 Root/Task。
+- stop/retry/resume 不覆写旧历史;续跑生成新 Attempt/revision,原快照保持不可变。
+- UI 区分“业务事实”、“执行通知”和“模型解释”,不用 best-effort Event 覆盖 DB 成品。

+ 453 - 28
脚本构建技术架构分析.md

@@ -1,17 +1,20 @@
 # ScriptBuild 脚本构建:技术架构分析
 
-> 源码路径:/Users/samlee/Documents/works/脚本构建第二版/aiddit/pattern/patter_from_global_and_build  
-> 分析日期:2026-07-17  
-> 本地分支:script_build_refactor_0709  
-> 本地提交:3b2db59(修复数据来源映射与缺失语义)  
-> 分析方式:静态代码、Prompt、模型与测试结构交叉阅读;未连接线上数据库,未实际发起 ScriptBuild 运行。
+> 上一代真实源码:`/home/sam/image_article_comprehension/aiddit/pattern/patter_from_global_and_build`<br>
+> 本项目:`/home/sam/script-build-and-framework`<br>
+> 分析日期:2026-07-18<br>
+> 上一代分支:script_build_refactor_0709<br>
+> 上一代提交:cc0e2a5<br>
+> 分析方式:逐段阅读入口 Agent、Prompt、工具 Schema/执行体、ORM模型、MySQL DDL迁移、HTTP 与前端消费链,并与本项目 `agent`/`visualization` 交叉对照。本次未用源码内生产凭据连接外部数据库;“DB 证据”仅指 ORM、迁移 DDL 和现有只读投影实现。
+
+> 证据引用约定:`[代码:文件:行号]`、`[DDL:文件:行号]`、`[Prompt:文件:行号]` 相对于上一代源码根目录;`[现项目:路径:行号]` 相对于本项目根目录。本文对“已实现”、“Prompt 约定”、“目标架构”使用不同语气,避免把设计当成事实。
 
 本文只回答技术问题:代码如何分层、Agent SDK 如何接入、数据如何持久化、并发与恢复如何实现、外部依赖有哪些、当前风险在哪里,以及建议按什么顺序改造。
 
 技术结论:
 
-- 当前生产链路已经使用 AgentRunner、RunConfig、ToolRegistry、FileSystemTraceStore 和 subagent 工具,重构重点应放在应用层状态机,而不是替换 Agent SDK。
-- branch_id、base_ref_id、overlay 和 copy-on-write 构成了可靠的候选分支隔离基础,是应当保留的核心技术资产
+- 被审查的上一代源码链路已经使用 AgentRunner、RunConfig、ToolRegistry、FileSystemTraceStore 和 subagent 工具,重构重点应放在应用层状态机,而不是替换 Agent SDK。本次没有部署证据,不将它称为“当前生产链路”。
+- branch_id、base_ref_id、overlay 和 copy-on-write 构成了值得保留的候选分支隔离基础,但 link/parent 查询作用域漏洞使它尚非完整可靠隔离
 - 当前最高优先级问题集中在成品终态判断、评估门禁、Prompt 版本一致性、续跑上下文一致性和数据库凭据管理。
 - 生产可靠性继续受 daemon 线程、进程内 Runner 注册表和本地 Trace 文件制约,需要逐步迁移到持久任务 Worker 与共享 TraceStore。
 
@@ -99,7 +102,7 @@ ScriptBuildAigcAgent.py 是应用编排层,负责:
 
 ### 2.2 Agent SDK 层
 
-当前生产主链路使用:
+被审查源码配置的主链路使用:
 
 - AgentRunner:执行主 Agent 和子 Agent。
 - RunConfig:模型、迭代次数、工具策略等。
@@ -473,12 +476,12 @@ script_tools_schemas.py 把本地 JSON 称为唯一事实来源,但 Pattern AP
 
 建议:
 
-- DomainInfo 增加 source_branch_id、evidence_status、verification_status。
+- 复用并强制填写 DomainInfo 已有 `branch_id`,增加 evidence_status、verification_status,必要时增 decision/retrieval refs。
 - discard 分支时,对“仅由该分支支持”的事实标记为 unverified,而不是直接删除。
 
-### 7.15 P2:核心生命周期缺少直接测试
+### 7.15 P2:Legacy 核心生命周期缺少直接测试
 
-现有测试大量覆盖可视化事件投影和前端展示,但没有发现直接针对以下核心行为的测试:
+上一代目录中的现有测试大量覆盖可视化事件投影和前端展示,但没有发现直接针对以下 legacy 核心行为的测试。这个结论不适用于本项目 `agent`;后者已有状态机、API、事件、因果和黑盒 E2E 测试,见第 21 节。
 
 - Round 上限和状态迁移。
 - 分支 copy-on-write overlay。
@@ -491,6 +494,18 @@ script_tools_schemas.py 把本地 JSON 称为唯一事实来源,但 Pattern AP
 
 ## 8. 建议的目标架构
 
+本节是最初针对 legacy 提出的目标。与本项目当前代码对照后,其中一部分通用合同已在 `agent` 实现,但尚未接入 ScriptBuild:
+
+| 初始目标 | 当前状态 |
+|---|---|
+| BuildGoal/ValidationReport/ExecutionEvent | 通用形态已分别由 Root TaskSpec/ValidationReport/Event v2 承载;ScriptBuild 未接入 |
+| ArtifactSnapshot | 通用 immutable snapshot 已实现;脚本 Paragraph/Element 正文 adapter 未实现 |
+| 状态机/角色 capability | framework 已实现;legacy 工具尚未按 capability 接入 |
+| RoundPlan/BranchPlan/BranchPatch/EvidenceBundle | 仍是 ScriptBuild 领域待实现合同,不应添加到通用 Ledger 顶层 |
+| TopicSnapshot/StrategySnapshot | 仍缺业务不可变快照 |
+| merge conflict/idempotent command | 仍缺业务实现 |
+| durable Worker/lease/heartbeat | framework operation 状态有持久化,但 runtime 仍不是分布式任务队列 |
+
 建议保留现有 Agent SDK 与多 Agent 角色,只拆分应用层职责:
 
 ~~~mermaid
@@ -515,7 +530,7 @@ flowchart LR
 
 - TopicSnapshot:一次构建使用的不可变选题输入。
 - StrategySnapshot:首次解析后的策略快照,续跑直接复用。
-- BuildGoal:冻结的总目标
+- ScriptDirectionSnapshot:带 version/hash 的脚本业务不可变输入/Artifact ref;它不是 Root objective 或第二套 Mission 状态
 - RoundPlan:一轮要解决什么。
 - BranchPlan:路径、模式、声明写集合和验收标准。
 - EvidenceBundle:检索结果和来源。
@@ -614,26 +629,436 @@ flowchart LR
 - dry-run 同步能发现 DB 缺行和 hash 不同。
 - 运行记录保存所有实际 Prompt hash。
 
-## 11. 适合本项目继续使用的 Skills
+## 11. 证据等级与可复现性
+
+| 标记 | 含义 | 本文如何使用 |
+|---|---|---|
+| CODE | 可达代码路径 | 证明组件、条件分支、事务与返回形状 |
+| PROMPT | 模型行为合同 | 只证明意图/约定,不单独证明强制不变式 |
+| ORM | SQLAlchemy 模型 | 证明代码期望的表/列/索引,不证明生产库已升级 |
+| DDL | 迁移 SQL | 证明预期的 MySQL 变更与约束,但该目录没有发现统一 migration runner/version table |
+| TEST | 可执行测试 | 证明本项目 framework 的代码行为,不代表 legacy 生产已接入 |
+| DATA | 仓库内数据文件 | 可作历史解构样本,不冒充生产 ScriptBuild 运行行 |
+| INFERENCE | 基于上述证据的推断 | 必须显式标注,不写成部署事实 |
+
+本次未查询远程 MySQL,也没有发现可用的 `.trace/script_build` 实例或 SQLite dump;因此不给出伪造的“线上成功率/真实运行 ID”。仓库内的历史 decode JSON 可用于证明真实数据形状,已在业务分析第 16.1 节标明边界。
+
+## 12. 三平面现状架构与部署边界
+
+~~~mermaid
+flowchart TB
+    subgraph L[Legacy ScriptBuild 业务平面]
+      LegacyAPI[pattern_server API]
+      LegacyAgent[ScriptBuildAigcAgent]
+      LegacyTools[script_build_agent_tools]
+      LegacyDB[(MySQL 业务表)]
+      LegacyTrace[(FileSystem Trace)]
+      LegacyAPI --> LegacyAgent --> LegacyTools --> LegacyDB
+      LegacyAgent --> LegacyTrace
+    end
+
+    subgraph C[agent 通用控制平面]
+      Host[Host / public agent entry]
+      Coord[TaskCoordinator]
+      Ledger[(TaskLedger + durable journal)]
+      Artifact[(ArtifactSnapshot refs)]
+      V2[optional V2 router / SDK]
+      Host --> Coord --> Ledger
+      Coord --> Artifact
+      V2 --> Ledger
+    end
+
+    subgraph V[visualization 读模型]
+      Provider[RuntimeDataProvider]
+      Repo[ScriptBuildRepository]
+      Projector[ScriptBuild projectors]
+      UI[V8 UI]
+      Provider --> Repo --> LegacyDB
+      Provider --> Projector --> UI
+    end
+
+    Adapter[尚未实现的 ScriptBuild Host/Artifact/Projection Adapter]
+    C -. 未接线 .-> Adapter -. 未接线 .-> L
+    C -. 未接线 .-> Adapter -. 未接线 .-> V
+~~~
+
+必须保留三个技术事实:
+
+1. legacy 代码是可读的上一代实现,本次没有部署或运行证据,不应称为“当前线上主链”。
+2. `agent` 中 explicit orchestration、Mission Snapshot、Event v2 和 Trace filter 是已实现的通用能力,但默认 Runner 仍可走 `legacy_auto`,且默认 API server 并未自动 mount V2 router/wire coordinator。[现项目:agent/agent/core/runner.py:123-149][现项目:agent/api_server.py:92-114]
+3. visualization 的 RuntimeDataProvider 入参是 `script_build_id`,还是通过 ScriptBuildRepository 读 legacy 表;它不是 Mission Snapshot 的前端。[现项目:visualization/backend/app/providers.py:8-64][现项目:visualization/backend/app/repositories.py:65-221]
+
+## 13. Legacy 模块与调用链
+
+### 13.1 请求到 Runner
+
+```text
+POST /api/pattern/script_builds
+  -> _normalize_aigc_agent_config
+  -> validate Topic exists
+  -> create_script_build_record() + commit
+  -> daemon Thread
+       -> new asyncio event loop
+       -> ScriptBuildAigcAgent.run()
+            -> ensure_tables()
+            -> set ContextVars
+            -> load DB/file prompts
+            -> _execute_reson()
+                 -> register presets/tool registry
+                 -> AgentRunner(FileSystemTraceStore, OpenRouter)
+                 -> runner.run(messages, RunConfig)
+            -> count/write status/usage/end_time
+```
+
+入口、线程和循环证据:[代码:pattern_server.py:1478-1611][代码:pattern_server.py:1614-1665];Runner 配置和生命周期证据:[代码:ScriptBuildAigcAgent.py:513-987][代码:ScriptBuildAigcAgent.py:989-1153]。
+
+### 13.2 代理委派和分支绑定
+
+`_agent_with_log` 在委派 implementer 前根据 task 中的 path_index 找预分配 branch,将 branch/round 写入 ContextVar,运行子 Agent,最后回填 self_assessment/sub-trace 并恢复上下文。`implement_paths` 则在最大并发 4 的 semaphore 下同时调用该包装,并用 `capture_agent_log_block` 防止线性日志交错。[代码:ScriptBuildAigcAgent.py:142-289][代码:ScriptBuildAigcAgent.py:633-779]
+
+这个绑定有两层:
+
+- 理想主路:`record_multipath_plan` 串行预分配 `path_index -> branch_id`,并发期只读映射,避免 `MAX(branch_id)+1` 竞态。
+- 历史兼容降级:没命中 plan 时,单路委派仍可按已有分支数量的 positional 下标,或从 task 文本解析 action/target/method/mode 后真实新建业务分支。这一路径会决定后续写入作用域,不应成为新 Host 的主合同。
+
+### 13.3 工具运行时
+
+```text
+role preset.allowed_tools
+        -> JSON/Pattern schema lookup
+        -> ToolRegistry.register(async wrapper)
+        -> LLM tool call
+        -> asyncio.to_thread(execute_script_tool_sync)
+        -> dispatcher(name,args)
+        -> script_build_agent_tools / HTTP adapter
+        -> DB/HTTP/file side effect
+        -> ToolResult(output|error)
+```
+
+Schema 是数据驱动的,但 dispatcher 仍是大型 `if name == ...` 链,新增工具需同时修改 schema、分组白名单和 dispatcher,存在人工漂移。[代码:script_build_tool_runtime.py:145-166][代码:script_build_tool_runtime.py:191-332][代码:script_build_tool_runtime.py:355-419]
+
+### 13.4 外部 Port 盘点
+
+| Port | 当前 adapter | 主要入参 | 主要输出 | 超时/错误边界 |
+|---|---|---|---|---|
+| LLM | OpenRouter call | model/messages/tools/temp | messages/tool calls/usage/cost | Runner 异常;部分旧评估直调 |
+| Business DB | SQLAlchemy MySQL session | ORM query/command | 业务行 | 工具多为自己 commit/rollback,无 Unit of Work 跨工具事务 |
+| Pattern QA | HTTP submit + polling | natural-language message | structured pattern result | 3s 轮询,默认 600s 超时 [代码:pattern_tool/pattern_qa_tool.py:93-157] |
+| Pattern tool | HTTP function adapter | tool name + JSON args | JSON/text | adapter error 包成 ToolResult.error |
+| Decode DB | PG/PGVector + local index | keyword/account/filter/top_k | matched cases/chunks | DSN/向量服务是独立可用性域 |
+| External search | external_search_service | keyword/platform/max_count | posts/body/images/vision text | 外网依赖;可写 case log |
+| Knowledge | local knowledge/index | keyword/max_count | knowledge entries/steps | 空召回可降级 |
+| Library detail | `/api/posts/batch`, `/api/scripts/batch` | post IDs | reference post/script detail | 详情 API 串行两次 30s,异常返空不标 partial [代码:pattern_server.py:1984-2039] |
+| Image loader | HTTP download | URL list | bytes/base64/images | 需域名、scheme、DNS/私网、size 策略;现有边界不足 |
+| Trace | FileSystemTraceStore | build ID/trace ID/messages | meta + message JSON | 本地目录丢失即不能 stop/resume |
+
+## 14. Legacy 数据架构、约束与事务
+
+### 14.1 持久化聚簇表
+
+| 表 | 主键/业务键 | 核心列 | 写入方 | 读取方 |
+|---|---|---|---|---|
+| `script_build_record` | id | upstream IDs、config/source/status/trace/direction/workflow/counts/usage/strategies/time | start/run/status/summary | list/detail/log/control |
+| `script_build_round` | id;unique(build,round) | goal、plan JSON、mode、note、status | begin_round/plan | Agent/visualization |
+| `script_build_branch` | id;unique(build,branch) | round/action/target/method/emphasis/path_type/mode/task/status/reason/snapshot/subtrace | plan/implement/decision | Agent/visualization |
+| paragraph | id | branch/base_ref/index/level/parent/content-range/4 texts/4 atoms/full-description/active | implementer/main cleanup/merge | overlay/detail/artifact |
+| element | id | branch/base_ref/name/primary/secondary/analysis/support/weight/active | implementer/main cleanup/merge | overlay/detail/artifact |
+| paragraph_element | id;unique(branch,paragraph,element) | build/branch/effective endpoint IDs | implementer/merge/discard | overlay/detail |
+| data_decision | id | build/branch/round/sources/decision/reason | implementer | evaluator/visualization |
+| multipath_decision | id | build/round/branch_ids/decision/reason | main | visualization |
+| task_plan_step | id;unique(build,branch,step_key) | title/data_needs/status/result/depends/sort | implementer | implementer/visualization |
+| domain_info | id | build/round/branch/content/source/note | implementer append-only | all roles/visualization |
+| decision_trace | id | phase/method/means/workflow/data/affected/state snapshot | legacy record_decision | old detail/UI |
+| log | id | build/log LONGTEXT | log capture updater | detail UI |
+| event + body | id;body unique(event_id) | seq/type/role/hierarchy/round/branch/time/status/preview/payload + input/output | best-effort emitter | visualization, not old detail UI |
+
+ORM 字段证据:[代码:models.py:492-860]。所有“FK”只存在注释,模型和 DDL 均未建数据库 Foreign Key;因此所有引用完整性都依赖应用查询。
+
+### 14.2 Patch/Overlay 算法
+
+对段落/元素,分支 B 的有效集合是:
+
+```text
+overlay(B) = { base row x | x.id not in B.base_ref_id }
+             ∪ { branch row y | y.branch_id = B }
+effective_id(y) = y.base_ref_id if override else y.id
+```
+
+`writable_paragraph/element` 在 B=0 时直接返 base row;B>0 时优先返已存 override,否则复制 base 字段新建 branch row,这是 copy-on-write。[代码:script_build_branch_core.py:113-161][代码:script_build_branch_core.py:316-415]
+
+merge 不是一个新 snapshot 指针,而是就地修改:override 字段拷回 base 并删 override;新行 `branch_id` 改 0;link 去重后改 0;branch status 改 merged。多分支 merge 只是按列表顺序串行调单分支 merge,没有 write-set 冲突检测。[代码:script_build_branch_core.py:166-255]
+
+### 14.3 迁移现状
+
+| 能力 | fresh/incremental DDL |
+|---|---|
+| branch/base_ref/branch ledger | `migration_script_build_branch.sql:6-48` |
+| emphasis/path_type/snapshot | `migration_script_build_branch_emphasis.sql:5-6`; `...path_type.sql:6-7`; `...snapshot.sql:1-3` |
+| round/data decision/reason | `migration_script_build_round.sql:6-38` |
+| round mode/multipath decision | `...round_mode.sql:1-3`; `...multipath_decision.sql:7-18` |
+| task plan/domain info | `...task_plan_step.sql:7-26`; `...domain_info.sql:6-19` |
+| trace ID | `migration_script_build_debug.sql:4-6` |
+| event/body | `migration_script_build_event.sql:5-52` |
+| 旧 event 逐步升级 | `...event_body_1to1.sql:5-20`; `...event_body_split_io.sql:4-14`; `...event_context.sql:4-13` |
+
+`Base.metadata.create_all()` 只能创建缺表,不能为已有表补列;而 fresh event SQL 已包含最终列,如果再线性执行旧 incremental SQL 会重复 ADD。目录中未见 Alembic/version table/runner,因此“ORM 有字段”不能推导“线上表已有字段”。[代码:pattern_server.py:85-93][代码:pattern_service.py:174-176][DDL:migration_sql/migration_script_build_branch.sql:1-4]
+
+### 14.4 事务边界
+
+- create record 是一次独立 commit,然后才启动线程。线程起不来时已有 running 行需补偿。
+- 上传 Topic 的 record/topic/points/items/relations 在一次 commit 中;ScriptBuildRecord 是后续另一次 commit。
+- 每个 tool 自己开 session/commit/rollback,一轮不是原子事务;子 Agent 中途失败会留下已提交的 plan/decision/content。
+- `batch_update_script_paragraphs` 等工具允许 partial commit:无效 item 收入 errors,其余 item 提交。[代码:script_build_agent_tools.py:3616-3624]
+- event header/body 是辅助投影;begin INSERT `running`,finish 会 UPDATE 同一 event 的 status/time/body,所以不是严格不可变 event sourcing。
+
+## 15. HTTP、SDK 与 Wire 合同
+
+### 15.1 Legacy HTTP 面
+
+| 方法 | 路径 | 输入 | 输出/作用 |
+|---|---|---|---|
+| POST | `/api/pattern/script_builds` | ScriptBuildRequest | 创建 running record,启 daemon,返 ID |
+| POST | `/api/pattern/script_builds/parse_topic_json` | `{json_data}` | dry-run 解析统计/points |
+| POST | `/api/pattern/script_builds/from_topic_json` | uploaded JSON + config | 合成 Topic 并启 build |
+| POST | `/{id}/retry` | 无/旧 prefill | 新建 ScriptBuildRecord,不是原地重试 |
+| GET | `/{id}/prefill` | path ID | 旧配置预填 |
+| DELETE | `/{id}` | path ID | soft delete |
+| PATCH | `/{id}/favorite` | favorite bool | 更新收藏 |
+| GET | `/api/pattern/script_builds` | filters/page | list |
+| GET | `/{id}` | path ID | base-only detail + old decision traces + external reference data |
+| GET | `/{id}/log` | path ID | `{log_content,live,status}` |
+| POST | `/{id}/stop` | path ID | process-local runner stop |
+| POST | `/{id}/resume` | `{after_message_id?,patch_tool_result?}` | tail continue 或覆写式 rewind |
+| GET | `/{id}/trace_messages` | path ID | tool/assistant metadata,不返 content |
+
+路由证据:[代码:pattern_server.py:1614-1954][代码:pattern_server.py:2146-2761]。soft delete 仅影响部分 list/control,detail/log/trace messages 只按 id 查,被软删记录仍可直接读,应统一资源可见性策略。
+
+Legacy 没有“一次读取所有 Round/Branch/Attempt-like/Decision/Event 的原子快照”。详情只返 base 成品与已废弃 DecisionTrace,新 Round/Branch/TaskPlan/DataDecision/Domain/Event 需其他内部读模型获取。[代码:pattern_server.py:2280-2442]
+
+### 15.2 当前 Framework V2 读取面
+
+| 方法 | 路径 | Wire 输出 | 性质 |
+|---|---|---|---|
+| GET | `/api/v2/capabilities` | API/Snapshot/Event schema 版本 + capability list | 调用方协商 |
+| GET | `/api/v2/roots/{root_trace_id}/snapshot` | MissionSnapshotView | 单次 store.load 的同 revision 原子视图 |
+| GET | `/api/v2/roots/{root_trace_id}/completion` | RootCompletionView | Root ID/objective/status/block/result summary |
+| GET | `/api/v2/roots/{root_trace_id}/snapshots/{snapshot_id}` | ArtifactSnapshotView | ID/attempt/hash/artifact refs/evidence refs/time,不返 normalized content |
+| GET | `/api/v2/roots/{root_trace_id}/events` | event page/cursor | durable Event v1/v2 读取 |
+| GET | task/attempt/validation/operation routes | 复用严格 Wire views | 详细/列表/控制 |
+
+MissionSnapshot 字段为 `schema_version/revision/root_trace_id/root_task_id/root_objective/focused_task_id/tasks/attempts/validations/decisions/operations`;集合稳定按 `created_at + id` 排序。[现项目:agent/agent/orchestration/wire.py:132-276][现项目:agent/agent/orchestration/api_v2.py:86-198]
+
+`OrchestrationClient` 已实现 Mission Snapshot、Completion、Artifact、Event 与 Trace 读取方法,但这只证明 SDK 能力存在;Host 需显式构造 coordinator/store/V2 router 并 mount。完整 Trace 读取还要另外 mount Trace API 并绑定同一 TraceStore;否则 capabilities 中无条件宣称的 trace filter 能力可能是假阳性。[现项目:agent/agent/orchestration/client_v2.py:145-275][现项目:agent/api_server.py:92-114]
+
+### 15.3 框架输入/输出 DTO
+
+| DTO | 关键字段 | 合同 |
+|---|---|---|
+| `TaskSpec` | objective、acceptance_criteria、context_refs、version | 可修订的任务目标/验收,Root 当前版本导出 root_objective |
+| `AttemptSubmission` | summary、artifact_refs、evidence_refs | Worker 交付;ArtifactRef 必须有 immutable version 或 digest |
+| `ValidationReport` | criterion_results、verdict、evidence_refs、unverified_claims、risks、recommendation、execution_stats | Validator 不直接改 Task 状态 |
+| `PlannerDecision` | action、from/to status、attempt/validation IDs、payload | 唯一可以将 validated 交付 accept/revise/retry/... 的计划决策 |
+| `ArtifactSnapshot` | attempt、sha256、refs/evidence、normalized content(内部) | store 首写不可变,wire 不复制正文 |
+
+证据:[现项目:agent/agent/orchestration/models.py:246-336][现项目:agent/agent/orchestration/models.py:388-427][现项目:agent/agent/orchestration/models.py:524-640]。
 
-本次分析使用了 senior-architect Skill,它适合把代码事实整理成系统边界、组件、接口、数据所有权、风险、决策和 Mermaid 架构图。
+## 16. Framework 已实现的控制面
+
+### 16.1 状态机与角色权限
+
+Task 状态迁移是白名单状态机,不允许调用方任意跳状态;Planner/Worker/Validator 的工具能力是 fail-closed,未分类或超出角色 capability 的工具被拒绝。[现项目:agent/agent/orchestration/state_machine.py:14-31][现项目:agent/agent/orchestration/policy.py:12-31][现项目:agent/agent/orchestration/policy.py:52-104]
+
+这并不会自动得到 legacy 的 8 个业务 Agent、57 个工具和 Prompt。Host 必须注册 ScriptBuild-specific presets/tools/adapters,并将写工具声明为对应 capability。通用 framework 不应引入 Round/Branch/Page 等业务节点。
+
+### 16.2 冻结子任务输入的因果链
+
+Attempt 创建时,Coordinator 把直接子 Task 当时的 ACCEPT PlannerDecision IDs 按 display_path 顺序冻结到 `accepted_child_decision_ids`。执行 Root/parent Worker 时,只根据这组 IDs 解析子产物,而不扫描“当前最新 child 状态”。[现项目:agent/agent/orchestration/models.py:454-503][现项目:agent/agent/orchestration/coordinator.py:1060-1073][现项目:agent/agent/orchestration/coordinator.py:2760-2889]
+
+```text
+ACCEPT Decision
+  -> same direct child Task
+  -> referenced Attempt
+  -> referenced Validation
+  -> validation.snapshot_id
+  -> immutable ArtifactSnapshot
+  -> artifact/evidence refs
+  -> correlated Trace IDs
+```
+
+校验会拒绝重复 ID、跨 Task decision、非 ACCEPT action、缺 Attempt/Validation/Snapshot 或无法闭合的引用。升级前旧 RUNNING Attempt 若字段为 `None`,不猜测历史输入,而是 protocol violation 后走正常 replan/retry。[现项目:agent/agent/orchestration/coordinator.py:1150-1161]
+
+### 16.3 唯一真源与兼容投影
+
+`TaskLedger` 是 explicit validation 模式的唯一真源。`root_objective` 从 Root Task 当前 `TaskSpec.objective` 派生;序列化时旧 `mission` 字段自动归一为当前 root objective,只有无 Root 的旧数据才回退旧 mission。GoalTree 是兼容投影,不是第二套状态。[现项目:agent/agent/orchestration/models.py:753-802]
+
+ArtifactSnapshot 首写不可变;Event v2 记录变化通知和实体 ID,与 Ledger 在同一 store commit 中持久化并用 cursor 读取,不复制 Task/Decision/Validation 对象。[现项目:agent/agent/orchestration/store.py:91-194][现项目:agent/agent/orchestration/store.py:241-318]
+
+### 16.4 可执行黑盒样例
+
+`agent/tests/test_framework_observation_e2e.py:32-140` 是本项目当前最有价值的真实技术 example:
+
+1. 只从 `agent` 包公开入口启动 Mission。
+2. child v1 交付后 Validator 失败,Planner revise。
+3. child v2 通过,Planner ACCEPT。
+4. Root objective revise。
+5. Root Worker 消费冻结的 child ACCEPT Decision,不消费旧 v1。
+6. Root 交付通过并 ACCEPT。
+7. 消费端只经 SDK 读 Snapshot/Completion/Artifact/Event/Trace。
+8. 测试校验 Decision→Attempt→Validation→Snapshot→Trace 闭合,且 wire 中不存在 Round/Branch/Page 业务字段。
+
+这个样例证明“通用控制面可用”,不证明“legacy ScriptBuild 已迁移”。
+
+## 17. 并发、幂等、恢复与可观测对比
+
+| 问题 | Legacy | 当前 framework | 接入要求 |
+|---|---|---|---|
+| 并发分支绑定 | plan 预分配后 semaphore<=4,ContextVar 隔离 | Task/Attempt ID 约束,Coordinator 调度 | Branch ref 作为业务 artifact/context,不用 Attempt ID 代替 branch ID |
+| 输入冻结 | implementer 读当时 base/DB,续跑可看到后续变化 | Attempt 冻结 accepted child decision IDs | Host 还需冻结业务 base revision/branch input hash |
+| 幂等 | plan 按 path_index 复用 branch;多数写工具无 command ID | Store/operations 具有幂等和持久记录 | 业务 merge/write 需 command ID + expected base revision |
+| 事务 | 每工具提交,轮次非原子 | Ledger + event journal 原子 store commit | 业务 DB 与 Ledger 不可假设分布式原子;用 outbox/saga |
+| 验证 | Markdown 报告,success 不强制评估通过 | explicit ValidationReport + PlannerDecision | ScriptBuild criteria adapter 必须生成强类型 criterion results |
+| 产物不可变 | merge 就地改 base;merge/discard 前保存 overlay snapshot,park 只保留可变工作行 | ArtifactSnapshot first-write immutable | Script 正文存业务 object store/DB,snapshot ref 带 digest/revision |
+| Event | best-effort,max+1 + 进程锁,同一行 finish UPDATE | durable journal、cursor、v1/v2 可读 | 业务 DB 变更用 outbox 向 journal 发 ID 通知 |
+| Trace | 本地文件,rewind 覆写 message/log | correlated Trace fields/filter-before-limit | 不覆写旧 trace,新 Attempt 产生新 trace/revision |
+| Resume | 原 trace 从 sequence 继续,DB 副作用不回滚 | Planner 显式不支持 rewind;Operation 只在安全 stage 恢复 | 用 retry/revise/replan,禁止把 trace rewind 宣称为业务回滚 |
+| Worker 存活 | daemon 线程+内存 runner registry | BackgroundOperation 持久状态,runtime 仍 process-local | 上线仍需 queue/lease/heartbeat/reconciler |
+
+Legacy event 的 `_safe_emit` 吞掉异常,seq 用进程内 `(build)->Lock` + `SELECT max+1`,DB 只有普通 index 无 unique,多 worker 无法保证唯一单调。[代码:script_build_event_emit.py:134-151][代码:script_build_event_emit.py:215-288][DDL:migration_sql/migration_script_build_event.sql:45-50]
+
+Trace filter 方面,当前 framework 使用已有 Trace 字段支持 `agent_role/parent_trace_id/root_trace_id/task_id/attempt_id/validation_id/operation_id`,并在 limit 前过滤;测试覆盖 1001 条无关 Trace 后仍能找到目标。[现项目:agent/agent/trace/models.py:39-78][现项目:agent/agent/trace/store.py:122-197][现项目:agent/tests/test_observation_events_and_traces.py:65-112]
+
+## 18. Visualization 读模型与目标投影
+
+### 18.1 当前事实来源
+
+`visualization/DATA_SOURCE_CONTRACT.md:3-24` 明确规定:
+
+- record/round/branch/data_decision/multipath_decision/domain_info 是业务事实。
+- event/body 只补充 Agent 活动、评审和运行细节。
+- `script_direction` 的当前事实在 record,`save_script_direction` event 只还原何时保存。
+- Round.plan 是当前保存值,不表示完整规划历史。
+- DataDecision.sources 没有 Agent event ID,只能做数据类型级对照,不能声称与某次取数调用一一对应。
+
+这个投影的限制也已被它自身记录:旧/部分事件的 round/branch 可能只是默认 0 或无法可靠归属,parent event 不稳定,且无逐轮 base snapshot。[现项目:visualization/EVENT_AUDIT_AND_GAPS.md:7-16]
+
+### 18.2 目标 Anti-Corruption Layer
+
+```text
+OrchestrationClient
+  MissionSnapshot / Completion / ArtifactSnapshot / Event / Trace
+        |
+        v
+GenericCausalityProjector
+  Task -> Attempt -> Validation -> Decision
+        |
+        +---- artifact_ref ----> ScriptBuildArtifactAdapter
+        |                         base/branch/round/paragraph/element
+        |
+        +---- trace IDs --------> TraceDetailAdapter
+        |
+        v
+ScriptBuildStoryProjector
+  explicit business bindings: round batch, path, branch disposition
+        |
+        v
+Existing Visualization ViewModels
+```
+
+该链路还必须有 Host 拥有的 `MissionCatalog/ScriptBuildMissionBinding`,持久化 `script_build_id <-> root_trace_id`。原因是现有 Provider 需要 `list_builds()` 且所有路由以 int `script_build_id` 寻址,而 V2 只能在已知 `root_trace_id` 时读取单个 Root,没有 Root 列表 API。该 Catalog 负责列表/筛选/反查和软删可见性,不是 Ledger 的第二套任务状态。另外,现 Provider 是同步接口,`OrchestrationClient` 为 async;应在应用启动层使用 async Provider,或明确的线程/事件循环边界,不在已运行 event loop 中直接 `asyncio.run`。[现项目:visualization/backend/app/providers.py:8-29]
+
+这里必须增加显式 binding,例如 artifact metadata 中的 `script_build_id/branch_id/base_revision/path_index/round_index`;但这些是业务 Artifact schema,不应加进通用 Event 或 MissionSnapshot 顶层。通用 Event v2 刻意只通知实体 ID,Projector 应回读 Snapshot/Artifact/Trace,不要让 Event 复制业务对象。
+
+## 19. 风险重分类与精确定性
+
+### 19.1 Legacy 业务引擎
+
+| 优先级 | 风险 | 确认证据/后果 |
+|---|---|---|
+| P0 | success/终态计数混入非 base 分支 | status/run count 只按 build+active,detail 只返 branch=0;计数可与数组长度不一致 [代码:script_build_agent_tools.py:4147-4165][代码:ScriptBuildAigcAgent.py:1063-1078][代码:pattern_server.py:2280-2312] |
+| P0 | 评估通过不是硬门禁 | code 注释明确移除最近评估门禁,无 status 调用时有任意产物即 auto success [代码:script_build_agent_tools.py:4094-4104][代码:script_build_agent_tools.py:4135-4178] |
+| P0 | 分支引用隔离漏洞 | link/parent 部分查询未限 base+当前 branch,可跨兄弟分支误引用/误 skipped [代码:script_build_agent_tools.py:2997-3012][代码:script_build_agent_tools.py:3317-3328][代码:script_build_agent_tools.py:3373-3400] |
+| P0 | multi-merge 无冲突检测 | 按顺序 merge,后分支可静默覆盖前分支 [代码:script_build_branch_core.py:248-255] |
+| P0 | migration 不可靠 | create_all 不升级;fresh/incremental event SQL 不可线性全跑 |
+| P1 | 上游 ID 归属未校验 + 无 FK | 可建造跨 execution/build 错挂 record |
+| P1 | rewind 覆写 Trace/log 且不回滚 DB | 重放可重复副作用,不是审计友好恢复 |
+| P1 | event 非唯一真源 | best-effort、可原地 finish UPDATE、多进程 seq 无唯一约束 |
+| P1 | 凭据/鉴权/主动出网 | 源码存在硬编码 DB 连接信息(本文不复制);API 未见路由鉴权;image URL 是 SSRF 边界 |
+| P2 | task plan 门禁覆盖不全 | 只在 create paragraph/element 前检查,append/update/link 可绕过 |
+| P2 | Direction 冻结只在 Prompt | save 可覆盖已有 direction |
+| P2 | decision snapshot 不完整 | element snapshot 未包含 analysis/support/weight 等详情字段 |
+| P2 | soft-delete 读取策略不一致 | detail/log/trace 未统一过滤 is_deleted |
+
+### 19.2 Framework 自身
+
+| 风险 | 定性 |
+|---|---|
+| 默认 completion policy 仍可是 legacy_auto | explicit validation 不是所有调用自动生效,Host 必须选择并提供 Root spec |
+| V2 API 是可选 adapter | 不得因 router/client 存在就声称默认 server 已暴露 |
+| operation runtime 仍 process-local | 持久状态不等于持久队列/lease/heartbeat;recover 主要对账,不自动重跑模型 |
+| ArtifactSnapshotView 无正文 | 是刻意的去重合同,但 Host 必须提供 artifact URI 可读性/权限/保留策略 |
+| Trace/Event 与业务 DB 不在同一事务 | 需 outbox/saga,不能假设通用 store 的原子性自动延伸到 MySQL ScriptBuild 表 |
+
+### 19.3 集成风险
+
+- 把 Round 直接存为 Task 或把 Branch 直接存为 Attempt,会丢失业务语义并破坏通用模型。
+- 把 Planner ACCEPT 当成已 merge,会在业务 DB merge 失败时造成控制面/业务面分裂。
+- 只让 visualization 读 Event v2,会丢掉 Round/Branch/Paragraph 正文;Event v2 是变化通知,不是业务数据包。
+- 沿用 legacy rewind 语义会破坏当前 framework 的 immutable Attempt/Artifact/历史决策设计。
+
+## 20. 目标集成架构与 ADR
+
+### 20.1 建议组件
+
+| 组件 | 责任 | 输入 | 输出 |
+|---|---|---|---|
+| `ScriptBuildMissionFactory` | Topic/persona/strategy 转 Root TaskSpec;脚本运行使命与冻结 direction 分离 | legacy start request | root spec + versioned direction artifact/context ref |
+| `ScriptBuildMissionCatalog` | 维护 `script_build_id <-> root_trace_id` 寻址、列表和可见性,不复制 Task 状态 | start/delete/list/query | binding/catalog rows |
+| `ScriptBuildPlannerAdapter` | 把业务目标分解为有界 Tasks,保留 Round/Path metadata 在业务 artifact | snapshot + validation feedback | create/revise/split decisions |
+| `ScriptBuildWorkerAdapter` | 调 legacy tool service 产候选 patch,不直接 accept | TaskSpec + frozen child decisions + base revision | AttemptSubmission + immutable branch snapshot ref |
+| `ScriptBuildValidatorAdapter` | 运行单候选/批次/base criteria | task spec + artifact snapshot | ValidationReport |
+| `ScriptBuildMergeService` | expected-base-revision + write-set conflict check + idempotent merge | ACCEPT intent + branch snapshot | merged base revision/artifact |
+| `ScriptBuildArtifactRepository` | 持久候选/base 正文和 digest | paragraph/element/link snapshot | immutable URI + sha256 |
+| `ScriptBuildOutbox` | 业务 DB 变化通知 | committed business transaction | entity-ID event |
+| `ScriptBuildProjectionAdapter` | 融合 Mission causal graph + artifact business graph,处理 sync Provider/async SDK 边界 | catalog + SDK + artifact API + traces | visualization view models |
+
+### 20.2 关键 ADR
+
+1. **Ledger 与业务库分权**:Ledger 对执行/验证/决策因果负责;ScriptBuild DB/Artifact Repository 对 Round/Branch/Paragraph/Element 正文负责;不复制两套状态。
+2. **ACCEPT 与 merge 分离**:ACCEPT 证明候选满足验收;merge 是可失败、幂等、带 expected revision 的业务命令。可将 merge 建模为后续 Task/Operation,成功后才更新 Root 成品引用。
+3. **Artifact 引用而非正文复制**:Ledger/Wire 保存 immutable URI/version/digest/evidence refs,Paragraph 全文由业务 artifact API 返回。
+4. **重试创建新 Attempt**:不覆写原 Trace/日志/快照;使用 retry/revise/replan 表达历史。
+5. **Event 仅通知 ID**:应用从 MissionSnapshot/Artifact/Trace 回读事实,避免第三套 Task/Decision/Branch 副本。
+6. **状态转移和写入统一强制**:不再依赖 Prompt 声明“应该先取证/后评估”,而是由 TaskSpec criteria、capability policy、snapshot validator 和 state machine 组合门禁。
+
+### 20.3 分阶段迁移
+
+| 阶段 | 改动 | 可回退点 | 验收 |
+|---|---|---|---|
+| 0 纠正 legacy | base-only counts/gates;branch reference scoping;merge conflicts;ID ownership;migration runner | 保持旧 HTTP/UI | 成品正确性测试全过 |
+| 1 产物化 | 为 branch/base 快照生成 immutable URI+digest,补 retrieval/decision IDs | legacy Agent 仍自编排 | 快照可重读、不可覆写、指纹稳定 |
+| 2 只读接入 | 把一次 legacy run 镜像为 Mission/Tasks/Attempts/Validations,不控制生产写入 | 关 projector 即回旧 UI | 因果链与旧表对账,不声称原子控制 |
+| 3 双跑验证 | framework Validator/Decision 旁路运行,legacy 仍决定 | 不采用 framework decision | 评估差异/成本/延迟有报表 |
+| 4 控制面切换 | framework dispatch/validate/decide,legacy tools 作 Worker adapter | feature flag 回 legacy orchestrator | retry/revise/stop 无历史覆写,不发生重复写 |
+| 5 投影切换 | visualization 用 SDK + Artifact + Trace projector | 保留 legacy Repository | 新旧页面核心业务事实对账 |
+| 6 可靠运行 | queue/lease/heartbeat/outbox/reconciler/shared trace | 分步切 worker | 进程崩溃可恢复,幂等不重复 merge |
 
-后续可以按任务选择:
+## 21. 测试与验收证据矩阵
 
-| Skill | 适用场景 | 对本项目的具体价值 |
+| 类别 | 用例 | 必须断言 |
 |---|---|---|
-| senior-architect | 架构梳理、ADR、目标架构、迁移计划 | 继续设计 ScriptBuild 目标架构与分阶段 ADR |
-| architecture-patterns | Clean/Hexagonal/Ports & Adapters 重构 | 拆分 4705 行工具文件,隔离 Repository 与外部 Gateway |
-| domain-driven-design | 聚合、值对象、领域服务和状态机 | 定义 Build、Round、Branch、Patch、Decision 聚合边界 |
-| codex-architect | 对具体设计做第二意见 | 评审 Worker、TraceStore、状态机和合并策略 |
-| security-threat-model | 明确要求做 AppSec 威胁建模时 | 系统分析 Prompt 注入、SSRF、凭据、越权和数据泄露路径 |
-
-建议的使用顺序是:
-
-1. 用 domain-driven-design 固化业务对象和状态机。
-2. 用 architecture-patterns 设计代码拆分与 Ports/Adapters。
-3. 用 senior-architect 形成 ADR、目标架构和迁移阶段。
-4. 如果要正式上线安全审查,再单独使用 security-threat-model。
+| Legacy branch | base、new patch、override、merge、discard、park | overlay 正确;兄弟不可见;冲突拒绝;无孤儿 link |
+| Legacy final | base 空 + parked 有内容;base 3 段 + patch 2 段 | 不得 success;count=3;detail 长度=count |
+| Legacy evidence | retrieval invocation、DataDecision、write | write 能闭合到具体调用/loc;缺引用拒绝 |
+| Legacy validation | 无报告、报告不通过、通过后 base 被改 | 不能 success;只能 continue/partial/failed;旧 hash 失效 |
+| Framework causal | None/empty/multiple/out-of-order/duplicate/cross-task/non-ACCEPT/missing refs | 严格区分旧未记录与新无子输入;所有异常引用拒绝 |
+| Framework snapshot | 多集合同时变化 | 仅一次 load;同 revision;稳定排序;严格 schema |
+| Framework event | v1/v2 mixed cursor;default wiring | 游标不重不漏;默认无重复 JSONL mirror |
+| Trace | 1001 unrelated + one target | filter-before-limit 仍找到目标 |
+| Integration E2E | child fail/revise/pass/accept + root revise/pass | frozen input;SDK-only reads;Decision→Artifact→Trace 闭合;wire 无脚本业务节点 |
+| Recovery | worker 在 plan/retrieval/write/merge 各点崩溃 | 新 Attempt 可恢复;旧 snapshot/trace 不变;command 幂等 |
+| Projection | 同一 run 的 legacy UI 和新 projector | status/round/branch disposition/base artifact 一致;未闭合关联显式标 unknown |
+
+当前 framework 已有的关键测试证据包括:Mission Snapshot 单次 load/严格 schema [现项目:agent/tests/test_orchestration_v2_api.py:337-360];全链黑盒 E2E [现项目:agent/tests/test_framework_observation_e2e.py:32-140];Trace filter-before-limit [现项目:agent/tests/test_observation_events_and_traces.py:65-112]。Legacy 的上述 P0 缺陷仍需单独测试,不能用 framework 测试代替。
 
 ## 附录 A:核心阅读入口